NeoMutt  2024-03-23-147-g885fbc
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
smime.c File Reference

SMIME helper routines. More...

#include "config.h"
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "private.h"
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "lib.h"
#include "editor/lib.h"
#include "expando/lib.h"
#include "history/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "copy.h"
#include "crypt.h"
#include "cryptglue.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.

Functions

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

Variables

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

Detailed Description

SMIME helper routines.

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

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

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

Definition in file smime.c.

Function Documentation

◆ smime_init()

void smime_init ( void  )

Initialise smime globals.

Definition at line 84 of file smime.c.

85{
89}
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:336
static struct Buffer SmimeIntermediateToUse
Smime intermediate certificate to use.
Definition: smime.c:79
static struct Buffer SmimeKeyToUse
Smime key to use.
Definition: smime.c:75
static struct Buffer SmimeCertToUse
Smime certificate to use.
Definition: smime.c:77
+ 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 94 of file smime.c.

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

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

131{
132 if (!key)
133 return NULL;
134
135 struct SmimeKey *copy = NULL;
136
137 copy = mutt_mem_calloc(1, sizeof(struct SmimeKey));
138 copy->email = mutt_str_dup(key->email);
139 copy->hash = mutt_str_dup(key->hash);
140 copy->label = mutt_str_dup(key->label);
141 copy->issuer = mutt_str_dup(key->issuer);
142 copy->trust = key->trust;
143 copy->flags = key->flags;
144
145 return copy;
146}
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:253
KeyFlags flags
Definition: smime.h:49
char trust
i=Invalid r=revoked e=expired u=unverified v=verified t=trusted
Definition: smime.h:48
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_command()

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

Format an SMIME command string.

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

Definition at line 338 of file smime.c.

340{
342 mutt_debug(LL_DEBUG2, "%s\n", buf_string(buf));
343}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
int expando_render(const struct Expando *exp, const struct ExpandoRenderData *rdata, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Render an Expando + data into a string.
Definition: expando.c:110
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: render.h:33
const struct ExpandoRenderData SmimeCommandRenderData[]
Callbacks for Smime Command Expandos.
Definition: smime.c:67
size_t dsize
Length of data.
Definition: buffer.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_invoke()

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

Run an SMIME command.

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

Definition at line 367 of file smime.c.

372{
373 struct SmimeCommandContext cctx = { 0 };
374
375 if (!exp)
376 return (pid_t) -1;
377
378 cctx.fname = fname;
379 cctx.sig_fname = sig_fname;
380 cctx.key = key;
381 cctx.cryptalg = cryptalg;
382 cctx.digestalg = digestalg;
385
386 struct Buffer *cmd = buf_pool_get();
387 smime_command(cmd, &cctx, exp);
388
389 pid_t pid = filter_create_fd(buf_string(cmd), fp_smime_in, fp_smime_out, fp_smime_err,
390 fp_smime_infd, fp_smime_outfd, fp_smime_errfd, EnvList);
391 buf_pool_release(&cmd);
392 return pid;
393}
pid_t filter_create_fd(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, int fdin, int fdout, int fderr, char **envlist)
Run a command on a pipe (optionally connect stdin/stdout)
Definition: filter.c:62
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:78
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 void smime_command(struct Buffer *buf, struct SmimeCommandContext *cctx, const struct Expando *exp)
Format an SMIME command string.
Definition: smime.c:338
String manipulation buffer.
Definition: buffer.h:36
Data for a SIME command.
Definition: smime.h:57
const char * sig_fname
s
Definition: smime.h:62
const char * intermediates
i
Definition: smime.h:64
const char * digestalg
d
Definition: smime.h:60
const char * cryptalg
a
Definition: smime.h:59
const char * key
k
Definition: smime.h:58
const char * fname
f
Definition: smime.h:61
const char * certificates
c
Definition: smime.h:63
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_parse_key()

static struct SmimeKey * smime_parse_key ( char *  buf)
static

Parse an SMIME key block.

Parameters
bufString to parse
Return values
ptrSMIME key
NULLError

Definition at line 401 of file smime.c.

402{
403 char *pend = NULL, *p = NULL;
404 int field = 0;
405
406 struct SmimeKey *key = mutt_mem_calloc(1, sizeof(struct SmimeKey));
407
408 for (p = buf; p; p = pend)
409 {
410 /* Some users manually maintain their .index file, and use a tab
411 * as a delimiter, which the old parsing code (using fscanf)
412 * happened to allow. smime_keys uses a space, so search for both. */
413 if ((pend = strchr(p, ' ')) || (pend = strchr(p, '\t')) || (pend = strchr(p, '\n')))
414 *pend++ = 0;
415
416 /* For backward compatibility, don't count consecutive delimiters
417 * as an empty field. */
418 if (*p == '\0')
419 continue;
420
421 field++;
422
423 switch (field)
424 {
425 case 1: /* mailbox */
426 key->email = mutt_str_dup(p);
427 break;
428 case 2: /* hash */
429 key->hash = mutt_str_dup(p);
430 break;
431 case 3: /* label */
432 key->label = mutt_str_dup(p);
433 break;
434 case 4: /* issuer */
435 key->issuer = mutt_str_dup(p);
436 break;
437 case 5: /* trust */
438 key->trust = *p;
439 break;
440 case 6: /* purpose */
441 while (*p)
442 {
443 switch (*p++)
444 {
445 case 'e':
447 break;
448
449 case 's':
450 key->flags |= KEYFLAG_CANSIGN;
451 break;
452 }
453 }
454 break;
455 }
456 }
457
458 /* Old index files could be missing issuer, trust, and purpose,
459 * but anything less than that is an error. */
460 if (field < 3)
461 {
462 smime_key_free(&key);
463 return NULL;
464 }
465
466 if (field < 4)
467 key->issuer = mutt_str_dup("?");
468
469 if (field < 5)
470 key->trust = 't';
471
472 if (field < 6)
474
475 return key;
476}
#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:105
+ 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 484 of file smime.c.

485{
486 char buf[1024] = { 0 };
487 struct SmimeKey *key = NULL, *results = NULL;
488 struct SmimeKey **results_end = &results;
489
490 struct Buffer *index_file = buf_pool_get();
491 const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
492 const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
493 buf_printf(index_file, "%s/.index",
494 only_public_key ? NONULL(c_smime_certificates) : NONULL(c_smime_keys));
495
496 FILE *fp = mutt_file_fopen(buf_string(index_file), "r");
497 if (!fp)
498 {
499 mutt_perror("%s", buf_string(index_file));
500 buf_pool_release(&index_file);
501 return NULL;
502 }
503 buf_pool_release(&index_file);
504
505 while (fgets(buf, sizeof(buf), fp))
506 {
507 if (((*search == '\0')) || mutt_istr_find(buf, search))
508 {
509 key = smime_parse_key(buf);
510 if (key)
511 {
512 *results_end = key;
513 results_end = &key->next;
514 }
515 }
516 }
517
518 mutt_file_fclose(&fp);
519
520 return results;
521}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:169
#define mutt_file_fclose(FP)
Definition: file.h:147
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:146
#define mutt_perror(...)
Definition: logging2.h:93
static int search(struct Menu *menu, int op)
Search a menu.
Definition: functions.c:58
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:570
static struct SmimeKey * smime_parse_key(char *buf)
Parse an SMIME key block.
Definition: smime.c:401
#define NONULL(x)
Definition: string2.h:37
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 532 of file smime.c.

533{
534 struct SmimeKey *match = NULL;
535 struct SmimeKey *results = smime_get_candidates(hash, only_public_key);
536 for (struct SmimeKey *result = results; result; result = result->next)
537 {
538 if (mutt_istr_equal(hash, result->hash))
539 {
540 match = smime_copy_key(result);
541 break;
542 }
543 }
544
545 smime_key_free(&results);
546
547 return match;
548}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:721
static struct SmimeKey * smime_copy_key(struct SmimeKey *key)
Copy an SMIME key.
Definition: smime.c:130
static struct SmimeKey * smime_get_candidates(const char *search, bool only_public_key)
Find keys matching a string.
Definition: smime.c:484
+ 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 558 of file smime.c.

560{
561 if (!mailbox)
562 return NULL;
563
564 struct SmimeKey *results = NULL, *result = NULL;
565 struct SmimeKey *matches = NULL;
566 struct SmimeKey **matches_end = &matches;
567 struct SmimeKey *match = NULL;
568 struct SmimeKey *trusted_match = NULL;
569 struct SmimeKey *valid_match = NULL;
570 struct SmimeKey *return_key = NULL;
571 bool multi_trusted_matches = false;
572
573 results = smime_get_candidates(mailbox, only_public_key);
574 for (result = results; result; result = result->next)
575 {
576 if (abilities && !(result->flags & abilities))
577 {
578 continue;
579 }
580
581 if (mutt_istr_equal(mailbox, result->email))
582 {
583 match = smime_copy_key(result);
584 *matches_end = match;
585 matches_end = &match->next;
586
587 if (match->trust == 't')
588 {
589 if (trusted_match && !mutt_istr_equal(match->hash, trusted_match->hash))
590 {
591 multi_trusted_matches = true;
592 }
593 trusted_match = match;
594 }
595 else if ((match->trust == 'u') || (match->trust == 'v'))
596 {
597 valid_match = match;
598 }
599 }
600 }
601
602 smime_key_free(&results);
603
604 if (matches)
605 {
606 if (oppenc_mode || !isatty(STDIN_FILENO))
607 {
608 const bool c_crypt_opportunistic_encrypt_strong_keys =
609 cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt_strong_keys");
610 if (trusted_match)
611 return_key = smime_copy_key(trusted_match);
612 else if (valid_match && !c_crypt_opportunistic_encrypt_strong_keys)
613 return_key = smime_copy_key(valid_match);
614 else
615 return_key = NULL;
616 }
617 else if (trusted_match && !multi_trusted_matches)
618 {
619 return_key = smime_copy_key(trusted_match);
620 }
621 else
622 {
623 return_key = smime_copy_key(dlg_smime(matches, mailbox));
624 }
625
626 smime_key_free(&matches);
627 }
628
629 return return_key;
630}
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:200
+ 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 639 of file smime.c.

640{
641 if (!str)
642 return NULL;
643
644 struct SmimeKey *results = NULL, *result = NULL;
645 struct SmimeKey *matches = NULL;
646 struct SmimeKey **matches_end = &matches;
647 struct SmimeKey *match = NULL;
648 struct SmimeKey *return_key = NULL;
649
650 results = smime_get_candidates(str, only_public_key);
651 for (result = results; result; result = result->next)
652 {
653 if (abilities && !(result->flags & abilities))
654 {
655 continue;
656 }
657
658 if (mutt_istr_equal(str, result->hash) ||
659 mutt_istr_find(result->email, str) || mutt_istr_find(result->label, str))
660 {
661 match = smime_copy_key(result);
662 *matches_end = match;
663 matches_end = &match->next;
664 }
665 }
666
667 smime_key_free(&results);
668
669 if (matches)
670 {
671 return_key = smime_copy_key(dlg_smime(matches, str));
672 smime_key_free(&matches);
673 }
674
675 return return_key;
676}
+ 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 685 of file smime.c.

686{
687 struct SmimeKey *key = NULL;
688 struct Buffer *resp = buf_pool_get();
689
690 if (!prompt)
691 prompt = _("Enter keyID: ");
692
694
695 while (true)
696 {
697 buf_reset(resp);
698 if (mw_get_field(prompt, resp, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0)
699 {
700 goto done;
701 }
702
703 key = smime_get_key_by_str(buf_string(resp), abilities, only_public_key);
704 if (key)
705 goto done;
706
707 mutt_error(_("No matching keys found for \"%s\""), buf_string(resp));
708 }
709
710done:
711 buf_pool_release(&resp);
712 return key;
713}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:75
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:274
#define mutt_error(...)
Definition: logging2.h:92
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:56
#define _(a)
Definition: message.h:28
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
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:639
+ 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 722 of file smime.c.

723{
724 const char *k = NULL;
725
726 struct SmimeKey *key = smime_get_key_by_addr(mailbox, KEYFLAG_CANENCRYPT, false, false);
727
728 if (!key)
729 {
730 char buf[256] = { 0 };
731 snprintf(buf, sizeof(buf), _("Enter keyID for %s: "), mailbox);
732 key = smime_ask_for_key(buf, KEYFLAG_CANENCRYPT, false);
733 }
734
735 const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
736 size_t smime_keys_len = mutt_str_len(c_smime_keys);
737
738 const char *const c_smime_default_key = cs_subset_string(NeoMutt->sub, "smime_default_key");
739 k = key ? key->hash : NONULL(c_smime_default_key);
740
741 /* if the key is different from last time */
742 if ((buf_len(&SmimeKeyToUse) <= smime_keys_len) ||
743 !mutt_istr_equal(k, SmimeKeyToUse.data + smime_keys_len + 1))
744 {
746 buf_printf(&SmimeKeyToUse, "%s/%s", NONULL(c_smime_keys), k);
747 const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
748 buf_printf(&SmimeCertToUse, "%s/%s", NONULL(c_smime_certificates), k);
749 }
750
751 smime_key_free(&key);
752}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:490
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)
Forget the cached passphrase - Implements CryptModuleSpecs::void_passphrase() -.
Definition: smime.c:155
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:545
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:558
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:685
char * data
Pointer to data.
Definition: buffer.h:37
+ 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 844 of file smime.c.

846{
847 char email[256] = { 0 };
848 int rc = -1, count = 0;
849 pid_t pid;
850
851 FILE *fp_err = mutt_file_mkstemp();
852 if (!fp_err)
853 {
854 mutt_perror(_("Can't create temporary file"));
855 return 1;
856 }
857
858 FILE *fp_out = mutt_file_mkstemp();
859 if (!fp_out)
860 {
861 mutt_file_fclose(&fp_err);
862 mutt_perror(_("Can't create temporary file"));
863 return 1;
864 }
865
866 const struct Expando *c_smime_get_cert_email_command =
867 cs_subset_expando(NeoMutt->sub, "smime_get_cert_email_command");
868 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), certificate,
869 NULL, NULL, NULL, NULL, NULL, NULL, c_smime_get_cert_email_command);
870 if (pid == -1)
871 {
872 mutt_message(_("Error: unable to create OpenSSL subprocess"));
873 mutt_file_fclose(&fp_err);
874 mutt_file_fclose(&fp_out);
875 return 1;
876 }
877
878 filter_wait(pid);
879
880 fflush(fp_out);
881 rewind(fp_out);
882 fflush(fp_err);
883 rewind(fp_err);
884
885 while ((fgets(email, sizeof(email), fp_out)))
886 {
887 size_t len = mutt_str_len(email);
888 if (len && (email[len - 1] == '\n'))
889 email[len - 1] = '\0';
890 if (mutt_istr_startswith(email, mailbox))
891 rc = 1;
892
893 rc = (rc < 0) ? 0 : rc;
894 count++;
895 }
896
897 if (rc == -1)
898 {
899 mutt_endwin();
900 mutt_file_copy_stream(fp_err, stdout);
901 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
902 rc = 1;
903 }
904 else if (rc == 0)
905 {
906 rc = 1;
907 }
908 else
909 {
910 rc = 0;
911 }
912
913 if (copy && buffer && num)
914 {
915 (*num) = count;
916 *buffer = mutt_mem_calloc(count, sizeof(char *));
917 count = 0;
918
919 rewind(fp_out);
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 (*buffer)[count] = mutt_mem_calloc(mutt_str_len(email) + 1, sizeof(char));
926 strncpy((*buffer)[count], email, mutt_str_len(email));
927 count++;
928 }
929 }
930 else if (copy)
931 {
932 rc = 2;
933 }
934
935 mutt_file_fclose(&fp_out);
936 mutt_file_fclose(&fp_err);
937
938 return rc;
939}
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
Definition: config_type.c:358
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:173
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:151
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:286
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:220
#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:242
static pid_t smime_invoke(FILE **fp_smime_in, FILE **fp_smime_out, FILE **fp_smime_err, int fp_smime_infd, int fp_smime_outfd, int fp_smime_errfd, const char *fname, const char *sig_fname, const char *cryptalg, const char *digestalg, const char *key, const char *certificates, const char *intermediates, const struct Expando *exp)
Run an SMIME command.
Definition: smime.c:367
Parsed Expando trees.
Definition: expando.h:41
#define mutt_file_mkstemp()
Definition: tmp.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_extract_certificate()

static char * smime_extract_certificate ( const char *  infile)
static

Extract an SMIME certificate from a file.

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

Definition at line 946 of file smime.c.

947{
948 FILE *fp_err = NULL;
949 FILE *fp_out = NULL;
950 FILE *fp_cert = NULL;
951 char *rc = NULL;
952 pid_t pid;
953 int empty;
954
955 struct Buffer *pk7out = buf_pool_get();
956 struct Buffer *certfile = buf_pool_get();
957
958 fp_err = mutt_file_mkstemp();
959 if (!fp_err)
960 {
961 mutt_perror(_("Can't create temporary file"));
962 goto cleanup;
963 }
964
965 buf_mktemp(pk7out);
966 fp_out = mutt_file_fopen(buf_string(pk7out), "w+");
967 if (!fp_out)
968 {
969 mutt_perror("%s", buf_string(pk7out));
970 goto cleanup;
971 }
972
973 /* Step 1: Convert the signature to a PKCS#7 structure, as we can't
974 * extract the full set of certificates directly. */
975 const struct Expando *c_smime_pk7out_command = cs_subset_expando(NeoMutt->sub, "smime_pk7out_command");
976 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), infile,
977 NULL, NULL, NULL, NULL, NULL, NULL, c_smime_pk7out_command);
978 if (pid == -1)
979 {
980 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
981 goto cleanup;
982 }
983
984 filter_wait(pid);
985
986 fflush(fp_out);
987 rewind(fp_out);
988 fflush(fp_err);
989 rewind(fp_err);
990 empty = (fgetc(fp_out) == EOF);
991 if (empty)
992 {
993 mutt_perror("%s", buf_string(pk7out));
994 mutt_file_copy_stream(fp_err, stdout);
995 goto cleanup;
996 }
997 mutt_file_fclose(&fp_out);
998
999 buf_mktemp(certfile);
1000 fp_cert = mutt_file_fopen(buf_string(certfile), "w+");
1001 if (!fp_cert)
1002 {
1003 mutt_perror("%s", buf_string(certfile));
1005 goto cleanup;
1006 }
1007
1008 // Step 2: Extract the certificates from a PKCS#7 structure.
1009 const struct Expando *c_smime_get_cert_command = cs_subset_expando(NeoMutt->sub, "smime_get_cert_command");
1010 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_cert), fileno(fp_err),
1011 buf_string(pk7out), NULL, NULL, NULL, NULL, NULL, NULL,
1012 c_smime_get_cert_command);
1013 if (pid == -1)
1014 {
1015 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
1017 goto cleanup;
1018 }
1019
1020 filter_wait(pid);
1021
1023
1024 fflush(fp_cert);
1025 rewind(fp_cert);
1026 fflush(fp_err);
1027 rewind(fp_err);
1028 empty = (fgetc(fp_cert) == EOF);
1029 if (empty)
1030 {
1031 mutt_file_copy_stream(fp_err, stdout);
1032 goto cleanup;
1033 }
1034
1035 mutt_file_fclose(&fp_cert);
1036
1037 rc = buf_strdup(certfile);
1038
1039cleanup:
1040 mutt_file_fclose(&fp_err);
1041 if (fp_out)
1042 {
1043 mutt_file_fclose(&fp_out);
1045 }
1046 if (fp_cert)
1047 {
1048 mutt_file_fclose(&fp_cert);
1049 mutt_file_unlink(buf_string(certfile));
1050 }
1051 buf_pool_release(&pk7out);
1052 buf_pool_release(&certfile);
1053 return rc;
1054}
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:570
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:220
#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 1061 of file smime.c.

1062{
1063 char *cert = NULL;
1064 struct Buffer *certfile = NULL;
1065 pid_t pid;
1066 int empty;
1067
1068 FILE *fp_err = mutt_file_mkstemp();
1069 if (!fp_err)
1070 {
1071 mutt_perror(_("Can't create temporary file"));
1072 return NULL;
1073 }
1074
1075 certfile = buf_pool_get();
1076 buf_mktemp(certfile);
1077 FILE *fp_out = mutt_file_fopen(buf_string(certfile), "w+");
1078 if (!fp_out)
1079 {
1080 mutt_file_fclose(&fp_err);
1081 mutt_perror("%s", buf_string(certfile));
1082 goto cleanup;
1083 }
1084
1085 /* Extract signer's certificate
1086 */
1087 const struct Expando *c_smime_get_signer_cert_command =
1088 cs_subset_expando(NeoMutt->sub, "smime_get_signer_cert_command");
1089 pid = smime_invoke(NULL, NULL, NULL, -1, -1, fileno(fp_err), infile, NULL, NULL, NULL,
1090 NULL, buf_string(certfile), NULL, c_smime_get_signer_cert_command);
1091 if (pid == -1)
1092 {
1093 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
1094 goto cleanup;
1095 }
1096
1097 filter_wait(pid);
1098
1099 fflush(fp_out);
1100 rewind(fp_out);
1101 fflush(fp_err);
1102 rewind(fp_err);
1103 empty = (fgetc(fp_out) == EOF);
1104 if (empty)
1105 {
1106 mutt_endwin();
1107 mutt_file_copy_stream(fp_err, stdout);
1109 goto cleanup;
1110 }
1111
1112 mutt_file_fclose(&fp_out);
1113 cert = buf_strdup(certfile);
1114
1115cleanup:
1116 mutt_file_fclose(&fp_err);
1117 if (fp_out)
1118 {
1119 mutt_file_fclose(&fp_out);
1120 mutt_file_unlink(buf_string(certfile));
1121 }
1122 buf_pool_release(&certfile);
1123 return cert;
1124}
+ 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 1289 of file smime.c.

1293{
1294 const char *const c_smime_encrypt_with = cs_subset_string(NeoMutt->sub, "smime_encrypt_with");
1295 const struct Expando *c_smime_encrypt_command = cs_subset_expando(NeoMutt->sub, "smime_encrypt_command");
1296 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1297 fp_smime_outfd, fp_smime_errfd, fname, NULL, c_smime_encrypt_with,
1298 NULL, NULL, uids, NULL, c_smime_encrypt_command);
1299}
+ 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 1316 of file smime.c.

1319{
1320 const char *const c_smime_sign_digest_alg = cs_subset_string(NeoMutt->sub, "smime_sign_digest_alg");
1321 const struct Expando *c_smime_sign_command = cs_subset_expando(NeoMutt->sub, "smime_sign_command");
1322 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd, fp_smime_outfd,
1323 fp_smime_errfd, fname, NULL, NULL, c_smime_sign_digest_alg,
1325 buf_string(&SmimeIntermediateToUse), c_smime_sign_command);
1326}
+ 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 1474 of file smime.c.

1475{
1476 if (!md)
1477 return NULL;
1478
1479 char *micalg = NULL;
1480 if (mutt_istr_startswith(md, "sha"))
1481 {
1482 mutt_str_asprintf(&micalg, "sha-%s", md + 3);
1483 }
1484 else
1485 {
1486 micalg = mutt_str_dup(md);
1487 }
1488
1489 return micalg;
1490}
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:852
+ 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 1662 of file smime.c.

1666{
1667 const struct Expando *c_smime_verify_opaque_command =
1668 cs_subset_expando(NeoMutt->sub, "smime_verify_opaque_command");
1669 const struct Expando *c_smime_verify_command = cs_subset_expando(NeoMutt->sub, "smime_verify_command");
1670 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd, fp_smime_outfd,
1671 fp_smime_errfd, fname, sig_fname, NULL, NULL, NULL, NULL, NULL,
1672 (opaque ? c_smime_verify_opaque_command : c_smime_verify_command));
1673}
+ 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 1690 of file smime.c.

1693{
1694 const struct Expando *c_smime_decrypt_command = cs_subset_expando(NeoMutt->sub, "smime_decrypt_command");
1695 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1696 fp_smime_outfd, fp_smime_errfd, fname, NULL, NULL, NULL,
1698 NULL, c_smime_decrypt_command);
1699}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_handle_entity()

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

Handle type application/pkcs7-mime.

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

This can either be a signed or an encrypted message.

Definition at line 1818 of file smime.c.

1819{
1820 struct Buffer *tmpfname = buf_pool_get();
1821 FILE *fp_smime_out = NULL, *fp_smime_in = NULL, *fp_smime_err = NULL;
1822 FILE *fp_tmp = NULL, *fp_out = NULL;
1823 struct Body *p = NULL;
1824 pid_t pid = -1;
1826
1827 if (!(type & APPLICATION_SMIME))
1828 return NULL;
1829
1830 /* Because of the mutt_body_handler() we avoid the buffer pool. */
1831 fp_smime_out = mutt_file_mkstemp();
1832 if (!fp_smime_out)
1833 {
1834 mutt_perror(_("Can't create temporary file"));
1835 goto cleanup;
1836 }
1837
1838 fp_smime_err = mutt_file_mkstemp();
1839 if (!fp_smime_err)
1840 {
1841 mutt_perror(_("Can't create temporary file"));
1842 goto cleanup;
1843 }
1844
1845 buf_mktemp(tmpfname);
1846 fp_tmp = mutt_file_fopen(buf_string(tmpfname), "w+");
1847 if (!fp_tmp)
1848 {
1849 mutt_perror("%s", buf_string(tmpfname));
1850 goto cleanup;
1851 }
1852
1853 if (!mutt_file_seek(state->fp_in, b->offset, SEEK_SET))
1854 {
1855 goto cleanup;
1856 }
1857
1858 mutt_file_copy_bytes(state->fp_in, fp_tmp, b->length);
1859
1860 fflush(fp_tmp);
1861 mutt_file_fclose(&fp_tmp);
1862
1863 if ((type & SEC_ENCRYPT) &&
1864 ((pid = smime_invoke_decrypt(&fp_smime_in, NULL, NULL, -1, fileno(fp_smime_out),
1865 fileno(fp_smime_err), buf_string(tmpfname))) == -1))
1866 {
1867 mutt_file_unlink(buf_string(tmpfname));
1868 if (state->flags & STATE_DISPLAY)
1869 {
1870 state_attach_puts(state, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1871 }
1872 goto cleanup;
1873 }
1874 else if ((type & SEC_SIGNOPAQUE) &&
1875 ((pid = smime_invoke_verify(&fp_smime_in, NULL, NULL, -1,
1876 fileno(fp_smime_out), fileno(fp_smime_err), NULL,
1877 buf_string(tmpfname), SEC_SIGNOPAQUE)) == -1))
1878 {
1879 mutt_file_unlink(buf_string(tmpfname));
1880 if (state->flags & STATE_DISPLAY)
1881 {
1882 state_attach_puts(state, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1883 }
1884 goto cleanup;
1885 }
1886
1887 if (type & SEC_ENCRYPT)
1888 {
1891 fputs(SmimePass, fp_smime_in);
1892 fputc('\n', fp_smime_in);
1893 }
1894
1895 mutt_file_fclose(&fp_smime_in);
1896
1897 filter_wait(pid);
1898 mutt_file_unlink(buf_string(tmpfname));
1899
1900 if (state->flags & STATE_DISPLAY)
1901 {
1902 fflush(fp_smime_err);
1903 rewind(fp_smime_err);
1904
1905 const int c = fgetc(fp_smime_err);
1906 if (c != EOF)
1907 {
1908 ungetc(c, fp_smime_err);
1909
1910 crypt_current_time(state, "OpenSSL");
1911 mutt_file_copy_stream(fp_smime_err, state->fp_out);
1912 state_attach_puts(state, _("[-- End of OpenSSL output --]\n\n"));
1913 }
1914
1915 if (type & SEC_ENCRYPT)
1916 {
1917 state_attach_puts(state, _("[-- The following data is S/MIME encrypted --]\n"));
1918 }
1919 else
1920 {
1921 state_attach_puts(state, _("[-- The following data is S/MIME signed --]\n"));
1922 }
1923 }
1924
1925 fflush(fp_smime_out);
1926 rewind(fp_smime_out);
1927
1928 if (type & SEC_ENCRYPT)
1929 {
1930 /* void the passphrase, even if that wasn't the problem */
1931 if (fgetc(fp_smime_out) == EOF)
1932 {
1933 mutt_error(_("Decryption failed"));
1935 }
1936 rewind(fp_smime_out);
1937 }
1938
1939 if (fp_out_file)
1940 {
1941 fp_out = fp_out_file;
1942 }
1943 else
1944 {
1945 fp_out = mutt_file_mkstemp();
1946 if (!fp_out)
1947 {
1948 mutt_perror(_("Can't create temporary file"));
1949 goto cleanup;
1950 }
1951 }
1952 char buf[8192] = { 0 };
1953 while (fgets(buf, sizeof(buf) - 1, fp_smime_out))
1954 {
1955 const size_t len = mutt_str_len(buf);
1956 if ((len > 1) && (buf[len - 2] == '\r'))
1957 {
1958 buf[len - 2] = '\n';
1959 buf[len - 1] = '\0';
1960 }
1961 fputs(buf, fp_out);
1962 }
1963 fflush(fp_out);
1964 rewind(fp_out);
1965
1966 const long size = mutt_file_get_size_fp(fp_out);
1967 if (size == 0)
1968 {
1969 goto cleanup;
1970 }
1971 p = mutt_read_mime_header(fp_out, 0);
1972 if (p)
1973 {
1974 p->length = size - p->offset;
1975
1976 mutt_parse_part(fp_out, p);
1977
1978 if (state->flags & STATE_DISPLAY)
1980
1981 /* Store any protected headers in the parent so they can be
1982 * accessed for index updates after the handler recursion is done.
1983 * This is done before the handler to prevent a nested encrypted
1984 * handler from freeing the headers. */
1986 b->mime_headers = p->mime_headers;
1987 p->mime_headers = NULL;
1988
1989 if (state->fp_out)
1990 {
1991 rewind(fp_out);
1992 FILE *fp_tmp_buffer = state->fp_in;
1993 state->fp_in = fp_out;
1994 mutt_body_handler(p, state);
1995 state->fp_in = fp_tmp_buffer;
1996 }
1997
1998 /* Embedded multipart signed protected headers override the
1999 * encrypted headers. We need to do this after the handler so
2000 * they can be printed in the pager. */
2001 if (!(type & SMIME_SIGN) && mutt_is_multipart_signed(p) && p->parts &&
2002 p->parts->mime_headers)
2003 {
2006 p->parts->mime_headers = NULL;
2007 }
2008 }
2009 mutt_file_fclose(&fp_smime_out);
2010
2011 if (!fp_out_file)
2012 {
2013 mutt_file_fclose(&fp_out);
2014 mutt_file_unlink(buf_string(tmpfname));
2015 }
2016 fp_out = NULL;
2017
2018 if (state->flags & STATE_DISPLAY)
2019 {
2020 if (type & SEC_ENCRYPT)
2021 state_attach_puts(state, _("\n[-- End of S/MIME encrypted data. --]\n"));
2022 else
2023 state_attach_puts(state, _("\n[-- End of S/MIME signed data. --]\n"));
2024 }
2025
2026 if (type & SEC_SIGNOPAQUE)
2027 {
2028 char *line = NULL;
2029 size_t linelen;
2030
2031 rewind(fp_smime_err);
2032
2033 line = mutt_file_read_line(line, &linelen, fp_smime_err, NULL, MUTT_RL_NO_FLAGS);
2034 if (linelen && mutt_istr_equal(line, "verification successful"))
2035 b->goodsig = true;
2036 FREE(&line);
2037 }
2038 else if (p)
2039 {
2040 b->goodsig = p->goodsig;
2041 b->badsig = p->badsig;
2042 }
2043
2044cleanup:
2045 mutt_file_fclose(&fp_smime_out);
2046 mutt_file_fclose(&fp_smime_err);
2047 mutt_file_fclose(&fp_tmp);
2048 mutt_file_fclose(&fp_out);
2049 buf_pool_release(&tmpfname);
2050 return p;
2051}
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:394
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:595
void crypt_current_time(struct State *state, const char *app_name)
Print the current time.
Definition: crypt.c:65
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1817
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1357
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:126
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:805
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:256
long mutt_file_get_size_fp(FILE *fp)
Get the size of a file.
Definition: file.c:1534
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:775
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:40
bool smime_class_valid_passphrase(void)
Ensure we have a valid passphrase - Implements CryptModuleSpecs::valid_passphrase() -.
Definition: smime.c:164
int mutt_protected_headers_handler(struct Body *b_email, struct State *state)
Handler for protected headers - Implements handler_t -.
Definition: crypt.c:1103
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition: handler.c:1631
void state_attach_puts(struct State *state, const char *t)
Write a string to the state.
Definition: state.c:103
#define STATE_DISPLAY
Output is displayed to the user.
Definition: state.h:33
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
static char SmimePass[256]
Cached Smime Passphrase.
Definition: smime.c:70
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:1662
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:1690
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:52
FILE * fp_out
File to write to.
Definition: state.h:50
FILE * fp_in
File to read from.
Definition: state.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ SmimeCommandRenderData

const struct ExpandoRenderData SmimeCommandRenderData
Initial value:
= {
{ -1, -1, NULL, NULL },
}
@ ED_SMIME_CMD
Smime Command ED_SMI_ ExpandoDataSmimeCmd.
Definition: domain.h:56
@ ED_GLOBAL
Global ED_GLO_ ExpandoDataGlobal.
Definition: domain.h:44
void smime_command_i(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Smime Command: Intermediate certificates - Implements ExpandoRenderData::get_string() -.
Definition: smime.c:293
void smime_command_k(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Smime Command: Key-pair - Implements ExpandoRenderData::get_string() -.
Definition: smime.c:307
void smime_command_C(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Smime Command: CA location - Implements ExpandoRenderData::get_string() -.
Definition: smime.c:230
void smime_command_a(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Smime Command: algorithm - Implements ExpandoRenderData::get_string() -.
Definition: smime.c:202
void smime_command_d(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Smime Command: Message digest algorithm - Implements ExpandoRenderData::get_string() -.
Definition: smime.c:265
void smime_command_s(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Smime Command: Filename of signature - Implements ExpandoRenderData::get_string() -.
Definition: smime.c:321
void smime_command_f(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Smime Command: Filename of message - Implements ExpandoRenderData::get_string() -.
Definition: smime.c:279
void smime_command_c(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Smime Command: certificate IDs - Implements ExpandoRenderData::get_string() -.
Definition: smime.c:216
@ ED_SMI_MESSAGE_FILE
SmimeCommandContext.fname.
Definition: smime.h:79
@ ED_SMI_ALGORITHM
SmimeCommandContext.cryptalg.
Definition: smime.h:74
@ ED_SMI_SIGNATURE_FILE
SmimeCommandContext.sig_fname.
Definition: smime.h:80
@ ED_SMI_DIGEST_ALGORITHM
SmimeCommandContext.digestalg.
Definition: smime.h:76
@ ED_SMI_CERTIFICATE_IDS
SmimeCommandContext.certificates.
Definition: smime.h:75
@ ED_SMI_KEY
SmimeCommandContext.key.
Definition: smime.h:78
@ ED_SMI_INTERMEDIATE_IDS
SmimeCommandContext.intermediates.
Definition: smime.h:77
@ ED_GLO_CERTIFICATE_PATH
Path of Smime certificates.
Definition: uid.h:34

Callbacks for Smime Command Expandos.

See also
SmimeCommandFormatDef, ExpandoDataGlobal, ExpandoDataSmimeCmd

Definition at line 67 of file smime.c.

◆ SmimePass

char SmimePass[256]
static

Cached Smime Passphrase.

Definition at line 70 of file smime.c.

◆ SmimeExpTime

time_t SmimeExpTime = 0
static

Unix time when SmimePass expires.

Definition at line 72 of file smime.c.

◆ SmimeKeyToUse

struct Buffer SmimeKeyToUse = { 0 }
static

Smime key to use.

Definition at line 75 of file smime.c.

◆ SmimeCertToUse

struct Buffer SmimeCertToUse = { 0 }
static

Smime certificate to use.

Definition at line 77 of file smime.c.

◆ SmimeIntermediateToUse

struct Buffer SmimeIntermediateToUse = { 0 }
static

Smime intermediate certificate to use.

Definition at line 79 of file smime.c.