NeoMutt
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 <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 "editor/lib.h"
#include "history/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "copy.h"
#include "crypt.h"
#include "cryptglue.h"
#include "format_flags.h"
#include "globals.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.
 
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)
 Implements CryptModuleSpecs::void_passphrase() -.
 
bool smime_class_valid_passphrase (void)
 Implements CryptModuleSpecs::valid_passphrase() -.
 
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 -.
 
static void smime_command (char *buf, size_t buflen, struct SmimeCommandContext *cctx, const char *fmt)
 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 char *format)
 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 (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)
 Implements CryptModuleSpecs::smime_getkeys() -.
 
char * smime_class_find_keys (const struct AddressList *al, bool oppenc_mode)
 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)
 Implements CryptModuleSpecs::smime_invoke_import() -.
 
int smime_class_verify_sender (struct Email *e, struct Message *msg)
 Implements CryptModuleSpecs::smime_verify_sender() -.
 
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 *a, char *certlist)
 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 *a, const struct AddressList *from)
 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 *sigbdy, struct State *state, const char *tempfile)
 Implements CryptModuleSpecs::verify_one() -.
 
static struct Bodysmime_handle_entity (struct Body *m, 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 **cur)
 Implements CryptModuleSpecs::decrypt_mime() -.
 
int smime_class_application_handler (struct Body *m, struct State *state)
 Implements CryptModuleSpecs::application_handler() -.
 
SecurityFlags smime_class_send_menu (struct Email *e)
 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
  • 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 95 of file smime.c.

96{
100}
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:349
static struct Buffer SmimeIntermediateToUse
Smime intermediate certificate to use.
Definition: smime.c:90
static struct Buffer SmimeKeyToUse
Smime key to use.
Definition: smime.c:86
static struct Buffer SmimeCertToUse
Smime certificate to use.
Definition: smime.c:88
+ 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 105 of file smime.c.

106{
110}
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:389
+ 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 116 of file smime.c.

117{
118 if (!keylist)
119 return;
120
121 struct SmimeKey *key = NULL;
122
123 while (*keylist)
124 {
125 key = *keylist;
126 *keylist = (*keylist)->next;
127
128 FREE(&key->email);
129 FREE(&key->hash);
130 FREE(&key->label);
131 FREE(&key->issuer);
132 FREE(&key);
133 }
134}
#define FREE(x)
Definition: memory.h:45
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 141 of file smime.c.

142{
143 if (!key)
144 return NULL;
145
146 struct SmimeKey *copy = NULL;
147
148 copy = mutt_mem_calloc(1, sizeof(struct SmimeKey));
149 copy->email = mutt_str_dup(key->email);
150 copy->hash = mutt_str_dup(key->hash);
151 copy->label = mutt_str_dup(key->label);
152 copy->issuer = mutt_str_dup(key->issuer);
153 copy->trust = key->trust;
154 copy->flags = key->flags;
155
156 return copy;
157}
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:251
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 396 of file smime.c.

398{
399 mutt_expando_format(buf, buflen, 0, buflen, NONULL(fmt), smime_command_format_str,
400 (intptr_t) cctx, MUTT_FORMAT_NO_FLAGS);
401 mutt_debug(LL_DEBUG2, "%s\n", buf);
402}
#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:224
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:745
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
#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 426 of file smime.c.

431{
432 struct SmimeCommandContext cctx = { 0 };
433 char cmd[STR_COMMAND] = { 0 };
434
435 if (!format || (*format == '\0'))
436 return (pid_t) -1;
437
438 cctx.fname = fname;
439 cctx.sig_fname = sig_fname;
440 cctx.key = key;
441 cctx.cryptalg = cryptalg;
442 cctx.digestalg = digestalg;
445
446 smime_command(cmd, sizeof(cmd), &cctx, format);
447
448 return filter_create_fd(cmd, fp_smime_in, fp_smime_out, fp_smime_err,
449 fp_smime_infd, fp_smime_outfd, fp_smime_errfd, EnvList);
450}
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:61
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:85
static void smime_command(char *buf, size_t buflen, struct SmimeCommandContext *cctx, const char *fmt)
Format an SMIME command string.
Definition: smime.c:396
#define STR_COMMAND
Enough space for a long command line.
Definition: string2.h:35
Data for a SIME command.
Definition: smime.c:70
const char * sig_fname
s
Definition: smime.c:75
const char * intermediates
i
Definition: smime.c:77
const char * digestalg
d
Definition: smime.c:73
const char * cryptalg
a
Definition: smime.c:72
const char * key
k
Definition: smime.c:71
const char * fname
f
Definition: smime.c:74
const char * certificates
c
Definition: smime.c:76
+ 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 458 of file smime.c.

459{
460 char *pend = NULL, *p = NULL;
461 int field = 0;
462
463 struct SmimeKey *key = mutt_mem_calloc(1, sizeof(struct SmimeKey));
464
465 for (p = buf; p; p = pend)
466 {
467 /* Some users manually maintain their .index file, and use a tab
468 * as a delimiter, which the old parsing code (using fscanf)
469 * happened to allow. smime_keys uses a space, so search for both. */
470 if ((pend = strchr(p, ' ')) || (pend = strchr(p, '\t')) || (pend = strchr(p, '\n')))
471 *pend++ = 0;
472
473 /* For backward compatibility, don't count consecutive delimiters
474 * as an empty field. */
475 if (*p == '\0')
476 continue;
477
478 field++;
479
480 switch (field)
481 {
482 case 1: /* mailbox */
483 key->email = mutt_str_dup(p);
484 break;
485 case 2: /* hash */
486 key->hash = mutt_str_dup(p);
487 break;
488 case 3: /* label */
489 key->label = mutt_str_dup(p);
490 break;
491 case 4: /* issuer */
492 key->issuer = mutt_str_dup(p);
493 break;
494 case 5: /* trust */
495 key->trust = *p;
496 break;
497 case 6: /* purpose */
498 while (*p)
499 {
500 switch (*p++)
501 {
502 case 'e':
504 break;
505
506 case 's':
507 key->flags |= KEYFLAG_CANSIGN;
508 break;
509 }
510 }
511 break;
512 }
513 }
514
515 /* Old index files could be missing issuer, trust, and purpose,
516 * but anything less than that is an error. */
517 if (field < 3)
518 {
519 smime_key_free(&key);
520 return NULL;
521 }
522
523 if (field < 4)
524 key->issuer = mutt_str_dup("?");
525
526 if (field < 5)
527 key->trust = 't';
528
529 if (field < 6)
531
532 return key;
533}
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition: lib.h:129
#define KEYFLAG_CANSIGN
Key is suitable for signing.
Definition: lib.h:128
static void smime_key_free(struct SmimeKey **keylist)
Free a list of SMIME keys.
Definition: smime.c:116
+ 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 541 of file smime.c.

542{
543 char buf[1024] = { 0 };
544 struct SmimeKey *key = NULL, *results = NULL;
545 struct SmimeKey **results_end = &results;
546
547 struct Buffer *index_file = buf_pool_get();
548 const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
549 const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
550 buf_printf(index_file, "%s/.index",
551 only_public_key ? NONULL(c_smime_certificates) : NONULL(c_smime_keys));
552
553 FILE *fp = mutt_file_fopen(buf_string(index_file), "r");
554 if (!fp)
555 {
556 mutt_perror("%s", buf_string(index_file));
557 buf_pool_release(&index_file);
558 return NULL;
559 }
560 buf_pool_release(&index_file);
561
562 while (fgets(buf, sizeof(buf), fp))
563 {
564 if (((*search == '\0')) || mutt_istr_find(buf, search))
565 {
566 key = smime_parse_key(buf);
567 if (key)
568 {
569 *results_end = key;
570 results_end = &key->next;
571 }
572 }
573 }
574
575 mutt_file_fclose(&fp);
576
577 return results;
578}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:173
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:169
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:636
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
#define mutt_perror(...)
Definition: logging2.h:93
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:593
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
static struct SmimeKey * smime_parse_key(char *buf)
Parse an SMIME key block.
Definition: smime.c:458
String manipulation buffer.
Definition: buffer.h:34
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
+ 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 589 of file smime.c.

590{
591 struct SmimeKey *match = NULL;
592 struct SmimeKey *results = smime_get_candidates(hash, only_public_key);
593 for (struct SmimeKey *result = results; result; result = result->next)
594 {
595 if (mutt_istr_equal(hash, result->hash))
596 {
597 match = smime_copy_key(result);
598 break;
599 }
600 }
601
602 smime_key_free(&results);
603
604 return match;
605}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:810
static struct SmimeKey * smime_copy_key(struct SmimeKey *key)
Copy an SMIME key.
Definition: smime.c:141
static struct SmimeKey * smime_get_candidates(const char *search, bool only_public_key)
Find keys matching a string.
Definition: smime.c:541
+ 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 615 of file smime.c.

617{
618 if (!mailbox)
619 return NULL;
620
621 struct SmimeKey *results = NULL, *result = NULL;
622 struct SmimeKey *matches = NULL;
623 struct SmimeKey **matches_end = &matches;
624 struct SmimeKey *match = NULL;
625 struct SmimeKey *trusted_match = NULL;
626 struct SmimeKey *valid_match = NULL;
627 struct SmimeKey *return_key = NULL;
628 bool multi_trusted_matches = false;
629
630 results = smime_get_candidates(mailbox, only_public_key);
631 for (result = results; result; result = result->next)
632 {
633 if (abilities && !(result->flags & abilities))
634 {
635 continue;
636 }
637
638 if (mutt_istr_equal(mailbox, result->email))
639 {
640 match = smime_copy_key(result);
641 *matches_end = match;
642 matches_end = &match->next;
643
644 if (match->trust == 't')
645 {
646 if (trusted_match && !mutt_istr_equal(match->hash, trusted_match->hash))
647 {
648 multi_trusted_matches = true;
649 }
650 trusted_match = match;
651 }
652 else if ((match->trust == 'u') || (match->trust == 'v'))
653 {
654 valid_match = match;
655 }
656 }
657 }
658
659 smime_key_free(&results);
660
661 if (matches)
662 {
663 if (oppenc_mode)
664 {
665 const bool c_crypt_opportunistic_encrypt_strong_keys =
666 cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt_strong_keys");
667 if (trusted_match)
668 return_key = smime_copy_key(trusted_match);
669 else if (valid_match && !c_crypt_opportunistic_encrypt_strong_keys)
670 return_key = smime_copy_key(valid_match);
671 else
672 return_key = NULL;
673 }
674 else if (trusted_match && !multi_trusted_matches)
675 {
676 return_key = smime_copy_key(trusted_match);
677 }
678 else
679 {
680 return_key = smime_copy_key(dlg_smime(matches, mailbox));
681 }
682
683 smime_key_free(&matches);
684 }
685
686 return return_key;
687}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
struct SmimeKey * dlg_smime(struct SmimeKey *keys, const char *query)
Get the user to select a key -.
Definition: dlg_smime.c:195
+ 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 696 of file smime.c.

697{
698 if (!str)
699 return NULL;
700
701 struct SmimeKey *results = NULL, *result = NULL;
702 struct SmimeKey *matches = NULL;
703 struct SmimeKey **matches_end = &matches;
704 struct SmimeKey *match = NULL;
705 struct SmimeKey *return_key = NULL;
706
707 results = smime_get_candidates(str, only_public_key);
708 for (result = results; result; result = result->next)
709 {
710 if (abilities && !(result->flags & abilities))
711 {
712 continue;
713 }
714
715 if (mutt_istr_equal(str, result->hash) ||
716 mutt_istr_find(result->email, str) || mutt_istr_find(result->label, str))
717 {
718 match = smime_copy_key(result);
719 *matches_end = match;
720 matches_end = &match->next;
721 }
722 }
723
724 smime_key_free(&results);
725
726 if (matches)
727 {
728 return_key = smime_copy_key(dlg_smime(matches, str));
729 smime_key_free(&matches);
730 }
731
732 return return_key;
733}
+ 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 742 of file smime.c.

743{
744 struct SmimeKey *key = NULL;
745 struct Buffer *resp = buf_pool_get();
746
747 if (!prompt)
748 prompt = _("Enter keyID: ");
749
751
752 while (true)
753 {
754 buf_reset(resp);
755 if (mw_get_field(prompt, resp, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0)
756 {
757 goto done;
758 }
759
760 key = smime_get_key_by_str(buf_string(resp), abilities, only_public_key);
761 if (key)
762 goto done;
763
764 mutt_error(_("No matching keys found for \"%s\""), buf_string(resp));
765 }
766
767done:
768 buf_pool_release(&resp);
769 return key;
770}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:88
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:275
#define mutt_error(...)
Definition: logging2.h:92
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:54
#define _(a)
Definition: message.h:28
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:55
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
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:696
+ 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 779 of file smime.c.

780{
781 const char *k = NULL;
782
783 struct SmimeKey *key = smime_get_key_by_addr(mailbox, KEYFLAG_CANENCRYPT, false, false);
784
785 if (!key)
786 {
787 char buf[256] = { 0 };
788 snprintf(buf, sizeof(buf), _("Enter keyID for %s: "), mailbox);
789 key = smime_ask_for_key(buf, KEYFLAG_CANENCRYPT, false);
790 }
791
792 const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
793 size_t smime_keys_len = mutt_str_len(c_smime_keys);
794
795 const char *const c_smime_default_key = cs_subset_string(NeoMutt->sub, "smime_default_key");
796 k = key ? key->hash : NONULL(c_smime_default_key);
797
798 /* if the key is different from last time */
799 if ((buf_len(&SmimeKeyToUse) <= smime_keys_len) ||
800 !mutt_istr_equal(k, SmimeKeyToUse.data + smime_keys_len + 1))
801 {
803 buf_printf(&SmimeKeyToUse, "%s/%s", NONULL(c_smime_keys), k);
804 const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
805 buf_printf(&SmimeCertToUse, "%s/%s", NONULL(c_smime_certificates), k);
806 }
807
808 smime_key_free(&key);
809}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:466
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
void smime_class_void_passphrase(void)
Implements CryptModuleSpecs::void_passphrase() -.
Definition: smime.c:166
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:568
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:615
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:742
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 ( 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 901 of file smime.c.

903{
904 char email[256] = { 0 };
905 int rc = -1, count = 0;
906 pid_t pid;
907
908 FILE *fp_err = mutt_file_mkstemp();
909 if (!fp_err)
910 {
911 mutt_perror(_("Can't create temporary file"));
912 return 1;
913 }
914
915 FILE *fp_out = mutt_file_mkstemp();
916 if (!fp_out)
917 {
918 mutt_file_fclose(&fp_err);
919 mutt_perror(_("Can't create temporary file"));
920 return 1;
921 }
922
923 const char *const c_smime_get_cert_email_command = cs_subset_string(NeoMutt->sub, "smime_get_cert_email_command");
924 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), certificate,
925 NULL, NULL, NULL, NULL, NULL, NULL, c_smime_get_cert_email_command);
926 if (pid == -1)
927 {
928 mutt_message(_("Error: unable to create OpenSSL subprocess"));
929 mutt_file_fclose(&fp_err);
930 mutt_file_fclose(&fp_out);
931 return 1;
932 }
933
934 filter_wait(pid);
935
936 fflush(fp_out);
937 rewind(fp_out);
938 fflush(fp_err);
939 rewind(fp_err);
940
941 while ((fgets(email, sizeof(email), fp_out)))
942 {
943 size_t len = mutt_str_len(email);
944 if (len && (email[len - 1] == '\n'))
945 email[len - 1] = '\0';
946 if (mutt_istr_startswith(email, mailbox))
947 rc = 1;
948
949 rc = (rc < 0) ? 0 : rc;
950 count++;
951 }
952
953 if (rc == -1)
954 {
955 mutt_endwin();
956 mutt_file_copy_stream(fp_err, stdout);
957 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
958 rc = 1;
959 }
960 else if (rc == 0)
961 {
962 rc = 1;
963 }
964 else
965 {
966 rc = 0;
967 }
968
969 if (copy && buffer && num)
970 {
971 (*num) = count;
972 *buffer = mutt_mem_calloc(count, sizeof(char *));
973 count = 0;
974
975 rewind(fp_out);
976 while ((fgets(email, sizeof(email), fp_out)))
977 {
978 size_t len = mutt_str_len(email);
979 if (len && (email[len - 1] == '\n'))
980 email[len - 1] = '\0';
981 (*buffer)[count] = mutt_mem_calloc(mutt_str_len(email) + 1, sizeof(char));
982 strncpy((*buffer)[count], email, mutt_str_len(email));
983 count++;
984 }
985 }
986 else if (copy)
987 {
988 rc = 2;
989 }
990
991 mutt_file_fclose(&fp_out);
992 mutt_file_fclose(&fp_err);
993
994 return rc;
995}
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:188
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:154
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:262
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:218
#define mutt_message(...)
Definition: logging2.h:91
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:240
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:426
#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 1002 of file smime.c.

1003{
1004 FILE *fp_err = NULL;
1005 FILE *fp_out = NULL;
1006 FILE *fp_cert = NULL;
1007 char *rc = NULL;
1008 pid_t pid;
1009 int empty;
1010
1011 struct Buffer *pk7out = buf_pool_get();
1012 struct Buffer *certfile = buf_pool_get();
1013
1014 fp_err = mutt_file_mkstemp();
1015 if (!fp_err)
1016 {
1017 mutt_perror(_("Can't create temporary file"));
1018 goto cleanup;
1019 }
1020
1021 buf_mktemp(pk7out);
1022 fp_out = mutt_file_fopen(buf_string(pk7out), "w+");
1023 if (!fp_out)
1024 {
1025 mutt_perror("%s", buf_string(pk7out));
1026 goto cleanup;
1027 }
1028
1029 /* Step 1: Convert the signature to a PKCS#7 structure, as we can't
1030 * extract the full set of certificates directly. */
1031 const char *const c_smime_pk7out_command = cs_subset_string(NeoMutt->sub, "smime_pk7out_command");
1032 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), infile,
1033 NULL, NULL, NULL, NULL, NULL, NULL, c_smime_pk7out_command);
1034 if (pid == -1)
1035 {
1036 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
1037 goto cleanup;
1038 }
1039
1040 filter_wait(pid);
1041
1042 fflush(fp_out);
1043 rewind(fp_out);
1044 fflush(fp_err);
1045 rewind(fp_err);
1046 empty = (fgetc(fp_out) == EOF);
1047 if (empty)
1048 {
1049 mutt_perror("%s", buf_string(pk7out));
1050 mutt_file_copy_stream(fp_err, stdout);
1051 goto cleanup;
1052 }
1053 mutt_file_fclose(&fp_out);
1054
1055 buf_mktemp(certfile);
1056 fp_cert = mutt_file_fopen(buf_string(certfile), "w+");
1057 if (!fp_cert)
1058 {
1059 mutt_perror("%s", buf_string(certfile));
1061 goto cleanup;
1062 }
1063
1064 // Step 2: Extract the certificates from a PKCS#7 structure.
1065 const char *const c_smime_get_cert_command = cs_subset_string(NeoMutt->sub, "smime_get_cert_command");
1066 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_cert), fileno(fp_err),
1067 buf_string(pk7out), NULL, NULL, NULL, NULL, NULL, NULL,
1068 c_smime_get_cert_command);
1069 if (pid == -1)
1070 {
1071 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
1073 goto cleanup;
1074 }
1075
1076 filter_wait(pid);
1077
1079
1080 fflush(fp_cert);
1081 rewind(fp_cert);
1082 fflush(fp_err);
1083 rewind(fp_err);
1084 empty = (fgetc(fp_cert) == EOF);
1085 if (empty)
1086 {
1087 mutt_file_copy_stream(fp_err, stdout);
1088 goto cleanup;
1089 }
1090
1091 mutt_file_fclose(&fp_cert);
1092
1093 rc = buf_strdup(certfile);
1094
1095cleanup:
1096 mutt_file_fclose(&fp_err);
1097 if (fp_out)
1098 {
1099 mutt_file_fclose(&fp_out);
1101 }
1102 if (fp_cert)
1103 {
1104 mutt_file_fclose(&fp_cert);
1105 mutt_file_unlink(buf_string(certfile));
1106 }
1107 buf_pool_release(&pk7out);
1108 buf_pool_release(&certfile);
1109 return rc;
1110}
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:542
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:196
#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 1117 of file smime.c.

1118{
1119 char *cert = NULL;
1120 struct Buffer *certfile = NULL;
1121 pid_t pid;
1122 int empty;
1123
1124 FILE *fp_err = mutt_file_mkstemp();
1125 if (!fp_err)
1126 {
1127 mutt_perror(_("Can't create temporary file"));
1128 return NULL;
1129 }
1130
1131 certfile = buf_pool_get();
1132 buf_mktemp(certfile);
1133 FILE *fp_out = mutt_file_fopen(buf_string(certfile), "w+");
1134 if (!fp_out)
1135 {
1136 mutt_file_fclose(&fp_err);
1137 mutt_perror("%s", buf_string(certfile));
1138 goto cleanup;
1139 }
1140
1141 /* Extract signer's certificate
1142 */
1143 const char *const c_smime_get_signer_cert_command = cs_subset_string(NeoMutt->sub, "smime_get_signer_cert_command");
1144 pid = smime_invoke(NULL, NULL, NULL, -1, -1, fileno(fp_err), infile, NULL, NULL, NULL,
1145 NULL, buf_string(certfile), NULL, c_smime_get_signer_cert_command);
1146 if (pid == -1)
1147 {
1148 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
1149 goto cleanup;
1150 }
1151
1152 filter_wait(pid);
1153
1154 fflush(fp_out);
1155 rewind(fp_out);
1156 fflush(fp_err);
1157 rewind(fp_err);
1158 empty = (fgetc(fp_out) == EOF);
1159 if (empty)
1160 {
1161 mutt_endwin();
1162 mutt_file_copy_stream(fp_err, stdout);
1164 goto cleanup;
1165 }
1166
1167 mutt_file_fclose(&fp_out);
1168 cert = buf_strdup(certfile);
1169
1170cleanup:
1171 mutt_file_fclose(&fp_err);
1172 if (fp_out)
1173 {
1174 mutt_file_fclose(&fp_out);
1175 mutt_file_unlink(buf_string(certfile));
1176 }
1177 buf_pool_release(&certfile);
1178 return cert;
1179}
+ 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 1342 of file smime.c.

1346{
1347 const char *const c_smime_encrypt_with = cs_subset_string(NeoMutt->sub, "smime_encrypt_with");
1348 const char *const c_smime_encrypt_command = cs_subset_string(NeoMutt->sub, "smime_encrypt_command");
1349 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1350 fp_smime_outfd, fp_smime_errfd, fname, NULL, c_smime_encrypt_with,
1351 NULL, NULL, uids, NULL, c_smime_encrypt_command);
1352}
+ 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 1369 of file smime.c.

1372{
1373 const char *const c_smime_sign_digest_alg = cs_subset_string(NeoMutt->sub, "smime_sign_digest_alg");
1374 const char *const c_smime_sign_command = cs_subset_string(NeoMutt->sub, "smime_sign_command");
1375 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd, fp_smime_outfd,
1376 fp_smime_errfd, fname, NULL, NULL, c_smime_sign_digest_alg,
1378 buf_string(&SmimeIntermediateToUse), c_smime_sign_command);
1379}
+ 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 1526 of file smime.c.

1527{
1528 if (!md)
1529 return NULL;
1530
1531 char *micalg = NULL;
1532 if (mutt_istr_startswith(md, "sha"))
1533 {
1534 mutt_str_asprintf(&micalg, "sha-%s", md + 3);
1535 }
1536 else
1537 {
1538 micalg = mutt_str_dup(md);
1539 }
1540
1541 return micalg;
1542}
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:1022
+ 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 1714 of file smime.c.

1718{
1719 const char *const c_smime_verify_opaque_command = cs_subset_string(NeoMutt->sub, "smime_verify_opaque_command");
1720 const char *const c_smime_verify_command = cs_subset_string(NeoMutt->sub, "smime_verify_command");
1721 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd, fp_smime_outfd,
1722 fp_smime_errfd, fname, sig_fname, NULL, NULL, NULL, NULL, NULL,
1723 (opaque ? c_smime_verify_opaque_command : c_smime_verify_command));
1724}
+ 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 1741 of file smime.c.

1744{
1745 const char *const c_smime_decrypt_command = cs_subset_string(NeoMutt->sub, "smime_decrypt_command");
1746 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1747 fp_smime_outfd, fp_smime_errfd, fname, NULL, NULL, NULL,
1749 NULL, c_smime_decrypt_command);
1750}
+ 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 state,
FILE *  fp_out_file 
)
static

Handle type application/pkcs7-mime.

Parameters
mBody 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 1869 of file smime.c.

1870{
1871 struct Buffer tmpfname = buf_make(0);
1872 FILE *fp_smime_out = NULL, *fp_smime_in = NULL, *fp_smime_err = NULL;
1873 FILE *fp_tmp = NULL, *fp_out = NULL;
1874 struct Body *p = NULL;
1875 pid_t pid = -1;
1877
1878 if (!(type & APPLICATION_SMIME))
1879 return NULL;
1880
1881 /* Because of the mutt_body_handler() we avoid the buffer pool. */
1882 fp_smime_out = mutt_file_mkstemp();
1883 if (!fp_smime_out)
1884 {
1885 mutt_perror(_("Can't create temporary file"));
1886 goto cleanup;
1887 }
1888
1889 fp_smime_err = mutt_file_mkstemp();
1890 if (!fp_smime_err)
1891 {
1892 mutt_perror(_("Can't create temporary file"));
1893 goto cleanup;
1894 }
1895
1896 buf_mktemp(&tmpfname);
1897 fp_tmp = mutt_file_fopen(buf_string(&tmpfname), "w+");
1898 if (!fp_tmp)
1899 {
1900 mutt_perror("%s", buf_string(&tmpfname));
1901 goto cleanup;
1902 }
1903
1904 if (!mutt_file_seek(state->fp_in, m->offset, SEEK_SET))
1905 {
1906 goto cleanup;
1907 }
1908
1909 mutt_file_copy_bytes(state->fp_in, fp_tmp, m->length);
1910
1911 fflush(fp_tmp);
1912 mutt_file_fclose(&fp_tmp);
1913
1914 if ((type & SEC_ENCRYPT) &&
1915 ((pid = smime_invoke_decrypt(&fp_smime_in, NULL, NULL, -1, fileno(fp_smime_out),
1916 fileno(fp_smime_err), buf_string(&tmpfname))) == -1))
1917 {
1918 mutt_file_unlink(buf_string(&tmpfname));
1919 if (state->flags & STATE_DISPLAY)
1920 {
1921 state_attach_puts(state, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1922 }
1923 goto cleanup;
1924 }
1925 else if ((type & SEC_SIGNOPAQUE) &&
1926 ((pid = smime_invoke_verify(&fp_smime_in, NULL, NULL, -1,
1927 fileno(fp_smime_out), fileno(fp_smime_err), NULL,
1928 buf_string(&tmpfname), SEC_SIGNOPAQUE)) == -1))
1929 {
1930 mutt_file_unlink(buf_string(&tmpfname));
1931 if (state->flags & STATE_DISPLAY)
1932 {
1933 state_attach_puts(state, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1934 }
1935 goto cleanup;
1936 }
1937
1938 if (type & SEC_ENCRYPT)
1939 {
1942 fputs(SmimePass, fp_smime_in);
1943 fputc('\n', fp_smime_in);
1944 }
1945
1946 mutt_file_fclose(&fp_smime_in);
1947
1948 filter_wait(pid);
1949 mutt_file_unlink(buf_string(&tmpfname));
1950
1951 if (state->flags & STATE_DISPLAY)
1952 {
1953 fflush(fp_smime_err);
1954 rewind(fp_smime_err);
1955
1956 const int c = fgetc(fp_smime_err);
1957 if (c != EOF)
1958 {
1959 ungetc(c, fp_smime_err);
1960
1961 crypt_current_time(state, "OpenSSL");
1962 mutt_file_copy_stream(fp_smime_err, state->fp_out);
1963 state_attach_puts(state, _("[-- End of OpenSSL output --]\n\n"));
1964 }
1965
1966 if (type & SEC_ENCRYPT)
1967 {
1968 state_attach_puts(state, _("[-- The following data is S/MIME encrypted --]\n"));
1969 }
1970 else
1971 {
1972 state_attach_puts(state, _("[-- The following data is S/MIME signed --]\n"));
1973 }
1974 }
1975
1976 fflush(fp_smime_out);
1977 rewind(fp_smime_out);
1978
1979 if (type & SEC_ENCRYPT)
1980 {
1981 /* void the passphrase, even if that wasn't the problem */
1982 if (fgetc(fp_smime_out) == EOF)
1983 {
1984 mutt_error(_("Decryption failed"));
1986 }
1987 rewind(fp_smime_out);
1988 }
1989
1990 if (fp_out_file)
1991 {
1992 fp_out = fp_out_file;
1993 }
1994 else
1995 {
1996 fp_out = mutt_file_mkstemp();
1997 if (!fp_out)
1998 {
1999 mutt_perror(_("Can't create temporary file"));
2000 goto cleanup;
2001 }
2002 }
2003 char buf[8192] = { 0 };
2004 while (fgets(buf, sizeof(buf) - 1, fp_smime_out))
2005 {
2006 const size_t len = mutt_str_len(buf);
2007 if ((len > 1) && (buf[len - 2] == '\r'))
2008 {
2009 buf[len - 2] = '\n';
2010 buf[len - 1] = '\0';
2011 }
2012 fputs(buf, fp_out);
2013 }
2014 fflush(fp_out);
2015 rewind(fp_out);
2016
2017 const long size = mutt_file_get_size_fp(fp_out);
2018 if (size == 0)
2019 {
2020 goto cleanup;
2021 }
2022 p = mutt_read_mime_header(fp_out, 0);
2023 if (p)
2024 {
2025 p->length = size - p->offset;
2026
2027 mutt_parse_part(fp_out, p);
2028
2029 if (state->flags & STATE_DISPLAY)
2031
2032 /* Store any protected headers in the parent so they can be
2033 * accessed for index updates after the handler recursion is done.
2034 * This is done before the handler to prevent a nested encrypted
2035 * handler from freeing the headers. */
2037 m->mime_headers = p->mime_headers;
2038 p->mime_headers = NULL;
2039
2040 if (state->fp_out)
2041 {
2042 rewind(fp_out);
2043 FILE *fp_tmp_buffer = state->fp_in;
2044 state->fp_in = fp_out;
2045 mutt_body_handler(p, state);
2046 state->fp_in = fp_tmp_buffer;
2047 }
2048
2049 /* Embedded multipart signed protected headers override the
2050 * encrypted headers. We need to do this after the handler so
2051 * they can be printed in the pager. */
2052 if (!(type & SMIME_SIGN) && mutt_is_multipart_signed(p) && p->parts &&
2053 p->parts->mime_headers)
2054 {
2057 p->parts->mime_headers = NULL;
2058 }
2059 }
2060 mutt_file_fclose(&fp_smime_out);
2061
2062 if (!fp_out_file)
2063 {
2064 mutt_file_fclose(&fp_out);
2065 mutt_file_unlink(buf_string(&tmpfname));
2066 }
2067 fp_out = NULL;
2068
2069 if (state->flags & STATE_DISPLAY)
2070 {
2071 if (type & SEC_ENCRYPT)
2072 state_attach_puts(state, _("\n[-- End of S/MIME encrypted data. --]\n"));
2073 else
2074 state_attach_puts(state, _("\n[-- End of S/MIME signed data. --]\n"));
2075 }
2076
2077 if (type & SEC_SIGNOPAQUE)
2078 {
2079 char *line = NULL;
2080 size_t linelen;
2081
2082 rewind(fp_smime_err);
2083
2084 line = mutt_file_read_line(line, &linelen, fp_smime_err, NULL, MUTT_RL_NO_FLAGS);
2085 if (linelen && mutt_istr_equal(line, "verification successful"))
2086 m->goodsig = true;
2087 FREE(&line);
2088 }
2089 else if (p)
2090 {
2091 m->goodsig = p->goodsig;
2092 m->badsig = p->badsig;
2093 }
2094
2095cleanup:
2096 mutt_file_fclose(&fp_smime_out);
2097 mutt_file_fclose(&fp_smime_err);
2098 mutt_file_fclose(&fp_tmp);
2099 mutt_file_fclose(&fp_out);
2100 buf_dealloc(&tmpfname);
2101 return p;
2102}
struct Buffer buf_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:70
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:397
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:598
void crypt_current_time(struct State *state, const char *app_name)
Print the current time.
Definition: crypt.c:69
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1779
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1344
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:763
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:232
long mutt_file_get_size_fp(FILE *fp)
Get the size of a file.
Definition: file.c:1578
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:733
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:39
bool smime_class_valid_passphrase(void)
Implements CryptModuleSpecs::valid_passphrase() -.
Definition: smime.c:175
int mutt_protected_headers_handler(struct Body *b, struct State *state)
Process a protected header - Implements handler_t -.
Definition: crypt.c:1106
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition: handler.c:1618
void state_attach_puts(struct State *state, const char *t)
Write a string to the state.
Definition: state.c:102
#define STATE_DISPLAY
Output is displayed to the user.
Definition: state.h:32
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:77
#define SEC_SIGNOPAQUE
Email has an opaque signature (encrypted)
Definition: lib.h:84
#define SMIME_SIGN
Definition: lib.h:104
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:92
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:79
static char SmimePass[256]
Cached Smime Passphrase.
Definition: smime.c:81
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:1714
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:1741
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. STATE_DISPLAY.
Definition: state.h:51
FILE * fp_out
File to write to.
Definition: state.h:49
FILE * fp_in
File to read from.
Definition: state.h:48
+ 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 81 of file smime.c.

◆ SmimeExpTime

time_t SmimeExpTime = 0
static

Unix time when SmimePass expires.

Definition at line 83 of file smime.c.

◆ SmimeKeyToUse

struct Buffer SmimeKeyToUse = { 0 }
static

Smime key to use.

Definition at line 86 of file smime.c.

◆ SmimeCertToUse

struct Buffer SmimeCertToUse = { 0 }
static

Smime certificate to use.

Definition at line 88 of file smime.c.

◆ SmimeIntermediateToUse

struct Buffer SmimeIntermediateToUse = { 0 }
static

Smime intermediate certificate to use.

Definition at line 90 of file smime.c.