NeoMutt  2025-12-11-435-g4ac674
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
smime.c File Reference

SMIME helper routines. More...

#include "config.h"
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "private.h"
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "lib.h"
#include "editor/lib.h"
#include "expando/lib.h"
#include "history/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "crypt.h"
#include "cryptglue.h"
#include "expando_smime.h"
#include "mutt_logging.h"
#include "smime.h"
+ Include dependency graph for smime.c:

Go to the source code of this file.

Functions

void smime_init (void)
 Initialise smime globals.
 
void smime_cleanup (void)
 Clean up smime globals.
 
static void smime_key_free (struct SmimeKey **keylist)
 Free a list of SMIME keys.
 
static struct SmimeKeysmime_copy_key (struct SmimeKey *key)
 Copy an SMIME key.
 
void smime_class_void_passphrase (void)
 Forget the cached passphrase - Implements CryptModuleSpecs::void_passphrase() -.
 
bool smime_class_valid_passphrase (void)
 Ensure we have a valid passphrase - Implements CryptModuleSpecs::valid_passphrase() -.
 
static void smime_command (struct Buffer *buf, struct SmimeCommandContext *cctx, const struct Expando *exp)
 Format an SMIME command string.
 
static pid_t smime_invoke (FILE **fp_smime_in, FILE **fp_smime_out, FILE **fp_smime_err, int fp_smime_infd, int fp_smime_outfd, int fp_smime_errfd, const char *fname, const char *sig_fname, const char *cryptalg, const char *digestalg, const char *key, const char *certificates, const char *intermediates, const struct Expando *exp)
 Run an SMIME command.
 
static struct SmimeKeysmime_parse_key (char *buf)
 Parse an SMIME key block.
 
static struct SmimeKeysmime_get_candidates (const char *search, bool only_public_key)
 Find keys matching a string.
 
static struct SmimeKeysmime_get_key_by_hash (const char *hash, bool only_public_key)
 Find a key by its hash.
 
static struct SmimeKeysmime_get_key_by_addr (const char *mailbox, KeyFlags abilities, bool only_public_key, bool oppenc_mode)
 Find an SIME key by address.
 
static struct SmimeKeysmime_get_key_by_str (const char *str, KeyFlags abilities, bool only_public_key)
 Find an SMIME key by string.
 
static struct SmimeKeysmime_ask_for_key (const char *prompt, KeyFlags abilities, bool only_public_key)
 Ask the user to select a key.
 
static void getkeys (const char *mailbox)
 Get the keys for a mailbox.
 
void smime_class_getkeys (struct Envelope *env)
 Get the S/MIME keys required to encrypt this email - Implements CryptModuleSpecs::smime_getkeys() -.
 
char * smime_class_find_keys (const struct AddressList *al, bool oppenc_mode)
 Find the keyids of the recipients of a message - Implements CryptModuleSpecs::find_keys() -.
 
static int smime_handle_cert_email (const char *certificate, const char *mailbox, bool copy, char ***buffer, int *num)
 Process an email containing certificates.
 
static char * smime_extract_certificate (const char *infile)
 Extract an SMIME certificate from a file.
 
static char * smime_extract_signer_certificate (const char *infile)
 Extract the signer's certificate.
 
void smime_class_invoke_import (const char *infile, const char *mailbox)
 Add a certificate and update index file (externally) - Implements CryptModuleSpecs::smime_invoke_import() -.
 
int smime_class_verify_sender (struct Email *e, struct Message *msg)
 Does the sender match the certificate?
 
static pid_t smime_invoke_encrypt (FILE **fp_smime_in, FILE **fp_smime_out, FILE **fp_smime_err, int fp_smime_infd, int fp_smime_outfd, int fp_smime_errfd, const char *fname, const char *uids)
 Use SMIME to encrypt a file.
 
static pid_t smime_invoke_sign (FILE **fp_smime_in, FILE **fp_smime_out, FILE **fp_smime_err, int fp_smime_infd, int fp_smime_outfd, int fp_smime_errfd, const char *fname)
 Use SMIME to sign a file.
 
struct Bodysmime_class_build_smime_entity (struct Body *b, char *certlist)
 Encrypt the email body to all recipients - Implements CryptModuleSpecs::smime_build_smime_entity() -.
 
static char * openssl_md_to_smime_micalg (const char *md)
 Change the algorithm names.
 
struct Bodysmime_class_sign_message (struct Body *b, const struct AddressList *from)
 Cryptographically sign the Body of a message - Implements CryptModuleSpecs::sign_message() -.
 
static pid_t smime_invoke_verify (FILE **fp_smime_in, FILE **fp_smime_out, FILE **fp_smime_err, int fp_smime_infd, int fp_smime_outfd, int fp_smime_errfd, const char *fname, const char *sig_fname, int opaque)
 Use SMIME to verify a file.
 
static pid_t smime_invoke_decrypt (FILE **fp_smime_in, FILE **fp_smime_out, FILE **fp_smime_err, int fp_smime_infd, int fp_smime_outfd, int fp_smime_errfd, const char *fname)
 Use SMIME to decrypt a file.
 
int smime_class_verify_one (struct Body *b, struct State *state, const char *tempfile)
 Check a signed MIME part against a signature - Implements CryptModuleSpecs::verify_one() -.
 
static struct Bodysmime_handle_entity (struct Body *b, struct State *state, FILE *fp_out_file)
 Handle type application/pkcs7-mime.
 
int smime_class_decrypt_mime (FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **b_dec)
 Decrypt an encrypted MIME part - Implements CryptModuleSpecs::decrypt_mime() -.
 
int smime_class_application_handler (struct Body *b, struct State *state)
 Manage the MIME type "application/pgp" or "application/smime" - Implements CryptModuleSpecs::application_handler() -.
 
SecurityFlags smime_class_send_menu (struct Email *e)
 Ask the user whether to sign and/or encrypt the email - Implements CryptModuleSpecs::send_menu() -.
 

Variables

static char SmimePass [256]
 Cached Smime Passphrase.
 
static time_t SmimeExpTime = 0
 Unix time when SmimePass expires.
 
static struct Buffer SmimeKeyToUse = { 0 }
 Smime key to use.
 
static struct Buffer SmimeCertToUse = { 0 }
 Smime certificate to use.
 
static struct Buffer SmimeIntermediateToUse = { 0 }
 Smime intermediate certificate to use.
 

Detailed Description

SMIME helper routines.

Authors
  • Richard Russon
  • Pietro Cerutti
  • Lars Haalck
  • Anna Figueiredo Gomes
  • Alejandro Colomar
  • Tóth János

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file smime.c.

Function Documentation

◆ smime_init()

void smime_init ( void )

Initialise smime globals.

Definition at line 79 of file smime.c.

80{
84}
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition buffer.c:337
static struct Buffer SmimeIntermediateToUse
Smime intermediate certificate to use.
Definition smime.c:74
static struct Buffer SmimeKeyToUse
Smime key to use.
Definition smime.c:70
static struct Buffer SmimeCertToUse
Smime certificate to use.
Definition smime.c:72
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_cleanup()

void smime_cleanup ( void )

Clean up smime globals.

Definition at line 89 of file smime.c.

90{
94}
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition buffer.c:377
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_key_free()

static void smime_key_free ( struct SmimeKey ** keylist)
static

Free a list of SMIME keys.

Parameters
[out]keylistList of keys to free

Definition at line 100 of file smime.c.

101{
102 if (!keylist)
103 return;
104
105 struct SmimeKey *key = NULL;
106
107 while (*keylist)
108 {
109 key = *keylist;
110 *keylist = (*keylist)->next;
111
112 FREE(&key->email);
113 FREE(&key->hash);
114 FREE(&key->label);
115 FREE(&key->issuer);
116 FREE(&key);
117 }
118}
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
An SIME key.
Definition smime.h:42
char * hash
Key hash.
Definition smime.h:44
struct SmimeKey * next
Linked list.
Definition smime.h:49
char * issuer
Key issuer.
Definition smime.h:46
char * email
Email address.
Definition smime.h:43
char * label
Key label.
Definition smime.h:45
+ Here is the caller graph for this function:

◆ smime_copy_key()

static struct SmimeKey * smime_copy_key ( struct SmimeKey * key)
static

Copy an SMIME key.

Parameters
keyKey to copy
Return values
ptrNewly allocated SMIME key

Definition at line 125 of file smime.c.

126{
127 if (!key)
128 return NULL;
129
130 struct SmimeKey *copy = NULL;
131
132 copy = MUTT_MEM_CALLOC(1, struct SmimeKey);
133 copy->email = mutt_str_dup(key->email);
134 copy->hash = mutt_str_dup(key->hash);
135 copy->label = mutt_str_dup(key->label);
136 copy->issuer = mutt_str_dup(key->issuer);
137 copy->trust = key->trust;
138 copy->flags = key->flags;
139
140 return copy;
141}
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:52
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
KeyFlags flags
Key flags.
Definition smime.h:48
char trust
i=Invalid r=revoked e=expired u=unverified v=verified t=trusted
Definition smime.h:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_command()

static void smime_command ( struct Buffer * buf,
struct SmimeCommandContext * cctx,
const struct Expando * exp )
static

Format an SMIME command string.

Parameters
bufBuffer for the result
cctxData to pass to the formatter
expExpando to use

Definition at line 192 of file smime.c.

194{
196 buf->dsize, buf);
197 mutt_debug(LL_DEBUG2, "%s\n", buf_string(buf));
198}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
int expando_render(const struct Expando *exp, const struct ExpandoRenderCallback *erc, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Render an Expando + data into a string.
Definition expando.c:118
const struct ExpandoRenderCallback SmimeCommandRenderCallbacks[]
Callbacks for Smime Command Expandos.
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:46
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition render.h:33
size_t dsize
Length of data.
Definition buffer.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_invoke()

static pid_t smime_invoke ( FILE ** fp_smime_in,
FILE ** fp_smime_out,
FILE ** fp_smime_err,
int fp_smime_infd,
int fp_smime_outfd,
int fp_smime_errfd,
const char * fname,
const char * sig_fname,
const char * cryptalg,
const char * digestalg,
const char * key,
const char * certificates,
const char * intermediates,
const struct Expando * exp )
static

Run an SMIME command.

Parameters
[out]fp_smime_instdin for the command, or NULL (OPTIONAL)
[out]fp_smime_outstdout for the command, or NULL (OPTIONAL)
[out]fp_smime_errstderr for the command, or NULL (OPTIONAL)
[in]fp_smime_infdstdin for the command, or -1 (OPTIONAL)
[in]fp_smime_outfdstdout for the command, or -1 (OPTIONAL)
[in]fp_smime_errfdstderr for the command, or -1 (OPTIONAL)
[in]fnameFilename to pass to the command
[in]sig_fnameSignature filename to pass to the command
[in]cryptalgEncryption algorithm
[in]digestalgHashing algorithm
[in]keySMIME key
[in]certificatesPublic certificates
[in]intermediatesIntermediate certificates
[in]expExpando format string
Return values
numPID of the created process
-1Error creating pipes or forking
Note
fp_smime_in has priority over fp_smime_infd. Likewise fp_smime_out and fp_smime_err.

Definition at line 222 of file smime.c.

227{
228 struct SmimeCommandContext cctx = { 0 };
229
230 if (!exp)
231 return (pid_t) -1;
232
233 cctx.fname = fname;
234 cctx.sig_fname = sig_fname;
235 cctx.key = key;
236 cctx.cryptalg = cryptalg;
237 cctx.digestalg = digestalg;
240
241 struct Buffer *cmd = buf_pool_get();
242 smime_command(cmd, &cctx, exp);
243
244 pid_t pid = filter_create_fd(buf_string(cmd), fp_smime_in, fp_smime_out,
245 fp_smime_err, fp_smime_infd, fp_smime_outfd,
246 fp_smime_errfd, NeoMutt->env);
247 buf_pool_release(&cmd);
248 return pid;
249}
pid_t filter_create_fd(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, int fdin, int fdout, int fderr, char **envlist)
Run a command on a pipe (optionally connect stdin/stdout)
Definition filter.c:62
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
static void smime_command(struct Buffer *buf, struct SmimeCommandContext *cctx, const struct Expando *exp)
Format an SMIME command string.
Definition smime.c:192
String manipulation buffer.
Definition buffer.h:36
Container for Accounts, Notifications.
Definition neomutt.h:41
char ** env
Private copy of the environment variables.
Definition neomutt.h:58
Data for a SIME command.
Definition smime.h:57
const char * sig_fname
s
Definition smime.h:62
const char * intermediates
i
Definition smime.h:64
const char * digestalg
d
Definition smime.h:60
const char * cryptalg
a
Definition smime.h:59
const char * key
k
Definition smime.h:58
const char * fname
f
Definition smime.h:61
const char * certificates
c
Definition smime.h:63
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_parse_key()

static struct SmimeKey * smime_parse_key ( char * buf)
static

Parse an SMIME key block.

Parameters
bufString to parse
Return values
ptrSMIME key
NULLError

Definition at line 257 of file smime.c.

258{
259 char *pend = NULL, *p = NULL;
260 int field = 0;
261
262 struct SmimeKey *key = MUTT_MEM_CALLOC(1, struct SmimeKey);
263
264 for (p = buf; p; p = pend)
265 {
266 /* Some users manually maintain their .index file, and use a tab
267 * as a delimiter, which the old parsing code (using fscanf)
268 * happened to allow. smime_keys uses a space, so search for both. */
269 if ((pend = strchr(p, ' ')) || (pend = strchr(p, '\t')) || (pend = strchr(p, '\n')))
270 *pend++ = 0;
271
272 /* For backward compatibility, don't count consecutive delimiters
273 * as an empty field. */
274 if (*p == '\0')
275 continue;
276
277 field++;
278
279 switch (field)
280 {
281 case 1: /* mailbox */
282 key->email = mutt_str_dup(p);
283 break;
284 case 2: /* hash */
285 key->hash = mutt_str_dup(p);
286 break;
287 case 3: /* label */
288 key->label = mutt_str_dup(p);
289 break;
290 case 4: /* issuer */
291 key->issuer = mutt_str_dup(p);
292 break;
293 case 5: /* trust */
294 key->trust = *p;
295 break;
296 case 6: /* purpose */
297 while (*p)
298 {
299 switch (*p++)
300 {
301 case 'e':
303 break;
304
305 case 's':
306 key->flags |= KEYFLAG_CANSIGN;
307 break;
308 }
309 }
310 break;
311 }
312 }
313
314 /* Old index files could be missing issuer, trust, and purpose,
315 * but anything less than that is an error. */
316 if (field < 3)
317 {
318 smime_key_free(&key);
319 return NULL;
320 }
321
322 if (field < 4)
323 key->issuer = mutt_str_dup("?");
324
325 if (field < 5)
326 key->trust = 't';
327
328 if (field < 6)
330
331 return key;
332}
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition lib.h:136
#define KEYFLAG_CANSIGN
Key is suitable for signing.
Definition lib.h:135
static void smime_key_free(struct SmimeKey **keylist)
Free a list of SMIME keys.
Definition smime.c:100
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_get_candidates()

static struct SmimeKey * smime_get_candidates ( const char * search,
bool only_public_key )
static

Find keys matching a string.

Parameters
searchString to match
only_public_keyIf true, only get the public keys
Return values
ptrMatching key

Definition at line 340 of file smime.c.

341{
342 char buf[1024] = { 0 };
343 struct SmimeKey *key = NULL, *results = NULL;
344 struct SmimeKey **results_end = &results;
345
346 struct Buffer *index_file = buf_pool_get();
347 const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
348 const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
349 buf_printf(index_file, "%s/.index",
350 only_public_key ? NONULL(c_smime_certificates) : NONULL(c_smime_keys));
351
352 FILE *fp = mutt_file_fopen(buf_string(index_file), "r");
353 if (!fp)
354 {
355 mutt_perror("%s", buf_string(index_file));
356 buf_pool_release(&index_file);
357 return NULL;
358 }
359 buf_pool_release(&index_file);
360
361 while (fgets(buf, sizeof(buf), fp))
362 {
363 if (((*search == '\0')) || mutt_istr_find(buf, search))
364 {
365 key = smime_parse_key(buf);
366 if (key)
367 {
368 *results_end = key;
369 results_end = &key->next;
370 }
371 }
372 }
373
374 mutt_file_fclose(&fp);
375
376 return results;
377}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition helpers.c:168
#define mutt_file_fclose(FP)
Definition file.h:139
#define mutt_file_fopen(PATH, MODE)
Definition file.h:138
#define mutt_perror(...)
Definition logging2.h:95
static int search(struct Menu *menu, int op)
Search a menu.
Definition functions.c:58
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition string.c:525
static struct SmimeKey * smime_parse_key(char *buf)
Parse an SMIME key block.
Definition smime.c:257
#define NONULL(x)
Definition string2.h:44
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_get_key_by_hash()

static struct SmimeKey * smime_get_key_by_hash ( const char * hash,
bool only_public_key )
static

Find a key by its hash.

Parameters
hashHash to find
only_public_keyIf true, only get the public keys
Return values
ptrMatching key

Returns the first matching key record, without prompting or checking of abilities or trust.

Definition at line 388 of file smime.c.

389{
390 struct SmimeKey *match = NULL;
391 struct SmimeKey *results = smime_get_candidates(hash, only_public_key);
392 for (struct SmimeKey *result = results; result; result = result->next)
393 {
394 if (mutt_istr_equal(hash, result->hash))
395 {
396 match = smime_copy_key(result);
397 break;
398 }
399 }
400
401 smime_key_free(&results);
402
403 return match;
404}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:674
static struct SmimeKey * smime_copy_key(struct SmimeKey *key)
Copy an SMIME key.
Definition smime.c:125
static struct SmimeKey * smime_get_candidates(const char *search, bool only_public_key)
Find keys matching a string.
Definition smime.c:340
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_get_key_by_addr()

static struct SmimeKey * smime_get_key_by_addr ( const char * mailbox,
KeyFlags abilities,
bool only_public_key,
bool oppenc_mode )
static

Find an SIME key by address.

Parameters
mailboxEmail address to match
abilitiesAbilities to match, see KeyFlags
only_public_keyIf true, only get the public keys
oppenc_modeIf true, use opportunistic encryption
Return values
ptrMatching key

Definition at line 414 of file smime.c.

416{
417 if (!mailbox)
418 return NULL;
419
420 struct SmimeKey *results = NULL, *result = NULL;
421 struct SmimeKey *matches = NULL;
422 struct SmimeKey **matches_end = &matches;
423 struct SmimeKey *match = NULL;
424 struct SmimeKey *trusted_match = NULL;
425 struct SmimeKey *valid_match = NULL;
426 struct SmimeKey *return_key = NULL;
427 bool multi_trusted_matches = false;
428
429 results = smime_get_candidates(mailbox, only_public_key);
430 for (result = results; result; result = result->next)
431 {
432 if (abilities && !(result->flags & abilities))
433 {
434 continue;
435 }
436
437 if (mutt_istr_equal(mailbox, result->email))
438 {
439 match = smime_copy_key(result);
440 *matches_end = match;
441 matches_end = &match->next;
442
443 if (match->trust == 't')
444 {
445 if (trusted_match && !mutt_istr_equal(match->hash, trusted_match->hash))
446 {
447 multi_trusted_matches = true;
448 }
449 trusted_match = match;
450 }
451 else if ((match->trust == 'u') || (match->trust == 'v'))
452 {
453 valid_match = match;
454 }
455 }
456 }
457
458 smime_key_free(&results);
459
460 if (matches)
461 {
462 if (oppenc_mode || !isatty(STDIN_FILENO))
463 {
464 const bool c_crypt_opportunistic_encrypt_strong_keys =
465 cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt_strong_keys");
466 if (trusted_match)
467 return_key = smime_copy_key(trusted_match);
468 else if (valid_match && !c_crypt_opportunistic_encrypt_strong_keys)
469 return_key = smime_copy_key(valid_match);
470 else
471 return_key = NULL;
472 }
473 else if (trusted_match && !multi_trusted_matches)
474 {
475 return_key = smime_copy_key(trusted_match);
476 }
477 else
478 {
479 return_key = smime_copy_key(dlg_smime(matches, mailbox));
480 }
481
482 smime_key_free(&matches);
483 }
484
485 return return_key;
486}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
struct SmimeKey * dlg_smime(struct SmimeKey *keys, const char *query)
Get the user to select a key -.
Definition dlg_smime.c:194
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_get_key_by_str()

static struct SmimeKey * smime_get_key_by_str ( const char * str,
KeyFlags abilities,
bool only_public_key )
static

Find an SMIME key by string.

Parameters
strString to match
abilitiesAbilities to match, see KeyFlags
only_public_keyIf true, only get the public keys
Return values
ptrMatching key

Definition at line 495 of file smime.c.

496{
497 if (!str)
498 return NULL;
499
500 struct SmimeKey *results = NULL, *result = NULL;
501 struct SmimeKey *matches = NULL;
502 struct SmimeKey **matches_end = &matches;
503 struct SmimeKey *match = NULL;
504 struct SmimeKey *return_key = NULL;
505
506 results = smime_get_candidates(str, only_public_key);
507 for (result = results; result; result = result->next)
508 {
509 if (abilities && !(result->flags & abilities))
510 {
511 continue;
512 }
513
514 if (mutt_istr_equal(str, result->hash) ||
515 mutt_istr_find(result->email, str) || mutt_istr_find(result->label, str))
516 {
517 match = smime_copy_key(result);
518 *matches_end = match;
519 matches_end = &match->next;
520 }
521 }
522
523 smime_key_free(&results);
524
525 if (matches)
526 {
527 return_key = smime_copy_key(dlg_smime(matches, str));
528 smime_key_free(&matches);
529 }
530
531 return return_key;
532}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_ask_for_key()

static struct SmimeKey * smime_ask_for_key ( const char * prompt,
KeyFlags abilities,
bool only_public_key )
static

Ask the user to select a key.

Parameters
promptPrompt to show the user
abilitiesAbilities to match, see KeyFlags
only_public_keyIf true, only get the public keys
Return values
ptrSelected SMIME key

Definition at line 541 of file smime.c.

542{
543 if (!prompt)
544 return NULL;
545
546 struct SmimeKey *key = NULL;
547 struct Buffer *resp = buf_pool_get();
548
550
551 while (true)
552 {
553 buf_reset(resp);
554 if (mw_get_field(prompt, resp, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0)
555 {
556 goto done;
557 }
558
559 key = smime_get_key_by_str(buf_string(resp), abilities, only_public_key);
560 if (key)
561 goto done;
562
563 mutt_error(_("No matching keys found for \"%s\""), buf_string(resp));
564 }
565
566done:
567 buf_pool_release(&resp);
568 return key;
569}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition wdata.h:42
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition window.c:270
#define mutt_error(...)
Definition logging2.h:94
@ HC_OTHER
Miscellaneous strings.
Definition lib.h:60
#define _(a)
Definition message.h:28
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
static struct SmimeKey * smime_get_key_by_str(const char *str, KeyFlags abilities, bool only_public_key)
Find an SMIME key by string.
Definition smime.c:495
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getkeys()

static void getkeys ( const char * mailbox)
static

Get the keys for a mailbox.

Parameters
mailboxEmail address

This sets the '*ToUse' variables for an upcoming decryption, where the required key is different from $smime_default_key.

Definition at line 578 of file smime.c.

579{
580 const char *k = NULL;
581
582 struct SmimeKey *key = smime_get_key_by_addr(mailbox, KEYFLAG_CANENCRYPT, false, false);
583
584 if (!key)
585 {
586 struct Buffer *prompt = buf_pool_get();
587 buf_printf(prompt, _("Enter keyID for %s: "), mailbox);
588 key = smime_ask_for_key(buf_string(prompt), KEYFLAG_CANENCRYPT, false);
589 buf_pool_release(&prompt);
590 }
591
592 const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
593 size_t smime_keys_len = mutt_str_len(c_smime_keys);
594
595 const char *const c_smime_default_key = cs_subset_string(NeoMutt->sub, "smime_default_key");
596 k = key ? key->hash : NONULL(c_smime_default_key);
597
598 /* if the key is different from last time */
599 if ((buf_len(&SmimeKeyToUse) <= smime_keys_len) ||
600 !mutt_istr_equal(k, SmimeKeyToUse.data + smime_keys_len + 1))
601 {
603 buf_printf(&SmimeKeyToUse, "%s/%s", NONULL(c_smime_keys), k);
604 const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
605 buf_printf(&SmimeCertToUse, "%s/%s", NONULL(c_smime_certificates), k);
606 }
607
608 smime_key_free(&key);
609}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition buffer.c:491
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
void smime_class_void_passphrase(void)
Forget the cached passphrase - Implements CryptModuleSpecs::void_passphrase() -.
Definition smime.c:146
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:500
static struct SmimeKey * smime_get_key_by_addr(const char *mailbox, KeyFlags abilities, bool only_public_key, bool oppenc_mode)
Find an SIME key by address.
Definition smime.c:414
static struct SmimeKey * smime_ask_for_key(const char *prompt, KeyFlags abilities, bool only_public_key)
Ask the user to select a key.
Definition smime.c:541
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_handle_cert_email()

static int smime_handle_cert_email ( const char * certificate,
const char * mailbox,
bool copy,
char *** buffer,
int * num )
static

Process an email containing certificates.

Parameters
[in]certificateEmail with certificates
[in]mailboxEmail address
[in]copyIf true, save the certificates to buffer
[out]bufferBuffer allocated to hold certificates
[out]numNumber of certificates in buffer
Return values
0Success
-1Error
-2Error

Definition at line 702 of file smime.c.

704{
705 char email[256] = { 0 };
706 int rc = -1, count = 0;
707 pid_t pid;
708
709 FILE *fp_err = mutt_file_mkstemp();
710 if (!fp_err)
711 {
712 mutt_perror(_("Can't create temporary file"));
713 return 1;
714 }
715
716 FILE *fp_out = mutt_file_mkstemp();
717 if (!fp_out)
718 {
719 mutt_file_fclose(&fp_err);
720 mutt_perror(_("Can't create temporary file"));
721 return 1;
722 }
723
724 const struct Expando *c_smime_get_cert_email_command =
725 cs_subset_expando(NeoMutt->sub, "smime_get_cert_email_command");
726 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), certificate,
727 NULL, NULL, NULL, NULL, NULL, NULL, c_smime_get_cert_email_command);
728 if (pid == -1)
729 {
730 mutt_message(_("Error: unable to create OpenSSL subprocess"));
731 mutt_file_fclose(&fp_err);
732 mutt_file_fclose(&fp_out);
733 return 1;
734 }
735
736 filter_wait(pid);
737
738 fflush(fp_out);
739 rewind(fp_out);
740 fflush(fp_err);
741 rewind(fp_err);
742
743 while ((fgets(email, sizeof(email), fp_out)))
744 {
745 size_t len = mutt_str_len(email);
746 if (len && (email[len - 1] == '\n'))
747 email[len - 1] = '\0';
748 if (mutt_istr_startswith(email, mailbox))
749 rc = 1;
750
751 rc = (rc < 0) ? 0 : rc;
752 count++;
753 }
754
755 if (rc == -1)
756 {
757 mutt_endwin();
758 mutt_file_copy_stream(fp_err, stdout);
759 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
760 rc = 1;
761 }
762 else if (rc == 0)
763 {
764 rc = 1;
765 }
766 else
767 {
768 rc = 0;
769 }
770
771 if (copy && buffer && num)
772 {
773 (*num) = count;
774 *buffer = MUTT_MEM_CALLOC(count, char *);
775 count = 0;
776
777 rewind(fp_out);
778 while ((fgets(email, sizeof(email), fp_out)))
779 {
780 size_t len = mutt_str_len(email);
781 if (len && (email[len - 1] == '\n'))
782 email[len - 1] = '\0';
783 (*buffer)[count] = MUTT_MEM_CALLOC(mutt_str_len(email) + 1, char);
784 strncpy((*buffer)[count], email, mutt_str_len(email));
785 count++;
786 }
787 }
788 else if (copy)
789 {
790 rc = 2;
791 }
792
793 mutt_file_fclose(&fp_out);
794 mutt_file_fclose(&fp_err);
795
796 return rc;
797}
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition curs_lib.c:173
void mutt_endwin(void)
Shutdown curses.
Definition curs_lib.c:151
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition file.c:222
#define mutt_message(...)
Definition logging2.h:93
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition filter.c:220
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition string.c:246
static pid_t smime_invoke(FILE **fp_smime_in, FILE **fp_smime_out, FILE **fp_smime_err, int fp_smime_infd, int fp_smime_outfd, int fp_smime_errfd, const char *fname, const char *sig_fname, const char *cryptalg, const char *digestalg, const char *key, const char *certificates, const char *intermediates, const struct Expando *exp)
Run an SMIME command.
Definition smime.c:222
Parsed Expando trees.
Definition expando.h:41
#define mutt_file_mkstemp()
Definition tmp.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_extract_certificate()

static char * smime_extract_certificate ( const char * infile)
static

Extract an SMIME certificate from a file.

Parameters
infileFile to read
Return values
ptrFilename of temporary file containing certificate

Definition at line 804 of file smime.c.

805{
806 FILE *fp_err = NULL;
807 FILE *fp_out = NULL;
808 FILE *fp_cert = NULL;
809 char *rc = NULL;
810 pid_t pid;
811 int empty;
812
813 struct Buffer *pk7out = buf_pool_get();
814 struct Buffer *certfile = buf_pool_get();
815
816 fp_err = mutt_file_mkstemp();
817 if (!fp_err)
818 {
819 mutt_perror(_("Can't create temporary file"));
820 goto cleanup;
821 }
822
823 buf_mktemp(pk7out);
824 fp_out = mutt_file_fopen(buf_string(pk7out), "w+");
825 if (!fp_out)
826 {
827 mutt_perror("%s", buf_string(pk7out));
828 goto cleanup;
829 }
830
831 /* Step 1: Convert the signature to a PKCS#7 structure, as we can't
832 * extract the full set of certificates directly. */
833 const struct Expando *c_smime_pk7out_command = cs_subset_expando(NeoMutt->sub, "smime_pk7out_command");
834 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), infile,
835 NULL, NULL, NULL, NULL, NULL, NULL, c_smime_pk7out_command);
836 if (pid == -1)
837 {
838 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
839 goto cleanup;
840 }
841
842 filter_wait(pid);
843
844 fflush(fp_out);
845 rewind(fp_out);
846 fflush(fp_err);
847 rewind(fp_err);
848 empty = (fgetc(fp_out) == EOF);
849 if (empty)
850 {
851 mutt_perror("%s", buf_string(pk7out));
852 mutt_file_copy_stream(fp_err, stdout);
853 goto cleanup;
854 }
855 mutt_file_fclose(&fp_out);
856
857 buf_mktemp(certfile);
858 fp_cert = mutt_file_fopen(buf_string(certfile), "w+");
859 if (!fp_cert)
860 {
861 mutt_perror("%s", buf_string(certfile));
863 goto cleanup;
864 }
865
866 // Step 2: Extract the certificates from a PKCS#7 structure.
867 const struct Expando *c_smime_get_cert_command = cs_subset_expando(NeoMutt->sub, "smime_get_cert_command");
868 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_cert), fileno(fp_err),
869 buf_string(pk7out), NULL, NULL, NULL, NULL, NULL, NULL,
870 c_smime_get_cert_command);
871 if (pid == -1)
872 {
873 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
875 goto cleanup;
876 }
877
878 filter_wait(pid);
879
881
882 fflush(fp_cert);
883 rewind(fp_cert);
884 fflush(fp_err);
885 rewind(fp_err);
886 empty = (fgetc(fp_cert) == EOF);
887 if (empty)
888 {
889 mutt_file_copy_stream(fp_err, stdout);
890 goto cleanup;
891 }
892
893 mutt_file_fclose(&fp_cert);
894
895 rc = buf_strdup(certfile);
896
897cleanup:
898 mutt_file_fclose(&fp_err);
899 if (fp_out)
900 {
901 mutt_file_fclose(&fp_out);
903 }
904 if (fp_cert)
905 {
906 mutt_file_fclose(&fp_cert);
907 mutt_file_unlink(buf_string(certfile));
908 }
909 buf_pool_release(&pk7out);
910 buf_pool_release(&certfile);
911 return rc;
912}
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:571
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition file.c:156
#define buf_mktemp(buf)
Definition tmp.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_extract_signer_certificate()

static char * smime_extract_signer_certificate ( const char * infile)
static

Extract the signer's certificate.

Parameters
infileFile to read
Return values
ptrName of temporary file containing certificate

Definition at line 919 of file smime.c.

920{
921 char *cert = NULL;
922 struct Buffer *certfile = NULL;
923 pid_t pid;
924 int empty;
925
926 FILE *fp_err = mutt_file_mkstemp();
927 if (!fp_err)
928 {
929 mutt_perror(_("Can't create temporary file"));
930 return NULL;
931 }
932
933 certfile = buf_pool_get();
934 buf_mktemp(certfile);
935 FILE *fp_out = mutt_file_fopen(buf_string(certfile), "w+");
936 if (!fp_out)
937 {
938 mutt_file_fclose(&fp_err);
939 mutt_perror("%s", buf_string(certfile));
940 goto cleanup;
941 }
942
943 /* Extract signer's certificate
944 */
945 const struct Expando *c_smime_get_signer_cert_command =
946 cs_subset_expando(NeoMutt->sub, "smime_get_signer_cert_command");
947 pid = smime_invoke(NULL, NULL, NULL, -1, -1, fileno(fp_err), infile, NULL, NULL, NULL,
948 NULL, buf_string(certfile), NULL, c_smime_get_signer_cert_command);
949 if (pid == -1)
950 {
951 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
952 goto cleanup;
953 }
954
955 filter_wait(pid);
956
957 fflush(fp_out);
958 rewind(fp_out);
959 fflush(fp_err);
960 rewind(fp_err);
961 empty = (fgetc(fp_out) == EOF);
962 if (empty)
963 {
964 mutt_endwin();
965 mutt_file_copy_stream(fp_err, stdout);
967 goto cleanup;
968 }
969
970 mutt_file_fclose(&fp_out);
971 cert = buf_strdup(certfile);
972
973cleanup:
974 mutt_file_fclose(&fp_err);
975 if (fp_out)
976 {
977 mutt_file_fclose(&fp_out);
978 mutt_file_unlink(buf_string(certfile));
979 }
980 buf_pool_release(&certfile);
981 return cert;
982}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_invoke_encrypt()

static pid_t smime_invoke_encrypt ( FILE ** fp_smime_in,
FILE ** fp_smime_out,
FILE ** fp_smime_err,
int fp_smime_infd,
int fp_smime_outfd,
int fp_smime_errfd,
const char * fname,
const char * uids )
static

Use SMIME to encrypt a file.

Parameters
[out]fp_smime_instdin for the command, or NULL (OPTIONAL)
[out]fp_smime_outstdout for the command, or NULL (OPTIONAL)
[out]fp_smime_errstderr for the command, or NULL (OPTIONAL)
[in]fp_smime_infdstdin for the command, or -1 (OPTIONAL)
[in]fp_smime_outfdstdout for the command, or -1 (OPTIONAL)
[in]fp_smime_errfdstderr for the command, or -1 (OPTIONAL)
[in]fnameFilename to pass to the command
[in]uidsList of IDs/fingerprints, space separated
Return values
numPID of the created process
-1Error creating pipes or forking
Note
fp_smime_in has priority over fp_smime_infd. Likewise fp_smime_out and fp_smime_err.

Definition at line 1147 of file smime.c.

1151{
1152 const char *const c_smime_encrypt_with = cs_subset_string(NeoMutt->sub, "smime_encrypt_with");
1153 const struct Expando *c_smime_encrypt_command = cs_subset_expando(NeoMutt->sub, "smime_encrypt_command");
1154 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1155 fp_smime_outfd, fp_smime_errfd, fname, NULL, c_smime_encrypt_with,
1156 NULL, NULL, uids, NULL, c_smime_encrypt_command);
1157}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_invoke_sign()

static pid_t smime_invoke_sign ( FILE ** fp_smime_in,
FILE ** fp_smime_out,
FILE ** fp_smime_err,
int fp_smime_infd,
int fp_smime_outfd,
int fp_smime_errfd,
const char * fname )
static

Use SMIME to sign a file.

Parameters
[out]fp_smime_instdin for the command, or NULL (OPTIONAL)
[out]fp_smime_outstdout for the command, or NULL (OPTIONAL)
[out]fp_smime_errstderr for the command, or NULL (OPTIONAL)
[in]fp_smime_infdstdin for the command, or -1 (OPTIONAL)
[in]fp_smime_outfdstdout for the command, or -1 (OPTIONAL)
[in]fp_smime_errfdstderr for the command, or -1 (OPTIONAL)
[in]fnameFilename to pass to the command
Return values
numPID of the created process
-1Error creating pipes or forking
Note
fp_smime_in has priority over fp_smime_infd. Likewise fp_smime_out and fp_smime_err.

Definition at line 1174 of file smime.c.

1177{
1178 const char *const c_smime_sign_digest_alg = cs_subset_string(NeoMutt->sub, "smime_sign_digest_alg");
1179 const struct Expando *c_smime_sign_command = cs_subset_expando(NeoMutt->sub, "smime_sign_command");
1180 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd, fp_smime_outfd,
1181 fp_smime_errfd, fname, NULL, NULL, c_smime_sign_digest_alg,
1183 buf_string(&SmimeIntermediateToUse), c_smime_sign_command);
1184}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ openssl_md_to_smime_micalg()

static char * openssl_md_to_smime_micalg ( const char * md)
static

Change the algorithm names.

Parameters
mdOpenSSL message digest name
Return values
ptrSMIME Message Integrity Check algorithm

The openssl -md doesn't want hyphens: md5, sha1, sha224, sha256, sha384, sha512 However, the micalg does: md5, sha-1, sha-224, sha-256, sha-384, sha-512

Note
The caller should free the returned string

Definition at line 1333 of file smime.c.

1334{
1335 if (!md)
1336 return NULL;
1337
1338 char *micalg = NULL;
1339 if (mutt_istr_startswith(md, "sha"))
1340 {
1341 mutt_str_asprintf(&micalg, "sha-%s", md + 3);
1342 }
1343 else
1344 {
1345 micalg = mutt_str_dup(md);
1346 }
1347
1348 return micalg;
1349}
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition string.c:805
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_invoke_verify()

static pid_t smime_invoke_verify ( FILE ** fp_smime_in,
FILE ** fp_smime_out,
FILE ** fp_smime_err,
int fp_smime_infd,
int fp_smime_outfd,
int fp_smime_errfd,
const char * fname,
const char * sig_fname,
int opaque )
static

Use SMIME to verify a file.

Parameters
[out]fp_smime_instdin for the command, or NULL (OPTIONAL)
[out]fp_smime_outstdout for the command, or NULL (OPTIONAL)
[out]fp_smime_errstderr for the command, or NULL (OPTIONAL)
[in]fp_smime_infdstdin for the command, or -1 (OPTIONAL)
[in]fp_smime_outfdstdout for the command, or -1 (OPTIONAL)
[in]fp_smime_errfdstderr for the command, or -1 (OPTIONAL)
[in]fnameFilename to pass to the command
[in]sig_fnameSignature filename to pass to the command
[in]opaqueIf true, use $smime_verify_opaque_command else $smime_verify_command
Return values
numPID of the created process
-1Error creating pipes or forking
Note
fp_smime_in has priority over fp_smime_infd. Likewise fp_smime_out and fp_smime_err.

Definition at line 1524 of file smime.c.

1528{
1529 const struct Expando *c_smime_verify_opaque_command =
1530 cs_subset_expando(NeoMutt->sub, "smime_verify_opaque_command");
1531 const struct Expando *c_smime_verify_command = cs_subset_expando(NeoMutt->sub, "smime_verify_command");
1532 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd, fp_smime_outfd,
1533 fp_smime_errfd, fname, sig_fname, NULL, NULL, NULL, NULL, NULL,
1534 (opaque ? c_smime_verify_opaque_command : c_smime_verify_command));
1535}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_invoke_decrypt()

static pid_t smime_invoke_decrypt ( FILE ** fp_smime_in,
FILE ** fp_smime_out,
FILE ** fp_smime_err,
int fp_smime_infd,
int fp_smime_outfd,
int fp_smime_errfd,
const char * fname )
static

Use SMIME to decrypt a file.

Parameters
[out]fp_smime_instdin for the command, or NULL (OPTIONAL)
[out]fp_smime_outstdout for the command, or NULL (OPTIONAL)
[out]fp_smime_errstderr for the command, or NULL (OPTIONAL)
[in]fp_smime_infdstdin for the command, or -1 (OPTIONAL)
[in]fp_smime_outfdstdout for the command, or -1 (OPTIONAL)
[in]fp_smime_errfdstderr for the command, or -1 (OPTIONAL)
[in]fnameFilename to pass to the command
Return values
numPID of the created process
-1Error creating pipes or forking
Note
fp_smime_in has priority over fp_smime_infd. Likewise fp_smime_out and fp_smime_err.

Definition at line 1552 of file smime.c.

1555{
1556 const struct Expando *c_smime_decrypt_command = cs_subset_expando(NeoMutt->sub, "smime_decrypt_command");
1557 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1558 fp_smime_outfd, fp_smime_errfd, fname, NULL, NULL, NULL,
1560 NULL, c_smime_decrypt_command);
1561}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_handle_entity()

static struct Body * smime_handle_entity ( struct Body * b,
struct State * state,
FILE * fp_out_file )
static

Handle type application/pkcs7-mime.

Parameters
bBody to handle
stateState to use
fp_out_fileFile for the result
Return values
ptrBody for parsed MIME part

This can either be a signed or an encrypted message.

Definition at line 1680 of file smime.c.

1681{
1682 struct Buffer *tmpfname = buf_pool_get();
1683 FILE *fp_smime_out = NULL, *fp_smime_in = NULL, *fp_smime_err = NULL;
1684 FILE *fp_tmp = NULL, *fp_out = NULL;
1685 struct Body *p = NULL;
1686 pid_t pid = -1;
1688
1689 if (!(type & APPLICATION_SMIME))
1690 return NULL;
1691
1692 /* Because of the mutt_body_handler() we avoid the buffer pool. */
1693 fp_smime_out = mutt_file_mkstemp();
1694 if (!fp_smime_out)
1695 {
1696 mutt_perror(_("Can't create temporary file"));
1697 goto cleanup;
1698 }
1699
1700 fp_smime_err = mutt_file_mkstemp();
1701 if (!fp_smime_err)
1702 {
1703 mutt_perror(_("Can't create temporary file"));
1704 goto cleanup;
1705 }
1706
1707 buf_mktemp(tmpfname);
1708 fp_tmp = mutt_file_fopen(buf_string(tmpfname), "w+");
1709 if (!fp_tmp)
1710 {
1711 mutt_perror("%s", buf_string(tmpfname));
1712 goto cleanup;
1713 }
1714
1715 if (!mutt_file_seek(state->fp_in, b->offset, SEEK_SET))
1716 {
1717 goto cleanup;
1718 }
1719
1720 mutt_file_copy_bytes(state->fp_in, fp_tmp, b->length);
1721
1722 fflush(fp_tmp);
1723 mutt_file_fclose(&fp_tmp);
1724
1725 if ((type & SEC_ENCRYPT) &&
1726 ((pid = smime_invoke_decrypt(&fp_smime_in, NULL, NULL, -1, fileno(fp_smime_out),
1727 fileno(fp_smime_err), buf_string(tmpfname))) == -1))
1728 {
1729 mutt_file_unlink(buf_string(tmpfname));
1730 if (state->flags & STATE_DISPLAY)
1731 {
1732 state_attach_puts(state, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1733 }
1734 goto cleanup;
1735 }
1736 else if ((type & SEC_SIGNOPAQUE) &&
1737 ((pid = smime_invoke_verify(&fp_smime_in, NULL, NULL, -1,
1738 fileno(fp_smime_out), fileno(fp_smime_err), NULL,
1739 buf_string(tmpfname), SEC_SIGNOPAQUE)) == -1))
1740 {
1741 mutt_file_unlink(buf_string(tmpfname));
1742 if (state->flags & STATE_DISPLAY)
1743 {
1744 state_attach_puts(state, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1745 }
1746 goto cleanup;
1747 }
1748
1749 if (type & SEC_ENCRYPT)
1750 {
1753 fputs(SmimePass, fp_smime_in);
1754 fputc('\n', fp_smime_in);
1755 }
1756
1757 mutt_file_fclose(&fp_smime_in);
1758
1759 filter_wait(pid);
1760 mutt_file_unlink(buf_string(tmpfname));
1761
1762 if (state->flags & STATE_DISPLAY)
1763 {
1764 fflush(fp_smime_err);
1765 rewind(fp_smime_err);
1766
1767 const int c = fgetc(fp_smime_err);
1768 if (c != EOF)
1769 {
1770 ungetc(c, fp_smime_err);
1771
1772 crypt_current_time(state, "OpenSSL");
1773 mutt_file_copy_stream(fp_smime_err, state->fp_out);
1774 state_attach_puts(state, _("[-- End of OpenSSL output --]\n\n"));
1775 }
1776
1777 if (type & SEC_ENCRYPT)
1778 {
1779 state_attach_puts(state, _("[-- The following data is S/MIME encrypted --]\n"));
1780 }
1781 else
1782 {
1783 state_attach_puts(state, _("[-- The following data is S/MIME signed --]\n"));
1784 }
1785 }
1786
1787 fflush(fp_smime_out);
1788 rewind(fp_smime_out);
1789
1790 if (type & SEC_ENCRYPT)
1791 {
1792 /* void the passphrase, even if that wasn't the problem */
1793 if (fgetc(fp_smime_out) == EOF)
1794 {
1795 mutt_error(_("Decryption failed"));
1797 }
1798 rewind(fp_smime_out);
1799 }
1800
1801 if (fp_out_file)
1802 {
1803 fp_out = fp_out_file;
1804 }
1805 else
1806 {
1807 fp_out = mutt_file_mkstemp();
1808 if (!fp_out)
1809 {
1810 mutt_perror(_("Can't create temporary file"));
1811 goto cleanup;
1812 }
1813 }
1814 char buf[8192] = { 0 };
1815 while (fgets(buf, sizeof(buf) - 1, fp_smime_out))
1816 {
1817 const size_t len = mutt_str_len(buf);
1818 if ((len > 1) && (buf[len - 2] == '\r'))
1819 {
1820 buf[len - 2] = '\n';
1821 buf[len - 1] = '\0';
1822 }
1823 fputs(buf, fp_out);
1824 }
1825 fflush(fp_out);
1826 rewind(fp_out);
1827
1828 const long size = mutt_file_get_size_fp(fp_out);
1829 if (size == 0)
1830 {
1831 goto cleanup;
1832 }
1833 p = mutt_read_mime_header(fp_out, 0);
1834 if (p)
1835 {
1836 p->length = size - p->offset;
1837
1838 mutt_parse_part(fp_out, p);
1839
1840 if (state->flags & STATE_DISPLAY)
1842
1843 /* Store any protected headers in the parent so they can be
1844 * accessed for index updates after the handler recursion is done.
1845 * This is done before the handler to prevent a nested encrypted
1846 * handler from freeing the headers. */
1848 b->mime_headers = p->mime_headers;
1849 p->mime_headers = NULL;
1850
1851 if (state->fp_out)
1852 {
1853 rewind(fp_out);
1854 FILE *fp_tmp_buffer = state->fp_in;
1855 state->fp_in = fp_out;
1856 mutt_body_handler(p, state);
1857 state->fp_in = fp_tmp_buffer;
1858 }
1859
1860 /* Embedded multipart signed protected headers override the
1861 * encrypted headers. We need to do this after the handler so
1862 * they can be printed in the pager. */
1863 if (!(type & SMIME_SIGN) && mutt_is_multipart_signed(p) && p->parts &&
1864 p->parts->mime_headers)
1865 {
1868 p->parts->mime_headers = NULL;
1869 }
1870 }
1871 mutt_file_fclose(&fp_smime_out);
1872
1873 if (!fp_out_file)
1874 {
1875 mutt_file_fclose(&fp_out);
1876 mutt_file_unlink(buf_string(tmpfname));
1877 }
1878 fp_out = NULL;
1879
1880 if (state->flags & STATE_DISPLAY)
1881 {
1882 if (type & SEC_ENCRYPT)
1883 state_attach_puts(state, _("[-- End of S/MIME encrypted data --]\n"));
1884 else
1885 state_attach_puts(state, _("[-- End of S/MIME signed data --]\n"));
1886 }
1887
1888 if (type & SEC_SIGNOPAQUE)
1889 {
1890 char *line = NULL;
1891 size_t linelen;
1892
1893 rewind(fp_smime_err);
1894
1895 line = mutt_file_read_line(line, &linelen, fp_smime_err, NULL, MUTT_RL_NO_FLAGS);
1896 if (linelen && mutt_istr_equal(line, "verification successful"))
1897 b->goodsig = true;
1898 FREE(&line);
1899 }
1900 else if (p)
1901 {
1902 b->goodsig = p->goodsig;
1903 b->badsig = p->badsig;
1904 }
1905
1906cleanup:
1907 mutt_file_fclose(&fp_smime_out);
1908 mutt_file_fclose(&fp_smime_err);
1909 mutt_file_fclose(&fp_tmp);
1910 mutt_file_fclose(&fp_out);
1911 buf_pool_release(&tmpfname);
1912 return p;
1913}
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition crypt.c:408
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition crypt.c:609
void crypt_current_time(struct State *state, const char *app_name)
Print the current time.
Definition crypt.c:64
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition parse.c:1833
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition parse.c:1370
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition envelope.c:125
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition file.c:682
int mutt_file_copy_bytes(FILE *fp_in, FILE *fp_out, size_t size)
Copy some content from one file to another.
Definition file.c:192
long mutt_file_get_size_fp(FILE *fp)
Get the size of a file.
Definition file.c:1427
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition file.c:652
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition file.h:40
bool smime_class_valid_passphrase(void)
Ensure we have a valid passphrase - Implements CryptModuleSpecs::valid_passphrase() -.
Definition smime.c:155
int mutt_protected_headers_handler(struct Body *b_email, struct State *state)
Handler for protected headers - Implements handler_t -.
Definition crypt.c:1117
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition handler.c:1659
void state_attach_puts(struct State *state, const char *t)
Write a string to the state.
Definition state.c:104
#define STATE_DISPLAY
Output is displayed to the user.
Definition state.h:33
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition lib.h:84
#define SEC_SIGNOPAQUE
Email has an opaque signature (encrypted)
Definition lib.h:91
#define SMIME_SIGN
Email is S/MIME signed.
Definition lib.h:111
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition lib.h:99
#define SEC_ENCRYPT
Email is encrypted.
Definition lib.h:86
static char SmimePass[256]
Cached Smime Passphrase.
Definition smime.c:65
static pid_t smime_invoke_verify(FILE **fp_smime_in, FILE **fp_smime_out, FILE **fp_smime_err, int fp_smime_infd, int fp_smime_outfd, int fp_smime_errfd, const char *fname, const char *sig_fname, int opaque)
Use SMIME to verify a file.
Definition smime.c:1524
static pid_t smime_invoke_decrypt(FILE **fp_smime_in, FILE **fp_smime_out, FILE **fp_smime_err, int fp_smime_infd, int fp_smime_outfd, int fp_smime_errfd, const char *fname)
Use SMIME to decrypt a file.
Definition smime.c:1552
The body of an email.
Definition body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition body.h:73
LOFF_T offset
offset where the actual data begins
Definition body.h:52
bool badsig
Bad cryptographic signature (needed to check encrypted s/mime-signatures)
Definition body.h:43
struct Envelope * mime_headers
Memory hole protected headers.
Definition body.h:76
LOFF_T length
length (in bytes) of attachment
Definition body.h:53
bool goodsig
Good cryptographic signature.
Definition body.h:45
unsigned int type
content-type primary type, ContentType
Definition body.h:40
StateFlags flags
Flags, e.g. STATE_DISPLAY.
Definition state.h:52
FILE * fp_out
File to write to.
Definition state.h:50
FILE * fp_in
File to read from.
Definition state.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ SmimePass

char SmimePass[256]
static

Cached Smime Passphrase.

Definition at line 65 of file smime.c.

◆ SmimeExpTime

time_t SmimeExpTime = 0
static

Unix time when SmimePass expires.

Definition at line 67 of file smime.c.

◆ SmimeKeyToUse

struct Buffer SmimeKeyToUse = { 0 }
static

Smime key to use.

Definition at line 70 of file smime.c.

70{ 0 };

◆ SmimeCertToUse

struct Buffer SmimeCertToUse = { 0 }
static

Smime certificate to use.

Definition at line 72 of file smime.c.

72{ 0 };

◆ SmimeIntermediateToUse

struct Buffer SmimeIntermediateToUse = { 0 }
static

Smime intermediate certificate to use.

Definition at line 74 of file smime.c.

74{ 0 };