NeoMutt  2020-08-07-1-gab41a1
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 "ncrypt/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 "state.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 (char *search, bool only_public_key)
 Find keys matching a string. More...
 
static struct SmimeKeysmime_get_key_by_hash (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 (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 Mailbox *m, struct Email *e)
 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 (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...
 
int 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 }
static struct Buffer SmimeKeyToUse
Definition: smime.c:80
static struct Buffer SmimeIntermediateToUse
Definition: smime.c:82
static struct Buffer SmimeCertToUse
Definition: smime.c:81
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
+ 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 }
static struct Buffer SmimeKeyToUse
Definition: smime.c:80
static struct Buffer SmimeIntermediateToUse
Definition: smime.c:82
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
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_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 }
An SIME key.
Definition: smime.h:43
struct SmimeKey * next
Definition: smime.h:51
char * email
Definition: smime.h:45
char * label
Definition: smime.h:47
char * hash
Definition: smime.h:46
#define FREE(x)
Definition: memory.h:40
char * issuer
Definition: smime.h:48
+ 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
KeyFlags flags
Definition: smime.h:50
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
char trust
i=Invalid r=revoked e=expired u=unverified v=verified t=trusted
Definition: smime.h:49
An SIME key.
Definition: smime.h:43
char * email
Definition: smime.h:45
char * label
Definition: smime.h:47
char * hash
Definition: smime.h:46
char * issuer
Definition: smime.h:48
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_class_void_passphrase()

void smime_class_void_passphrase ( void  )

Implements CryptModuleSpecs::void_passphrase()

Definition at line 158 of file smime.c.

159 {
160  memset(SmimePass, 0, sizeof(SmimePass));
161  SmimeExpTime = 0;
162 }
char SmimePass[256]
Definition: smime.c:77
time_t SmimeExpTime
Definition: smime.c:78
+ Here is the caller graph for this function:

◆ smime_class_valid_passphrase()

bool smime_class_valid_passphrase ( void  )

Implements CryptModuleSpecs::valid_passphrase()

Definition at line 167 of file smime.c.

168 {
169  const time_t now = mutt_date_epoch();
170  if (now < SmimeExpTime)
171  {
172  /* Use cached copy. */
173  return true;
174  }
175 
177 
178  if (mutt_get_password(_("Enter S/MIME passphrase:"), SmimePass, sizeof(SmimePass)) == 0)
179  {
181  return true;
182  }
183  else
184  SmimeExpTime = 0;
185 
186  return false;
187 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:416
#define mutt_get_password(msg, buf, buflen)
Definition: curs_lib.h:92
#define _(a)
Definition: message.h:28
long C_SmimeTimeout
Config: Time in seconds to cache a passphrase.
Definition: config.c:104
time_t mutt_date_add_timeout(time_t now, time_t timeout)
Safely add a timeout to a given time_t value.
Definition: date.c:625
char SmimePass[256]
Definition: smime.c:77
void smime_class_void_passphrase(void)
Implements CryptModuleSpecs::void_passphrase()
Definition: smime.c:158
time_t SmimeExpTime
Definition: smime.c:78
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_command_format_str()

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 
)
static

Format an SMIME command - Implements format_t.

Expando Description
%a Algorithm used for encryption
%C CA location: Depending on whether $smime_ca_location points to a directory or file
%c One or more certificate IDs
%d Message digest algorithm specified with $smime_sign_digest_alg
%f File containing a message
%i Intermediate certificates
%k The key-pair specified with $smime_default_key
%s File containing the signature part of a multipart/signed attachment when verifying it

Definition at line 207 of file smime.c.

212 {
213  char fmt[128];
214  struct SmimeCommandContext *cctx = (struct SmimeCommandContext *) data;
215  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
216 
217  switch (op)
218  {
219  case 'C':
220  {
221  if (!optional)
222  {
223  struct Buffer *path = mutt_buffer_pool_get();
224  struct Buffer *buf1 = mutt_buffer_pool_get();
225  struct Buffer *buf2 = mutt_buffer_pool_get();
226  struct stat sb;
227 
230  mutt_buffer_quote_filename(buf1, mutt_b2s(path), true);
231 
232  if ((stat(mutt_b2s(path), &sb) != 0) || !S_ISDIR(sb.st_mode))
233  mutt_buffer_printf(buf2, "-CAfile %s", mutt_b2s(buf1));
234  else
235  mutt_buffer_printf(buf2, "-CApath %s", mutt_b2s(buf1));
236 
237  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
238  snprintf(buf, buflen, fmt, mutt_b2s(buf2));
239 
243  }
244  else if (!C_SmimeCaLocation)
245  optional = false;
246  break;
247  }
248 
249  case 'c':
250  { /* certificate (list) */
251  if (!optional)
252  {
253  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
254  snprintf(buf, buflen, fmt, NONULL(cctx->certificates));
255  }
256  else if (!cctx->certificates)
257  optional = false;
258  break;
259  }
260 
261  case 'i':
262  { /* intermediate certificates */
263  if (!optional)
264  {
265  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
266  snprintf(buf, buflen, fmt, NONULL(cctx->intermediates));
267  }
268  else if (!cctx->intermediates)
269  optional = false;
270  break;
271  }
272 
273  case 's':
274  { /* detached signature */
275  if (!optional)
276  {
277  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
278  snprintf(buf, buflen, fmt, NONULL(cctx->sig_fname));
279  }
280  else if (!cctx->sig_fname)
281  optional = false;
282  break;
283  }
284 
285  case 'k':
286  { /* private key */
287  if (!optional)
288  {
289  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
290  snprintf(buf, buflen, fmt, NONULL(cctx->key));
291  }
292  else if (!cctx->key)
293  optional = false;
294  break;
295  }
296 
297  case 'a':
298  { /* algorithm for encryption */
299  if (!optional)
300  {
301  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
302  snprintf(buf, buflen, fmt, NONULL(cctx->cryptalg));
303  }
304  else if (!cctx->key)
305  optional = false;
306  break;
307  }
308 
309  case 'f':
310  { /* file to process */
311  if (!optional)
312  {
313  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
314  snprintf(buf, buflen, fmt, NONULL(cctx->fname));
315  }
316  else if (!cctx->fname)
317  optional = false;
318  break;
319  }
320 
321  case 'd':
322  { /* algorithm for the signature message digest */
323  if (!optional)
324  {
325  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
326  snprintf(buf, buflen, fmt, NONULL(cctx->digestalg));
327  }
328  else if (!cctx->key)
329  optional = false;
330  break;
331  }
332 
333  default:
334  *buf = '\0';
335  break;
336  }
337 
338  if (optional)
339  {
340  mutt_expando_format(buf, buflen, col, cols, if_str,
342  }
343  else if (flags & MUTT_FORMAT_OPTIONAL)
344  {
345  mutt_expando_format(buf, buflen, col, cols, else_str,
347  }
348 
349  return src;
350 }
void mutt_buffer_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell&#39;s quoting rules.
Definition: file.c:836
const char * certificates
c
Definition: smime.c:73
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
static int const char * fmt
Definition: acutest.h:488
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
const char * sig_fname
s
Definition: smime.c:72
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:207
const char * digestalg
d
Definition: smime.c:70
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
Data for a SIME command.
Definition: smime.c:66
const char * fname
f
Definition: smime.c:71
const char * cryptalg
a
Definition: smime.c:69
#define mutt_b2s(buf)
Definition: buffer.h:41
char * C_SmimeCaLocation
Config: File containing trusted certificates.
Definition: config.c:91
const char * key
k
Definition: smime.c:68
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
const char * intermediates
i
Definition: smime.c:74
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:323
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:772
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
+ 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 359 of file smime.c.

361 {
362  mutt_expando_format(buf, buflen, 0, buflen, NONULL(fmt), smime_command_format_str,
363  (intptr_t) cctx, MUTT_FORMAT_NO_FLAGS);
364  mutt_debug(LL_DEBUG2, "%s\n", buf);
365 }
#define NONULL(x)
Definition: string2.h:37
static int const char * fmt
Definition: acutest.h:488
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:207
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
Log at debug level 2.
Definition: logging.h:41
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:772
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
+ 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 389 of file smime.c.

394 {
395  struct SmimeCommandContext cctx = { 0 };
396  char cmd[STR_COMMAND];
397 
398  if (!format || (*format == '\0'))
399  return (pid_t) -1;
400 
401  cctx.fname = fname;
402  cctx.sig_fname = sig_fname;
403  cctx.key = key;
404  cctx.cryptalg = cryptalg;
405  cctx.digestalg = digestalg;
406  cctx.certificates = certificates;
408 
409  smime_command(cmd, sizeof(cmd), &cctx, format);
410 
411  return filter_create_fd(cmd, fp_smime_in, fp_smime_out, fp_smime_err,
412  fp_smime_infd, fp_smime_outfd, fp_smime_errfd);
413 }
const char * certificates
c
Definition: smime.c:73
const char * sig_fname
s
Definition: smime.c:72
const char * digestalg
d
Definition: smime.c:70
Data for a SIME command.
Definition: smime.c:66
const char * fname
f
Definition: smime.c:71
const char * cryptalg
a
Definition: smime.c:69
const char * key
k
Definition: smime.c:68
const char * intermediates
i
Definition: smime.c:74
#define STR_COMMAND
Enough space for a long command line.
Definition: string2.h:35
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:359
+ 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 421 of file smime.c.

422 {
423  char *pend = NULL, *p = NULL;
424  int field = 0;
425 
426  struct SmimeKey *key = mutt_mem_calloc(1, sizeof(struct SmimeKey));
427 
428  for (p = buf; p; p = pend)
429  {
430  /* Some users manually maintain their .index file, and use a tab
431  * as a delimiter, which the old parsing code (using fscanf)
432  * happened to allow. smime_keys uses a space, so search for both. */
433  if ((pend = strchr(p, ' ')) || (pend = strchr(p, '\t')) || (pend = strchr(p, '\n')))
434  *pend++ = 0;
435 
436  /* For backward compatibility, don't count consecutive delimiters
437  * as an empty field. */
438  if (*p == '\0')
439  continue;
440 
441  field++;
442 
443  switch (field)
444  {
445  case 1: /* mailbox */
446  key->email = mutt_str_dup(p);
447  break;
448  case 2: /* hash */
449  key->hash = mutt_str_dup(p);
450  break;
451  case 3: /* label */
452  key->label = mutt_str_dup(p);
453  break;
454  case 4: /* issuer */
455  key->issuer = mutt_str_dup(p);
456  break;
457  case 5: /* trust */
458  key->trust = *p;
459  break;
460  case 6: /* purpose */
461  while (*p)
462  {
463  switch (*p++)
464  {
465  case 'e':
466  key->flags |= KEYFLAG_CANENCRYPT;
467  break;
468 
469  case 's':
470  key->flags |= KEYFLAG_CANSIGN;
471  break;
472  }
473  }
474  break;
475  }
476  }
477 
478  /* Old index files could be missing issuer, trust, and purpose,
479  * but anything less than that is an error. */
480  if (field < 3)
481  {
482  smime_key_free(&key);
483  return NULL;
484  }
485 
486  if (field < 4)
487  key->issuer = mutt_str_dup("?");
488 
489  if (field < 5)
490  key->trust = 't';
491 
492  if (field < 6)
494 
495  return key;
496 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
KeyFlags flags
Definition: smime.h:50
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
char trust
i=Invalid r=revoked e=expired u=unverified v=verified t=trusted
Definition: smime.h:49
An SIME key.
Definition: smime.h:43
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition: lib.h:135
static void smime_key_free(struct SmimeKey **keylist)
Free a list of SMIME keys.
Definition: smime.c:108
#define KEYFLAG_CANSIGN
Key is suitable for signing.
Definition: lib.h:134
char * email
Definition: smime.h:45
char * label
Definition: smime.h:47
char * hash
Definition: smime.h:46
char * issuer
Definition: smime.h:48
+ 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 ( 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 504 of file smime.c.

505 {
506  char buf[1024];
507  struct SmimeKey *key = NULL, *results = NULL;
508  struct SmimeKey **results_end = &results;
509 
510  struct Buffer *index_file = mutt_buffer_pool_get();
511  mutt_buffer_printf(index_file, "%s/.index",
512  only_public_key ? NONULL(C_SmimeCertificates) : NONULL(C_SmimeKeys));
513 
514  FILE *fp = mutt_file_fopen(mutt_b2s(index_file), "r");
515  if (!fp)
516  {
517  mutt_perror(mutt_b2s(index_file));
518  mutt_buffer_pool_release(&index_file);
519  return NULL;
520  }
521  mutt_buffer_pool_release(&index_file);
522 
523  while (fgets(buf, sizeof(buf), fp))
524  {
525  if (((*search == '\0')) || mutt_istr_find(buf, search))
526  {
527  key = smime_parse_key(buf);
528  if (key)
529  {
530  *results_end = key;
531  results_end = &key->next;
532  }
533  }
534  }
535 
536  mutt_file_fclose(&fp);
537 
538  return results;
539 }
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
An SIME key.
Definition: smime.h:43
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
char * C_SmimeKeys
Config: File containing user&#39;s private certificates.
Definition: config.c:100
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define mutt_b2s(buf)
Definition: buffer.h:41
static struct SmimeKey * smime_parse_key(char *buf)
Parse an SMIME key block.
Definition: smime.c:421
char * C_SmimeCertificates
Config: File containing user&#39;s public certificates.
Definition: config.c:92
struct SmimeKey * next
Definition: smime.h:51
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:661
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
+ 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 ( 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 550 of file smime.c.

551 {
552  struct SmimeKey *match = NULL;
553  struct SmimeKey *results = smime_get_candidates(hash, only_public_key);
554  for (struct SmimeKey *result = results; result; result = result->next)
555  {
556  if (mutt_istr_equal(hash, result->hash))
557  {
558  match = smime_copy_key(result);
559  break;
560  }
561  }
562 
563  smime_key_free(&results);
564 
565  return match;
566 }
An SIME key.
Definition: smime.h:43
static struct SmimeKey * smime_copy_key(struct SmimeKey *key)
Copy an SMIME key.
Definition: smime.c:133
static void smime_key_free(struct SmimeKey **keylist)
Free a list of SMIME keys.
Definition: smime.c:108
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
struct SmimeKey * next
Definition: smime.h:51
char * hash
Definition: smime.h:46
static struct SmimeKey * smime_get_candidates(char *search, bool only_public_key)
Find keys matching a string.
Definition: smime.c:504
+ 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 576 of file smime.c.

578 {
579  if (!mailbox)
580  return NULL;
581 
582  struct SmimeKey *results = NULL, *result = NULL;
583  struct SmimeKey *matches = NULL;
584  struct SmimeKey **matches_end = &matches;
585  struct SmimeKey *match = NULL;
586  struct SmimeKey *trusted_match = NULL;
587  struct SmimeKey *valid_match = NULL;
588  struct SmimeKey *return_key = NULL;
589  bool multi_trusted_matches = false;
590 
591  results = smime_get_candidates(mailbox, only_public_key);
592  for (result = results; result; result = result->next)
593  {
594  if (abilities && !(result->flags & abilities))
595  {
596  continue;
597  }
598 
599  if (mutt_istr_equal(mailbox, result->email))
600  {
601  match = smime_copy_key(result);
602  *matches_end = match;
603  matches_end = &match->next;
604 
605  if (match->trust == 't')
606  {
607  if (trusted_match && !mutt_istr_equal(match->hash, trusted_match->hash))
608  {
609  multi_trusted_matches = true;
610  }
611  trusted_match = match;
612  }
613  else if ((match->trust == 'u') || (match->trust == 'v'))
614  {
615  valid_match = match;
616  }
617  }
618  }
619 
620  smime_key_free(&results);
621 
622  if (matches)
623  {
624  if (oppenc_mode)
625  {
626  if (trusted_match)
627  return_key = smime_copy_key(trusted_match);
628  else if (valid_match && !C_CryptOpportunisticEncryptStrongKeys)
629  return_key = smime_copy_key(valid_match);
630  else
631  return_key = NULL;
632  }
633  else if (trusted_match && !multi_trusted_matches)
634  {
635  return_key = smime_copy_key(trusted_match);
636  }
637  else
638  {
639  return_key = smime_copy_key(dlg_select_smime_key(matches, mailbox));
640  }
641 
642  smime_key_free(&matches);
643  }
644 
645  return return_key;
646 }
char trust
i=Invalid r=revoked e=expired u=unverified v=verified t=trusted
Definition: smime.h:49
An SIME key.
Definition: smime.h:43
bool C_CryptOpportunisticEncryptStrongKeys
Config: Enable encryption only when strong a key is available.
Definition: config.c:42
static struct SmimeKey * smime_copy_key(struct SmimeKey *key)
Copy an SMIME key.
Definition: smime.c:133
static void smime_key_free(struct SmimeKey **keylist)
Free a list of SMIME keys.
Definition: smime.c:108
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
struct SmimeKey * next
Definition: smime.h:51
struct SmimeKey * dlg_select_smime_key(struct SmimeKey *keys, char *query)
Get the user to select a key.
Definition: dlgsmime.c:156
char * hash
Definition: smime.h:46
static struct SmimeKey * smime_get_candidates(char *search, bool only_public_key)
Find keys matching a string.
Definition: smime.c:504
+ 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 655 of file smime.c.

656 {
657  if (!str)
658  return NULL;
659 
660  struct SmimeKey *results = NULL, *result = NULL;
661  struct SmimeKey *matches = NULL;
662  struct SmimeKey **matches_end = &matches;
663  struct SmimeKey *match = NULL;
664  struct SmimeKey *return_key = NULL;
665 
666  results = smime_get_candidates(str, only_public_key);
667  for (result = results; result; result = result->next)
668  {
669  if (abilities && !(result->flags & abilities))
670  {
671  continue;
672  }
673 
674  if (mutt_istr_equal(str, result->hash) ||
675  mutt_istr_find(result->email, str) || mutt_istr_find(result->label, str))
676  {
677  match = smime_copy_key(result);
678  *matches_end = match;
679  matches_end = &match->next;
680  }
681  }
682 
683  smime_key_free(&results);
684 
685  if (matches)
686  {
687  return_key = smime_copy_key(dlg_select_smime_key(matches, str));
688  smime_key_free(&matches);
689  }
690 
691  return return_key;
692 }
An SIME key.
Definition: smime.h:43
static struct SmimeKey * smime_copy_key(struct SmimeKey *key)
Copy an SMIME key.
Definition: smime.c:133
static void smime_key_free(struct SmimeKey **keylist)
Free a list of SMIME keys.
Definition: smime.c:108
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
struct SmimeKey * next
Definition: smime.h:51
struct SmimeKey * dlg_select_smime_key(struct SmimeKey *keys, char *query)
Get the user to select a key.
Definition: dlgsmime.c:156
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:661
static struct SmimeKey * smime_get_candidates(char *search, bool only_public_key)
Find keys matching a string.
Definition: smime.c:504
+ 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 701 of file smime.c.

702 {
703  struct SmimeKey *key = NULL;
704  char resp[128];
705 
706  if (!prompt)
707  prompt = _("Enter keyID: ");
708 
710 
711  while (true)
712  {
713  resp[0] = '\0';
714  if (mutt_get_field(prompt, resp, sizeof(resp), MUTT_COMP_NO_FLAGS) != 0)
715  return NULL;
716 
717  key = smime_get_key_by_str(resp, abilities, only_public_key);
718  if (key)
719  return key;
720 
721  mutt_error(_("No matching keys found for \"%s\""), resp);
722  }
723 }
#define _(a)
Definition: message.h:28
An SIME key.
Definition: smime.h:43
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:91
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c: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:655
#define mutt_error(...)
Definition: logging.h:84
+ 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 C_SmimeDefaultKey.

Definition at line 732 of file smime.c.

733 {
734  const char *k = NULL;
735 
736  struct SmimeKey *key = smime_get_key_by_addr(mailbox, KEYFLAG_CANENCRYPT, false, false);
737 
738  if (!key)
739  {
740  char buf[256];
741  snprintf(buf, sizeof(buf), _("Enter keyID for %s: "), mailbox);
742  key = smime_ask_for_key(buf, KEYFLAG_CANENCRYPT, false);
743  }
744 
745  size_t smime_keys_len = mutt_str_len(C_SmimeKeys);
746 
747  k = key ? key->hash : NONULL(C_SmimeDefaultKey);
748 
749  /* if the key is different from last time */
750  if ((mutt_buffer_len(&SmimeKeyToUse) <= smime_keys_len) ||
751  !mutt_istr_equal(k, SmimeKeyToUse.data + smime_keys_len + 1))
752  {
756  }
757 
758  smime_key_free(&key);
759 }
static struct Buffer SmimeKeyToUse
Definition: smime.c:80
#define NONULL(x)
Definition: string2.h:37
#define _(a)
Definition: message.h:28
An SIME key.
Definition: smime.h:43
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition: lib.h:135
static void smime_key_free(struct SmimeKey **keylist)
Free a list of SMIME keys.
Definition: smime.c:108
char * C_SmimeKeys
Config: File containing user&#39;s private certificates.
Definition: config.c:100
static struct Buffer SmimeCertToUse
Definition: smime.c:81
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:701
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
char * C_SmimeCertificates
Config: File containing user&#39;s public certificates.
Definition: config.c:92
char * data
Pointer to data.
Definition: buffer.h:35
void smime_class_void_passphrase(void)
Implements CryptModuleSpecs::void_passphrase()
Definition: smime.c:158
char * C_SmimeDefaultKey
Config: Default key for SMIME operations.
Definition: config.c:54
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
char * hash
Definition: smime.h:46
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:576
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_class_getkeys()

void smime_class_getkeys ( struct Envelope env)

Implements CryptModuleSpecs::smime_getkeys()

Definition at line 764 of file smime.c.

765 {
767  {
770  return;
771  }
772 
773  struct Address *a = NULL;
774  TAILQ_FOREACH(a, &env->to, entries)
775  {
776  if (mutt_addr_is_user(a))
777  {
778  getkeys(a->mailbox);
779  return;
780  }
781  }
782 
783  TAILQ_FOREACH(a, &env->cc, entries)
784  {
785  if (mutt_addr_is_user(a))
786  {
787  getkeys(a->mailbox);
788  return;
789  }
790  }
791 
792  struct Address *f = mutt_default_from(NeoMutt->sub);
793  getkeys(f->mailbox);
794  mutt_addr_free(&f);
795 }
static struct Buffer SmimeKeyToUse
Definition: smime.c:80
#define NONULL(x)
Definition: string2.h:37
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:440
Container for Accounts, Notifications.
Definition: neomutt.h:36
char * C_SmimeKeys
Config: File containing user&#39;s private certificates.
Definition: config.c:100
static void getkeys(char *mailbox)
Get the keys for a mailbox.
Definition: smime.c:732
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
static struct Buffer SmimeCertToUse
Definition: smime.c:81
struct Address * mutt_default_from(struct ConfigSubset *sub)
Get a default &#39;from&#39; Address.
Definition: send.c:1323
char * C_SmimeCertificates
Config: File containing user&#39;s public certificates.
Definition: config.c:92
char * C_SmimeDefaultKey
Config: Default key for SMIME operations.
Definition: config.c:54
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:544
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
bool C_SmimeDecryptUseDefaultKey
Config: Use the default key for decryption.
Definition: config.c:94
+ Here is the call graph for this function:

◆ smime_class_find_keys()

char* smime_class_find_keys ( struct AddressList *  al,
bool  oppenc_mode 
)

Implements CryptModuleSpecs::find_keys()

Definition at line 800 of file smime.c.

801 {
802  struct SmimeKey *key = NULL;
803  char *keyid = NULL, *keylist = NULL;
804  size_t keylist_size = 0;
805  size_t keylist_used = 0;
806 
807  struct Address *a = NULL;
808  TAILQ_FOREACH(a, al, entries)
809  {
810  key = smime_get_key_by_addr(a->mailbox, KEYFLAG_CANENCRYPT, true, oppenc_mode);
811  if (!key && !oppenc_mode)
812  {
813  char buf[1024];
814  snprintf(buf, sizeof(buf), _("Enter keyID for %s: "), a->mailbox);
815  key = smime_ask_for_key(buf, KEYFLAG_CANENCRYPT, true);
816  }
817  if (!key)
818  {
819  if (!oppenc_mode)
820  mutt_message(_("No (valid) certificate found for %s"), a->mailbox);
821  FREE(&keylist);
822  return NULL;
823  }
824 
825  keyid = key->hash;
826  keylist_size += mutt_str_len(keyid) + 2;
827  mutt_mem_realloc(&keylist, keylist_size);
828  sprintf(keylist + keylist_used, "%s%s", keylist_used ? " " : "", keyid);
829  keylist_used = mutt_str_len(keylist);
830 
831  smime_key_free(&key);
832  }
833  return keylist;
834 }
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
#define mutt_message(...)
Definition: logging.h:83
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
An SIME key.
Definition: smime.h:43
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition: lib.h:135
static void smime_key_free(struct SmimeKey **keylist)
Free a list of SMIME keys.
Definition: smime.c:108
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:701
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
char * hash
Definition: smime.h:46
#define FREE(x)
Definition: memory.h:40
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:576
+ Here is the call 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 847 of file smime.c.

849 {
850  char email[256];
851  int rc = -1, count = 0;
852  pid_t pid;
853 
854  FILE *fp_err = mutt_file_mkstemp();
855  if (!fp_err)
856  {
857  mutt_perror(_("Can't create temporary file"));
858  return 1;
859  }
860 
861  FILE *fp_out = mutt_file_mkstemp();
862  if (!fp_out)
863  {
864  mutt_file_fclose(&fp_err);
865  mutt_perror(_("Can't create temporary file"));
866  return 1;
867  }
868 
869  pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), certificate,
870  NULL, NULL, NULL, NULL, NULL, NULL, C_SmimeGetCertEmailCommand);
871  if (pid == -1)
872  {
873  mutt_message(_("Error: unable to create OpenSSL subprocess"));
874  mutt_file_fclose(&fp_err);
875  mutt_file_fclose(&fp_out);
876  return 1;
877  }
878 
879  filter_wait(pid);
880 
881  fflush(fp_out);
882  rewind(fp_out);
883  fflush(fp_err);
884  rewind(fp_err);
885 
886  while ((fgets(email, sizeof(email), fp_out)))
887  {
888  size_t len = mutt_str_len(email);
889  if (len && (email[len - 1] == '\n'))
890  email[len - 1] = '\0';
891  if (mutt_istr_startswith(email, mailbox))
892  rc = 1;
893 
894  rc = (rc < 0) ? 0 : rc;
895  count++;
896  }
897 
898  if (rc == -1)
899  {
900  mutt_endwin();
901  mutt_file_copy_stream(fp_err, stdout);
902  mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
903  rc = 1;
904  }
905  else if (rc == 0)
906  rc = 1;
907  else
908  rc = 0;
909 
910  if (copy && buffer && num)
911  {
912  (*num) = count;
913  *buffer = mutt_mem_calloc(count, sizeof(char *));
914  count = 0;
915 
916  rewind(fp_out);
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  (*buffer)[count] = mutt_mem_calloc(mutt_str_len(email) + 1, sizeof(char));
923  strncpy((*buffer)[count], email, mutt_str_len(email));
924  count++;
925  }
926  }
927  else if (copy)
928  rc = 2;
929 
930  mutt_file_fclose(&fp_out);
931  mutt_file_fclose(&fp_err);
932 
933  return rc;
934 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define mutt_perror(...)
Definition: logging.h:85
#define mutt_message(...)
Definition: logging.h:83
#define _(a)
Definition: message.h:28
char * mailbox
Mailbox and host address.
Definition: address.h:37
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
static int const char char buffer[256]
Definition: acutest.h:489
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:571
#define mutt_file_mkstemp()
Definition: file.h:106
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:389
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:177
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:604
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
char * C_SmimeGetCertEmailCommand
Config: (smime) External command to get a certificate for an email.
Definition: config.c:97
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
+ 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 941 of file smime.c.

942 {
943  FILE *fp_err = NULL;
944  FILE *fp_out = NULL;
945  FILE *fp_cert = NULL;
946  char *retval = NULL;
947  pid_t pid;
948  int empty;
949 
950  struct Buffer *pk7out = mutt_buffer_pool_get();
951  struct Buffer *certfile = mutt_buffer_pool_get();
952 
953  fp_err = mutt_file_mkstemp();
954  if (!fp_err)
955  {
956  mutt_perror(_("Can't create temporary file"));
957  goto cleanup;
958  }
959 
960  mutt_buffer_mktemp(pk7out);
961  fp_out = mutt_file_fopen(mutt_b2s(pk7out), "w+");
962  if (!fp_out)
963  {
964  mutt_perror(mutt_b2s(pk7out));
965  goto cleanup;
966  }
967 
968  /* Step 1: Convert the signature to a PKCS#7 structure, as we can't
969  * extract the full set of certificates directly. */
970  pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), infile,
971  NULL, NULL, NULL, NULL, NULL, NULL, C_SmimePk7outCommand);
972  if (pid == -1)
973  {
974  mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
975  goto cleanup;
976  }
977 
978  filter_wait(pid);
979 
980  fflush(fp_out);
981  rewind(fp_out);
982  fflush(fp_err);
983  rewind(fp_err);
984  empty = (fgetc(fp_out) == EOF);
985  if (empty)
986  {
987  mutt_perror(mutt_b2s(pk7out));
988  mutt_file_copy_stream(fp_err, stdout);
989  goto cleanup;
990  }
991  mutt_file_fclose(&fp_out);
992 
993  mutt_buffer_mktemp(certfile);
994  fp_cert = mutt_file_fopen(mutt_b2s(certfile), "w+");
995  if (!fp_cert)
996  {
997  mutt_perror(mutt_b2s(certfile));
998  mutt_file_unlink(mutt_b2s(pk7out));
999  goto cleanup;
1000  }
1001 
1002  // Step 2: Extract the certificates from a PKCS#7 structure.
1003  pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_cert), fileno(fp_err),
1004  mutt_b2s(pk7out), NULL, NULL, NULL, NULL, NULL, NULL,
1006  if (pid == -1)
1007  {
1008  mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
1009  mutt_file_unlink(mutt_b2s(pk7out));
1010  goto cleanup;
1011  }
1012 
1013  filter_wait(pid);
1014 
1015  mutt_file_unlink(mutt_b2s(pk7out));
1016 
1017  fflush(fp_cert);
1018  rewind(fp_cert);
1019  fflush(fp_err);
1020  rewind(fp_err);
1021  empty = (fgetc(fp_cert) == EOF);
1022  if (empty)
1023  {
1024  mutt_file_copy_stream(fp_err, stdout);
1025  goto cleanup;
1026  }
1027 
1028  mutt_file_fclose(&fp_cert);
1029 
1030  retval = mutt_buffer_strdup(certfile);
1031 
1032 cleanup:
1033  mutt_file_fclose(&fp_err);
1034  if (fp_out)
1035  {
1036  mutt_file_fclose(&fp_out);
1037  mutt_file_unlink(mutt_b2s(pk7out));
1038  }
1039  if (fp_cert)
1040  {
1041  mutt_file_fclose(&fp_cert);
1042  mutt_file_unlink(mutt_b2s(certfile));
1043  }
1044  mutt_buffer_pool_release(&pk7out);
1045  mutt_buffer_pool_release(&certfile);
1046  return retval;
1047 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
char * C_SmimePk7outCommand
Config: (smime) External command to extract a public certificate.
Definition: config.c:101
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define mutt_b2s(buf)
Definition: buffer.h:41
#define mutt_file_mkstemp()
Definition: file.h:106
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:389
char * C_SmimeGetCertCommand
Config: (smime) External command to extract a certificate from a message.
Definition: config.c:96
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:604
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
+ 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 1054 of file smime.c.

1055 {
1056  char *cert = NULL;
1057  struct Buffer *certfile = NULL;
1058  pid_t pid;
1059  int empty;
1060 
1061  FILE *fp_err = mutt_file_mkstemp();
1062  if (!fp_err)
1063  {
1064  mutt_perror(_("Can't create temporary file"));
1065  return NULL;
1066  }
1067 
1068  certfile = mutt_buffer_pool_get();
1069  mutt_buffer_mktemp(certfile);
1070  FILE *fp_out = mutt_file_fopen(mutt_b2s(certfile), "w+");
1071  if (!fp_out)
1072  {
1073  mutt_file_fclose(&fp_err);
1074  mutt_perror(mutt_b2s(certfile));
1075  goto cleanup;
1076  }
1077 
1078  /* Extract signer's certificate
1079  */
1080  pid = smime_invoke(NULL, NULL, NULL, -1, -1, fileno(fp_err), infile, NULL, NULL, NULL,
1081  NULL, mutt_b2s(certfile), NULL, C_SmimeGetSignerCertCommand);
1082  if (pid == -1)
1083  {
1084  mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
1085  goto cleanup;
1086  }
1087 
1088  filter_wait(pid);
1089 
1090  fflush(fp_out);
1091  rewind(fp_out);
1092  fflush(fp_err);
1093  rewind(fp_err);
1094  empty = (fgetc(fp_out) == EOF);
1095  if (empty)
1096  {
1097  mutt_endwin();
1098  mutt_file_copy_stream(fp_err, stdout);
1100  goto cleanup;
1101  }
1102 
1103  mutt_file_fclose(&fp_out);
1104  cert = mutt_buffer_strdup(certfile);
1105 
1106 cleanup:
1107  mutt_file_fclose(&fp_err);
1108  if (fp_out)
1109  {
1110  mutt_file_fclose(&fp_out);
1111  mutt_file_unlink(mutt_b2s(certfile));
1112  }
1113  mutt_buffer_pool_release(&certfile);
1114  return cert;
1115 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
char * C_SmimeGetSignerCertCommand
Config: (smime) External command to extract a certificate from an email.
Definition: config.c:98
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define mutt_b2s(buf)
Definition: buffer.h:41
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:571
#define mutt_file_mkstemp()
Definition: file.h:106
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:389
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:604
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_class_invoke_import()

void smime_class_invoke_import ( const char *  infile,
const char *  mailbox 
)

Implements CryptModuleSpecs::smime_invoke_import()

Definition at line 1120 of file smime.c.

1121 {
1122  char *certfile = NULL;
1123  char buf[256];
1124  FILE *fp_smime_in = NULL;
1125 
1126  FILE *fp_err = mutt_file_mkstemp();
1127  if (!fp_err)
1128  {
1129  mutt_perror(_("Can't create temporary file"));
1130  return;
1131  }
1132 
1133  FILE *fp_out = mutt_file_mkstemp();
1134  if (!fp_out)
1135  {
1136  mutt_file_fclose(&fp_err);
1137  mutt_perror(_("Can't create temporary file"));
1138  return;
1139  }
1140 
1141  buf[0] = '\0';
1142  if (C_SmimeAskCertLabel)
1143  {
1144  if ((mutt_get_field(_("Label for certificate: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0) ||
1145  (buf[0] == '\0'))
1146  {
1147  mutt_file_fclose(&fp_out);
1148  mutt_file_fclose(&fp_err);
1149  return;
1150  }
1151  }
1152 
1153  mutt_endwin();
1154  certfile = smime_extract_certificate(infile);
1155  if (certfile)
1156  {
1157  mutt_endwin();
1158 
1159  pid_t pid = smime_invoke(&fp_smime_in, NULL, NULL, -1, fileno(fp_out),
1160  fileno(fp_err), certfile, NULL, NULL, NULL, NULL,
1161  NULL, NULL, C_SmimeImportCertCommand);
1162  if (pid == -1)
1163  {
1164  mutt_message(_("Error: unable to create OpenSSL subprocess"));
1165  return;
1166  }
1167  fputs(buf, fp_smime_in);
1168  fputc('\n', fp_smime_in);
1169  mutt_file_fclose(&fp_smime_in);
1170 
1171  filter_wait(pid);
1172 
1173  mutt_file_unlink(certfile);
1174  FREE(&certfile);
1175  }
1176 
1177  fflush(fp_out);
1178  rewind(fp_out);
1179  fflush(fp_err);
1180  rewind(fp_err);
1181 
1182  mutt_file_copy_stream(fp_out, stdout);
1183  mutt_file_copy_stream(fp_err, stdout);
1184 
1185  mutt_file_fclose(&fp_out);
1186  mutt_file_fclose(&fp_err);
1187 }
#define mutt_perror(...)
Definition: logging.h:85
#define mutt_message(...)
Definition: logging.h:83
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
#define _(a)
Definition: message.h:28
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:91
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:571
bool C_SmimeAskCertLabel
Config: Prompt the user for a label for SMIME certificates.
Definition: config.c:90
char * C_SmimeImportCertCommand
Config: (smime) External command to import a certificate.
Definition: config.c:99
#define mutt_file_mkstemp()
Definition: file.h:106
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:389
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
#define FREE(x)
Definition: memory.h:40
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
static char * smime_extract_certificate(const char *infile)
Extract an SMIME certificate from a file.
Definition: smime.c:941
+ Here is the call graph for this function:

◆ smime_class_verify_sender()

int smime_class_verify_sender ( struct Mailbox m,
struct Email e 
)

Implements CryptModuleSpecs::smime_verify_sender()

Definition at line 1192 of file smime.c.

1193 {
1194  char *mbox = NULL, *certfile = NULL;
1195  int rc = 1;
1196 
1197  struct Buffer *tempfname = mutt_buffer_pool_get();
1198  mutt_buffer_mktemp(tempfname);
1199  FILE *fp_out = mutt_file_fopen(mutt_b2s(tempfname), "w");
1200  if (!fp_out)
1201  {
1202  mutt_perror(mutt_b2s(tempfname));
1203  goto cleanup;
1204  }
1205 
1206  if (e->security & SEC_ENCRYPT)
1207  {
1209  CH_MIME | CH_WEED | CH_NONEWLINE, 0);
1210  }
1211  else
1212  mutt_copy_message(fp_out, m, e, MUTT_CM_NO_FLAGS, CH_NO_FLAGS, 0);
1213 
1214  fflush(fp_out);
1215  mutt_file_fclose(&fp_out);
1216 
1217  if (!TAILQ_EMPTY(&e->env->from))
1218  {
1220  mbox = TAILQ_FIRST(&e->env->from)->mailbox;
1221  }
1222  else if (!TAILQ_EMPTY(&e->env->sender))
1223  {
1225  mbox = TAILQ_FIRST(&e->env->sender)->mailbox;
1226  }
1227 
1228  if (mbox)
1229  {
1230  certfile = smime_extract_signer_certificate(mutt_b2s(tempfname));
1231  if (certfile)
1232  {
1233  mutt_file_unlink(mutt_b2s(tempfname));
1234  if (smime_handle_cert_email(certfile, mbox, false, NULL, NULL))
1235  {
1236  if (isendwin())
1238  }
1239  else
1240  rc = 0;
1241  mutt_file_unlink(certfile);
1242  FREE(&certfile);
1243  }
1244  else
1245  mutt_any_key_to_continue(_("no certfile"));
1246  }
1247  else
1248  mutt_any_key_to_continue(_("no mbox"));
1249 
1250  mutt_file_unlink(mutt_b2s(tempfname));
1251 
1252 cleanup:
1253  mutt_buffer_pool_release(&tempfname);
1254  return rc;
1255 }
#define MUTT_CM_DECODE_CRYPT
Definition: copy.h:47
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
#define CH_MIME
Ignore MIME fields.
Definition: copy.h:60
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:294
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define TAILQ_FIRST(head)
Definition: queue.h:716
#define mutt_perror(...)
Definition: logging.h:85
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:85
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
String manipulation buffer.
Definition: buffer.h:33
int mutt_copy_message(FILE *fp_out, struct Mailbox *m, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Copy a message from a Mailbox.
Definition: copy.c:830
#define _(a)
Definition: message.h:28
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:34
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
#define CH_WEED
Weed the headers?
Definition: copy.h:52
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Envelope * env
Envelope information.
Definition: email.h:90
static int smime_handle_cert_email(char *certificate, char *mailbox, bool copy, char ***buffer, int *num)
Process an email containing certificates.
Definition: smime.c:847
#define mutt_b2s(buf)
Definition: buffer.h:41
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:50
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
#define MUTT_CM_DECODE_SMIME
Used for decoding S/MIME messages.
Definition: copy.h:45
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:604
static char * smime_extract_signer_certificate(const char *infile)
Extract the signer&#39;s certificate.
Definition: smime.c:1054
#define FREE(x)
Definition: memory.h:40
struct AddressList sender
Email&#39;s sender.
Definition: envelope.h:61
#define TAILQ_EMPTY(head)
Definition: queue.h:714
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
#define CH_NONEWLINE
Don&#39;t output terminating newline after the header.
Definition: copy.h:59
+ Here is the call 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 1273 of file smime.c.

1277 {
1278  return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1279  fp_smime_outfd, fp_smime_errfd, fname, NULL, C_SmimeEncryptWith,
1280  NULL, NULL, uids, NULL, C_SmimeEncryptCommand);
1281 }
char * C_SmimeEncryptCommand
Config: (smime) External command to encrypt a message.
Definition: config.c:95
char * C_SmimeEncryptWith
Config: Algorithm for encryption.
Definition: config.c:56
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:389
+ 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 1298 of file smime.c.

1301 {
1302  return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd, fp_smime_outfd,
1303  fp_smime_errfd, fname, NULL, NULL, C_SmimeSignDigestAlg,
1306 }
static struct Buffer SmimeKeyToUse
Definition: smime.c:80
static struct Buffer SmimeIntermediateToUse
Definition: smime.c:82
static struct Buffer SmimeCertToUse
Definition: smime.c:81
#define mutt_b2s(buf)
Definition: buffer.h:41
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:389
char * C_SmimeSignDigestAlg
Config: Digest algorithm.
Definition: config.c:103
char * C_SmimeSignCommand
Config: (smime) External command to sign a message.
Definition: config.c:102
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_class_build_smime_entity()

struct Body* smime_class_build_smime_entity ( struct Body a,
char *  certlist 
)

Implements CryptModuleSpecs::smime_build_smime_entity()

Definition at line 1311 of file smime.c.

1312 {
1313  char buf[1024], certfile[PATH_MAX];
1314  char *cert_end = NULL;
1315  FILE *fp_smime_in = NULL, *fp_smime_err = NULL, *fp_out = NULL, *fp_tmp = NULL;
1316  struct Body *t = NULL;
1317  int err = 0, empty, off;
1318  pid_t pid;
1319 
1320  struct Buffer *tempfile = mutt_buffer_pool_get();
1321  struct Buffer *smime_infile = mutt_buffer_pool_get();
1322 
1323  mutt_buffer_mktemp(tempfile);
1324  fp_out = mutt_file_fopen(mutt_b2s(tempfile), "w+");
1325  if (!fp_out)
1326  {
1327  mutt_perror(mutt_b2s(tempfile));
1328  goto cleanup;
1329  }
1330 
1331  fp_smime_err = mutt_file_mkstemp();
1332  if (!fp_smime_err)
1333  {
1334  mutt_perror(_("Can't create temporary file"));
1335  goto cleanup;
1336  }
1337 
1338  mutt_buffer_mktemp(smime_infile);
1339  fp_tmp = mutt_file_fopen(mutt_b2s(smime_infile), "w+");
1340  if (!fp_tmp)
1341  {
1342  mutt_perror(mutt_b2s(smime_infile));
1343  goto cleanup;
1344  }
1345 
1346  *certfile = '\0';
1347  for (char *cert_start = certlist; cert_start; cert_start = cert_end)
1348  {
1349  cert_end = strchr(cert_start, ' ');
1350  if (cert_end)
1351  *cert_end = '\0';
1352  if (*cert_start)
1353  {
1354  off = mutt_str_len(certfile);
1355  snprintf(certfile + off, sizeof(certfile) - off, "%s%s/%s",
1356  (off != 0) ? " " : "", NONULL(C_SmimeCertificates), cert_start);
1357  }
1358  if (cert_end)
1359  *cert_end++ = ' ';
1360  }
1361 
1362  /* write a MIME entity */
1363  mutt_write_mime_header(a, fp_tmp, NeoMutt->sub);
1364  fputc('\n', fp_tmp);
1365  mutt_write_mime_body(a, fp_tmp, NeoMutt->sub);
1366  mutt_file_fclose(&fp_tmp);
1367 
1368  pid = smime_invoke_encrypt(&fp_smime_in, NULL, NULL, -1, fileno(fp_out),
1369  fileno(fp_smime_err), mutt_b2s(smime_infile), certfile);
1370  if (pid == -1)
1371  {
1372  mutt_file_unlink(mutt_b2s(smime_infile));
1373  goto cleanup;
1374  }
1375 
1376  mutt_file_fclose(&fp_smime_in);
1377 
1378  filter_wait(pid);
1379  mutt_file_unlink(mutt_b2s(smime_infile));
1380 
1381  fflush(fp_out);
1382  rewind(fp_out);
1383  empty = (fgetc(fp_out) == EOF);
1384  mutt_file_fclose(&fp_out);
1385 
1386  fflush(fp_smime_err);
1387  rewind(fp_smime_err);
1388  while (fgets(buf, sizeof(buf) - 1, fp_smime_err))
1389  {
1390  err = 1;
1391  fputs(buf, stdout);
1392  }
1393  mutt_file_fclose(&fp_smime_err);
1394 
1395  /* pause if there is any error output from SMIME */
1396  if (err)
1398 
1399  if (empty)
1400  {
1401  /* fatal error while trying to encrypt message */
1402  if (err == 0)
1403  mutt_any_key_to_continue(_("No output from OpenSSL..."));
1404  mutt_file_unlink(mutt_b2s(tempfile));
1405  goto cleanup;
1406  }
1407 
1408  t = mutt_body_new();
1409  t->type = TYPE_APPLICATION;
1410  t->subtype = mutt_str_dup("x-pkcs7-mime");
1411  mutt_param_set(&t->parameter, "name", "smime.p7m");
1412  mutt_param_set(&t->parameter, "smime-type", "enveloped-data");
1413  t->encoding = ENC_BASE64; /* The output of OpenSSL SHOULD be binary */
1414  t->use_disp = true;
1415  t->disposition = DISP_ATTACH;
1416  t->d_filename = mutt_str_dup("smime.p7m");
1417  t->filename = mutt_buffer_strdup(tempfile);
1418  t->unlink = true; /* delete after sending the message */
1419  t->parts = NULL;
1420  t->next = NULL;
1421 
1422 cleanup:
1423  if (fp_out)
1424  {
1425  mutt_file_fclose(&fp_out);
1426  mutt_file_unlink(mutt_b2s(tempfile));
1427  }
1428  mutt_file_fclose(&fp_smime_err);
1429  if (fp_tmp)
1430  {
1431  mutt_file_fclose(&fp_tmp);
1432  mutt_file_unlink(mutt_b2s(smime_infile));
1433  }
1434  mutt_buffer_pool_release(&tempfile);
1435  mutt_buffer_pool_release(&smime_infile);
1436 
1437  return t;
1438 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
int mutt_write_mime_body(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:314
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
Container for Accounts, Notifications.
Definition: neomutt.h:36
The body of an email.
Definition: body.h:34
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
Content is attached.
Definition: mime.h:63
int mutt_write_mime_header(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition: header.c:760
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
char * subtype
content-type subtype
Definition: body.h:37
#define mutt_b2s(buf)
Definition: buffer.h:41
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.
Definition: smime.c:1273
#define PATH_MAX
Definition: mutt.h:44
char * C_SmimeCertificates
Config: File containing user&#39;s public certificates.
Definition: config.c:92
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
#define mutt_file_mkstemp()
Definition: file.h:106
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:604
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
Type: &#39;application/*&#39;.
Definition: mime.h:33
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
+ Here is the call graph for this function:

◆ openssl_md_to_smime_micalg()

static char* openssl_md_to_smime_micalg ( 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 1452 of file smime.c.

1453 {
1454  if (!md)
1455  return 0;
1456 
1457  char *micalg = NULL;
1458  if (mutt_istr_startswith(md, "sha"))
1459  {
1460  const size_t l = strlen(md) + 2;
1461  micalg = mutt_mem_malloc(l);
1462  snprintf(micalg, l, "sha-%s", md + 3);
1463  }
1464  else
1465  {
1466  micalg = mutt_str_dup(md);
1467  }
1468 
1469  return micalg;
1470 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:177
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_class_sign_message()

struct Body* smime_class_sign_message ( struct Body a,
const struct AddressList *  from 
)

Implements CryptModuleSpecs::sign_message()

Definition at line 1475 of file smime.c.

1476 {
1477  struct Body *t = NULL;
1478  struct Body *retval = NULL;
1479  char buf[1024];
1480  struct Buffer *filetosign = NULL, *signedfile = NULL;
1481  FILE *fp_smime_in = NULL, *fp_smime_out = NULL, *fp_smime_err = NULL, *fp_sign = NULL;
1482  int err = 0;
1483  int empty = 0;
1484  pid_t pid;
1485  char *intermediates = NULL;
1486 
1487  char *signas = C_SmimeSignAs ? C_SmimeSignAs : C_SmimeDefaultKey;
1488  if (!signas || (*signas == '\0'))
1489  {
1490  mutt_error(_("Can't sign: No key specified. Use Sign As."));
1491  return NULL;
1492  }
1493 
1494  crypt_convert_to_7bit(a); /* Signed data _must_ be in 7-bit format. */
1495 
1496  filetosign = mutt_buffer_pool_get();
1497  signedfile = mutt_buffer_pool_get();
1498 
1499  mutt_buffer_mktemp(filetosign);
1500  fp_sign = mutt_file_fopen(mutt_b2s(filetosign), "w+");
1501  if (!fp_sign)
1502  {
1503  mutt_perror(mutt_b2s(filetosign));
1504  goto cleanup;
1505  }
1506 
1507  mutt_buffer_mktemp(signedfile);
1508  fp_smime_out = mutt_file_fopen(mutt_b2s(signedfile), "w+");
1509  if (!fp_smime_out)
1510  {
1511  mutt_perror(mutt_b2s(signedfile));
1512  goto cleanup;
1513  }
1514 
1515  mutt_write_mime_header(a, fp_sign, NeoMutt->sub);
1516  fputc('\n', fp_sign);
1517  mutt_write_mime_body(a, fp_sign, NeoMutt->sub);
1518  mutt_file_fclose(&fp_sign);
1519 
1520  mutt_buffer_printf(&SmimeKeyToUse, "%s/%s", NONULL(C_SmimeKeys), signas);
1522 
1523  struct SmimeKey *signas_key = smime_get_key_by_hash(signas, 1);
1524  if (!signas_key || mutt_str_equal("?", signas_key->issuer))
1525  intermediates = signas; /* so openssl won't complain in any case */
1526  else
1527  intermediates = signas_key->issuer;
1528 
1530  NONULL(C_SmimeCertificates), intermediates);
1531 
1532  smime_key_free(&signas_key);
1533 
1534  pid = smime_invoke_sign(&fp_smime_in, NULL, &fp_smime_err, -1,
1535  fileno(fp_smime_out), -1, mutt_b2s(filetosign));
1536  if (pid == -1)
1537  {
1538  mutt_perror(_("Can't open OpenSSL subprocess"));
1539  mutt_file_unlink(mutt_b2s(filetosign));
1540  goto cleanup;
1541  }
1542  fputs(SmimePass, fp_smime_in);
1543  fputc('\n', fp_smime_in);
1544  mutt_file_fclose(&fp_smime_in);
1545 
1546  filter_wait(pid);
1547 
1548  /* check for errors from OpenSSL */
1549  err = 0;
1550  fflush(fp_smime_err);
1551  rewind(fp_smime_err);
1552  while (fgets(buf, sizeof(buf) - 1, fp_smime_err))
1553  {
1554  err = 1;
1555  fputs(buf, stdout);
1556  }
1557  mutt_file_fclose(&fp_smime_err);
1558 
1559  fflush(fp_smime_out);
1560  rewind(fp_smime_out);
1561  empty = (fgetc(fp_smime_out) == EOF);
1562  mutt_file_fclose(&fp_smime_out);
1563 
1564  mutt_file_unlink(mutt_b2s(filetosign));
1565 
1566  if (err)
1568 
1569  if (empty)
1570  {
1571  mutt_any_key_to_continue(_("No output from OpenSSL..."));
1572  mutt_file_unlink(mutt_b2s(signedfile));
1573  goto cleanup; /* fatal error while signing */
1574  }
1575 
1576  t = mutt_body_new();
1577  t->type = TYPE_MULTIPART;
1578  t->subtype = mutt_str_dup("signed");
1579  t->encoding = ENC_7BIT;
1580  t->use_disp = false;
1581  t->disposition = DISP_INLINE;
1582 
1584 
1586  mutt_param_set(&t->parameter, "micalg", micalg);
1587  FREE(&micalg);
1588 
1589  mutt_param_set(&t->parameter, "protocol", "application/x-pkcs7-signature");
1590 
1591  t->parts = a;
1592  retval = t;
1593 
1594  t->parts->next = mutt_body_new();
1595  t = t->parts->next;
1596  t->type = TYPE_APPLICATION;
1597  t->subtype = mutt_str_dup("x-pkcs7-signature");
1598  t->filename = mutt_buffer_strdup(signedfile);
1599  t->d_filename = mutt_str_dup("smime.p7s");
1600  t->use_disp = true;
1601  t->disposition = DISP_ATTACH;
1602  t->encoding = ENC_BASE64;
1603  t->unlink = true; /* ok to remove this file after sending. */
1604 
1605 cleanup:
1606  if (fp_sign)
1607  {
1608  mutt_file_fclose(&fp_sign);
1609  mutt_file_unlink(mutt_b2s(filetosign));
1610  }
1611  if (fp_smime_out)
1612  {
1613  mutt_file_fclose(&fp_smime_out);
1614  mutt_file_unlink(mutt_b2s(signedfile));
1615  }
1616  mutt_buffer_pool_release(&filetosign);
1617  mutt_buffer_pool_release(&signedfile);
1618  return retval;
1619 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
static struct Buffer SmimeKeyToUse
Definition: smime.c:80
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
7-bit text
Definition: mime.h:49
int mutt_write_mime_body(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:314
void crypt_convert_to_7bit(struct Body *a)
Convert an email to 7bit encoding.
Definition: crypt.c:801
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
String manipulation buffer.
Definition: buffer.h:33
static char * openssl_md_to_smime_micalg(char *md)
Change the algorithm names.
Definition: smime.c:1452
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
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.
Definition: smime.c:1298
static struct Buffer SmimeIntermediateToUse
Definition: smime.c:82
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
An SIME key.
Definition: smime.h:43
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
Container for Accounts, Notifications.
Definition: neomutt.h:36
The body of an email.
Definition: body.h:34
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
static void smime_key_free(struct SmimeKey **keylist)
Free a list of SMIME keys.
Definition: smime.c:108
char * C_SmimeKeys
Config: File containing user&#39;s private certificates.
Definition: config.c:100
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void mutt_generate_boundary(struct ParameterList *pl)
Create a unique boundary id for a MIME part.
Definition: multipart.c:85
char SmimePass[256]
Definition: smime.c:77
Content is attached.
Definition: mime.h:63
int mutt_write_mime_header(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition: header.c:760
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
static struct Buffer SmimeCertToUse
Definition: smime.c:81
char * subtype
content-type subtype
Definition: body.h:37
#define mutt_b2s(buf)
Definition: buffer.h:41
char * C_SmimeCertificates
Config: File containing user&#39;s public certificates.
Definition: config.c:92
static struct SmimeKey * smime_get_key_by_hash(char *hash, bool only_public_key)
Find a key by its hash.
Definition: smime.c:550
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
char * C_SmimeDefaultKey
Config: Default key for SMIME operations.
Definition: config.c:54
char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: config.c:55
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:604
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
#define mutt_error(...)
Definition: logging.h:84
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
char * C_SmimeSignDigestAlg
Config: Digest algorithm.
Definition: config.c:103
#define FREE(x)
Definition: memory.h:40
char * issuer
Definition: smime.h:48
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
Type: &#39;application/*&#39;.
Definition: mime.h:33
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
+ Here is the call 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 1638 of file smime.c.

1642 {
1643  return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd, fp_smime_outfd,
1644  fp_smime_errfd, fname, sig_fname, NULL, NULL, NULL, NULL, NULL,
1646 }
char * C_SmimeVerifyOpaqueCommand
Config: (smime) External command to verify a signature.
Definition: config.c:106
char * C_SmimeVerifyCommand
Config: (smime) External command to verify a signed message.
Definition: config.c:105
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:389
+ 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 1663 of file smime.c.

1666 {
1667  return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1668  fp_smime_outfd, fp_smime_errfd, fname, NULL, NULL, NULL,
1671 }
static struct Buffer SmimeKeyToUse
Definition: smime.c:80
char * C_SmimeDecryptCommand
Config: (smime) External command to decrypt an SMIME message.
Definition: config.c:93
static struct Buffer SmimeCertToUse
Definition: smime.c:81
#define mutt_b2s(buf)
Definition: buffer.h:41
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:389
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_class_verify_one()

int smime_class_verify_one ( struct Body sigbdy,
struct State s,
const char *  tempfile 
)

Implements CryptModuleSpecs::verify_one()

Definition at line 1676 of file smime.c.

1677 {
1678  FILE *fp = NULL, *fp_smime_out = NULL, *fp_smime_err = NULL;
1679  pid_t pid;
1680  int badsig = -1;
1681 
1682  LOFF_T tmpoffset = 0;
1683  size_t tmplength = 0;
1684  int orig_type = sigbdy->type;
1685 
1686  struct Buffer *signedfile = mutt_buffer_pool_get();
1687 
1688  mutt_buffer_printf(signedfile, "%s.sig", tempfile);
1689 
1690  /* decode to a tempfile, saving the original destination */
1691  fp = s->fp_out;
1692  s->fp_out = mutt_file_fopen(mutt_b2s(signedfile), "w");
1693  if (!s->fp_out)
1694  {
1695  mutt_perror(mutt_b2s(signedfile));
1696  goto cleanup;
1697  }
1698  /* decoding the attachment changes the size and offset, so save a copy
1699  * of the "real" values now, and restore them after processing */
1700  tmplength = sigbdy->length;
1701  tmpoffset = sigbdy->offset;
1702 
1703  /* if we are decoding binary bodies, we don't want to prefix each
1704  * line with the prefix or else the data will get corrupted. */
1705  char *save_prefix = s->prefix;
1706  s->prefix = NULL;
1707 
1708  mutt_decode_attachment(sigbdy, s);
1709 
1710  sigbdy->length = ftello(s->fp_out);
1711  sigbdy->offset = 0;
1712  mutt_file_fclose(&s->fp_out);
1713 
1714  /* restore final destination and substitute the tempfile for input */
1715  s->fp_out = fp;
1716  fp = s->fp_in;
1717  s->fp_in = fopen(mutt_b2s(signedfile), "r");
1718 
1719  /* restore the prefix */
1720  s->prefix = save_prefix;
1721 
1722  sigbdy->type = orig_type;
1723 
1724  fp_smime_err = mutt_file_mkstemp();
1725  if (!fp_smime_err)
1726  {
1727  mutt_perror(_("Can't create temporary file"));
1728  goto cleanup;
1729  }
1730 
1731  crypt_current_time(s, "OpenSSL");
1732 
1733  pid = smime_invoke_verify(NULL, &fp_smime_out, NULL, -1, -1, fileno(fp_smime_err),
1734  tempfile, mutt_b2s(signedfile), 0);
1735  if (pid != -1)
1736  {
1737  fflush(fp_smime_out);
1738  mutt_file_fclose(&fp_smime_out);
1739 
1740  if (filter_wait(pid))
1741  badsig = -1;
1742  else
1743  {
1744  char *line = NULL;
1745  size_t linelen;
1746 
1747  fflush(fp_smime_err);
1748  rewind(fp_smime_err);
1749 
1750  line = mutt_file_read_line(line, &linelen, fp_smime_err, NULL, 0);
1751  if (linelen && mutt_istr_equal(line, "verification successful"))
1752  badsig = 0;
1753 
1754  FREE(&line);
1755  }
1756  }
1757 
1758  fflush(fp_smime_err);
1759  rewind(fp_smime_err);
1760  mutt_file_copy_stream(fp_smime_err, s->fp_out);
1761  mutt_file_fclose(&fp_smime_err);
1762 
1763  state_attach_puts(s, _("[-- End of OpenSSL output --]\n\n"));
1764 
1765  mutt_file_unlink(mutt_b2s(signedfile));
1766 
1767  sigbdy->length = tmplength;
1768  sigbdy->offset = tmpoffset;
1769 
1770  /* restore the original source stream */
1771  mutt_file_fclose(&s->fp_in);
1772  s->fp_in = fp;
1773 
1774 cleanup:
1775  mutt_buffer_pool_release(&signedfile);
1776  return badsig;
1777 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1843
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
String manipulation buffer.
Definition: buffer.h:33
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, int flags)
Read a line from a file.
Definition: file.c:667
FILE * fp_out
File to write to.
Definition: state.h:47
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
FILE * fp_in
File to read from.
Definition: state.h:46
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void crypt_current_time(struct State *s, const char *app_name)
Print the current time.
Definition: crypt.c:71
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
#define mutt_b2s(buf)
Definition: buffer.h:41
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:1638
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define mutt_file_mkstemp()
Definition: file.h:106
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:70
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
#define FREE(x)
Definition: memory.h:40
int const char int line
Definition: acutest.h:617
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
+ Here is the call 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 1788 of file smime.c.

1789 {
1790  struct Buffer tmpfname = mutt_buffer_make(0);
1791  FILE *fp_smime_out = NULL, *fp_smime_in = NULL, *fp_smime_err = NULL;
1792  FILE *fp_tmp = NULL, *fp_out = NULL;
1793  struct stat info;
1794  struct Body *p = NULL;
1795  pid_t pid = -1;
1797 
1798  if (!(type & APPLICATION_SMIME))
1799  return NULL;
1800 
1801  /* Because of the mutt_body_handler() we avoid the buffer pool. */
1802  fp_smime_out = mutt_file_mkstemp();
1803  if (!fp_smime_out)
1804  {
1805  mutt_perror(_("Can't create temporary file"));
1806  goto cleanup;
1807  }
1808 
1809  fp_smime_err = mutt_file_mkstemp();
1810  if (!fp_smime_err)
1811  {
1812  mutt_perror(_("Can't create temporary file"));
1813  goto cleanup;
1814  }
1815 
1816  mutt_buffer_mktemp(&tmpfname);
1817  fp_tmp = mutt_file_fopen(mutt_b2s(&tmpfname), "w+");
1818  if (!fp_tmp)
1819  {
1820  mutt_perror(mutt_b2s(&tmpfname));
1821  goto cleanup;
1822  }
1823 
1824  fseeko(s->fp_in, m->offset, SEEK_SET);
1825 
1826  mutt_file_copy_bytes(s->fp_in, fp_tmp, m->length);
1827 
1828  fflush(fp_tmp);
1829  mutt_file_fclose(&fp_tmp);
1830 
1831  if ((type & SEC_ENCRYPT) &&
1832  ((pid = smime_invoke_decrypt(&fp_smime_in, NULL, NULL, -1, fileno(fp_smime_out),
1833  fileno(fp_smime_err), mutt_b2s(&tmpfname))) == -1))
1834  {
1835  mutt_file_unlink(mutt_b2s(&tmpfname));
1836  if (s->flags & MUTT_DISPLAY)
1837  {
1839  s, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1840  }
1841  goto cleanup;
1842  }
1843  else if ((type & SEC_SIGNOPAQUE) &&
1844  ((pid = smime_invoke_verify(&fp_smime_in, NULL, NULL, -1,
1845  fileno(fp_smime_out), fileno(fp_smime_err), NULL,
1846  mutt_b2s(&tmpfname), SEC_SIGNOPAQUE)) == -1))
1847  {
1848  mutt_file_unlink(mutt_b2s(&tmpfname));
1849  if (s->flags & MUTT_DISPLAY)
1850  {
1852  s, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1853  }
1854  goto cleanup;
1855  }
1856 
1857  if (type & SEC_ENCRYPT)
1858  {
1861  fputs(SmimePass, fp_smime_in);
1862  fputc('\n', fp_smime_in);
1863  }
1864 
1865  mutt_file_fclose(&fp_smime_in);
1866 
1867  filter_wait(pid);
1868  mutt_file_unlink(mutt_b2s(&tmpfname));
1869 
1870  if (s->flags & MUTT_DISPLAY)
1871  {
1872  fflush(fp_smime_err);
1873  rewind(fp_smime_err);
1874 
1875  const int c = fgetc(fp_smime_err);
1876  if (c != EOF)
1877  {
1878  ungetc(c, fp_smime_err);
1879 
1880  crypt_current_time(s, "OpenSSL");
1881  mutt_file_copy_stream(fp_smime_err, s->fp_out);
1882  state_attach_puts(s, _("[-- End of OpenSSL output --]\n\n"));
1883  }
1884 
1885  if (type & SEC_ENCRYPT)
1886  {
1888  _("[-- The following data is S/MIME encrypted --]\n"));
1889  }
1890  else
1891  state_attach_puts(s, _("[-- The following data is S/MIME signed --]\n"));
1892  }
1893 
1894  fflush(fp_smime_out);
1895  rewind(fp_smime_out);
1896 
1897  if (type & SEC_ENCRYPT)
1898  {
1899  /* void the passphrase, even if that wasn't the problem */
1900  if (fgetc(fp_smime_out) == EOF)
1901  {
1902  mutt_error(_("Decryption failed"));
1904  }
1905  rewind(fp_smime_out);
1906  }
1907 
1908  if (fp_out_file)
1909  fp_out = fp_out_file;
1910  else
1911  {
1912  fp_out = mutt_file_mkstemp();
1913  if (!fp_out)
1914  {
1915  mutt_perror(_("Can't create temporary file"));
1916  goto cleanup;
1917  }
1918  }
1919  char buf[8192];
1920  while (fgets(buf, sizeof(buf) - 1, fp_smime_out))
1921  {
1922  const size_t len = mutt_str_len(buf);
1923  if ((len > 1) && (buf[len - 2] == '\r'))
1924  {
1925  buf[len - 2] = '\n';
1926  buf[len - 1] = '\0';
1927  }
1928  fputs(buf, fp_out);
1929  }
1930  fflush(fp_out);
1931  rewind(fp_out);
1932 
1933  p = mutt_read_mime_header(fp_out, 0);
1934  if (p)
1935  {
1936  fstat(fileno(fp_out), &info);
1937  p->length = info.st_size - p->offset;
1938 
1939  mutt_parse_part(fp_out, p);
1940 
1941  if (s->flags & MUTT_DISPLAY)
1943 
1944  /* Store any protected headers in the parent so they can be
1945  * accessed for index updates after the handler recursion is done.
1946  * This is done before the handler to prevent a nested encrypted
1947  * handler from freeing the headers. */
1949  m->mime_headers = p->mime_headers;
1950  p->mime_headers = NULL;
1951 
1952  if (s->fp_out)
1953  {
1954  rewind(fp_out);
1955  FILE *fp_tmp_buffer = s->fp_in;
1956  s->fp_in = fp_out;
1957  mutt_body_handler(p, s);
1958  s->fp_in = fp_tmp_buffer;
1959  }
1960 
1961  /* Embedded multipart signed protected headers override the
1962  * encrypted headers. We need to do this after the handler so
1963  * they can be printed in the pager. */
1964  if (!(type & SMIME_SIGN) && mutt_is_multipart_signed(p) && p->parts &&
1965  p->parts->mime_headers)
1966  {
1968  m->mime_headers = p->parts->mime_headers;
1969  p->parts->mime_headers = NULL;
1970  }
1971  }
1972  mutt_file_fclose(&fp_smime_out);
1973 
1974  if (!fp_out_file)
1975  {
1976  mutt_file_fclose(&fp_out);
1977  mutt_file_unlink(mutt_b2s(&tmpfname));
1978  }
1979  fp_out = NULL;
1980 
1981  if (s->flags & MUTT_DISPLAY)
1982  {
1983  if (type & SEC_ENCRYPT)
1984  state_attach_puts(s, _("\n[-- End of S/MIME encrypted data. --]\n"));
1985  else
1986  state_attach_puts(s, _("\n[-- End of S/MIME signed data. --]\n"));
1987  }
1988 
1989  if (type & SEC_SIGNOPAQUE)
1990  {
1991  char *line = NULL;
1992  size_t linelen;
1993 
1994  rewind(fp_smime_err);
1995 
1996  line = mutt_file_read_line(line, &linelen, fp_smime_err, NULL, 0);
1997  if (linelen && mutt_istr_equal(line, "verification successful"))
1998  m->goodsig = true;
1999  FREE(&line);
2000  }
2001  else if (p)
2002  {
2003  m->goodsig = p->goodsig;
2004  m->badsig = p->badsig;
2005  }
2006 
2007 cleanup:
2008  mutt_file_fclose(&fp_smime_out);
2009  mutt_file_fclose(&fp_smime_err);
2010  mutt_file_fclose(&fp_tmp);
2011  mutt_file_fclose(&fp_out);
2012  mutt_buffer_dealloc(&tmpfname);
2013  return p;
2014 }
int mutt_protected_headers_handler(struct Body *a, struct State *s)
Process a protected header - Implements handler_t.
Definition: crypt.c:1087
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
#define SMIME_SIGN
Definition: lib.h:110
#define mutt_perror(...)
Definition: logging.h:85
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:85
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, int flags)
Read a line from a file.
Definition: file.c:667
FILE * fp_out
File to write to.
Definition: state.h:47
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:83
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:1663
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
bool smime_class_valid_passphrase(void)
Implements CryptModuleSpecs::valid_passphrase()
Definition: smime.c:167
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void crypt_current_time(struct State *s, const char *app_name)
Print the current time.
Definition: crypt.c:71
bool badsig
Bad cryptographic signature (needed to check encrypted s/mime-signatures)
Definition: body.h:77
char SmimePass[256]
Definition: smime.c:77
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:407
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
#define mutt_b2s(buf)
Definition: buffer.h:41
bool goodsig
Good cryptographic signature.
Definition: body.h:75
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98
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:1638
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
void smime_class_void_passphrase(void)
Implements CryptModuleSpecs::void_passphrase()
Definition: smime.c:158
#define mutt_file_mkstemp()
Definition: file.h:106
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:610
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
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:70
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1657
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
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_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1593
int const char int line
Definition: acutest.h:617
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1267
#define SEC_SIGNOPAQUE
Email has an opaque signature (encrypted)
Definition: lib.h:90
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_class_decrypt_mime()

int smime_class_decrypt_mime ( FILE *  fp_in,
FILE **  fp_out,
struct Body b,
struct Body **  cur 
)

Implements CryptModuleSpecs::decrypt_mime()

Definition at line 2019 of file smime.c.

2020 {
2021  struct State s = { 0 };
2022  LOFF_T tmpoffset = b->offset;
2023  size_t tmplength = b->length;
2024  int orig_type = b->type;
2025  int rc = -1;
2026 
2027  if (!mutt_is_application_smime(b))
2028  return -1;
2029 
2030  if (b->parts)
2031  return -1;
2032 
2033  s.fp_in = fp_in;
2034  fseeko(s.fp_in, b->offset, SEEK_SET);
2035 
2036  FILE *fp_tmp = mutt_file_mkstemp();
2037  if (!fp_tmp)
2038  {
2039  mutt_perror(_("Can't create temporary file"));
2040  return -1;
2041  }
2042 
2043  s.fp_out = fp_tmp;
2044  mutt_decode_attachment(b, &s);
2045  fflush(fp_tmp);
2046  b->length = ftello(s.fp_out);
2047  b->offset = 0;
2048  rewind(fp_tmp);
2049  s.fp_in = fp_tmp;
2050  s.fp_out = 0;
2051 
2053  if (!*fp_out)
2054  {
2055  mutt_perror(_("Can't create temporary file"));
2056  goto bail;
2057  }
2058 
2059  *cur = smime_handle_entity(b, &s, *fp_out);
2060  if (!*cur)
2061  goto bail;
2062 
2063  (*cur)->goodsig = b->goodsig;
2064  (*cur)->badsig = b->badsig;
2065  rc = 0;
2066 
2067 bail:
2068  b->type = orig_type;
2069  b->length = tmplength;
2070  b->offset = tmpoffset;
2071  mutt_file_fclose(&fp_tmp);
2072  if (*fp_out)
2073  rewind(*fp_out);
2074 
2075  return rc;
2076 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1843
#define mutt_perror(...)
Definition: logging.h:85
static struct Body * smime_handle_entity(struct Body *m, struct State *s, FILE *fp_out_file)
Handle type application/pkcs7-mime.
Definition: smime.c:1788
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
FILE * fp_out
File to write to.
Definition: state.h:47
FILE * fp_in
File to read from.
Definition: state.h:46
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
bool badsig
Bad cryptographic signature (needed to check encrypted s/mime-signatures)
Definition: body.h:77
bool goodsig
Good cryptographic signature.
Definition: body.h:75
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
#define mutt_file_mkstemp()
Definition: file.h:106
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:610
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Keep track when processing files.
Definition: state.h:44
+ Here is the call graph for this function:

◆ smime_class_application_handler()

int smime_class_application_handler ( struct Body m,
struct State s 
)

Implements CryptModuleSpecs::application_handler()

Definition at line 2081 of file smime.c.

2082 {
2083  int rc = -1;
2084 
2085  /* clear out any mime headers before the handler, so they can't be spoofed. */
2087 
2088  struct Body *tattach = smime_handle_entity(m, s, NULL);
2089  if (tattach)
2090  {
2091  rc = 0;
2092  mutt_body_free(&tattach);
2093  }
2094  return rc;
2095 }
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
static struct Body * smime_handle_entity(struct Body *m, struct State *s, FILE *fp_out_file)
Handle type application/pkcs7-mime.
Definition: smime.c:1788
The body of an email.
Definition: body.h:34
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
+ Here is the call graph for this function:

◆ smime_class_send_menu()

int smime_class_send_menu ( struct Email e)

Implements CryptModuleSpecs::send_menu()

Definition at line 2100 of file smime.c.

2101 {
2102  struct SmimeKey *key = NULL;
2103  const char *prompt = NULL;
2104  const char *letters = NULL;
2105  const char *choices = NULL;
2106  int choice;
2107 
2108  if (!(WithCrypto & APPLICATION_SMIME))
2109  return e->security;
2110 
2112 
2113  /* Opportunistic encrypt is controlling encryption.
2114  * NOTE: "Signing" and "Clearing" only adjust the sign bit, so we have different
2115  * letter choices for those. */
2117  {
2118  /* L10N: S/MIME options (opportunistic encryption is on) */
2119  prompt = _("S/MIME (s)ign, encrypt (w)ith, sign (a)s, (c)lear, or (o)ppenc "
2120  "mode off?");
2121  /* L10N: S/MIME options (opportunistic encryption is on) */
2122  letters = _("swaco");
2123  choices = "SwaCo";
2124  }
2125  /* Opportunistic encryption option is set, but is toggled off
2126  * for this message. */
2127  else if (C_CryptOpportunisticEncrypt)
2128  {
2129  /* L10N: S/MIME options (opportunistic encryption is off) */
2130  prompt = _("S/MIME (e)ncrypt, (s)ign, encrypt (w)ith, sign (a)s, (b)oth, "
2131  "(c)lear, or (o)ppenc mode?");
2132  /* L10N: S/MIME options (opportunistic encryption is off) */
2133  letters = _("eswabco");
2134  choices = "eswabcO";
2135  }
2136  /* Opportunistic encryption is unset */
2137  else
2138  {
2139  /* L10N: S/MIME options */
2140  prompt = _("S/MIME (e)ncrypt, (s)ign, encrypt (w)ith, sign (a)s, (b)oth, "
2141  "or (c)lear?");
2142  /* L10N: S/MIME options */
2143  letters = _("eswabc");
2144  choices = "eswabc";
2145  }
2146 
2147  choice = mutt_multi_choice(prompt, letters);
2148  if (choice > 0)
2149  {
2150  switch (choices[choice - 1])
2151  {
2152  case 'a': /* sign (a)s */
2153  key = smime_ask_for_key(_("Sign as: "), KEYFLAG_CANSIGN, false);
2154  if (key)
2155  {
2157  smime_key_free(&key);
2158 
2159  e->security |= SEC_SIGN;
2160 
2161  /* probably need a different passphrase */
2163  }
2164 
2165  break;
2166 
2167  case 'b': /* (b)oth */
2168  e->security |= (SEC_ENCRYPT | SEC_SIGN);
2169  break;
2170 
2171  case 'c': /* (c)lear */
2172  e->security &= ~(SEC_ENCRYPT | SEC_SIGN);
2173  break;
2174 
2175  case 'C':
2176  e->security &= ~SEC_SIGN;
2177  break;
2178 
2179  case 'e': /* (e)ncrypt */
2180  e->security |= SEC_ENCRYPT;
2181  e->security &= ~SEC_SIGN;
2182  break;
2183 
2184  case 'O': /* oppenc mode on */
2185  e->security |= SEC_OPPENCRYPT;
2187  break;
2188 
2189  case 'o': /* oppenc mode off */
2190  e->security &= ~SEC_OPPENCRYPT;
2191  break;
2192 
2193  case 'S': /* (s)ign in oppenc mode */
2194  e->security |= SEC_SIGN;
2195  break;
2196 
2197  case 's': /* (s)ign */
2198  e->security &= ~SEC_ENCRYPT;
2199  e->security |= SEC_SIGN;
2200  break;
2201 
2202  case 'w': /* encrypt (w)ith */
2203  {
2204  e->security |= SEC_ENCRYPT;
2205  do
2206  {
2207  struct Buffer errmsg = mutt_buffer_make(0);
2208  int rc = CSR_SUCCESS;
2209  switch (mutt_multi_choice(_("Choose algorithm family: (1) DES, (2) "
2210  "RC2, (3) AES, or (c)lear?"),
2211  // L10N: Options for: Choose algorithm family: (1) DES, (2) RC2, (3) AES, or (c)lear?
2212  _("123c")))
2213  {
2214  case 1:
2215  switch (choice = mutt_multi_choice(_("(1) DES, (2) Triple-DES?"),
2216  // L10N: Options for: (1) DES, (2) Triple-DES
2217  _("12")))
2218  {
2219  case 1:
2220  rc = cs_subset_str_string_set(NeoMutt->sub, "smime_encrypt_with",
2221  "des", &errmsg);
2222  break;
2223  case 2:
2224  rc = cs_subset_str_string_set(NeoMutt->sub, "smime_encrypt_with",
2225  "des3", &errmsg);
2226  break;
2227  }
2228  break;
2229 
2230  case 2:
2231  switch (choice = mutt_multi_choice(
2232  _("(1) RC2-40, (2) RC2-64, (3) RC2-128?"),
2233  // L10N: Options for: (1) RC2-40, (2) RC2-64, (3) RC2-128
2234  _("123")))
2235  {
2236  case 1:
2237  rc = cs_subset_str_string_set(NeoMutt->sub, "smime_encrypt_with",
2238  "rc2-40", &errmsg);
2239  break;
2240  case 2:
2241  rc = cs_subset_str_string_set(NeoMutt->sub, "smime_encrypt_with",
2242  "rc2-64", &errmsg);
2243  break;
2244  case 3:
2245  rc = cs_subset_str_string_set(NeoMutt->sub, "smime_encrypt_with",
2246  "rc2-128", &errmsg);
2247  break;
2248  }
2249  break;
2250 
2251  case 3:
2252  switch (choice = mutt_multi_choice(
2253  _("(1) AES128, (2) AES192, (3) AES256?"),
2254  // L10N: Options for: (1) AES128, (2) AES192, (3) AES256
2255  _("123")))
2256  {
2257  case 1:
2258  rc = cs_subset_str_string_set(NeoMutt->sub, "smime_encrypt_with",
2259  "aes128", &errmsg);
2260  break;
2261  case 2:
2262  rc = cs_subset_str_string_set(NeoMutt->sub, "smime_encrypt_with",
2263  "aes192", &errmsg);
2264  break;
2265  case 3:
2266  rc = cs_subset_str_string_set(NeoMutt->sub, "smime_encrypt_with",
2267  "aes256", &errmsg);
2268  break;
2269  }
2270  break;
2271 
2272  case 4:
2273  rc = cs_subset_str_string_set(NeoMutt->sub, "smime_encrypt_with",
2274  NULL, &errmsg);
2275  /* (c)lear */
2276  /* fallthrough */
2277  case -1: /* Ctrl-G or Enter */
2278  choice = 0;
2279  break;
2280  }
2281 
2282  if ((CSR_RESULT(rc) != CSR_SUCCESS) && !mutt_buffer_is_empty(&errmsg))
2283  mutt_error("%s", mutt_b2s(&errmsg));
2284 
2285  mutt_buffer_dealloc(&errmsg);
2286  } while (choice == -1);
2287  break;
2288  }
2289  }
2290  }
2291 
2292  return e->security;
2293 }
#define WithCrypto
Definition: lib.h:123
#define CSR_RESULT(x)
Definition: set.h:52
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:85
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
An SIME key.
Definition: smime.h:43
int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: subset.c:395
Container for Accounts, Notifications.
Definition: neomutt.h:36
static void smime_key_free(struct SmimeKey **keylist)
Free a list of SMIME keys.
Definition: smime.c:108
bool C_CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: config.c:41
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
void crypt_smime_void_passphrase(void)
Wrapper for CryptModuleSpecs::void_passphrase()
Definition: cryptglue.c:411
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
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:701
#define mutt_b2s(buf)
Definition: buffer.h:41
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: curs_lib.c:933
#define KEYFLAG_CANSIGN
Key is suitable for signing.
Definition: lib.h:134
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:93
char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: config.c:55
#define SEC_SIGN
Email is signed.
Definition: lib.h:86
void crypt_opportunistic_encrypt(struct Email *e)
Can all recipients be determined.
Definition: crypt.c:1021
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:451
#define mutt_error(...)
Definition: logging.h:84
char * hash
Definition: smime.h:46
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
+ Here is the call 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 80 of file smime.c.

◆ SmimeCertToUse

struct Buffer SmimeCertToUse = { 0 }
static

Definition at line 81 of file smime.c.

◆ SmimeIntermediateToUse

struct Buffer SmimeIntermediateToUse = { 0 }
static

Definition at line 82 of file smime.c.