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

SMIME helper routines. More...

#include "config.h"
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include "private.h"
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "copy.h"
#include "crypt.h"
#include "cryptglue.h"
#include "format_flags.h"
#include "handler.h"
#include "mutt_logging.h"
#include "muttlib.h"
#include "smime.h"
+ Include dependency graph for smime.c:

Go to the source code of this file.

Data Structures

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

Functions

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

Variables

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

Detailed Description

SMIME helper routines.

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

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

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

Definition in file smime.c.

Function Documentation

◆ smime_init()

void smime_init ( void  )

Initialise smime globals.

Definition at line 87 of file smime.c.

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

98 {
102 }
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
+ Here is the call 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 108 of file smime.c.

109 {
110  if (!keylist)
111  return;
112 
113  struct SmimeKey *key = NULL;
114 
115  while (*keylist)
116  {
117  key = *keylist;
118  *keylist = (*keylist)->next;
119 
120  FREE(&key->email);
121  FREE(&key->hash);
122  FREE(&key->label);
123  FREE(&key->issuer);
124  FREE(&key);
125  }
126 }
#define FREE(x)
Definition: memory.h:40
An SIME key.
Definition: smime.h:44
char * hash
Definition: smime.h:46
struct SmimeKey * next
Definition: smime.h:51
char * issuer
Definition: smime.h:48
char * email
Definition: smime.h:45
char * label
Definition: smime.h:47
+ Here is the caller graph for this function:

◆ smime_copy_key()

static struct SmimeKey* smime_copy_key ( struct SmimeKey key)
static

Copy an SMIME key.

Parameters
keyKey to copy
Return values
ptrNewly allocated SMIME key

Definition at line 133 of file smime.c.

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

◆ smime_command()

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

Format an SMIME command string.

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

Definition at line 371 of file smime.c.

373 {
374  mutt_expando_format(buf, buflen, 0, buflen, NONULL(fmt), smime_command_format_str,
375  (intptr_t) cctx, MUTT_FORMAT_NO_FLAGS);
376  mutt_debug(LL_DEBUG2, "%s\n", buf);
377 }
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string -.
Definition: muttlib.c:776
static const char * smime_command_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format an SMIME command - Implements format_t -.
Definition: smime.c:215
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
#define NONULL(x)
Definition: string2.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_invoke()

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

Run an SMIME command.

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

Definition at line 401 of file smime.c.

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

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

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

◆ smime_get_key_by_hash()

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

Find a key by its hash.

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

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

Definition at line 564 of file smime.c.

565 {
566  struct SmimeKey *match = NULL;
567  struct SmimeKey *results = smime_get_candidates(hash, only_public_key);
568  for (struct SmimeKey *result = results; result; result = result->next)
569  {
570  if (mutt_istr_equal(hash, result->hash))
571  {
572  match = smime_copy_key(result);
573  break;
574  }
575  }
576 
577  smime_key_free(&results);
578 
579  return match;
580 }
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:796
static struct SmimeKey * smime_copy_key(struct SmimeKey *key)
Copy an SMIME key.
Definition: smime.c:133
static struct SmimeKey * smime_get_candidates(const char *search, bool only_public_key)
Find keys matching a string.
Definition: smime.c:516
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_get_key_by_addr()

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

Find an SIME key by address.

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

Definition at line 590 of file smime.c.

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

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

718 {
719  struct SmimeKey *key = NULL;
720  struct Buffer *resp = mutt_buffer_pool_get();
721 
722  if (!prompt)
723  prompt = _("Enter keyID: ");
724 
726 
727  while (true)
728  {
729  mutt_buffer_reset(resp);
730  if (mutt_buffer_get_field(prompt, resp, MUTT_COMP_NO_FLAGS, false, NULL, NULL, NULL) != 0)
731  {
732  goto done;
733  }
734 
735  key = smime_get_key_by_str(mutt_buffer_string(resp), abilities, only_public_key);
736  if (key)
737  goto done;
738 
739  mutt_error(_("No matching keys found for \"%s\""), mutt_buffer_string(resp));
740  }
741 
742 done:
744  return key;
745 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: curs_lib.c:337
#define mutt_error(...)
Definition: logging.h:87
#define _(a)
Definition: message.h:28
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:52
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
static struct SmimeKey * smime_get_key_by_str(const char *str, KeyFlags abilities, bool only_public_key)
Find an SMIME key by string.
Definition: smime.c:671
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getkeys()

static void getkeys ( char *  mailbox)
static

Get the keys for a mailbox.

Parameters
mailboxEmail address

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

Definition at line 754 of file smime.c.

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

◆ smime_handle_cert_email()

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

Process an email containing certificates.

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

Definition at line 877 of file smime.c.

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

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

◆ smime_extract_signer_certificate()

static char* smime_extract_signer_certificate ( const char *  infile)
static

Extract the signer's certificate.

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

Definition at line 1087 of file smime.c.

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

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

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

1494 {
1495  if (!md)
1496  return 0;
1497 
1498  char *micalg = NULL;
1499  if (mutt_istr_startswith(md, "sha"))
1500  {
1501  const size_t l = strlen(md) + 2;
1502  micalg = mutt_mem_malloc(l);
1503  snprintf(micalg, l, "sha-%s", md + 3);
1504  }
1505  else
1506  {
1507  micalg = mutt_str_dup(md);
1508  }
1509 
1510  return micalg;
1511 }
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_invoke_verify()

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

Use SMIME to verify a file.

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

Definition at line 1684 of file smime.c.

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

1714 {
1715  const char *const c_smime_decrypt_command = cs_subset_string(NeoMutt->sub, "smime_decrypt_command");
1716  return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1717  fp_smime_outfd, fp_smime_errfd, fname, NULL, NULL, NULL,
1719  mutt_buffer_string(&SmimeCertToUse), NULL, c_smime_decrypt_command);
1720 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_handle_entity()

static struct Body* smime_handle_entity ( struct Body m,
struct State s,
FILE *  fp_out_file 
)
static

Handle type application/pkcs7-mime.

Parameters
mBody to handle
sState to use
fp_out_fileFile for the result
Return values
ptrBody for parsed MIME part

This can either be a signed or an encrypted message.

Definition at line 1837 of file smime.c.

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

Variable Documentation

◆ SmimePass

char SmimePass[256]

Definition at line 77 of file smime.c.

◆ SmimeExpTime

time_t SmimeExpTime = 0

Definition at line 78 of file smime.c.

◆ SmimeKeyToUse

struct Buffer SmimeKeyToUse = { 0 }
static

Definition at line 78 of file smime.c.

◆ SmimeCertToUse

struct Buffer SmimeCertToUse = { 0 }
static

Definition at line 78 of file smime.c.

◆ SmimeIntermediateToUse

struct Buffer SmimeIntermediateToUse = { 0 }
static

Definition at line 78 of file smime.c.