NeoMutt  2022-04-29-249-gaae397
Teaching an old dog new tricks
DOXYGEN
smime.c File Reference

SMIME helper routines. More...

#include "config.h"
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <time.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 "enter/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "copy.h"
#include "crypt.h"
#include "cryptglue.h"
#include "format_flags.h"
#include "handler.h"
#include "mutt_logging.h"
#include "muttlib.h"
#include "smime.h"
+ Include dependency graph for smime.c:

Go to the source code of this file.

Data Structures

struct  SmimeCommandContext
 Data for a SIME command. More...
 

Functions

void smime_init (void)
 Initialise smime globals. More...
 
void smime_cleanup (void)
 Clean up smime globals. More...
 
static void smime_key_free (struct SmimeKey **keylist)
 Free a list of SMIME keys. More...
 
static struct SmimeKeysmime_copy_key (struct SmimeKey *key)
 Copy an SMIME key. More...
 
void smime_class_void_passphrase (void)
 Implements CryptModuleSpecs::void_passphrase() -. More...
 
bool smime_class_valid_passphrase (void)
 Implements CryptModuleSpecs::valid_passphrase() -. More...
 
static const char * smime_command_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format an SMIME command - Implements format_t -. More...
 
static void smime_command (char *buf, size_t buflen, struct SmimeCommandContext *cctx, const char *fmt)
 Format an SMIME command string. More...
 
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 char *format)
 Run an SMIME command. More...
 
static struct SmimeKeysmime_parse_key (char *buf)
 Parse an SMIME key block. More...
 
static struct SmimeKeysmime_get_candidates (const char *search, bool only_public_key)
 Find keys matching a string. More...
 
static struct SmimeKeysmime_get_key_by_hash (const char *hash, bool only_public_key)
 Find a key by its hash. More...
 
static struct SmimeKeysmime_get_key_by_addr (char *mailbox, KeyFlags abilities, bool only_public_key, bool oppenc_mode)
 Find an SIME key by address. More...
 
static struct SmimeKeysmime_get_key_by_str (const char *str, KeyFlags abilities, bool only_public_key)
 Find an SMIME key by string. More...
 
static struct SmimeKeysmime_ask_for_key (char *prompt, KeyFlags abilities, bool only_public_key)
 Ask the user to select a key. More...
 
static void getkeys (char *mailbox)
 Get the keys for a mailbox. More...
 
void smime_class_getkeys (struct Envelope *env)
 Implements CryptModuleSpecs::smime_getkeys() -. More...
 
char * smime_class_find_keys (const struct AddressList *al, bool oppenc_mode)
 Implements CryptModuleSpecs::find_keys() -. More...
 
static int smime_handle_cert_email (char *certificate, char *mailbox, bool copy, char ***buffer, int *num)
 Process an email containing certificates. More...
 
static char * smime_extract_certificate (const char *infile)
 Extract an SMIME certificate from a file. More...
 
static char * smime_extract_signer_certificate (const char *infile)
 Extract the signer's certificate. More...
 
void smime_class_invoke_import (const char *infile, const char *mailbox)
 Implements CryptModuleSpecs::smime_invoke_import() -. More...
 
int smime_class_verify_sender (struct Email *e, struct Message *msg)
 Implements CryptModuleSpecs::smime_verify_sender() -. More...
 
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. More...
 
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. More...
 
struct Bodysmime_class_build_smime_entity (struct Body *a, char *certlist)
 Implements CryptModuleSpecs::smime_build_smime_entity() -. More...
 
static char * openssl_md_to_smime_micalg (const char *md)
 Change the algorithm names. More...
 
struct Bodysmime_class_sign_message (struct Body *a, const struct AddressList *from)
 Implements CryptModuleSpecs::sign_message() -. More...
 
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. More...
 
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. More...
 
int smime_class_verify_one (struct Body *sigbdy, struct State *s, const char *tempfile)
 Implements CryptModuleSpecs::verify_one() -. More...
 
static struct Bodysmime_handle_entity (struct Body *m, struct State *s, FILE *fp_out_file)
 Handle type application/pkcs7-mime. More...
 
int smime_class_decrypt_mime (FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
 Implements CryptModuleSpecs::decrypt_mime() -. More...
 
int smime_class_application_handler (struct Body *m, struct State *s)
 Implements CryptModuleSpecs::application_handler() -. More...
 
SecurityFlags smime_class_send_menu (struct Email *e)
 Implements CryptModuleSpecs::send_menu() -. More...
 

Variables

char SmimePass [256]
 
time_t SmimeExpTime = 0
 
static struct Buffer SmimeKeyToUse = { 0 }
 
static struct Buffer SmimeCertToUse = { 0 }
 
static struct Buffer SmimeIntermediateToUse = { 0 }
 

Detailed Description

SMIME helper routines.

Authors
  • Oliver Ehli
  • Mike Schiraldi
  • g10 Code GmbH
  • Pietro Cerutti

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 88 of file smime.c.

89{
93}
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:275
static struct Buffer SmimeIntermediateToUse
Definition: smime.c:83
static struct Buffer SmimeKeyToUse
Definition: smime.c:81
static struct Buffer SmimeCertToUse
Definition: smime.c:82
+ 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 98 of file smime.c.

99{
103}
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:309
+ 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 109 of file smime.c.

110{
111 if (!keylist)
112 return;
113
114 struct SmimeKey *key = NULL;
115
116 while (*keylist)
117 {
118 key = *keylist;
119 *keylist = (*keylist)->next;
120
121 FREE(&key->email);
122 FREE(&key->hash);
123 FREE(&key->label);
124 FREE(&key->issuer);
125 FREE(&key);
126 }
127}
#define FREE(x)
Definition: memory.h:43
An SIME key.
Definition: smime.h:44
char * hash
Definition: smime.h:46
struct SmimeKey * next
Definition: smime.h:51
char * issuer
Definition: smime.h:48
char * email
Definition: smime.h:45
char * label
Definition: smime.h:47
+ 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 134 of file smime.c.

135{
136 if (!key)
137 return NULL;
138
139 struct SmimeKey *copy = NULL;
140
141 copy = mutt_mem_calloc(1, sizeof(struct SmimeKey));
142 copy->email = mutt_str_dup(key->email);
143 copy->hash = mutt_str_dup(key->hash);
144 copy->label = mutt_str_dup(key->label);
145 copy->issuer = mutt_str_dup(key->issuer);
146 copy->trust = key->trust;
147 copy->flags = key->flags;
148
149 return copy;
150}
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
KeyFlags flags
Definition: smime.h:50
char trust
i=Invalid r=revoked e=expired u=unverified v=verified t=trusted
Definition: smime.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_command()

static void smime_command ( char *  buf,
size_t  buflen,
struct SmimeCommandContext cctx,
const char *  fmt 
)
static

Format an SMIME command string.

Parameters
bufBuffer for the result
buflenLength of buffer
cctxData to pass to the formatter
fmtprintf-like formatting string
See also
smime_command_format_str()

Definition at line 374 of file smime.c.

376{
377 mutt_expando_format(buf, buflen, 0, buflen, NONULL(fmt), smime_command_format_str,
378 (intptr_t) cctx, MUTT_FORMAT_NO_FLAGS);
379 mutt_debug(LL_DEBUG2, "%s\n", buf);
380}
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
static const char * smime_command_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format an SMIME command - Implements format_t -.
Definition: smime.c:218
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string -.
Definition: muttlib.c:777
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
#define NONULL(x)
Definition: string2.h:37
+ 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 char *  format 
)
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]formatprintf-like 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 404 of file smime.c.

409{
410 struct SmimeCommandContext cctx = { 0 };
411 char cmd[STR_COMMAND] = { 0 };
412
413 if (!format || (*format == '\0'))
414 return (pid_t) -1;
415
416 cctx.fname = fname;
417 cctx.sig_fname = sig_fname;
418 cctx.key = key;
419 cctx.cryptalg = cryptalg;
420 cctx.digestalg = digestalg;
423
424 smime_command(cmd, sizeof(cmd), &cctx, format);
425
426 return filter_create_fd(cmd, fp_smime_in, fp_smime_out, fp_smime_err,
427 fp_smime_infd, fp_smime_outfd, fp_smime_errfd);
428}
pid_t filter_create_fd(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, int fdin, int fdout, int fderr)
Run a command on a pipe (optionally connect stdin/stdout)
Definition: filter.c:61
static void smime_command(char *buf, size_t buflen, struct SmimeCommandContext *cctx, const char *fmt)
Format an SMIME command string.
Definition: smime.c:374
#define STR_COMMAND
Enough space for a long command line.
Definition: string2.h:35
Data for a SIME command.
Definition: smime.c:68
const char * sig_fname
s
Definition: smime.c:73
const char * intermediates
i
Definition: smime.c:75
const char * digestalg
d
Definition: smime.c:71
const char * cryptalg
a
Definition: smime.c:70
const char * key
k
Definition: smime.c:69
const char * fname
f
Definition: smime.c:72
const char * certificates
c
Definition: smime.c:74
+ 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 436 of file smime.c.

437{
438 char *pend = NULL, *p = NULL;
439 int field = 0;
440
441 struct SmimeKey *key = mutt_mem_calloc(1, sizeof(struct SmimeKey));
442
443 for (p = buf; p; p = pend)
444 {
445 /* Some users manually maintain their .index file, and use a tab
446 * as a delimiter, which the old parsing code (using fscanf)
447 * happened to allow. smime_keys uses a space, so search for both. */
448 if ((pend = strchr(p, ' ')) || (pend = strchr(p, '\t')) || (pend = strchr(p, '\n')))
449 *pend++ = 0;
450
451 /* For backward compatibility, don't count consecutive delimiters
452 * as an empty field. */
453 if (*p == '\0')
454 continue;
455
456 field++;
457
458 switch (field)
459 {
460 case 1: /* mailbox */
461 key->email = mutt_str_dup(p);
462 break;
463 case 2: /* hash */
464 key->hash = mutt_str_dup(p);
465 break;
466 case 3: /* label */
467 key->label = mutt_str_dup(p);
468 break;
469 case 4: /* issuer */
470 key->issuer = mutt_str_dup(p);
471 break;
472 case 5: /* trust */
473 key->trust = *p;
474 break;
475 case 6: /* purpose */
476 while (*p)
477 {
478 switch (*p++)
479 {
480 case 'e':
482 break;
483
484 case 's':
485 key->flags |= KEYFLAG_CANSIGN;
486 break;
487 }
488 }
489 break;
490 }
491 }
492
493 /* Old index files could be missing issuer, trust, and purpose,
494 * but anything less than that is an error. */
495 if (field < 3)
496 {
497 smime_key_free(&key);
498 return NULL;
499 }
500
501 if (field < 4)
502 key->issuer = mutt_str_dup("?");
503
504 if (field < 5)
505 key->trust = 't';
506
507 if (field < 6)
509
510 return key;
511}
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition: lib.h:128
#define KEYFLAG_CANSIGN
Key is suitable for signing.
Definition: lib.h:127
static void smime_key_free(struct SmimeKey **keylist)
Free a list of SMIME keys.
Definition: smime.c:109
+ 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 519 of file smime.c.

520{
521 char buf[1024] = { 0 };
522 struct SmimeKey *key = NULL, *results = NULL;
523 struct SmimeKey **results_end = &results;
524
525 struct Buffer *index_file = mutt_buffer_pool_get();
526 const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
527 const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
528 mutt_buffer_printf(index_file, "%s/.index",
529 only_public_key ? NONULL(c_smime_certificates) : NONULL(c_smime_keys));
530
531 FILE *fp = mutt_file_fopen(mutt_buffer_string(index_file), "r");
532 if (!fp)
533 {
534 mutt_perror(mutt_buffer_string(index_file));
535 mutt_buffer_pool_release(&index_file);
536 return NULL;
537 }
538 mutt_buffer_pool_release(&index_file);
539
540 while (fgets(buf, sizeof(buf), fp))
541 {
542 if (((*search == '\0')) || mutt_istr_find(buf, search))
543 {
544 key = smime_parse_key(buf);
545 if (key)
546 {
547 *results_end = key;
548 results_end = &key->next;
549 }
550 }
551 }
552
553 mutt_file_fclose(&fp);
554
555 return results;
556}
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
#define mutt_perror(...)
Definition: logging.h:88
static int search(struct Menu *menu, int op)
Search a menu.
Definition: functions.c:57
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:592
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
static struct SmimeKey * smime_parse_key(char *buf)
Parse an SMIME key block.
Definition: smime.c:436
String manipulation buffer.
Definition: buffer.h:34
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ 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 567 of file smime.c.

568{
569 struct SmimeKey *match = NULL;
570 struct SmimeKey *results = smime_get_candidates(hash, only_public_key);
571 for (struct SmimeKey *result = results; result; result = result->next)
572 {
573 if (mutt_istr_equal(hash, result->hash))
574 {
575 match = smime_copy_key(result);
576 break;
577 }
578 }
579
580 smime_key_free(&results);
581
582 return match;
583}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:819
static struct SmimeKey * smime_copy_key(struct SmimeKey *key)
Copy an SMIME key.
Definition: smime.c:134
static struct SmimeKey * smime_get_candidates(const char *search, bool only_public_key)
Find keys matching a string.
Definition: smime.c:519
+ 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 ( 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 593 of file smime.c.

595{
596 if (!mailbox)
597 return NULL;
598
599 struct SmimeKey *results = NULL, *result = NULL;
600 struct SmimeKey *matches = NULL;
601 struct SmimeKey **matches_end = &matches;
602 struct SmimeKey *match = NULL;
603 struct SmimeKey *trusted_match = NULL;
604 struct SmimeKey *valid_match = NULL;
605 struct SmimeKey *return_key = NULL;
606 bool multi_trusted_matches = false;
607
608 results = smime_get_candidates(mailbox, only_public_key);
609 for (result = results; result; result = result->next)
610 {
611 if (abilities && !(result->flags & abilities))
612 {
613 continue;
614 }
615
616 if (mutt_istr_equal(mailbox, result->email))
617 {
618 match = smime_copy_key(result);
619 *matches_end = match;
620 matches_end = &match->next;
621
622 if (match->trust == 't')
623 {
624 if (trusted_match && !mutt_istr_equal(match->hash, trusted_match->hash))
625 {
626 multi_trusted_matches = true;
627 }
628 trusted_match = match;
629 }
630 else if ((match->trust == 'u') || (match->trust == 'v'))
631 {
632 valid_match = match;
633 }
634 }
635 }
636
637 smime_key_free(&results);
638
639 if (matches)
640 {
641 if (oppenc_mode)
642 {
643 const bool c_crypt_opportunistic_encrypt_strong_keys =
644 cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt_strong_keys");
645 if (trusted_match)
646 return_key = smime_copy_key(trusted_match);
647 else if (valid_match && !c_crypt_opportunistic_encrypt_strong_keys)
648 return_key = smime_copy_key(valid_match);
649 else
650 return_key = NULL;
651 }
652 else if (trusted_match && !multi_trusted_matches)
653 {
654 return_key = smime_copy_key(trusted_match);
655 }
656 else
657 {
658 return_key = smime_copy_key(dlg_select_smime_key(matches, mailbox));
659 }
660
661 smime_key_free(&matches);
662 }
663
664 return return_key;
665}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
struct SmimeKey * dlg_select_smime_key(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 674 of file smime.c.

675{
676 if (!str)
677 return NULL;
678
679 struct SmimeKey *results = NULL, *result = NULL;
680 struct SmimeKey *matches = NULL;
681 struct SmimeKey **matches_end = &matches;
682 struct SmimeKey *match = NULL;
683 struct SmimeKey *return_key = NULL;
684
685 results = smime_get_candidates(str, only_public_key);
686 for (result = results; result; result = result->next)
687 {
688 if (abilities && !(result->flags & abilities))
689 {
690 continue;
691 }
692
693 if (mutt_istr_equal(str, result->hash) ||
694 mutt_istr_find(result->email, str) || mutt_istr_find(result->label, str))
695 {
696 match = smime_copy_key(result);
697 *matches_end = match;
698 matches_end = &match->next;
699 }
700 }
701
702 smime_key_free(&results);
703
704 if (matches)
705 {
706 return_key = smime_copy_key(dlg_select_smime_key(matches, str));
707 smime_key_free(&matches);
708 }
709
710 return return_key;
711}
+ 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 ( 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 720 of file smime.c.

721{
722 struct SmimeKey *key = NULL;
723 struct Buffer *resp = mutt_buffer_pool_get();
724
725 if (!prompt)
726 prompt = _("Enter keyID: ");
727
729
730 while (true)
731 {
732 mutt_buffer_reset(resp);
733 if (mutt_buffer_get_field(prompt, resp, MUTT_COMP_NO_FLAGS, false, NULL, NULL, NULL) != 0)
734 {
735 goto done;
736 }
737
738 key = smime_get_key_by_str(mutt_buffer_string(resp), abilities, only_public_key);
739 if (key)
740 goto done;
741
742 mutt_error(_("No matching keys found for \"%s\""), mutt_buffer_string(resp));
743 }
744
745done:
747 return key;
748}
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: window.c:180
#define mutt_error(...)
Definition: logging.h:87
#define _(a)
Definition: message.h:28
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:52
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
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:674
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getkeys()

static void getkeys ( 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 757 of file smime.c.

758{
759 const char *k = NULL;
760
761 struct SmimeKey *key = smime_get_key_by_addr(mailbox, KEYFLAG_CANENCRYPT, false, false);
762
763 if (!key)
764 {
765 char buf[256] = { 0 };
766 snprintf(buf, sizeof(buf), _("Enter keyID for %s: "), mailbox);
767 key = smime_ask_for_key(buf, KEYFLAG_CANENCRYPT, false);
768 }
769
770 const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
771 size_t smime_keys_len = mutt_str_len(c_smime_keys);
772
773 const char *const c_smime_default_key = cs_subset_string(NeoMutt->sub, "smime_default_key");
774 k = key ? key->hash : NONULL(c_smime_default_key);
775
776 /* if the key is different from last time */
777 if ((mutt_buffer_len(&SmimeKeyToUse) <= smime_keys_len) ||
778 !mutt_istr_equal(k, SmimeKeyToUse.data + smime_keys_len + 1))
779 {
781 mutt_buffer_printf(&SmimeKeyToUse, "%s/%s", NONULL(c_smime_keys), k);
782 const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
783 mutt_buffer_printf(&SmimeCertToUse, "%s/%s", NONULL(c_smime_certificates), k);
784 }
785
786 smime_key_free(&key);
787}
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:371
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
void smime_class_void_passphrase(void)
Implements CryptModuleSpecs::void_passphrase() -.
Definition: smime.c:159
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
static struct SmimeKey * smime_ask_for_key(char *prompt, KeyFlags abilities, bool only_public_key)
Ask the user to select a key.
Definition: smime.c:720
static struct SmimeKey * smime_get_key_by_addr(char *mailbox, KeyFlags abilities, bool only_public_key, bool oppenc_mode)
Find an SIME key by address.
Definition: smime.c:593
char * data
Pointer to data.
Definition: buffer.h:35
+ 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 ( char *  certificate,
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 880 of file smime.c.

882{
883 char email[256] = { 0 };
884 int rc = -1, count = 0;
885 pid_t pid;
886
887 FILE *fp_err = mutt_file_mkstemp();
888 if (!fp_err)
889 {
890 mutt_perror(_("Can't create temporary file"));
891 return 1;
892 }
893
894 FILE *fp_out = mutt_file_mkstemp();
895 if (!fp_out)
896 {
897 mutt_file_fclose(&fp_err);
898 mutt_perror(_("Can't create temporary file"));
899 return 1;
900 }
901
902 const char *const c_smime_get_cert_email_command = cs_subset_string(NeoMutt->sub, "smime_get_cert_email_command");
903 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), certificate,
904 NULL, NULL, NULL, NULL, NULL, NULL, c_smime_get_cert_email_command);
905 if (pid == -1)
906 {
907 mutt_message(_("Error: unable to create OpenSSL subprocess"));
908 mutt_file_fclose(&fp_err);
909 mutt_file_fclose(&fp_out);
910 return 1;
911 }
912
913 filter_wait(pid);
914
915 fflush(fp_out);
916 rewind(fp_out);
917 fflush(fp_err);
918 rewind(fp_err);
919
920 while ((fgets(email, sizeof(email), fp_out)))
921 {
922 size_t len = mutt_str_len(email);
923 if (len && (email[len - 1] == '\n'))
924 email[len - 1] = '\0';
925 if (mutt_istr_startswith(email, mailbox))
926 rc = 1;
927
928 rc = (rc < 0) ? 0 : rc;
929 count++;
930 }
931
932 if (rc == -1)
933 {
934 mutt_endwin();
935 mutt_file_copy_stream(fp_err, stdout);
936 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
937 rc = 1;
938 }
939 else if (rc == 0)
940 rc = 1;
941 else
942 rc = 0;
943
944 if (copy && buffer && num)
945 {
946 (*num) = count;
947 *buffer = mutt_mem_calloc(count, sizeof(char *));
948 count = 0;
949
950 rewind(fp_out);
951 while ((fgets(email, sizeof(email), fp_out)))
952 {
953 size_t len = mutt_str_len(email);
954 if (len && (email[len - 1] == '\n'))
955 email[len - 1] = '\0';
956 (*buffer)[count] = mutt_mem_calloc(mutt_str_len(email) + 1, sizeof(char));
957 strncpy((*buffer)[count], email, mutt_str_len(email));
958 count++;
959 }
960 }
961 else if (copy)
962 rc = 2;
963
964 mutt_file_fclose(&fp_out);
965 mutt_file_fclose(&fp_err);
966
967 return rc;
968}
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:387
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:354
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:260
#define mutt_file_mkstemp()
Definition: file.h:112
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
#define mutt_message(...)
Definition: logging.h:86
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:239
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 char *format)
Run an SMIME command.
Definition: smime.c:404
+ 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 975 of file smime.c.

976{
977 FILE *fp_err = NULL;
978 FILE *fp_out = NULL;
979 FILE *fp_cert = NULL;
980 char *retval = NULL;
981 pid_t pid;
982 int empty;
983
984 struct Buffer *pk7out = mutt_buffer_pool_get();
985 struct Buffer *certfile = mutt_buffer_pool_get();
986
987 fp_err = mutt_file_mkstemp();
988 if (!fp_err)
989 {
990 mutt_perror(_("Can't create temporary file"));
991 goto cleanup;
992 }
993
994 mutt_buffer_mktemp(pk7out);
995 fp_out = mutt_file_fopen(mutt_buffer_string(pk7out), "w+");
996 if (!fp_out)
997 {
999 goto cleanup;
1000 }
1001
1002 /* Step 1: Convert the signature to a PKCS#7 structure, as we can't
1003 * extract the full set of certificates directly. */
1004 const char *const c_smime_pk7out_command = cs_subset_string(NeoMutt->sub, "smime_pk7out_command");
1005 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), infile,
1006 NULL, NULL, NULL, NULL, NULL, NULL, c_smime_pk7out_command);
1007 if (pid == -1)
1008 {
1009 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
1010 goto cleanup;
1011 }
1012
1013 filter_wait(pid);
1014
1015 fflush(fp_out);
1016 rewind(fp_out);
1017 fflush(fp_err);
1018 rewind(fp_err);
1019 empty = (fgetc(fp_out) == EOF);
1020 if (empty)
1021 {
1023 mutt_file_copy_stream(fp_err, stdout);
1024 goto cleanup;
1025 }
1026 mutt_file_fclose(&fp_out);
1027
1028 mutt_buffer_mktemp(certfile);
1029 fp_cert = mutt_file_fopen(mutt_buffer_string(certfile), "w+");
1030 if (!fp_cert)
1031 {
1034 goto cleanup;
1035 }
1036
1037 // Step 2: Extract the certificates from a PKCS#7 structure.
1038 const char *const c_smime_get_cert_command = cs_subset_string(NeoMutt->sub, "smime_get_cert_command");
1039 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_cert), fileno(fp_err),
1040 mutt_buffer_string(pk7out), NULL, NULL, NULL, NULL, NULL,
1041 NULL, c_smime_get_cert_command);
1042 if (pid == -1)
1043 {
1044 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
1046 goto cleanup;
1047 }
1048
1049 filter_wait(pid);
1050
1052
1053 fflush(fp_cert);
1054 rewind(fp_cert);
1055 fflush(fp_err);
1056 rewind(fp_err);
1057 empty = (fgetc(fp_cert) == EOF);
1058 if (empty)
1059 {
1060 mutt_file_copy_stream(fp_err, stdout);
1061 goto cleanup;
1062 }
1063
1064 mutt_file_fclose(&fp_cert);
1065
1066 retval = mutt_buffer_strdup(certfile);
1067
1068cleanup:
1069 mutt_file_fclose(&fp_err);
1070 if (fp_out)
1071 {
1072 mutt_file_fclose(&fp_out);
1074 }
1075 if (fp_cert)
1076 {
1077 mutt_file_fclose(&fp_cert);
1079 }
1080 mutt_buffer_pool_release(&pk7out);
1081 mutt_buffer_pool_release(&certfile);
1082 return retval;
1083}
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:447
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:194
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
+ 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 1090 of file smime.c.

1091{
1092 char *cert = NULL;
1093 struct Buffer *certfile = NULL;
1094 pid_t pid;
1095 int empty;
1096
1097 FILE *fp_err = mutt_file_mkstemp();
1098 if (!fp_err)
1099 {
1100 mutt_perror(_("Can't create temporary file"));
1101 return NULL;
1102 }
1103
1104 certfile = mutt_buffer_pool_get();
1105 mutt_buffer_mktemp(certfile);
1106 FILE *fp_out = mutt_file_fopen(mutt_buffer_string(certfile), "w+");
1107 if (!fp_out)
1108 {
1109 mutt_file_fclose(&fp_err);
1111 goto cleanup;
1112 }
1113
1114 /* Extract signer's certificate
1115 */
1116 const char *const c_smime_get_signer_cert_command = cs_subset_string(NeoMutt->sub, "smime_get_signer_cert_command");
1117 pid = smime_invoke(NULL, NULL, NULL, -1, -1, fileno(fp_err), infile, NULL,
1118 NULL, NULL, NULL, mutt_buffer_string(certfile), NULL,
1119 c_smime_get_signer_cert_command);
1120 if (pid == -1)
1121 {
1122 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
1123 goto cleanup;
1124 }
1125
1126 filter_wait(pid);
1127
1128 fflush(fp_out);
1129 rewind(fp_out);
1130 fflush(fp_err);
1131 rewind(fp_err);
1132 empty = (fgetc(fp_out) == EOF);
1133 if (empty)
1134 {
1135 mutt_endwin();
1136 mutt_file_copy_stream(fp_err, stdout);
1138 goto cleanup;
1139 }
1140
1141 mutt_file_fclose(&fp_out);
1142 cert = mutt_buffer_strdup(certfile);
1143
1144cleanup:
1145 mutt_file_fclose(&fp_err);
1146 if (fp_out)
1147 {
1148 mutt_file_fclose(&fp_out);
1150 }
1151 mutt_buffer_pool_release(&certfile);
1152 return cert;
1153}
+ 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 1310 of file smime.c.

1314{
1315 const char *const c_smime_encrypt_with = cs_subset_string(NeoMutt->sub, "smime_encrypt_with");
1316 const char *const c_smime_encrypt_command = cs_subset_string(NeoMutt->sub, "smime_encrypt_command");
1317 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1318 fp_smime_outfd, fp_smime_errfd, fname, NULL, c_smime_encrypt_with,
1319 NULL, NULL, uids, NULL, c_smime_encrypt_command);
1320}
+ 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 1337 of file smime.c.

1340{
1341 const char *const c_smime_sign_digest_alg = cs_subset_string(NeoMutt->sub, "smime_sign_digest_alg");
1342 const char *const c_smime_sign_command = cs_subset_string(NeoMutt->sub, "smime_sign_command");
1343 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1344 fp_smime_outfd, fp_smime_errfd, fname, NULL, NULL,
1345 c_smime_sign_digest_alg, mutt_buffer_string(&SmimeKeyToUse),
1347 mutt_buffer_string(&SmimeIntermediateToUse), c_smime_sign_command);
1348}
+ 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 1496 of file smime.c.

1497{
1498 if (!md)
1499 return 0;
1500
1501 char *micalg = NULL;
1502 if (mutt_istr_startswith(md, "sha"))
1503 {
1504 const size_t l = strlen(md) + 2;
1505 micalg = mutt_mem_malloc(l);
1506 snprintf(micalg, l, "sha-%s", md + 3);
1507 }
1508 else
1509 {
1510 micalg = mutt_str_dup(md);
1511 }
1512
1513 return micalg;
1514}
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
+ 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 1687 of file smime.c.

1691{
1692 const char *const c_smime_verify_opaque_command = cs_subset_string(NeoMutt->sub, "smime_verify_opaque_command");
1693 const char *const c_smime_verify_command = cs_subset_string(NeoMutt->sub, "smime_verify_command");
1694 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd, fp_smime_outfd,
1695 fp_smime_errfd, fname, sig_fname, NULL, NULL, NULL, NULL, NULL,
1696 (opaque ? c_smime_verify_opaque_command : c_smime_verify_command));
1697}
+ 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 1714 of file smime.c.

1717{
1718 const char *const c_smime_decrypt_command = cs_subset_string(NeoMutt->sub, "smime_decrypt_command");
1719 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1720 fp_smime_outfd, fp_smime_errfd, fname, NULL, NULL, NULL,
1722 mutt_buffer_string(&SmimeCertToUse), NULL, c_smime_decrypt_command);
1723}
+ 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 m,
struct State s,
FILE *  fp_out_file 
)
static

Handle type application/pkcs7-mime.

Parameters
mBody to handle
sState 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 1840 of file smime.c.

1841{
1842 struct Buffer tmpfname = mutt_buffer_make(0);
1843 FILE *fp_smime_out = NULL, *fp_smime_in = NULL, *fp_smime_err = NULL;
1844 FILE *fp_tmp = NULL, *fp_out = NULL;
1845 struct Body *p = NULL;
1846 pid_t pid = -1;
1848
1849 if (!(type & APPLICATION_SMIME))
1850 return NULL;
1851
1852 /* Because of the mutt_body_handler() we avoid the buffer pool. */
1853 fp_smime_out = mutt_file_mkstemp();
1854 if (!fp_smime_out)
1855 {
1856 mutt_perror(_("Can't create temporary file"));
1857 goto cleanup;
1858 }
1859
1860 fp_smime_err = mutt_file_mkstemp();
1861 if (!fp_smime_err)
1862 {
1863 mutt_perror(_("Can't create temporary file"));
1864 goto cleanup;
1865 }
1866
1867 mutt_buffer_mktemp(&tmpfname);
1868 fp_tmp = mutt_file_fopen(mutt_buffer_string(&tmpfname), "w+");
1869 if (!fp_tmp)
1870 {
1871 mutt_perror(mutt_buffer_string(&tmpfname));
1872 goto cleanup;
1873 }
1874
1875 if (!mutt_file_seek(s->fp_in, m->offset, SEEK_SET))
1876 {
1877 goto cleanup;
1878 }
1879
1880 mutt_file_copy_bytes(s->fp_in, fp_tmp, m->length);
1881
1882 fflush(fp_tmp);
1883 mutt_file_fclose(&fp_tmp);
1884
1885 if ((type & SEC_ENCRYPT) &&
1886 ((pid = smime_invoke_decrypt(&fp_smime_in, NULL, NULL, -1,
1887 fileno(fp_smime_out), fileno(fp_smime_err),
1888 mutt_buffer_string(&tmpfname))) == -1))
1889 {
1891 if (s->flags & MUTT_DISPLAY)
1892 {
1893 state_attach_puts(s, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1894 }
1895 goto cleanup;
1896 }
1897 else if ((type & SEC_SIGNOPAQUE) &&
1898 ((pid = smime_invoke_verify(&fp_smime_in, NULL, NULL, -1,
1899 fileno(fp_smime_out), fileno(fp_smime_err), NULL,
1900 mutt_buffer_string(&tmpfname), SEC_SIGNOPAQUE)) == -1))
1901 {
1903 if (s->flags & MUTT_DISPLAY)
1904 {
1905 state_attach_puts(s, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1906 }
1907 goto cleanup;
1908 }
1909
1910 if (type & SEC_ENCRYPT)
1911 {
1914 fputs(SmimePass, fp_smime_in);
1915 fputc('\n', fp_smime_in);
1916 }
1917
1918 mutt_file_fclose(&fp_smime_in);
1919
1920 filter_wait(pid);
1922
1923 if (s->flags & MUTT_DISPLAY)
1924 {
1925 fflush(fp_smime_err);
1926 rewind(fp_smime_err);
1927
1928 const int c = fgetc(fp_smime_err);
1929 if (c != EOF)
1930 {
1931 ungetc(c, fp_smime_err);
1932
1933 crypt_current_time(s, "OpenSSL");
1934 mutt_file_copy_stream(fp_smime_err, s->fp_out);
1935 state_attach_puts(s, _("[-- End of OpenSSL output --]\n\n"));
1936 }
1937
1938 if (type & SEC_ENCRYPT)
1939 {
1940 state_attach_puts(s, _("[-- The following data is S/MIME encrypted --]\n"));
1941 }
1942 else
1943 state_attach_puts(s, _("[-- The following data is S/MIME signed --]\n"));
1944 }
1945
1946 fflush(fp_smime_out);
1947 rewind(fp_smime_out);
1948
1949 if (type & SEC_ENCRYPT)
1950 {
1951 /* void the passphrase, even if that wasn't the problem */
1952 if (fgetc(fp_smime_out) == EOF)
1953 {
1954 mutt_error(_("Decryption failed"));
1956 }
1957 rewind(fp_smime_out);
1958 }
1959
1960 if (fp_out_file)
1961 fp_out = fp_out_file;
1962 else
1963 {
1964 fp_out = mutt_file_mkstemp();
1965 if (!fp_out)
1966 {
1967 mutt_perror(_("Can't create temporary file"));
1968 goto cleanup;
1969 }
1970 }
1971 char buf[8192] = { 0 };
1972 while (fgets(buf, sizeof(buf) - 1, fp_smime_out))
1973 {
1974 const size_t len = mutt_str_len(buf);
1975 if ((len > 1) && (buf[len - 2] == '\r'))
1976 {
1977 buf[len - 2] = '\n';
1978 buf[len - 1] = '\0';
1979 }
1980 fputs(buf, fp_out);
1981 }
1982 fflush(fp_out);
1983 rewind(fp_out);
1984
1985 const long size = mutt_file_get_size_fp(fp_out);
1986 if (size == 0)
1987 {
1988 goto cleanup;
1989 }
1990 p = mutt_read_mime_header(fp_out, 0);
1991 if (p)
1992 {
1993 p->length = size - p->offset;
1994
1995 mutt_parse_part(fp_out, p);
1996
1997 if (s->flags & MUTT_DISPLAY)
1999
2000 /* Store any protected headers in the parent so they can be
2001 * accessed for index updates after the handler recursion is done.
2002 * This is done before the handler to prevent a nested encrypted
2003 * handler from freeing the headers. */
2005 m->mime_headers = p->mime_headers;
2006 p->mime_headers = NULL;
2007
2008 if (s->fp_out)
2009 {
2010 rewind(fp_out);
2011 FILE *fp_tmp_buffer = s->fp_in;
2012 s->fp_in = fp_out;
2013 mutt_body_handler(p, s);
2014 s->fp_in = fp_tmp_buffer;
2015 }
2016
2017 /* Embedded multipart signed protected headers override the
2018 * encrypted headers. We need to do this after the handler so
2019 * they can be printed in the pager. */
2020 if (!(type & SMIME_SIGN) && mutt_is_multipart_signed(p) && p->parts &&
2021 p->parts->mime_headers)
2022 {
2025 p->parts->mime_headers = NULL;
2026 }
2027 }
2028 mutt_file_fclose(&fp_smime_out);
2029
2030 if (!fp_out_file)
2031 {
2032 mutt_file_fclose(&fp_out);
2034 }
2035 fp_out = NULL;
2036
2037 if (s->flags & MUTT_DISPLAY)
2038 {
2039 if (type & SEC_ENCRYPT)
2040 state_attach_puts(s, _("\n[-- End of S/MIME encrypted data. --]\n"));
2041 else
2042 state_attach_puts(s, _("\n[-- End of S/MIME signed data. --]\n"));
2043 }
2044
2045 if (type & SEC_SIGNOPAQUE)
2046 {
2047 char *line = NULL;
2048 size_t linelen;
2049
2050 rewind(fp_smime_err);
2051
2052 line = mutt_file_read_line(line, &linelen, fp_smime_err, NULL, MUTT_RL_NO_FLAGS);
2053 if (linelen && mutt_istr_equal(line, "verification successful"))
2054 m->goodsig = true;
2055 FREE(&line);
2056 }
2057 else if (p)
2058 {
2059 m->goodsig = p->goodsig;
2060 m->badsig = p->badsig;
2061 }
2062
2063cleanup:
2064 mutt_file_fclose(&fp_smime_out);
2065 mutt_file_fclose(&fp_smime_err);
2066 mutt_file_fclose(&fp_tmp);
2067 mutt_file_fclose(&fp_out);
2068 mutt_buffer_dealloc(&tmpfname);
2069 return p;
2070}
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:67
void crypt_current_time(struct State *s, const char *app_name)
Print the current time.
Definition: crypt.c:70
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:402
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:601
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:97
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:720
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:230
long mutt_file_get_size_fp(FILE *fp)
Get the size of a file.
Definition: file.c:1569
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:690
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:38
bool smime_class_valid_passphrase(void)
Implements CryptModuleSpecs::valid_passphrase() -.
Definition: smime.c:168
int mutt_protected_headers_handler(struct Body *b, struct State *s)
Process a protected header - Implements handler_t -.
Definition: crypt.c:1095
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1597
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:100
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:76
#define SEC_SIGNOPAQUE
Email has an opaque signature (encrypted)
Definition: lib.h:83
#define SMIME_SIGN
Definition: lib.h:103
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:91
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:78
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1736
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1317
char SmimePass[256]
Definition: smime.c:78
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:1687
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:1714
The body of an email.
Definition: body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:72
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:75
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. MUTT_DISPLAY.
Definition: state.h:50
FILE * fp_out
File to write to.
Definition: state.h:48
FILE * fp_in
File to read from.
Definition: state.h:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ SmimePass

char SmimePass[256]

Definition at line 78 of file smime.c.

◆ SmimeExpTime

time_t SmimeExpTime = 0

Definition at line 79 of file smime.c.

◆ SmimeKeyToUse

struct Buffer SmimeKeyToUse = { 0 }
static

Definition at line 81 of file smime.c.

◆ SmimeCertToUse

struct Buffer SmimeCertToUse = { 0 }
static

Definition at line 82 of file smime.c.

◆ SmimeIntermediateToUse

struct Buffer SmimeIntermediateToUse = { 0 }
static

Definition at line 83 of file smime.c.