NeoMutt  2025-12-11-1039-g550ac6
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 "crypt.h"
#include "cryptglue.h"
#include "expando_smime.h"
#include "module_data.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 (struct NcryptModuleData *mod_data)
 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?
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() -.

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 68 of file smime.c.

69{
71 buf_alloc(&mod_data->smime_key_to_use, 256);
72 buf_alloc(&mod_data->smime_cert_to_use, 256);
73 buf_alloc(&mod_data->smime_intermediate_to_use, 256);
74}
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition buffer.c:342
@ MODULE_ID_NCRYPT
ModuleNcrypt, Ncrypt
Definition module_api.h:82
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:666
Ncrypt private Module data.
Definition module_data.h:39
struct Buffer smime_cert_to_use
S/MIME certificate to use.
Definition module_data.h:59
struct Buffer smime_intermediate_to_use
S/MIME intermediate certificate to use.
Definition module_data.h:60
struct Buffer smime_key_to_use
S/MIME key to use.
Definition module_data.h:58
Container for Accounts, Notifications.
Definition neomutt.h:41
Here is the call graph for this function:
Here is the caller graph for this function:

◆ smime_cleanup()

void smime_cleanup ( struct NcryptModuleData * mod_data)

Clean up smime globals.

Parameters
mod_dataNcrypt module data

Definition at line 80 of file smime.c.

81{
82 buf_dealloc(&mod_data->smime_key_to_use);
85}
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition buffer.c:383
Here is the call graph for this function:
Here is the caller graph for this function:

◆ smime_key_free()

void smime_key_free ( struct SmimeKey ** keylist)
static

Free a list of SMIME keys.

Parameters
[out]keylistList of keys to free

Definition at line 91 of file smime.c.

92{
93 if (!keylist)
94 return;
95
96 struct SmimeKey *key = NULL;
97
98 while (*keylist)
99 {
100 key = *keylist;
101 *keylist = (*keylist)->next;
102
103 FREE(&key->email);
104 FREE(&key->hash);
105 FREE(&key->label);
106 FREE(&key->issuer);
107 FREE(&key);
108 }
109}
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
An SIME key.
Definition smime.h:43
char * hash
Key hash.
Definition smime.h:45
struct SmimeKey * next
Linked list.
Definition smime.h:50
char * issuer
Key issuer.
Definition smime.h:47
char * email
Email address.
Definition smime.h:44
char * label
Key label.
Definition smime.h:46
Here is the caller graph for this function:

◆ smime_copy_key()

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 116 of file smime.c.

117{
118 if (!key)
119 return NULL;
120
121 struct SmimeKey *copy = NULL;
122
123 copy = MUTT_MEM_CALLOC(1, struct SmimeKey);
124 copy->email = mutt_str_dup(key->email);
125 copy->hash = mutt_str_dup(key->hash);
126 copy->label = mutt_str_dup(key->label);
127 copy->issuer = mutt_str_dup(key->issuer);
128 copy->trust = key->trust;
129 copy->flags = key->flags;
130
131 return copy;
132}
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:52
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
KeyFlags flags
Key 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()

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 185 of file smime.c.

187{
189 mutt_debug(LL_DEBUG2, "%s\n", buf_string(buf));
190}
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:161
const struct ExpandoRenderCallback SmimeCommandRenderCallbacks[]
Callbacks for Smime Command Expandos.
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:46
@ MUTT_FORMAT_NONE
No flags are set.
Definition render.h:37
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()

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 214 of file smime.c.

219{
220 struct SmimeCommandContext cctx = { 0 };
221
222 if (!exp)
223 return (pid_t) -1;
224
225 cctx.fname = fname;
226 cctx.sig_fname = sig_fname;
227 cctx.key = key;
228 cctx.cryptalg = cryptalg;
229 cctx.digestalg = digestalg;
232
233 struct Buffer *cmd = buf_pool_get();
234 smime_command(cmd, &cctx, exp);
235
236 pid_t pid = filter_create_fd(buf_string(cmd), fp_smime_in, fp_smime_out,
237 fp_smime_err, fp_smime_infd, fp_smime_outfd,
238 fp_smime_errfd, NeoMutt->env);
239 buf_pool_release(&cmd);
240 return pid;
241}
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:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
static void smime_command(struct Buffer *buf, struct SmimeCommandContext *cctx, const struct Expando *exp)
Format an SMIME command string.
Definition smime.c:185
String manipulation buffer.
Definition buffer.h:36
char ** env
Private copy of the environment variables.
Definition neomutt.h:57
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()

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 249 of file smime.c.

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

◆ smime_get_candidates()

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 339 of file smime.c.

340{
341 char buf[1024] = { 0 };
342 struct SmimeKey *key = NULL;
343 struct SmimeKey *results = NULL;
344 struct SmimeKey **results_end = &results;
345
346 struct Buffer *index_file = buf_pool_get();
347 const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
348 const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
349 buf_printf(index_file, "%s/.index",
350 only_public_key ? NONULL(c_smime_certificates) : NONULL(c_smime_keys));
351
352 FILE *fp = mutt_file_fopen(buf_string(index_file), "r");
353 if (!fp)
354 {
355 mutt_perror("%s", buf_string(index_file));
356 buf_pool_release(&index_file);
357 return NULL;
358 }
359 buf_pool_release(&index_file);
360
361 while (fgets(buf, sizeof(buf), fp))
362 {
363 if (((*search == '\0')) || mutt_istr_find(buf, search))
364 {
365 key = smime_parse_key(buf);
366 if (key)
367 {
368 *results_end = key;
369 results_end = &key->next;
370 }
371 }
372 }
373
374 mutt_file_fclose(&fp);
375
376 return results;
377}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:168
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:144
#define mutt_file_fopen(PATH, MODE)
Definition file.h:143
#define mutt_perror(...)
Definition logging2.h:95
static int search(struct Menu *menu, int op, int *match)
Search a menu.
Definition functions.c:59
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case).
Definition string.c:528
static struct SmimeKey * smime_parse_key(char *buf)
Parse an SMIME key block.
Definition smime.c:249
#define NONULL(x)
Definition string2.h:44
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
Here is the call graph for this function:
Here is the caller graph for this function:

◆ smime_get_key_by_hash()

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 388 of file smime.c.

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

◆ smime_get_key_by_addr()

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 414 of file smime.c.

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

◆ smime_get_key_by_str()

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 496 of file smime.c.

497{
498 if (!str)
499 return NULL;
500
501 struct SmimeKey *results = NULL;
502 struct SmimeKey *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()

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_NONE, HC_OTHER, NULL, NULL) != 0)
557 {
558 goto done;
559 }
560
561 if (buf_is_empty(resp))
562 goto done;
563
564 key = smime_get_key_by_str(buf_string(resp), abilities, only_public_key);
565 if (key)
566 goto done;
567
568 mutt_error(_("No matching keys found for \"%s\""), buf_string(resp));
569 }
570
571done:
572 buf_pool_release(&resp);
573 return key;
574}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:89
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:298
@ MUTT_COMP_NONE
No flags are set.
Definition wdata.h:46
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:502
#define mutt_error(...)
Definition logging2.h:94
@ HC_OTHER
Miscellaneous strings.
Definition lib.h:61
#define _(a)
Definition message.h:28
void mutt_clear_error(void)
Clear the message line (bottom line of screen).
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:496
Here is the call graph for this function:
Here is the caller graph for this function:

◆ getkeys()

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 583 of file smime.c.

584{
586 const char *k = NULL;
587
588 struct SmimeKey *key = smime_get_key_by_addr(mailbox, KEYFLAG_CANENCRYPT, false, false);
589
590 if (!key)
591 {
592 struct Buffer *prompt = buf_pool_get();
593 buf_printf(prompt, _("Enter keyID for %s: "), mailbox);
594 key = smime_ask_for_key(buf_string(prompt), KEYFLAG_CANENCRYPT, false);
595 buf_pool_release(&prompt);
596 }
597
598 const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
599 size_t smime_keys_len = mutt_str_len(c_smime_keys);
600
601 const char *const c_smime_default_key = cs_subset_string(NeoMutt->sub, "smime_default_key");
602 k = key ? key->hash : NONULL(c_smime_default_key);
603
604 /* if the key is different from last time */
605 if ((buf_len(&mod_data->smime_key_to_use) <= smime_keys_len) ||
606 !mutt_istr_equal(k, mod_data->smime_key_to_use.data + smime_keys_len + 1))
607 {
609 buf_printf(&mod_data->smime_key_to_use, "%s/%s", NONULL(c_smime_keys), k);
610 const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
611 buf_printf(&mod_data->smime_cert_to_use, "%s/%s", NONULL(c_smime_certificates), k);
612 }
613
614 smime_key_free(&key);
615}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition buffer.c:497
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:137
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:503
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:414
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()

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 711 of file smime.c.

713{
714 char email[256] = { 0 };
715 int rc = -1;
716 int count = 0;
717 pid_t pid;
718
719 FILE *fp_err = mutt_file_mkstemp();
720 if (!fp_err)
721 {
722 mutt_perror(_("Can't create temporary file"));
723 return 1;
724 }
725
726 FILE *fp_out = mutt_file_mkstemp();
727 if (!fp_out)
728 {
729 mutt_file_fclose(&fp_err);
730 mutt_perror(_("Can't create temporary file"));
731 return 1;
732 }
733
734 const struct Expando *c_smime_get_cert_email_command =
735 cs_subset_expando(NeoMutt->sub, "smime_get_cert_email_command");
736 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), certificate,
737 NULL, NULL, NULL, NULL, NULL, NULL, c_smime_get_cert_email_command);
738 if (pid == -1)
739 {
740 mutt_message(_("Error: unable to create OpenSSL subprocess"));
741 mutt_file_fclose(&fp_err);
742 mutt_file_fclose(&fp_out);
743 return 1;
744 }
745
746 filter_wait(pid);
747
748 fflush(fp_out);
749 fseek(fp_out, 0, SEEK_SET);
750 clearerr(fp_out);
751 fflush(fp_err);
752 fseek(fp_err, 0, SEEK_SET);
753 clearerr(fp_err);
754
755 while ((fgets(email, sizeof(email), fp_out)))
756 {
757 size_t len = mutt_str_len(email);
758 if (len && (email[len - 1] == '\n'))
759 email[len - 1] = '\0';
760 if (mutt_istr_startswith(email, mailbox))
761 rc = 1;
762
763 rc = (rc < 0) ? 0 : rc;
764 count++;
765 }
766
767 if (rc == -1)
768 {
769 mutt_endwin();
770 mutt_file_copy_stream(fp_err, stdout);
771 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
772 rc = 1;
773 }
774 else if (rc == 0)
775 {
776 rc = 1;
777 }
778 else
779 {
780 rc = 0;
781 }
782
783 if (copy && buffer && num)
784 {
785 (*num) = count;
786 *buffer = MUTT_MEM_CALLOC(count, char *);
787 count = 0;
788
789 fseek(fp_out, 0, SEEK_SET);
790 clearerr(fp_out);
791 while ((fgets(email, sizeof(email), fp_out)))
792 {
793 size_t len = mutt_str_len(email);
794 if (len && (email[len - 1] == '\n'))
795 email[len - 1] = '\0';
796 (*buffer)[count] = MUTT_MEM_CALLOC(mutt_str_len(email) + 1, char);
797 strncpy((*buffer)[count], email, mutt_str_len(email));
798 count++;
799 }
800 }
801 else if (copy)
802 {
803 rc = 2;
804 }
805
806 mutt_file_fclose(&fp_out);
807 mutt_file_fclose(&fp_err);
808
809 return rc;
810}
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition curs_lib.c:174
void mutt_endwin(void)
Shutdown curses.
Definition curs_lib.c:152
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition file.c:224
#define mutt_message(...)
Definition logging2.h:93
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition filter.c:231
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition string.c:246
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:214
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()

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 817 of file smime.c.

818{
819 FILE *fp_err = NULL;
820 FILE *fp_out = NULL;
821 FILE *fp_cert = NULL;
822 char *rc = NULL;
823 pid_t pid;
824 int empty;
825
826 struct Buffer *pk7out = buf_pool_get();
827 struct Buffer *certfile = buf_pool_get();
828
829 fp_err = mutt_file_mkstemp();
830 if (!fp_err)
831 {
832 mutt_perror(_("Can't create temporary file"));
833 goto cleanup;
834 }
835
836 buf_mktemp(pk7out);
837 fp_out = mutt_file_fopen(buf_string(pk7out), "w+");
838 if (!fp_out)
839 {
840 mutt_perror("%s", buf_string(pk7out));
841 goto cleanup;
842 }
843
844 /* Step 1: Convert the signature to a PKCS#7 structure, as we can't
845 * extract the full set of certificates directly. */
846 const struct Expando *c_smime_pk7out_command = cs_subset_expando(NeoMutt->sub, "smime_pk7out_command");
847 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_out), fileno(fp_err), infile,
848 NULL, NULL, NULL, NULL, NULL, NULL, c_smime_pk7out_command);
849 if (pid == -1)
850 {
851 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
852 goto cleanup;
853 }
854
855 filter_wait(pid);
856
857 fflush(fp_out);
858 fseek(fp_out, 0, SEEK_SET);
859 clearerr(fp_out);
860 fflush(fp_err);
861 fseek(fp_err, 0, SEEK_SET);
862 clearerr(fp_err);
863 empty = (fgetc(fp_out) == EOF);
864 if (empty)
865 {
866 mutt_perror("%s", buf_string(pk7out));
867 mutt_file_copy_stream(fp_err, stdout);
868 goto cleanup;
869 }
870 mutt_file_fclose(&fp_out);
871
872 buf_mktemp(certfile);
873 fp_cert = mutt_file_fopen(buf_string(certfile), "w+");
874 if (!fp_cert)
875 {
876 mutt_perror("%s", buf_string(certfile));
878 goto cleanup;
879 }
880
881 // Step 2: Extract the certificates from a PKCS#7 structure.
882 const struct Expando *c_smime_get_cert_command = cs_subset_expando(NeoMutt->sub, "smime_get_cert_command");
883 pid = smime_invoke(NULL, NULL, NULL, -1, fileno(fp_cert), fileno(fp_err),
884 buf_string(pk7out), NULL, NULL, NULL, NULL, NULL, NULL,
885 c_smime_get_cert_command);
886 if (pid == -1)
887 {
888 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
890 goto cleanup;
891 }
892
893 filter_wait(pid);
894
896
897 fflush(fp_cert);
898 fseek(fp_cert, 0, SEEK_SET);
899 clearerr(fp_cert);
900 fflush(fp_err);
901 fseek(fp_err, 0, SEEK_SET);
902 clearerr(fp_err);
903 empty = (fgetc(fp_cert) == EOF);
904 if (empty)
905 {
906 mutt_file_copy_stream(fp_err, stdout);
907 goto cleanup;
908 }
909
910 mutt_file_fclose(&fp_cert);
911
912 rc = buf_strdup(certfile);
913
914cleanup:
915 mutt_file_fclose(&fp_err);
916 if (fp_out)
917 {
918 mutt_file_fclose(&fp_out);
920 }
921 if (fp_cert)
922 {
923 mutt_file_fclose(&fp_cert);
924 mutt_file_unlink(buf_string(certfile));
925 }
926 buf_pool_release(&pk7out);
927 buf_pool_release(&certfile);
928 return rc;
929}
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:577
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition file.c:156
#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()

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 936 of file smime.c.

937{
938 char *cert = NULL;
939 struct Buffer *certfile = NULL;
940 pid_t pid;
941 int empty;
942
943 FILE *fp_err = mutt_file_mkstemp();
944 if (!fp_err)
945 {
946 mutt_perror(_("Can't create temporary file"));
947 return NULL;
948 }
949
950 certfile = buf_pool_get();
951 buf_mktemp(certfile);
952 FILE *fp_out = mutt_file_fopen(buf_string(certfile), "w+");
953 if (!fp_out)
954 {
955 mutt_file_fclose(&fp_err);
956 mutt_perror("%s", buf_string(certfile));
957 goto cleanup;
958 }
959
960 /* Extract signer's certificate
961 */
962 const struct Expando *c_smime_get_signer_cert_command =
963 cs_subset_expando(NeoMutt->sub, "smime_get_signer_cert_command");
964 pid = smime_invoke(NULL, NULL, NULL, -1, -1, fileno(fp_err), infile, NULL, NULL, NULL,
965 NULL, buf_string(certfile), NULL, c_smime_get_signer_cert_command);
966 if (pid == -1)
967 {
968 mutt_any_key_to_continue(_("Error: unable to create OpenSSL subprocess"));
969 goto cleanup;
970 }
971
972 filter_wait(pid);
973
974 fflush(fp_out);
975 fseek(fp_out, 0, SEEK_SET);
976 clearerr(fp_out);
977 fflush(fp_err);
978 fseek(fp_err, 0, SEEK_SET);
979 clearerr(fp_err);
980 empty = (fgetc(fp_out) == EOF);
981 if (empty)
982 {
983 mutt_endwin();
984 mutt_file_copy_stream(fp_err, stdout);
986 goto cleanup;
987 }
988
989 mutt_file_fclose(&fp_out);
990 cert = buf_strdup(certfile);
991
992cleanup:
993 mutt_file_fclose(&fp_err);
994 if (fp_out)
995 {
996 mutt_file_fclose(&fp_out);
997 mutt_file_unlink(buf_string(certfile));
998 }
999 buf_pool_release(&certfile);
1000 return cert;
1001}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ smime_invoke_encrypt()

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 1169 of file smime.c.

1173{
1174 const char *const c_smime_encrypt_with = cs_subset_string(NeoMutt->sub, "smime_encrypt_with");
1175 const struct Expando *c_smime_encrypt_command = cs_subset_expando(NeoMutt->sub, "smime_encrypt_command");
1176 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1177 fp_smime_outfd, fp_smime_errfd, fname, NULL, c_smime_encrypt_with,
1178 NULL, NULL, uids, NULL, c_smime_encrypt_command);
1179}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ smime_invoke_sign()

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 1196 of file smime.c.

1199{
1201 const char *const c_smime_sign_digest_alg = cs_subset_string(NeoMutt->sub, "smime_sign_digest_alg");
1202 const struct Expando *c_smime_sign_command = cs_subset_expando(NeoMutt->sub, "smime_sign_command");
1203 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1204 fp_smime_outfd, fp_smime_errfd, fname, NULL, NULL,
1205 c_smime_sign_digest_alg, buf_string(&mod_data->smime_key_to_use),
1206 buf_string(&mod_data->smime_cert_to_use),
1207 buf_string(&mod_data->smime_intermediate_to_use), c_smime_sign_command);
1208}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ openssl_md_to_smime_micalg()

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 1363 of file smime.c.

1364{
1365 if (!md)
1366 return NULL;
1367
1368 char *micalg = NULL;
1369 if (mutt_istr_startswith(md, "sha"))
1370 {
1371 mutt_str_asprintf(&micalg, "sha-%s", md + 3);
1372 }
1373 else
1374 {
1375 micalg = mutt_str_dup(md);
1376 }
1377
1378 return micalg;
1379}
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition string.c:809
Here is the call graph for this function:
Here is the caller graph for this function:

◆ smime_invoke_verify()

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 1562 of file smime.c.

1566{
1567 const struct Expando *c_smime_verify_opaque_command =
1568 cs_subset_expando(NeoMutt->sub, "smime_verify_opaque_command");
1569 const struct Expando *c_smime_verify_command = cs_subset_expando(NeoMutt->sub, "smime_verify_command");
1570 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd, fp_smime_outfd,
1571 fp_smime_errfd, fname, sig_fname, NULL, NULL, NULL, NULL, NULL,
1572 (opaque ? c_smime_verify_opaque_command : c_smime_verify_command));
1573}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ smime_invoke_decrypt()

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 1590 of file smime.c.

1593{
1595 const struct Expando *c_smime_decrypt_command = cs_subset_expando(NeoMutt->sub, "smime_decrypt_command");
1596 return smime_invoke(fp_smime_in, fp_smime_out, fp_smime_err, fp_smime_infd,
1597 fp_smime_outfd, fp_smime_errfd, fname, NULL, NULL, NULL,
1598 buf_string(&mod_data->smime_key_to_use),
1599 buf_string(&mod_data->smime_cert_to_use), NULL,
1600 c_smime_decrypt_command);
1601}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ smime_handle_entity()

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 1724 of file smime.c.

1725{
1727 struct Buffer *tmpfname = buf_pool_get();
1728 FILE *fp_smime_out = NULL;
1729 FILE *fp_smime_in = NULL;
1730 FILE *fp_smime_err = NULL;
1731 FILE *fp_tmp = NULL;
1732 FILE *fp_out = NULL;
1733 struct Body *p = NULL;
1734 pid_t pid = -1;
1736
1737 if (!(type & APPLICATION_SMIME))
1738 return NULL;
1739
1740 /* Because of the mutt_body_handler() we avoid the buffer pool. */
1741 fp_smime_out = mutt_file_mkstemp();
1742 if (!fp_smime_out)
1743 {
1744 mutt_perror(_("Can't create temporary file"));
1745 goto cleanup;
1746 }
1747
1748 fp_smime_err = mutt_file_mkstemp();
1749 if (!fp_smime_err)
1750 {
1751 mutt_perror(_("Can't create temporary file"));
1752 goto cleanup;
1753 }
1754
1755 buf_mktemp(tmpfname);
1756 fp_tmp = mutt_file_fopen(buf_string(tmpfname), "w+");
1757 if (!fp_tmp)
1758 {
1759 mutt_perror("%s", buf_string(tmpfname));
1760 goto cleanup;
1761 }
1762
1763 if (!mutt_file_seek(state->fp_in, b->offset, SEEK_SET))
1764 {
1765 goto cleanup;
1766 }
1767
1768 mutt_file_copy_bytes(state->fp_in, fp_tmp, b->length);
1769
1770 fflush(fp_tmp);
1771 mutt_file_fclose(&fp_tmp);
1772
1773 if ((type & SEC_ENCRYPT) &&
1774 ((pid = smime_invoke_decrypt(&fp_smime_in, NULL, NULL, -1, fileno(fp_smime_out),
1775 fileno(fp_smime_err), buf_string(tmpfname))) == -1))
1776 {
1777 mutt_file_unlink(buf_string(tmpfname));
1778 if (state->flags & STATE_DISPLAY)
1779 {
1780 state_attach_puts(state, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1781 }
1782 goto cleanup;
1783 }
1784 else if ((type & SEC_SIGNOPAQUE) &&
1785 ((pid = smime_invoke_verify(&fp_smime_in, NULL, NULL, -1,
1786 fileno(fp_smime_out), fileno(fp_smime_err), NULL,
1787 buf_string(tmpfname), SEC_SIGNOPAQUE)) == -1))
1788 {
1789 mutt_file_unlink(buf_string(tmpfname));
1790 if (state->flags & STATE_DISPLAY)
1791 {
1792 state_attach_puts(state, _("[-- Error: unable to create OpenSSL subprocess --]\n"));
1793 }
1794 goto cleanup;
1795 }
1796
1797 if (type & SEC_ENCRYPT)
1798 {
1801 fputs(mod_data->smime_pass, fp_smime_in);
1802 fputc('\n', fp_smime_in);
1803 }
1804
1805 mutt_file_fclose(&fp_smime_in);
1806
1807 filter_wait(pid);
1808 mutt_file_unlink(buf_string(tmpfname));
1809
1810 if (state->flags & STATE_DISPLAY)
1811 {
1812 fflush(fp_smime_err);
1813 fseek(fp_smime_err, 0, SEEK_SET);
1814 clearerr(fp_smime_err);
1815
1816 const int c = fgetc(fp_smime_err);
1817 if (c != EOF)
1818 {
1819 ungetc(c, fp_smime_err);
1820
1821 crypt_current_time(state, "OpenSSL");
1822 mutt_file_copy_stream(fp_smime_err, state->fp_out);
1823 state_attach_puts(state, _("[-- End of OpenSSL output --]\n\n"));
1824 }
1825
1826 if (type & SEC_ENCRYPT)
1827 {
1828 state_attach_puts(state, _("[-- The following data is S/MIME encrypted --]\n"));
1829 }
1830 else
1831 {
1832 state_attach_puts(state, _("[-- The following data is S/MIME signed --]\n"));
1833 }
1834 }
1835
1836 fflush(fp_smime_out);
1837 fseek(fp_smime_out, 0, SEEK_SET);
1838 clearerr(fp_smime_out);
1839
1840 if (type & SEC_ENCRYPT)
1841 {
1842 /* void the passphrase, even if that wasn't the problem */
1843 if (fgetc(fp_smime_out) == EOF)
1844 {
1845 mutt_error(_("Decryption failed"));
1847 }
1848 fseek(fp_smime_out, 0, SEEK_SET);
1849 clearerr(fp_smime_out);
1850 }
1851
1852 if (fp_out_file)
1853 {
1854 fp_out = fp_out_file;
1855 }
1856 else
1857 {
1858 fp_out = mutt_file_mkstemp();
1859 if (!fp_out)
1860 {
1861 mutt_perror(_("Can't create temporary file"));
1862 goto cleanup;
1863 }
1864 }
1865 char buf[8192] = { 0 };
1866 while (fgets(buf, sizeof(buf) - 1, fp_smime_out))
1867 {
1868 const size_t len = mutt_str_len(buf);
1869 if ((len > 1) && (buf[len - 2] == '\r'))
1870 {
1871 buf[len - 2] = '\n';
1872 buf[len - 1] = '\0';
1873 }
1874 fputs(buf, fp_out);
1875 }
1876 fflush(fp_out);
1877 fseek(fp_out, 0, SEEK_SET);
1878 clearerr(fp_out);
1879
1880 const long size = mutt_file_get_size_fp(fp_out);
1881 if (size == 0)
1882 {
1883 goto cleanup;
1884 }
1885 p = mutt_read_mime_header(fp_out, 0);
1886 if (p)
1887 {
1888 p->length = size - p->offset;
1889
1890 mutt_parse_part(fp_out, p);
1891
1892 if (state->flags & STATE_DISPLAY)
1894
1895 /* Store any protected headers in the parent so they can be
1896 * accessed for index updates after the handler recursion is done.
1897 * This is done before the handler to prevent a nested encrypted
1898 * handler from freeing the headers. */
1900 b->mime_headers = p->mime_headers;
1901 p->mime_headers = NULL;
1902
1903 if (state->fp_out)
1904 {
1905 fseek(fp_out, 0, SEEK_SET);
1906 clearerr(fp_out);
1907 FILE *fp_tmp_buffer = state->fp_in;
1908 state->fp_in = fp_out;
1909 mutt_body_handler(p, state);
1910 state->fp_in = fp_tmp_buffer;
1911 }
1912
1913 /* Embedded multipart signed protected headers override the
1914 * encrypted headers. We need to do this after the handler so
1915 * they can be printed in the pager. */
1916 if (!(type & SMIME_SIGN) && mutt_is_multipart_signed(p) && p->parts &&
1917 p->parts->mime_headers)
1918 {
1921 p->parts->mime_headers = NULL;
1922 }
1923 }
1924 mutt_file_fclose(&fp_smime_out);
1925
1926 if (!fp_out_file)
1927 {
1928 mutt_file_fclose(&fp_out);
1929 mutt_file_unlink(buf_string(tmpfname));
1930 }
1931 fp_out = NULL;
1932
1933 if (state->flags & STATE_DISPLAY)
1934 {
1935 if (type & SEC_ENCRYPT)
1936 state_attach_puts(state, _("[-- End of S/MIME encrypted data --]\n"));
1937 else
1938 state_attach_puts(state, _("[-- End of S/MIME signed data --]\n"));
1939 }
1940
1941 if (type & SEC_SIGNOPAQUE)
1942 {
1943 char *line = NULL;
1944 size_t linelen = 0;
1945
1946 fseek(fp_smime_err, 0, SEEK_SET);
1947 clearerr(fp_smime_err);
1948
1949 line = mutt_file_read_line(line, &linelen, fp_smime_err, NULL, MUTT_RL_NONE);
1950 if (linelen && mutt_istr_equal(line, "verification successful"))
1951 b->goodsig = true;
1952 FREE(&line);
1953 }
1954 else if (p)
1955 {
1956 b->goodsig = p->goodsig;
1957 b->badsig = p->badsig;
1958 }
1959
1960cleanup:
1961 mutt_file_fclose(&fp_smime_out);
1962 mutt_file_fclose(&fp_smime_err);
1963 mutt_file_fclose(&fp_tmp);
1964 mutt_file_fclose(&fp_out);
1965 buf_pool_release(&tmpfname);
1966 return p;
1967}
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition crypt.c:409
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition crypt.c:610
void crypt_current_time(struct State *state, const char *app_name)
Print the current time.
Definition crypt.c:64
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition parse.c:1982
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition parse.c:1517
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition envelope.c:125
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:678
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:192
long mutt_file_get_size_fp(FILE *fp)
Get the size of a file.
Definition file.c:1433
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition file.c:648
@ MUTT_RL_NONE
No flags are set.
Definition file.h:43
bool smime_class_valid_passphrase(void)
Ensure we have a valid passphrase - Implements CryptModuleSpecs::valid_passphrase() -.
Definition smime.c:147
int mutt_protected_headers_handler(struct Body *b_email, struct State *state)
Handler for protected headers - Implements handler_t -.
Definition crypt.c:1124
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition handler.c:1675
void state_attach_puts(struct State *state, const char *t)
Write a string to the state.
Definition state.c:104
@ STATE_DISPLAY
Output is displayed to the user.
Definition state.h:37
uint16_t SecurityFlags
Definition lib.h:104
@ SEC_SIGNOPAQUE
Email has an opaque signature (encrypted).
Definition lib.h:97
@ SEC_ENCRYPT
Email is encrypted.
Definition lib.h:92
#define SMIME_SIGN
Email is S/MIME signed.
Definition lib.h:119
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition lib.h:107
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:1562
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:1590
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
char smime_pass[256]
Cached S/MIME Passphrase.
Definition module_data.h:56
StateFlags flags
Flags, e.g. STATE_DISPLAY.
Definition state.h:58
FILE * fp_out
File to write to.
Definition state.h:56
FILE * fp_in
File to read from.
Definition state.h:55
Here is the call graph for this function:
Here is the caller graph for this function: