NeoMutt  2024-11-14-138-ge5ca67
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
smime.c File Reference

SMIME helper routines. More...

#include "config.h"
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "private.h"
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "lib.h"
#include "editor/lib.h"
#include "expando/lib.h"
#include "history/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "copy.h"
#include "crypt.h"
#include "cryptglue.h"
#include "expando_smime.h"
#include "globals.h"
#include "handler.h"
#include "mutt_logging.h"
#include "smime.h"
+ Include dependency graph for smime.c:

Go to the source code of this file.

Functions

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

Variables

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

Detailed Description

SMIME helper routines.

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

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

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

Definition in file smime.c.

Function Documentation

◆ smime_init()

void smime_init ( void  )

Initialise smime globals.

Definition at line 82 of file smime.c.

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

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

◆ smime_key_free()

static void smime_key_free ( struct SmimeKey **  keylist)
static

Free a list of SMIME keys.

Parameters
[out]keylistList of keys to free

Definition at line 103 of file smime.c.

104{
105 if (!keylist)
106 return;
107
108 struct SmimeKey *key = NULL;
109
110 while (*keylist)
111 {
112 key = *keylist;
113 *keylist = (*keylist)->next;
114
115 FREE(&key->email);
116 FREE(&key->hash);
117 FREE(&key->label);
118 FREE(&key->issuer);
119 FREE(&key);
120 }
121}
#define FREE(x)
Definition: memory.h:55
An SIME key.
Definition: smime.h:43
char * hash
Definition: smime.h:45
struct SmimeKey * next
Definition: smime.h:50
char * issuer
Definition: smime.h:47
char * email
Definition: smime.h:44
char * label
Definition: smime.h:46
+ Here is the caller graph for this function:

◆ smime_copy_key()

static struct SmimeKey * smime_copy_key ( struct SmimeKey key)
static

Copy an SMIME key.

Parameters
keyKey to copy
Return values
ptrNewly allocated SMIME key

Definition at line 128 of file smime.c.

129{
130 if (!key)
131 return NULL;
132
133 struct SmimeKey *copy = NULL;
134
135 copy = MUTT_MEM_CALLOC(1, struct SmimeKey);
136 copy->email = mutt_str_dup(key->email);
137 copy->hash = mutt_str_dup(key->hash);
138 copy->label = mutt_str_dup(key->label);
139 copy->issuer = mutt_str_dup(key->issuer);
140 copy->trust = key->trust;
141 copy->flags = key->flags;
142
143 return copy;
144}
#define MUTT_MEM_CALLOC(n, type)
Definition: memory.h:40
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
KeyFlags flags
Definition: smime.h:49
char trust
i=Invalid r=revoked e=expired u=unverified v=verified t=trusted
Definition: smime.h:48
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_command()

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

Format an SMIME command string.

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

Definition at line 195 of file smime.c.

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

◆ smime_invoke()

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

Run an SMIME command.

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

Definition at line 225 of file smime.c.

230{
231 struct SmimeCommandContext cctx = { 0 };
232
233 if (!exp)
234 return (pid_t) -1;
235
236 cctx.fname = fname;
237 cctx.sig_fname = sig_fname;
238 cctx.key = key;
239 cctx.cryptalg = cryptalg;
240 cctx.digestalg = digestalg;
243
244 struct Buffer *cmd = buf_pool_get();
245 smime_command(cmd, &cctx, exp);
246
247 pid_t pid = filter_create_fd(buf_string(cmd), fp_smime_in, fp_smime_out, fp_smime_err,
248 fp_smime_infd, fp_smime_outfd, fp_smime_errfd, EnvList);
249 buf_pool_release(&cmd);
250 return pid;
251}
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:75
pid_t filter_create_fd(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, int fdin, int fdout, int fderr, char **envlist)
Run a command on a pipe (optionally connect stdin/stdout)
Definition: filter.c:62
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:96
static void smime_command(struct Buffer *buf, struct SmimeCommandContext *cctx, const struct Expando *exp)
Format an SMIME command string.
Definition: smime.c:195
String manipulation buffer.
Definition: buffer.h:36
Data for a SIME command.
Definition: smime.h:58
const char * sig_fname
s
Definition: smime.h:63
const char * intermediates
i
Definition: smime.h:65
const char * digestalg
d
Definition: smime.h:61
const char * cryptalg
a
Definition: smime.h:60
const char * key
k
Definition: smime.h:59
const char * fname
f
Definition: smime.h:62
const char * certificates
c
Definition: smime.h:64
+ 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 259 of file smime.c.

260{
261 char *pend = NULL, *p = NULL;
262 int field = 0;
263
264 struct SmimeKey *key = MUTT_MEM_CALLOC(1, struct SmimeKey);
265
266 for (p = buf; p; p = pend)
267 {
268 /* Some users manually maintain their .index file, and use a tab
269 * as a delimiter, which the old parsing code (using fscanf)
270 * happened to allow. smime_keys uses a space, so search for both. */
271 if ((pend = strchr(p, ' ')) || (pend = strchr(p, '\t')) || (pend = strchr(p, '\n')))
272 *pend++ = 0;
273
274 /* For backward compatibility, don't count consecutive delimiters
275 * as an empty field. */
276 if (*p == '\0')
277 continue;
278
279 field++;
280
281 switch (field)
282 {
283 case 1: /* mailbox */
284 key->email = mutt_str_dup(p);
285 break;
286 case 2: /* hash */
287 key->hash = mutt_str_dup(p);
288 break;
289 case 3: /* label */
290 key->label = mutt_str_dup(p);
291 break;
292 case 4: /* issuer */
293 key->issuer = mutt_str_dup(p);
294 break;
295 case 5: /* trust */
296 key->trust = *p;
297 break;
298 case 6: /* purpose */
299 while (*p)
300 {
301 switch (*p++)
302 {
303 case 'e':
305 break;
306
307 case 's':
308 key->flags |= KEYFLAG_CANSIGN;
309 break;
310 }
311 }
312 break;
313 }
314 }
315
316 /* Old index files could be missing issuer, trust, and purpose,
317 * but anything less than that is an error. */
318 if (field < 3)
319 {
320 smime_key_free(&key);
321 return NULL;
322 }
323
324 if (field < 4)
325 key->issuer = mutt_str_dup("?");
326
327 if (field < 5)
328 key->trust = 't';
329
330 if (field < 6)
332
333 return key;
334}
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition: lib.h:134
#define KEYFLAG_CANSIGN
Key is suitable for signing.
Definition: lib.h:133
static void smime_key_free(struct SmimeKey **keylist)
Free a list of SMIME keys.
Definition: smime.c:103
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_get_candidates()

static struct SmimeKey * smime_get_candidates ( const char *  search,
bool  only_public_key 
)
static

Find keys matching a string.

Parameters
searchString to match
only_public_keyIf true, only get the public keys
Return values
ptrMatching key

Definition at line 342 of file smime.c.

343{
344 char buf[1024] = { 0 };
345 struct SmimeKey *key = NULL, *results = NULL;
346 struct SmimeKey **results_end = &results;
347
348 struct Buffer *index_file = buf_pool_get();
349 const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
350 const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
351 buf_printf(index_file, "%s/.index",
352 only_public_key ? NONULL(c_smime_certificates) : NONULL(c_smime_keys));
353
354 FILE *fp = mutt_file_fopen(buf_string(index_file), "r");
355 if (!fp)
356 {
357 mutt_perror("%s", buf_string(index_file));
358 buf_pool_release(&index_file);
359 return NULL;
360 }
361 buf_pool_release(&index_file);
362
363 while (fgets(buf, sizeof(buf), fp))
364 {
365 if (((*search == '\0')) || mutt_istr_find(buf, search))
366 {
367 key = smime_parse_key(buf);
368 if (key)
369 {
370 *results_end = key;
371 results_end = &key->next;
372 }
373 }
374 }
375
376 mutt_file_fclose(&fp);
377
378 return results;
379}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:168
#define mutt_file_fclose(FP)
Definition: file.h:138
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:137
#define mutt_perror(...)
Definition: logging2.h:93
static int search(struct Menu *menu, int op)
Search a menu.
Definition: functions.c:58
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:521
static struct SmimeKey * smime_parse_key(char *buf)
Parse an SMIME key block.
Definition: smime.c:259
#define NONULL(x)
Definition: string2.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_get_key_by_hash()

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

Find a key by its hash.

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

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

Definition at line 390 of file smime.c.

391{
392 struct SmimeKey *match = NULL;
393 struct SmimeKey *results = smime_get_candidates(hash, only_public_key);
394 for (struct SmimeKey *result = results; result; result = result->next)
395 {
396 if (mutt_istr_equal(hash, result->hash))
397 {
398 match = smime_copy_key(result);
399 break;
400 }
401 }
402
403 smime_key_free(&results);
404
405 return match;
406}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:672
static struct SmimeKey * smime_copy_key(struct SmimeKey *key)
Copy an SMIME key.
Definition: smime.c:128
static struct SmimeKey * smime_get_candidates(const char *search, bool only_public_key)
Find keys matching a string.
Definition: smime.c:342
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_get_key_by_addr()

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

Find an SIME key by address.

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

Definition at line 416 of file smime.c.

418{
419 if (!mailbox)
420 return NULL;
421
422 struct SmimeKey *results = NULL, *result = NULL;
423 struct SmimeKey *matches = NULL;
424 struct SmimeKey **matches_end = &matches;
425 struct SmimeKey *match = NULL;
426 struct SmimeKey *trusted_match = NULL;
427 struct SmimeKey *valid_match = NULL;
428 struct SmimeKey *return_key = NULL;
429 bool multi_trusted_matches = false;
430
431 results = smime_get_candidates(mailbox, only_public_key);
432 for (result = results; result; result = result->next)
433 {
434 if (abilities && !(result->flags & abilities))
435 {
436 continue;
437 }
438
439 if (mutt_istr_equal(mailbox, result->email))
440 {
441 match = smime_copy_key(result);
442 *matches_end = match;
443 matches_end = &match->next;
444
445 if (match->trust == 't')
446 {
447 if (trusted_match && !mutt_istr_equal(match->hash, trusted_match->hash))
448 {
449 multi_trusted_matches = true;
450 }
451 trusted_match = match;
452 }
453 else if ((match->trust == 'u') || (match->trust == 'v'))
454 {
455 valid_match = match;
456 }
457 }
458 }
459
460 smime_key_free(&results);
461
462 if (matches)
463 {
464 if (oppenc_mode || !isatty(STDIN_FILENO))
465 {
466 const bool c_crypt_opportunistic_encrypt_strong_keys =
467 cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt_strong_keys");
468 if (trusted_match)
469 return_key = smime_copy_key(trusted_match);
470 else if (valid_match && !c_crypt_opportunistic_encrypt_strong_keys)
471 return_key = smime_copy_key(valid_match);
472 else
473 return_key = NULL;
474 }
475 else if (trusted_match && !multi_trusted_matches)
476 {
477 return_key = smime_copy_key(trusted_match);
478 }
479 else
480 {
481 return_key = smime_copy_key(dlg_smime(matches, mailbox));
482 }
483
484 smime_key_free(&matches);
485 }
486
487 return return_key;
488}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:47
struct SmimeKey * dlg_smime(struct SmimeKey *keys, const char *query)
Get the user to select a key -.
Definition: dlg_smime.c:194
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_get_key_by_str()

static struct SmimeKey * smime_get_key_by_str ( const char *  str,
KeyFlags  abilities,
bool  only_public_key 
)
static

Find an SMIME key by string.

Parameters
strString to match
abilitiesAbilities to match, see KeyFlags
only_public_keyIf true, only get the public keys
Return values
ptrMatching key

Definition at line 497 of file smime.c.

498{
499 if (!str)
500 return NULL;
501
502 struct SmimeKey *results = NULL, *result = NULL;
503 struct SmimeKey *matches = NULL;
504 struct SmimeKey **matches_end = &matches;
505 struct SmimeKey *match = NULL;
506 struct SmimeKey *return_key = NULL;
507
508 results = smime_get_candidates(str, only_public_key);
509 for (result = results; result; result = result->next)
510 {
511 if (abilities && !(result->flags & abilities))
512 {
513 continue;
514 }
515
516 if (mutt_istr_equal(str, result->hash) ||
517 mutt_istr_find(result->email, str) || mutt_istr_find(result->label, str))
518 {
519 match = smime_copy_key(result);
520 *matches_end = match;
521 matches_end = &match->next;
522 }
523 }
524
525 smime_key_free(&results);
526
527 if (matches)
528 {
529 return_key = smime_copy_key(dlg_smime(matches, str));
530 smime_key_free(&matches);
531 }
532
533 return return_key;
534}
+ 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 ( const 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 543 of file smime.c.

544{
545 if (!prompt)
546 return NULL;
547
548 struct SmimeKey *key = NULL;
549 struct Buffer *resp = buf_pool_get();
550
552
553 while (true)
554 {
555 buf_reset(resp);
556 if (mw_get_field(prompt, resp, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0)
557 {
558 goto done;
559 }
560
561 key = smime_get_key_by_str(buf_string(resp), abilities, only_public_key);
562 if (key)
563 goto done;
564
565 mutt_error(_("No matching keys found for \"%s\""), buf_string(resp));
566 }
567
568done:
569 buf_pool_release(&resp);
570 return key;
571}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:76
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition: window.c:274
#define mutt_error(...)
Definition: logging2.h:92
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:58
#define _(a)
Definition: message.h:28
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
static struct SmimeKey * smime_get_key_by_str(const char *str, KeyFlags abilities, bool only_public_key)
Find an SMIME key by string.
Definition: smime.c:497
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getkeys()

static void getkeys ( const char *  mailbox)
static

Get the keys for a mailbox.

Parameters
mailboxEmail address

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

Definition at line 580 of file smime.c.

581{
582 const char *k = NULL;
583
584 struct SmimeKey *key = smime_get_key_by_addr(mailbox, KEYFLAG_CANENCRYPT, false, false);
585
586 if (!key)
587 {
588 struct Buffer *prompt = buf_pool_get();
589 buf_printf(prompt, _("Enter keyID for %s: "), mailbox);
590 key = smime_ask_for_key(buf_string(prompt), KEYFLAG_CANENCRYPT, false);
591 buf_pool_release(&prompt);
592 }
593
594 const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
595 size_t smime_keys_len = mutt_str_len(c_smime_keys);
596
597 const char *const c_smime_default_key = cs_subset_string(NeoMutt->sub, "smime_default_key");
598 k = key ? key->hash : NONULL(c_smime_default_key);
599
600 /* if the key is different from last time */
601 if ((buf_len(&SmimeKeyToUse) <= smime_keys_len) ||
602 !mutt_istr_equal(k, SmimeKeyToUse.data + smime_keys_len + 1))
603 {
605 buf_printf(&SmimeKeyToUse, "%s/%s", NONULL(c_smime_keys), k);
606 const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
607 buf_printf(&SmimeCertToUse, "%s/%s", NONULL(c_smime_certificates), k);
608 }
609
610 smime_key_free(&key);
611}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:491
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:291
void smime_class_void_passphrase(void)
Forget the cached passphrase - Implements CryptModuleSpecs::void_passphrase() -.
Definition: smime.c:149
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:496
static struct SmimeKey * smime_get_key_by_addr(const char *mailbox, KeyFlags abilities, bool only_public_key, bool oppenc_mode)
Find an SIME key by address.
Definition: smime.c:416
static struct SmimeKey * smime_ask_for_key(const char *prompt, KeyFlags abilities, bool only_public_key)
Ask the user to select a key.
Definition: smime.c:543
char * data
Pointer to data.
Definition: buffer.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_handle_cert_email()

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

Process an email containing certificates.

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

Definition at line 704 of file smime.c.

706{
707 char email[256] = { 0 };
708 int rc = -1, count = 0;
709 pid_t pid;
710
711 FILE *fp_err = mutt_file_mkstemp();
712 if (!fp_err)
713 {
714 mutt_perror(_("Can't create temporary file"));
715 return 1;
716 }
717
718 FILE *fp_out = mutt_file_mkstemp();
719 if (!fp_out)
720 {
721 mutt_file_fclose(&fp_err);
722 mutt_perror(_("Can't create temporary file"));
723 return 1;
724 }
725
726 const struct Expando *c_smime_get_cert_email_command =
727 cs_subset_expando(NeoMutt->sub, "smime_get_cert_email_command");
728 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), certificate,
729 NULL, NULL, NULL, NULL, NULL, NULL, c_smime_get_cert_email_command);
730 if (pid == -1)
731 {
732 mutt_message(_("Error: unable to create OpenSSL subprocess"));
733 mutt_file_fclose(&fp_err);
734 mutt_file_fclose(&fp_out);
735 return 1;
736 }
737
738 filter_wait(pid);
739
740 fflush(fp_out);
741 rewind(fp_out);
742 fflush(fp_err);
743 rewind(fp_err);
744
745 while ((fgets(email, sizeof(email), fp_out)))
746 {
747 size_t len = mutt_str_len(email);
748 if (len && (email[len - 1] == '\n'))
749 email[len - 1] = '\0';
750 if (mutt_istr_startswith(email, mailbox))
751 rc = 1;
752
753 rc = (rc < 0) ? 0 : rc;
754 count++;
755 }
756
757 if (rc == -1)
758 {
759 mutt_endwin();
760 mutt_file_copy_stream(fp_err, stdout);
761 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
762 rc = 1;
763 }
764 else if (rc == 0)
765 {
766 rc = 1;
767 }
768 else
769 {
770 rc = 0;
771 }
772
773 if (copy && buffer && num)
774 {
775 (*num) = count;
776 *buffer = MUTT_MEM_CALLOC(count, char *);
777 count = 0;
778
779 rewind(fp_out);
780 while ((fgets(email, sizeof(email), fp_out)))
781 {
782 size_t len = mutt_str_len(email);
783 if (len && (email[len - 1] == '\n'))
784 email[len - 1] = '\0';
785 (*buffer)[count] = MUTT_MEM_CALLOC(mutt_str_len(email) + 1, char);
786 strncpy((*buffer)[count], email, mutt_str_len(email));
787 count++;
788 }
789 }
790 else if (copy)
791 {
792 rc = 2;
793 }
794
795 mutt_file_fclose(&fp_out);
796 mutt_file_fclose(&fp_err);
797
798 return rc;
799}
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
Definition: config_type.c:357
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:173
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:151
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:287
#define mutt_message(...)
Definition: logging2.h:91
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:220
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:242
static pid_t smime_invoke(FILE **fp_smime_in, FILE **fp_smime_out, FILE **fp_smime_err, int fp_smime_infd, int fp_smime_outfd, int fp_smime_errfd, const char *fname, const char *sig_fname, const char *cryptalg, const char *digestalg, const char *key, const char *certificates, const char *intermediates, const struct Expando *exp)
Run an SMIME command.
Definition: smime.c:225
Parsed Expando trees.
Definition: expando.h:41
#define mutt_file_mkstemp()
Definition: tmp.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_extract_certificate()

static char * smime_extract_certificate ( const char *  infile)
static

Extract an SMIME certificate from a file.

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

Definition at line 806 of file smime.c.

807{
808 FILE *fp_err = NULL;
809 FILE *fp_out = NULL;
810 FILE *fp_cert = NULL;
811 char *rc = NULL;
812 pid_t pid;
813 int empty;
814
815 struct Buffer *pk7out = buf_pool_get();
816 struct Buffer *certfile = buf_pool_get();
817
818 fp_err = mutt_file_mkstemp();
819 if (!fp_err)
820 {
821 mutt_perror(_("Can't create temporary file"));
822 goto cleanup;
823 }
824
825 buf_mktemp(pk7out);
826 fp_out = mutt_file_fopen(buf_string(pk7out), "w+");
827 if (!fp_out)
828 {
829 mutt_perror("%s", buf_string(pk7out));
830 goto cleanup;
831 }
832
833 /* Step 1: Convert the signature to a PKCS#7 structure, as we can't
834 * extract the full set of certificates directly. */
835 const struct Expando *c_smime_pk7out_command = cs_subset_expando(NeoMutt->sub, "smime_pk7out_command");
836 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), infile,
837 NULL, NULL, NULL, NULL, NULL, NULL, c_smime_pk7out_command);
838 if (pid == -1)
839 {
840 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
841 goto cleanup;
842 }
843
844 filter_wait(pid);
845
846 fflush(fp_out);
847 rewind(fp_out);
848 fflush(fp_err);
849 rewind(fp_err);
850 empty = (fgetc(fp_out) == EOF);
851 if (empty)
852 {
853 mutt_perror("%s", buf_string(pk7out));
854 mutt_file_copy_stream(fp_err, stdout);
855 goto cleanup;
856 }
857 mutt_file_fclose(&fp_out);
858
859 buf_mktemp(certfile);
860 fp_cert = mutt_file_fopen(buf_string(certfile), "w+");
861 if (!fp_cert)
862 {
863 mutt_perror("%s", buf_string(certfile));
865 goto cleanup;
866 }
867
868 // Step 2: Extract the certificates from a PKCS#7 structure.
869 const struct Expando *c_smime_get_cert_command = cs_subset_expando(NeoMutt->sub, "smime_get_cert_command");
870 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_cert), fileno(fp_err),
871 buf_string(pk7out), NULL, NULL, NULL, NULL, NULL, NULL,
872 c_smime_get_cert_command);
873 if (pid == -1)
874 {
875 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
877 goto cleanup;
878 }
879
880 filter_wait(pid);
881
883
884 fflush(fp_cert);
885 rewind(fp_cert);
886 fflush(fp_err);
887 rewind(fp_err);
888 empty = (fgetc(fp_cert) == EOF);
889 if (empty)
890 {
891 mutt_file_copy_stream(fp_err, stdout);
892 goto cleanup;
893 }
894
895 mutt_file_fclose(&fp_cert);
896
897 rc = buf_strdup(certfile);
898
899cleanup:
900 mutt_file_fclose(&fp_err);
901 if (fp_out)
902 {
903 mutt_file_fclose(&fp_out);
905 }
906 if (fp_cert)
907 {
908 mutt_file_fclose(&fp_cert);
909 mutt_file_unlink(buf_string(certfile));
910 }
911 buf_pool_release(&pk7out);
912 buf_pool_release(&certfile);
913 return rc;
914}
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:571
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:221
#define buf_mktemp(buf)
Definition: tmp.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_extract_signer_certificate()

static char * smime_extract_signer_certificate ( const char *  infile)
static

Extract the signer's certificate.

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

Definition at line 921 of file smime.c.

922{
923 char *cert = NULL;
924 struct Buffer *certfile = NULL;
925 pid_t pid;
926 int empty;
927
928 FILE *fp_err = mutt_file_mkstemp();
929 if (!fp_err)
930 {
931 mutt_perror(_("Can't create temporary file"));
932 return NULL;
933 }
934
935 certfile = buf_pool_get();
936 buf_mktemp(certfile);
937 FILE *fp_out = mutt_file_fopen(buf_string(certfile), "w+");
938 if (!fp_out)
939 {
940 mutt_file_fclose(&fp_err);
941 mutt_perror("%s", buf_string(certfile));
942 goto cleanup;
943 }
944
945 /* Extract signer's certificate
946 */
947 const struct Expando *c_smime_get_signer_cert_command =
948 cs_subset_expando(NeoMutt->sub, "smime_get_signer_cert_command");
949 pid = smime_invoke(NULL, NULL, NULL, -1, -1, fileno(fp_err), infile, NULL, NULL, NULL,
950 NULL, buf_string(certfile), NULL, c_smime_get_signer_cert_command);
951 if (pid == -1)
952 {
953 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
954 goto cleanup;
955 }
956
957 filter_wait(pid);
958
959 fflush(fp_out);
960 rewind(fp_out);
961 fflush(fp_err);
962 rewind(fp_err);
963 empty = (fgetc(fp_out) == EOF);
964 if (empty)
965 {
966 mutt_endwin();
967 mutt_file_copy_stream(fp_err, stdout);
969 goto cleanup;
970 }
971
972 mutt_file_fclose(&fp_out);
973 cert = buf_strdup(certfile);
974
975cleanup:
976 mutt_file_fclose(&fp_err);
977 if (fp_out)
978 {
979 mutt_file_fclose(&fp_out);
980 mutt_file_unlink(buf_string(certfile));
981 }
982 buf_pool_release(&certfile);
983 return cert;
984}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_invoke_encrypt()

static pid_t smime_invoke_encrypt ( FILE **  fp_smime_in,
FILE **  fp_smime_out,
FILE **  fp_smime_err,
int  fp_smime_infd,
int  fp_smime_outfd,
int  fp_smime_errfd,
const char *  fname,
const char *  uids 
)
static

Use SMIME to encrypt a file.

Parameters
[out]fp_smime_instdin for the command, or NULL (OPTIONAL)
[out]fp_smime_outstdout for the command, or NULL (OPTIONAL)
[out]fp_smime_errstderr for the command, or NULL (OPTIONAL)
[in]fp_smime_infdstdin for the command, or -1 (OPTIONAL)
[in]fp_smime_outfdstdout for the command, or -1 (OPTIONAL)
[in]fp_smime_errfdstderr for the command, or -1 (OPTIONAL)
[in]fnameFilename to pass to the command
[in]uidsList of IDs/fingerprints, space separated
Return values
numPID of the created process
-1Error creating pipes or forking
Note
fp_smime_in has priority over fp_smime_infd. Likewise fp_smime_out and fp_smime_err.

Definition at line 1149 of file smime.c.

1153{
1154 const char *const c_smime_encrypt_with = cs_subset_string(NeoMutt->sub, "smime_encrypt_with");
1155 const struct Expando *c_smime_encrypt_command = cs_subset_expando(NeoMutt->sub, "smime_encrypt_command");
1156 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1157 fp_smime_outfd, fp_smime_errfd, fname, NULL, c_smime_encrypt_with,
1158 NULL, NULL, uids, NULL, c_smime_encrypt_command);
1159}
+ 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 1176 of file smime.c.

1179{
1180 const char *const c_smime_sign_digest_alg = cs_subset_string(NeoMutt->sub, "smime_sign_digest_alg");
1181 const struct Expando *c_smime_sign_command = cs_subset_expando(NeoMutt->sub, "smime_sign_command");
1182 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd, fp_smime_outfd,
1183 fp_smime_errfd, fname, NULL, NULL, c_smime_sign_digest_alg,
1185 buf_string(&SmimeIntermediateToUse), c_smime_sign_command);
1186}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ openssl_md_to_smime_micalg()

static char * openssl_md_to_smime_micalg ( const char *  md)
static

Change the algorithm names.

Parameters
mdOpenSSL message digest name
Return values
ptrSMIME Message Integrity Check algorithm

The openssl -md doesn't want hyphens: md5, sha1, sha224, sha256, sha384, sha512 However, the micalg does: md5, sha-1, sha-224, sha-256, sha-384, sha-512

Note
The caller should free the returned string

Definition at line 1335 of file smime.c.

1336{
1337 if (!md)
1338 return NULL;
1339
1340 char *micalg = NULL;
1341 if (mutt_istr_startswith(md, "sha"))
1342 {
1343 mutt_str_asprintf(&micalg, "sha-%s", md + 3);
1344 }
1345 else
1346 {
1347 micalg = mutt_str_dup(md);
1348 }
1349
1350 return micalg;
1351}
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:803
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_invoke_verify()

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

Use SMIME to verify a file.

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

Definition at line 1523 of file smime.c.

1527{
1528 const struct Expando *c_smime_verify_opaque_command =
1529 cs_subset_expando(NeoMutt->sub, "smime_verify_opaque_command");
1530 const struct Expando *c_smime_verify_command = cs_subset_expando(NeoMutt->sub, "smime_verify_command");
1531 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd, fp_smime_outfd,
1532 fp_smime_errfd, fname, sig_fname, NULL, NULL, NULL, NULL, NULL,
1533 (opaque ? c_smime_verify_opaque_command : c_smime_verify_command));
1534}
+ 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 1551 of file smime.c.

1554{
1555 const struct Expando *c_smime_decrypt_command = cs_subset_expando(NeoMutt->sub, "smime_decrypt_command");
1556 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1557 fp_smime_outfd, fp_smime_errfd, fname, NULL, NULL, NULL,
1559 NULL, c_smime_decrypt_command);
1560}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_handle_entity()

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

Handle type application/pkcs7-mime.

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

This can either be a signed or an encrypted message.

Definition at line 1679 of file smime.c.

1680{
1681 struct Buffer *tmpfname = buf_pool_get();
1682 FILE *fp_smime_out = NULL, *fp_smime_in = NULL, *fp_smime_err = NULL;
1683 FILE *fp_tmp = NULL, *fp_out = NULL;
1684 struct Body *p = NULL;
1685 pid_t pid = -1;
1687
1688 if (!(type & APPLICATION_SMIME))
1689 return NULL;
1690
1691 /* Because of the mutt_body_handler() we avoid the buffer pool. */
1692 fp_smime_out = mutt_file_mkstemp();
1693 if (!fp_smime_out)
1694 {
1695 mutt_perror(_("Can't create temporary file"));
1696 goto cleanup;
1697 }
1698
1699 fp_smime_err = mutt_file_mkstemp();
1700 if (!fp_smime_err)
1701 {
1702 mutt_perror(_("Can't create temporary file"));
1703 goto cleanup;
1704 }
1705
1706 buf_mktemp(tmpfname);
1707 fp_tmp = mutt_file_fopen(buf_string(tmpfname), "w+");
1708 if (!fp_tmp)
1709 {
1710 mutt_perror("%s", buf_string(tmpfname));
1711 goto cleanup;
1712 }
1713
1714 if (!mutt_file_seek(state->fp_in, b->offset, SEEK_SET))
1715 {
1716 goto cleanup;
1717 }
1718
1719 mutt_file_copy_bytes(state->fp_in, fp_tmp, b->length);
1720
1721 fflush(fp_tmp);
1722 mutt_file_fclose(&fp_tmp);
1723
1724 if ((type & SEC_ENCRYPT) &&
1725 ((pid = smime_invoke_decrypt(&fp_smime_in, NULL, NULL, -1, fileno(fp_smime_out),
1726 fileno(fp_smime_err), buf_string(tmpfname))) == -1))
1727 {
1728 mutt_file_unlink(buf_string(tmpfname));
1729 if (state->flags & STATE_DISPLAY)
1730 {
1731 state_attach_puts(state, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1732 }
1733 goto cleanup;
1734 }
1735 else if ((type & SEC_SIGNOPAQUE) &&
1736 ((pid = smime_invoke_verify(&fp_smime_in, NULL, NULL, -1,
1737 fileno(fp_smime_out), fileno(fp_smime_err), NULL,
1738 buf_string(tmpfname), SEC_SIGNOPAQUE)) == -1))
1739 {
1740 mutt_file_unlink(buf_string(tmpfname));
1741 if (state->flags & STATE_DISPLAY)
1742 {
1743 state_attach_puts(state, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1744 }
1745 goto cleanup;
1746 }
1747
1748 if (type & SEC_ENCRYPT)
1749 {
1752 fputs(SmimePass, fp_smime_in);
1753 fputc('\n', fp_smime_in);
1754 }
1755
1756 mutt_file_fclose(&fp_smime_in);
1757
1758 filter_wait(pid);
1759 mutt_file_unlink(buf_string(tmpfname));
1760
1761 if (state->flags & STATE_DISPLAY)
1762 {
1763 fflush(fp_smime_err);
1764 rewind(fp_smime_err);
1765
1766 const int c = fgetc(fp_smime_err);
1767 if (c != EOF)
1768 {
1769 ungetc(c, fp_smime_err);
1770
1771 crypt_current_time(state, "OpenSSL");
1772 mutt_file_copy_stream(fp_smime_err, state->fp_out);
1773 state_attach_puts(state, _("[-- End of OpenSSL output --]\n\n"));
1774 }
1775
1776 if (type & SEC_ENCRYPT)
1777 {
1778 state_attach_puts(state, _("[-- The following data is S/MIME encrypted --]\n"));
1779 }
1780 else
1781 {
1782 state_attach_puts(state, _("[-- The following data is S/MIME signed --]\n"));
1783 }
1784 }
1785
1786 fflush(fp_smime_out);
1787 rewind(fp_smime_out);
1788
1789 if (type & SEC_ENCRYPT)
1790 {
1791 /* void the passphrase, even if that wasn't the problem */
1792 if (fgetc(fp_smime_out) == EOF)
1793 {
1794 mutt_error(_("Decryption failed"));
1796 }
1797 rewind(fp_smime_out);
1798 }
1799
1800 if (fp_out_file)
1801 {
1802 fp_out = fp_out_file;
1803 }
1804 else
1805 {
1806 fp_out = mutt_file_mkstemp();
1807 if (!fp_out)
1808 {
1809 mutt_perror(_("Can't create temporary file"));
1810 goto cleanup;
1811 }
1812 }
1813 char buf[8192] = { 0 };
1814 while (fgets(buf, sizeof(buf) - 1, fp_smime_out))
1815 {
1816 const size_t len = mutt_str_len(buf);
1817 if ((len > 1) && (buf[len - 2] == '\r'))
1818 {
1819 buf[len - 2] = '\n';
1820 buf[len - 1] = '\0';
1821 }
1822 fputs(buf, fp_out);
1823 }
1824 fflush(fp_out);
1825 rewind(fp_out);
1826
1827 const long size = mutt_file_get_size_fp(fp_out);
1828 if (size == 0)
1829 {
1830 goto cleanup;
1831 }
1832 p = mutt_read_mime_header(fp_out, 0);
1833 if (p)
1834 {
1835 p->length = size - p->offset;
1836
1837 mutt_parse_part(fp_out, p);
1838
1839 if (state->flags & STATE_DISPLAY)
1841
1842 /* Store any protected headers in the parent so they can be
1843 * accessed for index updates after the handler recursion is done.
1844 * This is done before the handler to prevent a nested encrypted
1845 * handler from freeing the headers. */
1847 b->mime_headers = p->mime_headers;
1848 p->mime_headers = NULL;
1849
1850 if (state->fp_out)
1851 {
1852 rewind(fp_out);
1853 FILE *fp_tmp_buffer = state->fp_in;
1854 state->fp_in = fp_out;
1855 mutt_body_handler(p, state);
1856 state->fp_in = fp_tmp_buffer;
1857 }
1858
1859 /* Embedded multipart signed protected headers override the
1860 * encrypted headers. We need to do this after the handler so
1861 * they can be printed in the pager. */
1862 if (!(type & SMIME_SIGN) && mutt_is_multipart_signed(p) && p->parts &&
1863 p->parts->mime_headers)
1864 {
1867 p->parts->mime_headers = NULL;
1868 }
1869 }
1870 mutt_file_fclose(&fp_smime_out);
1871
1872 if (!fp_out_file)
1873 {
1874 mutt_file_fclose(&fp_out);
1875 mutt_file_unlink(buf_string(tmpfname));
1876 }
1877 fp_out = NULL;
1878
1879 if (state->flags & STATE_DISPLAY)
1880 {
1881 if (type & SEC_ENCRYPT)
1882 state_attach_puts(state, _("[-- End of S/MIME encrypted data --]\n"));
1883 else
1884 state_attach_puts(state, _("[-- End of S/MIME signed data --]\n"));
1885 }
1886
1887 if (type & SEC_SIGNOPAQUE)
1888 {
1889 char *line = NULL;
1890 size_t linelen;
1891
1892 rewind(fp_smime_err);
1893
1894 line = mutt_file_read_line(line, &linelen, fp_smime_err, NULL, MUTT_RL_NO_FLAGS);
1895 if (linelen && mutt_istr_equal(line, "verification successful"))
1896 b->goodsig = true;
1897 FREE(&line);
1898 }
1899 else if (p)
1900 {
1901 b->goodsig = p->goodsig;
1902 b->badsig = p->badsig;
1903 }
1904
1905cleanup:
1906 mutt_file_fclose(&fp_smime_out);
1907 mutt_file_fclose(&fp_smime_err);
1908 mutt_file_fclose(&fp_tmp);
1909 mutt_file_fclose(&fp_out);
1910 buf_pool_release(&tmpfname);
1911 return p;
1912}
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:408
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:609
void crypt_current_time(struct State *state, const char *app_name)
Print the current time.
Definition: crypt.c:65
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1822
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1362
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:126
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:808
int mutt_file_copy_bytes(FILE *fp_in, FILE *fp_out, size_t size)
Copy some content from one file to another.
Definition: file.c:257
long mutt_file_get_size_fp(FILE *fp)
Get the size of a file.
Definition: file.c:1537
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:778
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:40
bool smime_class_valid_passphrase(void)
Ensure we have a valid passphrase - Implements CryptModuleSpecs::valid_passphrase() -.
Definition: smime.c:158
int mutt_protected_headers_handler(struct Body *b_email, struct State *state)
Handler for protected headers - Implements handler_t -.
Definition: crypt.c:1117
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition: handler.c:1632
void state_attach_puts(struct State *state, const char *t)
Write a string to the state.
Definition: state.c:104
#define STATE_DISPLAY
Output is displayed to the user.
Definition: state.h:33
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:82
#define SEC_SIGNOPAQUE
Email has an opaque signature (encrypted)
Definition: lib.h:89
#define SMIME_SIGN
Definition: lib.h:109
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:97
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:84
static char SmimePass[256]
Cached Smime Passphrase.
Definition: smime.c:68
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:1523
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:1551
The body of an email.
Definition: body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:73
LOFF_T offset
offset where the actual data begins
Definition: body.h:52
bool badsig
Bad cryptographic signature (needed to check encrypted s/mime-signatures)
Definition: body.h:43
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:76
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
bool goodsig
Good cryptographic signature.
Definition: body.h:45
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
StateFlags flags
Flags, e.g. STATE_DISPLAY.
Definition: state.h:52
FILE * fp_out
File to write to.
Definition: state.h:50
FILE * fp_in
File to read from.
Definition: state.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ SmimePass

char SmimePass[256]
static

Cached Smime Passphrase.

Definition at line 68 of file smime.c.

◆ SmimeExpTime

time_t SmimeExpTime = 0
static

Unix time when SmimePass expires.

Definition at line 70 of file smime.c.

◆ SmimeKeyToUse

struct Buffer SmimeKeyToUse = { 0 }
static

Smime key to use.

Definition at line 73 of file smime.c.

◆ SmimeCertToUse

struct Buffer SmimeCertToUse = { 0 }
static

Smime certificate to use.

Definition at line 75 of file smime.c.

◆ SmimeIntermediateToUse

struct Buffer SmimeIntermediateToUse = { 0 }
static

Smime intermediate certificate to use.

Definition at line 77 of file smime.c.