NeoMutt  2021-10-29-43-g6b8931
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 (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:181
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

Definition at line 365 of file smime.c.

367 {
368  mutt_expando_format(buf, buflen, 0, buflen, NONULL(fmt), smime_command_format_str,
369  (intptr_t) cctx, MUTT_FORMAT_NO_FLAGS);
370  mutt_debug(LL_DEBUG2, "%s\n", buf);
371 }
#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:780
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:210
#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 395 of file smime.c.

400 {
401  struct SmimeCommandContext cctx = { 0 };
402  char cmd[STR_COMMAND];
403 
404  if (!format || (*format == '\0'))
405  return (pid_t) -1;
406 
407  cctx.fname = fname;
408  cctx.sig_fname = sig_fname;
409  cctx.key = key;
410  cctx.cryptalg = cryptalg;
411  cctx.digestalg = digestalg;
412  cctx.certificates = certificates;
414 
415  smime_command(cmd, sizeof(cmd), &cctx, format);
416 
417  return filter_create_fd(cmd, fp_smime_in, fp_smime_out, fp_smime_err,
418  fp_smime_infd, fp_smime_outfd, fp_smime_errfd);
419 }
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:365
#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 427 of file smime.c.

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

511 {
512  char buf[1024];
513  struct SmimeKey *key = NULL, *results = NULL;
514  struct SmimeKey **results_end = &results;
515 
516  struct Buffer *index_file = mutt_buffer_pool_get();
517  const char *const c_smime_certificates =
518  cs_subset_path(NeoMutt->sub, "smime_certificates");
519  const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
520  mutt_buffer_printf(index_file, "%s/.index",
521  only_public_key ? NONULL(c_smime_certificates) : NONULL(c_smime_keys));
522 
523  FILE *fp = mutt_file_fopen(mutt_buffer_string(index_file), "r");
524  if (!fp)
525  {
526  mutt_perror(mutt_buffer_string(index_file));
527  mutt_buffer_pool_release(&index_file);
528  return NULL;
529  }
530  mutt_buffer_pool_release(&index_file);
531 
532  while (fgets(buf, sizeof(buf), fp))
533  {
534  if (((*search == '\0')) || mutt_istr_find(buf, search))
535  {
536  key = smime_parse_key(buf);
537  if (key)
538  {
539  *results_end = key;
540  results_end = &key->next;
541  }
542  }
543  }
544 
545  mutt_file_fclose(&fp);
546 
547  return results;
548 }
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:153
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:593
#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: menu.c:142
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:500
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:427
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 559 of file smime.c.

560 {
561  struct SmimeKey *match = NULL;
562  struct SmimeKey *results = smime_get_candidates(hash, only_public_key);
563  for (struct SmimeKey *result = results; result; result = result->next)
564  {
565  if (mutt_istr_equal(hash, result->hash))
566  {
567  match = smime_copy_key(result);
568  break;
569  }
570  }
571 
572  smime_key_free(&results);
573 
574  return match;
575 }
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:727
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:510
+ 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 585 of file smime.c.

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

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

713 {
714  struct SmimeKey *key = NULL;
715  char resp[128];
716 
717  if (!prompt)
718  prompt = _("Enter keyID: ");
719 
721 
722  while (true)
723  {
724  resp[0] = '\0';
725  if (mutt_get_field(prompt, resp, sizeof(resp), MUTT_COMP_NO_FLAGS, false, NULL, NULL) != 0)
726  {
727  return NULL;
728  }
729 
730  key = smime_get_key_by_str(resp, abilities, only_public_key);
731  if (key)
732  return key;
733 
734  mutt_error(_("No matching keys found for \"%s\""), resp);
735  }
736 }
int mutt_get_field(const char *field, char *buf, size_t buflen, CompletionFlags complete, bool multiple, char ***files, int *numfiles)
Ask the user for a string.
Definition: curs_lib.c:335
#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:113
static struct SmimeKey * smime_get_key_by_str(char *str, KeyFlags abilities, bool only_public_key)
Find an SMIME key by string.
Definition: smime.c:666
+ 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 745 of file smime.c.

746 {
747  const char *k = NULL;
748 
749  struct SmimeKey *key = smime_get_key_by_addr(mailbox, KEYFLAG_CANENCRYPT, false, false);
750 
751  if (!key)
752  {
753  char buf[256];
754  snprintf(buf, sizeof(buf), _("Enter keyID for %s: "), mailbox);
755  key = smime_ask_for_key(buf, KEYFLAG_CANENCRYPT, false);
756  }
757 
758  const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
759  size_t smime_keys_len = mutt_str_len(c_smime_keys);
760 
761  const char *const c_smime_default_key =
762  cs_subset_string(NeoMutt->sub, "smime_default_key");
763  k = key ? key->hash : NONULL(c_smime_default_key);
764 
765  /* if the key is different from last time */
766  if ((mutt_buffer_len(&SmimeKeyToUse) <= smime_keys_len) ||
767  !mutt_istr_equal(k, SmimeKeyToUse.data + smime_keys_len + 1))
768  {
770  mutt_buffer_printf(&SmimeKeyToUse, "%s/%s", NONULL(c_smime_keys), k);
771  const char *const c_smime_certificates =
772  cs_subset_path(NeoMutt->sub, "smime_certificates");
773  mutt_buffer_printf(&SmimeCertToUse, "%s/%s", NONULL(c_smime_certificates), k);
774  }
775 
776  smime_key_free(&key);
777 }
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:475
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:585
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:712
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 873 of file smime.c.

875 {
876  char email[256];
877  int rc = -1, count = 0;
878  pid_t pid;
879 
880  FILE *fp_err = mutt_file_mkstemp();
881  if (!fp_err)
882  {
883  mutt_perror(_("Can't create temporary file"));
884  return 1;
885  }
886 
887  FILE *fp_out = mutt_file_mkstemp();
888  if (!fp_out)
889  {
890  mutt_file_fclose(&fp_err);
891  mutt_perror(_("Can't create temporary file"));
892  return 1;
893  }
894 
895  const char *const c_smime_get_cert_email_command =
896  cs_subset_string(NeoMutt->sub, "smime_get_cert_email_command");
897  pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), certificate,
898  NULL, NULL, NULL, NULL, NULL, NULL, c_smime_get_cert_email_command);
899  if (pid == -1)
900  {
901  mutt_message(_("Error: unable to create OpenSSL subprocess"));
902  mutt_file_fclose(&fp_err);
903  mutt_file_fclose(&fp_out);
904  return 1;
905  }
906 
907  filter_wait(pid);
908 
909  fflush(fp_out);
910  rewind(fp_out);
911  fflush(fp_err);
912  rewind(fp_err);
913 
914  while ((fgets(email, sizeof(email), fp_out)))
915  {
916  size_t len = mutt_str_len(email);
917  if (len && (email[len - 1] == '\n'))
918  email[len - 1] = '\0';
919  if (mutt_istr_startswith(email, mailbox))
920  rc = 1;
921 
922  rc = (rc < 0) ? 0 : rc;
923  count++;
924  }
925 
926  if (rc == -1)
927  {
928  mutt_endwin();
929  mutt_file_copy_stream(fp_err, stdout);
930  mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
931  rc = 1;
932  }
933  else if (rc == 0)
934  rc = 1;
935  else
936  rc = 0;
937 
938  if (copy && buffer && num)
939  {
940  (*num) = count;
941  *buffer = mutt_mem_calloc(count, sizeof(char *));
942  count = 0;
943 
944  rewind(fp_out);
945  while ((fgets(email, sizeof(email), fp_out)))
946  {
947  size_t len = mutt_str_len(email);
948  if (len && (email[len - 1] == '\n'))
949  email[len - 1] = '\0';
950  (*buffer)[count] = mutt_mem_calloc(mutt_str_len(email) + 1, sizeof(char));
951  strncpy((*buffer)[count], email, mutt_str_len(email));
952  count++;
953  }
954  }
955  else if (copy)
956  rc = 2;
957 
958  mutt_file_fclose(&fp_out);
959  mutt_file_fclose(&fp_err);
960 
961  return rc;
962 }
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:455
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:422
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
#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:170
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:395
+ 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 969 of file smime.c.

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

1087 {
1088  char *cert = NULL;
1089  struct Buffer *certfile = NULL;
1090  pid_t pid;
1091  int empty;
1092 
1093  FILE *fp_err = mutt_file_mkstemp();
1094  if (!fp_err)
1095  {
1096  mutt_perror(_("Can't create temporary file"));
1097  return NULL;
1098  }
1099 
1100  certfile = mutt_buffer_pool_get();
1101  mutt_buffer_mktemp(certfile);
1102  FILE *fp_out = mutt_file_fopen(mutt_buffer_string(certfile), "w+");
1103  if (!fp_out)
1104  {
1105  mutt_file_fclose(&fp_err);
1106  mutt_perror(mutt_buffer_string(certfile));
1107  goto cleanup;
1108  }
1109 
1110  /* Extract signer's certificate
1111  */
1112  const char *const c_smime_get_signer_cert_command =
1113  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 1310 of file smime.c.

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

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

1502 {
1503  if (!md)
1504  return 0;
1505 
1506  char *micalg = NULL;
1507  if (mutt_istr_startswith(md, "sha"))
1508  {
1509  const size_t l = strlen(md) + 2;
1510  micalg = mutt_mem_malloc(l);
1511  snprintf(micalg, l, "sha-%s", md + 3);
1512  }
1513  else
1514  {
1515  micalg = mutt_str_dup(md);
1516  }
1517 
1518  return micalg;
1519 }
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 1696 of file smime.c.

1700 {
1701  const char *const c_smime_verify_opaque_command =
1702  cs_subset_string(NeoMutt->sub, "smime_verify_opaque_command");
1703  const char *const c_smime_verify_command =
1704  cs_subset_string(NeoMutt->sub, "smime_verify_command");
1705  return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd, fp_smime_outfd,
1706  fp_smime_errfd, fname, sig_fname, NULL, NULL, NULL, NULL, NULL,
1707  (opaque ? c_smime_verify_opaque_command : c_smime_verify_command));
1708 }
+ 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 1725 of file smime.c.

1728 {
1729  const char *const c_smime_decrypt_command =
1730  cs_subset_string(NeoMutt->sub, "smime_decrypt_command");
1731  return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1732  fp_smime_outfd, fp_smime_errfd, fname, NULL, NULL, NULL,
1734  mutt_buffer_string(&SmimeCertToUse), NULL, c_smime_decrypt_command);
1735 }
+ 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 1852 of file smime.c.

1853 {
1854  struct Buffer tmpfname = mutt_buffer_make(0);
1855  FILE *fp_smime_out = NULL, *fp_smime_in = NULL, *fp_smime_err = NULL;
1856  FILE *fp_tmp = NULL, *fp_out = NULL;
1857  struct Body *p = NULL;
1858  pid_t pid = -1;
1860 
1861  if (!(type & APPLICATION_SMIME))
1862  return NULL;
1863 
1864  /* Because of the mutt_body_handler() we avoid the buffer pool. */
1865  fp_smime_out = mutt_file_mkstemp();
1866  if (!fp_smime_out)
1867  {
1868  mutt_perror(_("Can't create temporary file"));
1869  goto cleanup;
1870  }
1871 
1872  fp_smime_err = mutt_file_mkstemp();
1873  if (!fp_smime_err)
1874  {
1875  mutt_perror(_("Can't create temporary file"));
1876  goto cleanup;
1877  }
1878 
1879  mutt_buffer_mktemp(&tmpfname);
1880  fp_tmp = mutt_file_fopen(mutt_buffer_string(&tmpfname), "w+");
1881  if (!fp_tmp)
1882  {
1883  mutt_perror(mutt_buffer_string(&tmpfname));
1884  goto cleanup;
1885  }
1886 
1887  if (!mutt_file_seek(s->fp_in, m->offset, SEEK_SET))
1888  {
1889  goto cleanup;
1890  }
1891 
1892  mutt_file_copy_bytes(s->fp_in, fp_tmp, m->length);
1893 
1894  fflush(fp_tmp);
1895  mutt_file_fclose(&fp_tmp);
1896 
1897  if ((type & SEC_ENCRYPT) &&
1898  ((pid = smime_invoke_decrypt(&fp_smime_in, NULL, NULL, -1,
1899  fileno(fp_smime_out), fileno(fp_smime_err),
1900  mutt_buffer_string(&tmpfname))) == -1))
1901  {
1903  if (s->flags & MUTT_DISPLAY)
1904  {
1906  s, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1907  }
1908  goto cleanup;
1909  }
1910  else if ((type & SEC_SIGNOPAQUE) &&
1911  ((pid = smime_invoke_verify(
1912  &fp_smime_in, NULL, NULL, -1, fileno(fp_smime_out), fileno(fp_smime_err),
1913  NULL, mutt_buffer_string(&tmpfname), SEC_SIGNOPAQUE)) == -1))
1914  {
1916  if (s->flags & MUTT_DISPLAY)
1917  {
1919  s, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1920  }
1921  goto cleanup;
1922  }
1923 
1924  if (type & SEC_ENCRYPT)
1925  {
1928  fputs(SmimePass, fp_smime_in);
1929  fputc('\n', fp_smime_in);
1930  }
1931 
1932  mutt_file_fclose(&fp_smime_in);
1933 
1934  filter_wait(pid);
1936 
1937  if (s->flags & MUTT_DISPLAY)
1938  {
1939  fflush(fp_smime_err);
1940  rewind(fp_smime_err);
1941 
1942  const int c = fgetc(fp_smime_err);
1943  if (c != EOF)
1944  {
1945  ungetc(c, fp_smime_err);
1946 
1947  crypt_current_time(s, "OpenSSL");
1948  mutt_file_copy_stream(fp_smime_err, s->fp_out);
1949  state_attach_puts(s, _("[-- End of OpenSSL output --]\n\n"));
1950  }
1951 
1952  if (type & SEC_ENCRYPT)
1953  {
1955  _("[-- The following data is S/MIME encrypted --]\n"));
1956  }
1957  else
1958  state_attach_puts(s, _("[-- The following data is S/MIME signed --]\n"));
1959  }
1960 
1961  fflush(fp_smime_out);
1962  rewind(fp_smime_out);
1963 
1964  if (type & SEC_ENCRYPT)
1965  {
1966  /* void the passphrase, even if that wasn't the problem */
1967  if (fgetc(fp_smime_out) == EOF)
1968  {
1969  mutt_error(_("Decryption failed"));
1971  }
1972  rewind(fp_smime_out);
1973  }
1974 
1975  if (fp_out_file)
1976  fp_out = fp_out_file;
1977  else
1978  {
1979  fp_out = mutt_file_mkstemp();
1980  if (!fp_out)
1981  {
1982  mutt_perror(_("Can't create temporary file"));
1983  goto cleanup;
1984  }
1985  }
1986  char buf[8192];
1987  while (fgets(buf, sizeof(buf) - 1, fp_smime_out))
1988  {
1989  const size_t len = mutt_str_len(buf);
1990  if ((len > 1) && (buf[len - 2] == '\r'))
1991  {
1992  buf[len - 2] = '\n';
1993  buf[len - 1] = '\0';
1994  }
1995  fputs(buf, fp_out);
1996  }
1997  fflush(fp_out);
1998  rewind(fp_out);
1999 
2000  const long size = mutt_file_get_size_fp(fp_out);
2001  if (size == 0)
2002  {
2003  goto cleanup;
2004  }
2005  p = mutt_read_mime_header(fp_out, 0);
2006  if (p)
2007  {
2008  p->length = size - p->offset;
2009 
2010  mutt_parse_part(fp_out, p);
2011 
2012  if (s->flags & MUTT_DISPLAY)
2014 
2015  /* Store any protected headers in the parent so they can be
2016  * accessed for index updates after the handler recursion is done.
2017  * This is done before the handler to prevent a nested encrypted
2018  * handler from freeing the headers. */
2020  m->mime_headers = p->mime_headers;
2021  p->mime_headers = NULL;
2022 
2023  if (s->fp_out)
2024  {
2025  rewind(fp_out);
2026  FILE *fp_tmp_buffer = s->fp_in;
2027  s->fp_in = fp_out;
2028  mutt_body_handler(p, s);
2029  s->fp_in = fp_tmp_buffer;
2030  }
2031 
2032  /* Embedded multipart signed protected headers override the
2033  * encrypted headers. We need to do this after the handler so
2034  * they can be printed in the pager. */
2035  if (!(type & SMIME_SIGN) && mutt_is_multipart_signed(p) && p->parts &&
2036  p->parts->mime_headers)
2037  {
2039  m->mime_headers = p->parts->mime_headers;
2040  p->parts->mime_headers = NULL;
2041  }
2042  }
2043  mutt_file_fclose(&fp_smime_out);
2044 
2045  if (!fp_out_file)
2046  {
2047  mutt_file_fclose(&fp_out);
2049  }
2050  fp_out = NULL;
2051 
2052  if (s->flags & MUTT_DISPLAY)
2053  {
2054  if (type & SEC_ENCRYPT)
2055  state_attach_puts(s, _("\n[-- End of S/MIME encrypted data. --]\n"));
2056  else
2057  state_attach_puts(s, _("\n[-- End of S/MIME signed data. --]\n"));
2058  }
2059 
2060  if (type & SEC_SIGNOPAQUE)
2061  {
2062  char *line = NULL;
2063  size_t linelen;
2064 
2065  rewind(fp_smime_err);
2066 
2067  line = mutt_file_read_line(line, &linelen, fp_smime_err, NULL, MUTT_RL_NO_FLAGS);
2068  if (linelen && mutt_istr_equal(line, "verification successful"))
2069  m->goodsig = true;
2070  FREE(&line);
2071  }
2072  else if (p)
2073  {
2074  m->goodsig = p->goodsig;
2075  m->badsig = p->badsig;
2076  }
2077 
2078 cleanup:
2079  mutt_file_fclose(&fp_smime_out);
2080  mutt_file_fclose(&fp_smime_err);
2081  mutt_file_fclose(&fp_tmp);
2082  mutt_file_fclose(&fp_out);
2083  mutt_buffer_dealloc(&tmpfname);
2084  return p;
2085 }
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:414
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:617
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
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:241
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:695
long mutt_file_get_size_fp(FILE *fp)
Get the size of a file.
Definition: file.c:1544
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:665
#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:1121
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1600
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:71
#define SEC_SIGNOPAQUE
Email has an opaque signature (encrypted)
Definition: lib.h:80
#define SMIME_SIGN
Definition: lib.h:100
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:88
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:75
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1721
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1327
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:1696
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:1725
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:102
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
The body of an email.
Definition: body.h:35
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:71
LOFF_T offset
offset where the actual data begins
Definition: body.h:51
bool badsig
Bad cryptographic signature (needed to check encrypted s/mime-signatures)
Definition: body.h:42
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:74
LOFF_T length
length (in bytes) of attachment
Definition: body.h:52
bool goodsig
Good cryptographic signature.
Definition: body.h:44
unsigned int type
content-type primary type, ContentType
Definition: body.h:39
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
FILE * fp_out
File to write to.
Definition: state.h:47
FILE * fp_in
File to read from.
Definition: state.h:46
+ 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.