NeoMutt  2024-04-25-76-g20fe7b
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 <sys/types.h>
#include <unistd.h>
#include "private.h"
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "lib.h"
#include "editor/lib.h"
#include "expando/lib.h"
#include "history/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "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 85 of file smime.c.

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

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

◆ smime_key_free()

static void smime_key_free ( struct SmimeKey **  keylist)
static

Free a list of SMIME keys.

Parameters
[out]keylistList of keys to free

Definition at line 106 of file smime.c.

107{
108 if (!keylist)
109 return;
110
111 struct SmimeKey *key = NULL;
112
113 while (*keylist)
114 {
115 key = *keylist;
116 *keylist = (*keylist)->next;
117
118 FREE(&key->email);
119 FREE(&key->hash);
120 FREE(&key->label);
121 FREE(&key->issuer);
122 FREE(&key);
123 }
124}
#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 131 of file smime.c.

132{
133 if (!key)
134 return NULL;
135
136 struct SmimeKey *copy = NULL;
137
138 copy = mutt_mem_calloc(1, sizeof(struct SmimeKey));
139 copy->email = mutt_str_dup(key->email);
140 copy->hash = mutt_str_dup(key->hash);
141 copy->label = mutt_str_dup(key->label);
142 copy->issuer = mutt_str_dup(key->issuer);
143 copy->trust = key->trust;
144 copy->flags = key->flags;
145
146 return copy;
147}
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
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 339 of file smime.c.

341{
343 mutt_debug(LL_DEBUG2, "%s\n", buf_string(buf));
344}
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:109
#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:68
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 368 of file smime.c.

373{
374 struct SmimeCommandContext cctx = { 0 };
375
376 if (!exp)
377 return (pid_t) -1;
378
379 cctx.fname = fname;
380 cctx.sig_fname = sig_fname;
381 cctx.key = key;
382 cctx.cryptalg = cryptalg;
383 cctx.digestalg = digestalg;
386
387 struct Buffer *cmd = buf_pool_get();
388 smime_command(cmd, &cctx, exp);
389
390 pid_t pid = filter_create_fd(buf_string(cmd), fp_smime_in, fp_smime_out, fp_smime_err,
391 fp_smime_infd, fp_smime_outfd, fp_smime_errfd, EnvList);
392 buf_pool_release(&cmd);
393 return pid;
394}
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:78
pid_t filter_create_fd(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, int fdin, int fdout, int fderr, char **envlist)
Run a command on a pipe (optionally connect stdin/stdout)
Definition: filter.c:62
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c: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:339
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 402 of file smime.c.

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

486{
487 char buf[1024] = { 0 };
488 struct SmimeKey *key = NULL, *results = NULL;
489 struct SmimeKey **results_end = &results;
490
491 struct Buffer *index_file = buf_pool_get();
492 const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
493 const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
494 buf_printf(index_file, "%s/.index",
495 only_public_key ? NONULL(c_smime_certificates) : NONULL(c_smime_keys));
496
497 FILE *fp = mutt_file_fopen(buf_string(index_file), "r");
498 if (!fp)
499 {
500 mutt_perror("%s", buf_string(index_file));
501 buf_pool_release(&index_file);
502 return NULL;
503 }
504 buf_pool_release(&index_file);
505
506 while (fgets(buf, sizeof(buf), fp))
507 {
508 if (((*search == '\0')) || mutt_istr_find(buf, search))
509 {
510 key = smime_parse_key(buf);
511 if (key)
512 {
513 *results_end = key;
514 results_end = &key->next;
515 }
516 }
517 }
518
519 mutt_file_fclose(&fp);
520
521 return results;
522}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:168
#define mutt_file_fclose(FP)
Definition: file.h:149
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:148
#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:521
static struct SmimeKey * smime_parse_key(char *buf)
Parse an SMIME key block.
Definition: smime.c:402
#define NONULL(x)
Definition: string2.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
+ 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 533 of file smime.c.

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

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

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

687{
688 struct SmimeKey *key = NULL;
689 struct Buffer *resp = buf_pool_get();
690
691 if (!prompt)
692 prompt = _("Enter keyID: ");
693
695
696 while (true)
697 {
698 buf_reset(resp);
699 if (mw_get_field(prompt, resp, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0)
700 {
701 goto done;
702 }
703
704 key = smime_get_key_by_str(buf_string(resp), abilities, only_public_key);
705 if (key)
706 goto done;
707
708 mutt_error(_("No matching keys found for \"%s\""), buf_string(resp));
709 }
710
711done:
712 buf_pool_release(&resp);
713 return key;
714}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:76
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:640
+ 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 723 of file smime.c.

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

847{
848 char email[256] = { 0 };
849 int rc = -1, count = 0;
850 pid_t pid;
851
852 FILE *fp_err = mutt_file_mkstemp();
853 if (!fp_err)
854 {
855 mutt_perror(_("Can't create temporary file"));
856 return 1;
857 }
858
859 FILE *fp_out = mutt_file_mkstemp();
860 if (!fp_out)
861 {
862 mutt_file_fclose(&fp_err);
863 mutt_perror(_("Can't create temporary file"));
864 return 1;
865 }
866
867 const struct Expando *c_smime_get_cert_email_command =
868 cs_subset_expando(NeoMutt->sub, "smime_get_cert_email_command");
869 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), certificate,
870 NULL, NULL, NULL, NULL, NULL, NULL, c_smime_get_cert_email_command);
871 if (pid == -1)
872 {
873 mutt_message(_("Error: unable to create OpenSSL subprocess"));
874 mutt_file_fclose(&fp_err);
875 mutt_file_fclose(&fp_out);
876 return 1;
877 }
878
879 filter_wait(pid);
880
881 fflush(fp_out);
882 rewind(fp_out);
883 fflush(fp_err);
884 rewind(fp_err);
885
886 while ((fgets(email, sizeof(email), fp_out)))
887 {
888 size_t len = mutt_str_len(email);
889 if (len && (email[len - 1] == '\n'))
890 email[len - 1] = '\0';
891 if (mutt_istr_startswith(email, mailbox))
892 rc = 1;
893
894 rc = (rc < 0) ? 0 : rc;
895 count++;
896 }
897
898 if (rc == -1)
899 {
900 mutt_endwin();
901 mutt_file_copy_stream(fp_err, stdout);
902 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
903 rc = 1;
904 }
905 else if (rc == 0)
906 {
907 rc = 1;
908 }
909 else
910 {
911 rc = 0;
912 }
913
914 if (copy && buffer && num)
915 {
916 (*num) = count;
917 *buffer = mutt_mem_calloc(count, sizeof(char *));
918 count = 0;
919
920 rewind(fp_out);
921 while ((fgets(email, sizeof(email), fp_out)))
922 {
923 size_t len = mutt_str_len(email);
924 if (len && (email[len - 1] == '\n'))
925 email[len - 1] = '\0';
926 (*buffer)[count] = mutt_mem_calloc(mutt_str_len(email) + 1, sizeof(char));
927 strncpy((*buffer)[count], email, mutt_str_len(email));
928 count++;
929 }
930 }
931 else if (copy)
932 {
933 rc = 2;
934 }
935
936 mutt_file_fclose(&fp_out);
937 mutt_file_fclose(&fp_err);
938
939 return rc;
940}
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
Definition: config_type.c:357
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:287
#define mutt_message(...)
Definition: logging2.h:91
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:220
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c: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:368
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 947 of file smime.c.

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

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

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

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

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

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

1695{
1696 const struct Expando *c_smime_decrypt_command = cs_subset_expando(NeoMutt->sub, "smime_decrypt_command");
1697 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1698 fp_smime_outfd, fp_smime_errfd, fname, NULL, NULL, NULL,
1700 NULL, c_smime_decrypt_command);
1701}
+ 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 1820 of file smime.c.

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

◆ SmimePass

char SmimePass[256]
static

Cached Smime Passphrase.

Definition at line 71 of file smime.c.

◆ SmimeExpTime

time_t SmimeExpTime = 0
static

Unix time when SmimePass expires.

Definition at line 73 of file smime.c.

◆ SmimeKeyToUse

struct Buffer SmimeKeyToUse = { 0 }
static

Smime key to use.

Definition at line 76 of file smime.c.

◆ SmimeCertToUse

struct Buffer SmimeCertToUse = { 0 }
static

Smime certificate to use.

Definition at line 78 of file smime.c.

◆ SmimeIntermediateToUse

struct Buffer SmimeIntermediateToUse = { 0 }
static

Smime intermediate certificate to use.

Definition at line 80 of file smime.c.