NeoMutt  2020-08-21-74-g346364
Teaching an old dog new tricks
DOXYGEN
crypt_gpgme.c File Reference

Wrapper for PGP/SMIME calls to GPGME. More...

#include "config.h"
#include <errno.h>
#include <gpg-error.h>
#include <gpgme.h>
#include <langinfo.h>
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/stat.h>
#include <time.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 "crypt_gpgme.h"
#include "ncrypt/lib.h"
#include "send/lib.h"
#include "crypt.h"
#include "handler.h"
#include "hook.h"
#include "mutt_attach.h"
#include "mutt_logging.h"
#include "muttlib.h"
#include "options.h"
#include "state.h"
#include "autocrypt/lib.h"
+ Include dependency graph for crypt_gpgme.c:

Go to the source code of this file.

Data Structures

struct  CryptCache
 Internal cache for GPGME. More...
 

Macros

#define CRYPT_KV_VALID   (1 << 0)
 
#define CRYPT_KV_ADDR   (1 << 1)
 
#define CRYPT_KV_STRING   (1 << 2)
 
#define CRYPT_KV_STRONGID   (1 << 3)
 
#define CRYPT_KV_MATCH   (CRYPT_KV_ADDR | CRYPT_KV_STRING)
 
#define PKA_NOTATION_NAME   "pka-address@gnupg.org"
 
#define _LINE_COMPARE(_x, _y)   line_compare(_x, sizeof(_x) - 1, _y)
 
#define MESSAGE(_y)   _LINE_COMPARE("MESSAGE-----", _y)
 
#define SIGNED_MESSAGE(_y)   _LINE_COMPARE("SIGNED MESSAGE-----", _y)
 
#define PUBLIC_KEY_BLOCK(_y)   _LINE_COMPARE("PUBLIC KEY BLOCK-----", _y)
 
#define BEGIN_PGP_SIGNATURE(_y)   _LINE_COMPARE("-----BEGIN PGP SIGNATURE-----", _y)
 

Functions

static bool is_pka_notation (gpgme_sig_notation_t notation)
 Is this the standard pka email address. More...
 
static void redraw_if_needed (gpgme_ctx_t ctx)
 accommodate for a redraw if needed More...
 
const char * crypt_keyid (struct CryptKeyInfo *k)
 Find the ID for the key. More...
 
static const char * crypt_long_keyid (struct CryptKeyInfo *k)
 Find the Long ID for the key. More...
 
static const char * crypt_short_keyid (struct CryptKeyInfo *k)
 Get the short keyID for a key. More...
 
static const char * crypt_fpr (struct CryptKeyInfo *k)
 Get the hexstring fingerprint from a key. More...
 
const char * crypt_fpr_or_lkeyid (struct CryptKeyInfo *k)
 Find the fingerprint of a key. More...
 
struct CryptKeyInfocrypt_copy_key (struct CryptKeyInfo *key)
 Return a copy of KEY. More...
 
static void crypt_key_free (struct CryptKeyInfo **keylist)
 Release all the keys in a list. More...
 
bool crypt_id_is_strong (struct CryptKeyInfo *key)
 Is the key strong. More...
 
int crypt_id_is_valid (struct CryptKeyInfo *key)
 Is key ID valid. More...
 
static int crypt_id_matches_addr (struct Address *addr, struct Address *u_addr, struct CryptKeyInfo *key)
 Does the key ID match the address. More...
 
gpgme_ctx_t create_gpgme_context (bool for_smime)
 Create a new GPGME context. More...
 
static gpgme_data_t create_gpgme_data (void)
 Create a new GPGME data object. More...
 
static gpgme_data_t body_to_data_object (struct Body *a, bool convert)
 Create GPGME object from the mail body. More...
 
static gpgme_data_t file_to_data_object (FILE *fp, long offset, size_t length)
 Create GPGME data object from file. More...
 
static int data_object_to_stream (gpgme_data_t data, FILE *fp)
 Write a GPGME data object to a file. More...
 
static char * data_object_to_tempfile (gpgme_data_t data, FILE **fp_ret)
 Copy a data object to a temporary file. More...
 
static void recipient_set_free (gpgme_key_t **p_rset)
 Free a set of recipients. More...
 
static gpgme_key_t * create_recipient_set (const char *keylist, bool use_smime)
 Create a GpgmeRecipientSet from a string of keys. More...
 
static bool set_signer_from_address (gpgme_ctx_t ctx, const char *address, bool for_smime)
 Try to set the context's signer from the address. More...
 
static int set_signer (gpgme_ctx_t ctx, const struct AddressList *al, bool for_smime)
 Make sure that the correct signer is set. More...
 
static gpgme_error_t set_pka_sig_notation (gpgme_ctx_t ctx)
 Set the signature notation. More...
 
static char * encrypt_gpgme_object (gpgme_data_t plaintext, char *keylist, bool use_smime, bool combined_signed, const struct AddressList *from)
 Encrypt the GPGPME data object. More...
 
static int get_micalg (gpgme_ctx_t ctx, int use_smime, char *buf, size_t buflen)
 Find the "micalg" parameter from the last GPGME operation. More...
 
static void print_time (time_t t, struct State *s)
 Print the date/time according to the locale. More...
 
static struct Bodysign_message (struct Body *a, const struct AddressList *from, bool use_smime)
 Sign a message. More...
 
struct Bodypgp_gpgme_sign_message (struct Body *a, const struct AddressList *from)
 Implements CryptModuleSpecs::sign_message() More...
 
struct Bodysmime_gpgme_sign_message (struct Body *a, const struct AddressList *from)
 Implements CryptModuleSpecs::sign_message() More...
 
struct Bodypgp_gpgme_encrypt_message (struct Body *a, char *keylist, bool sign, const struct AddressList *from)
 Implements CryptModuleSpecs::pgp_encrypt_message() More...
 
struct Bodysmime_gpgme_build_smime_entity (struct Body *a, char *keylist)
 Implements CryptModuleSpecs::smime_build_smime_entity() More...
 
static int show_sig_summary (unsigned long sum, gpgme_ctx_t ctx, gpgme_key_t key, int idx, struct State *s, gpgme_signature_t sig)
 Show a signature summary. More...
 
static void show_fingerprint (gpgme_key_t key, struct State *state)
 Write a key's fingerprint. More...
 
static void show_one_sig_validity (gpgme_ctx_t ctx, int idx, struct State *s)
 Show the validity of a key used for one signature. More...
 
static void print_smime_keyinfo (const char *msg, gpgme_signature_t sig, gpgme_key_t key, struct State *s)
 Print key info about an SMIME key. More...
 
static int show_one_sig_status (gpgme_ctx_t ctx, int idx, struct State *s)
 Show information about one signature. More...
 
static int verify_one (struct Body *sigbdy, struct State *s, const char *tempfile, bool is_smime)
 Do the actual verification step. More...
 
int pgp_gpgme_verify_one (struct Body *sigbdy, struct State *s, const char *tempfile)
 Implements CryptModuleSpecs::verify_one() More...
 
int smime_gpgme_verify_one (struct Body *sigbdy, struct State *s, const char *tempfile)
 Implements CryptModuleSpecs::verify_one() More...
 
static struct Bodydecrypt_part (struct Body *a, struct State *s, FILE *fp_out, bool is_smime, int *r_is_signed)
 Decrypt a PGP or SMIME message. More...
 
int pgp_gpgme_decrypt_mime (FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
 Implements CryptModuleSpecs::decrypt_mime() More...
 
int smime_gpgme_decrypt_mime (FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
 Implements CryptModuleSpecs::decrypt_mime() More...
 
static int pgp_gpgme_extract_keys (gpgme_data_t keydata, FILE **fp)
 Write PGP keys to a file. More...
 
static int line_compare (const char *a, size_t n, const char *b)
 Compare two strings ignore line endings. More...
 
static int pgp_check_traditional_one_body (FILE *fp, struct Body *b)
 Check one inline PGP body part. More...
 
int pgp_gpgme_check_traditional (FILE *fp, struct Body *b, bool just_one)
 Implements CryptModuleSpecs::pgp_check_traditional() More...
 
void pgp_gpgme_invoke_import (const char *fname)
 Implements CryptModuleSpecs::pgp_invoke_import() More...
 
static void copy_clearsigned (gpgme_data_t data, struct State *s, char *charset)
 Copy a clearsigned message. More...
 
int pgp_gpgme_application_handler (struct Body *m, struct State *s)
 Implements CryptModuleSpecs::application_handler() More...
 
int pgp_gpgme_encrypted_handler (struct Body *a, struct State *s)
 Implements CryptModuleSpecs::encrypted_handler() More...
 
int smime_gpgme_application_handler (struct Body *a, struct State *s)
 Implements CryptModuleSpecs::application_handler() More...
 
unsigned int key_check_cap (gpgme_key_t key, enum KeyCap cap)
 Check the capabilities of a key. More...
 
static char * list_to_pattern (struct ListHead *list)
 Convert STailQ to GPGME-compatible pattern. More...
 
static struct CryptKeyInfoget_candidates (struct ListHead *hints, SecurityFlags app, int secret)
 Get a list of keys which are candidates for the selection. More...
 
static void crypt_add_string_to_hints (const char *str, struct ListHead *hints)
 Split a string and add the parts to a List. More...
 
static struct CryptKeyInfocrypt_getkeybyaddr (struct Address *a, KeyFlags abilities, unsigned int app, int *forced_valid, bool oppenc_mode)
 Find a key by email address. More...
 
static struct CryptKeyInfocrypt_getkeybystr (const char *p, KeyFlags abilities, unsigned int app, int *forced_valid)
 Find a key by string. More...
 
static struct CryptKeyInfocrypt_ask_for_key (char *tag, char *whatfor, KeyFlags abilities, unsigned int app, int *forced_valid)
 Ask the user for a key. More...
 
static char * find_keys (struct AddressList *addrlist, unsigned int app, bool oppenc_mode)
 Find keys of the recipients of the message. More...
 
char * pgp_gpgme_find_keys (struct AddressList *addrlist, bool oppenc_mode)
 Implements CryptModuleSpecs::find_keys() More...
 
char * smime_gpgme_find_keys (struct AddressList *addrlist, bool oppenc_mode)
 Implements CryptModuleSpecs::find_keys() More...
 
int mutt_gpgme_select_secret_key (struct Buffer *keyid)
 Select a private Autocrypt key for a new account. More...
 
struct Bodypgp_gpgme_make_key_attachment (void)
 Implements CryptModuleSpecs::pgp_make_key_attachment() More...
 
static void init_common (void)
 Initialise code common to PGP and SMIME parts of GPGME. More...
 
static void init_pgp (void)
 Initialise the PGP crypto backend. More...
 
static void init_smime (void)
 Initialise the SMIME crypto backend. More...
 
void pgp_gpgme_init (void)
 Implements CryptModuleSpecs::init() More...
 
void smime_gpgme_init (void)
 Implements CryptModuleSpecs::init() More...
 
static int gpgme_send_menu (struct Email *e, bool is_smime)
 Show the user the encryption/signing menu. More...
 
int pgp_gpgme_send_menu (struct Email *e)
 Implements CryptModuleSpecs::send_menu() More...
 
int smime_gpgme_send_menu (struct Email *e)
 Implements CryptModuleSpecs::send_menu() More...
 
static bool verify_sender (struct Email *e)
 Verify the sender of a message. More...
 
int smime_gpgme_verify_sender (struct Mailbox *m, struct Email *e)
 Implements CryptModuleSpecs::smime_verify_sender() More...
 
void pgp_gpgme_set_sender (const char *sender)
 Implements CryptModuleSpecs::set_sender() More...
 
const char * mutt_gpgme_print_version (void)
 Get version of GPGME. More...
 

Variables

static struct CryptCacheid_defaults = NULL
 
static gpgme_key_t signature_key = NULL
 
static char * current_sender = NULL
 

Detailed Description

Wrapper for PGP/SMIME calls to GPGME.

Authors
  • Michael R. Elkins
  • Thomas Roessler
  • Thomas Roessler
  • Oliver Ehli
  • 2018 g10 Code GmbH
  • Michael R. Elkins
  • Pietro Cerutti

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

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

Definition in file crypt_gpgme.c.

Macro Definition Documentation

◆ CRYPT_KV_VALID

#define CRYPT_KV_VALID   (1 << 0)

Definition at line 75 of file crypt_gpgme.c.

◆ CRYPT_KV_ADDR

#define CRYPT_KV_ADDR   (1 << 1)

Definition at line 76 of file crypt_gpgme.c.

◆ CRYPT_KV_STRING

#define CRYPT_KV_STRING   (1 << 2)

Definition at line 77 of file crypt_gpgme.c.

◆ CRYPT_KV_STRONGID

#define CRYPT_KV_STRONGID   (1 << 3)

Definition at line 78 of file crypt_gpgme.c.

◆ CRYPT_KV_MATCH

#define CRYPT_KV_MATCH   (CRYPT_KV_ADDR | CRYPT_KV_STRING)

Definition at line 79 of file crypt_gpgme.c.

◆ PKA_NOTATION_NAME

#define PKA_NOTATION_NAME   "pka-address@gnupg.org"

Definition at line 96 of file crypt_gpgme.c.

◆ _LINE_COMPARE

#define _LINE_COMPARE (   _x,
  _y 
)    line_compare(_x, sizeof(_x) - 1, _y)

Definition at line 98 of file crypt_gpgme.c.

◆ MESSAGE

#define MESSAGE (   _y)    _LINE_COMPARE("MESSAGE-----", _y)

Definition at line 99 of file crypt_gpgme.c.

◆ SIGNED_MESSAGE

#define SIGNED_MESSAGE (   _y)    _LINE_COMPARE("SIGNED MESSAGE-----", _y)

Definition at line 100 of file crypt_gpgme.c.

◆ PUBLIC_KEY_BLOCK

#define PUBLIC_KEY_BLOCK (   _y)    _LINE_COMPARE("PUBLIC KEY BLOCK-----", _y)

Definition at line 101 of file crypt_gpgme.c.

◆ BEGIN_PGP_SIGNATURE

#define BEGIN_PGP_SIGNATURE (   _y)    _LINE_COMPARE("-----BEGIN PGP SIGNATURE-----", _y)

Definition at line 102 of file crypt_gpgme.c.

Function Documentation

◆ is_pka_notation()

static bool is_pka_notation ( gpgme_sig_notation_t  notation)
static

Is this the standard pka email address.

Parameters
notationGPGME notation
Return values
trueIf it is

Definition at line 110 of file crypt_gpgme.c.

111 {
112  return mutt_str_equal(notation->name, PKA_NOTATION_NAME);
113 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
#define PKA_NOTATION_NAME
Definition: crypt_gpgme.c:96
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ redraw_if_needed()

static void redraw_if_needed ( gpgme_ctx_t  ctx)
static

accommodate for a redraw if needed

Parameters
ctxGPGME handle

Definition at line 119 of file crypt_gpgme.c.

120 {
121 #if (GPGME_VERSION_NUMBER < 0x010800)
122  /* gpgme_get_ctx_flag is not available in GPGME < 1.8.0. In this case, stay
123  * on the safe side and always redraw. */
124  (void) ctx;
126 #else
127  const char *s = gpgme_get_ctx_flag(ctx, "redraw");
128  if (!s /* flag not known */ || *s /* flag true */)
129  {
131  }
132 #endif
133 }
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:130
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_keyid()

const char* crypt_keyid ( struct CryptKeyInfo k)

Find the ID for the key.

Parameters
kKey to use
Return values
ptrID string for the key

Return the keyID for the key K. Note that this string is valid as long as K is valid

Definition at line 347 of file crypt_gpgme.c.

348 {
349  const char *s = "????????";
350 
351  if (k->kobj && k->kobj->subkeys)
352  {
353  s = k->kobj->subkeys->keyid;
354  if ((!C_PgpLongIds) && (strlen(s) == 16))
355  {
356  /* Return only the short keyID. */
357  s += 8;
358  }
359  }
360 
361  return s;
362 }
gpgme_key_t kobj
Definition: crypt_gpgme.h:46
bool C_PgpLongIds
Config: Display long PGP key IDs to the user.
Definition: config.c:63
+ Here is the caller graph for this function:

◆ crypt_long_keyid()

static const char* crypt_long_keyid ( struct CryptKeyInfo k)
static

Find the Long ID for the key.

Parameters
kKey to use
Return values
ptrLong ID string for the key

Return the long keyID for the key K.

Definition at line 371 of file crypt_gpgme.c.

372 {
373  const char *s = "????????????????";
374 
375  if (k->kobj && k->kobj->subkeys)
376  {
377  s = k->kobj->subkeys->keyid;
378  }
379 
380  return s;
381 }
gpgme_key_t kobj
Definition: crypt_gpgme.h:46
+ Here is the caller graph for this function:

◆ crypt_short_keyid()

static const char* crypt_short_keyid ( struct CryptKeyInfo k)
static

Get the short keyID for a key.

Parameters
kKey to use
Return values
ptrShort key string

Definition at line 388 of file crypt_gpgme.c.

389 {
390  const char *s = "????????";
391 
392  if (k->kobj && k->kobj->subkeys)
393  {
394  s = k->kobj->subkeys->keyid;
395  if (strlen(s) == 16)
396  s += 8;
397  }
398 
399  return s;
400 }
gpgme_key_t kobj
Definition: crypt_gpgme.h:46
+ Here is the caller graph for this function:

◆ crypt_fpr()

static const char* crypt_fpr ( struct CryptKeyInfo k)
static

Get the hexstring fingerprint from a key.

Parameters
kKey to use
Return values
ptrHexstring fingerprint

Definition at line 407 of file crypt_gpgme.c.

408 {
409  const char *s = "";
410 
411  if (k->kobj && k->kobj->subkeys)
412  s = k->kobj->subkeys->fpr;
413 
414  return s;
415 }
gpgme_key_t kobj
Definition: crypt_gpgme.h:46
+ Here is the caller graph for this function:

◆ crypt_fpr_or_lkeyid()

const char* crypt_fpr_or_lkeyid ( struct CryptKeyInfo k)

Find the fingerprint of a key.

Parameters
kKey to examine
Return values
ptrFingerprint if available, otherwise the long keyid

Definition at line 422 of file crypt_gpgme.c.

423 {
424  const char *s = "????????????????";
425 
426  if (k->kobj && k->kobj->subkeys)
427  {
428  if (k->kobj->subkeys->fpr)
429  s = k->kobj->subkeys->fpr;
430  else
431  s = k->kobj->subkeys->keyid;
432  }
433 
434  return s;
435 }
gpgme_key_t kobj
Definition: crypt_gpgme.h:46
+ Here is the caller graph for this function:

◆ crypt_copy_key()

struct CryptKeyInfo* crypt_copy_key ( struct CryptKeyInfo key)

Return a copy of KEY.

Parameters
keyKey to copy
Return values
ptrCopy of key

Definition at line 442 of file crypt_gpgme.c.

443 {
444  struct CryptKeyInfo *k = NULL;
445 
446  k = mutt_mem_calloc(1, sizeof(*k));
447  k->kobj = key->kobj;
448  gpgme_key_ref(key->kobj);
449  k->idx = key->idx;
450  k->uid = key->uid;
451  k->flags = key->flags;
452  k->validity = key->validity;
453 
454  return k;
455 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
A stored PGP key.
Definition: crypt_gpgme.h:43
int idx
and the user ID at this index
Definition: crypt_gpgme.h:47
const char * uid
and for convenience point to this user ID
Definition: crypt_gpgme.h:48
gpgme_key_t kobj
Definition: crypt_gpgme.h:46
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.h:49
gpgme_validity_t validity
uid validity (cached for convenience)
Definition: crypt_gpgme.h:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_key_free()

static void crypt_key_free ( struct CryptKeyInfo **  keylist)
static

Release all the keys in a list.

Parameters
[out]keylistList of keys

Definition at line 461 of file crypt_gpgme.c.

462 {
463  if (!keylist)
464  return;
465 
466  struct CryptKeyInfo *k = NULL;
467 
468  while (*keylist)
469  {
470  k = *keylist;
471  *keylist = (*keylist)->next;
472 
473  gpgme_key_unref(k->kobj);
474  FREE(&k);
475  }
476 }
struct CryptKeyInfo * next
Definition: crypt_gpgme.h:45
A stored PGP key.
Definition: crypt_gpgme.h:43
gpgme_key_t kobj
Definition: crypt_gpgme.h:46
#define FREE(x)
Definition: memory.h:40
+ Here is the caller graph for this function:

◆ crypt_id_is_strong()

bool crypt_id_is_strong ( struct CryptKeyInfo key)

Is the key strong.

Parameters
keyKey to test
Return values
trueValidity of key is sufficient

Definition at line 483 of file crypt_gpgme.c.

484 {
485  if (!key)
486  return false;
487 
488  bool is_strong = false;
489 
490  if ((key->flags & KEYFLAG_ISX509))
491  return true;
492 
493  switch (key->validity)
494  {
495  case GPGME_VALIDITY_MARGINAL:
496  case GPGME_VALIDITY_NEVER:
497  case GPGME_VALIDITY_UNDEFINED:
498  case GPGME_VALIDITY_UNKNOWN:
499  is_strong = false;
500  break;
501 
502  case GPGME_VALIDITY_FULL:
503  case GPGME_VALIDITY_ULTIMATE:
504  is_strong = true;
505  break;
506  }
507 
508  return is_strong;
509 }
#define KEYFLAG_ISX509
Key is an X.509 key.
Definition: lib.h:136
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.h:49
gpgme_validity_t validity
uid validity (cached for convenience)
Definition: crypt_gpgme.h:50
+ Here is the caller graph for this function:

◆ crypt_id_is_valid()

int crypt_id_is_valid ( struct CryptKeyInfo key)

Is key ID valid.

Parameters
keyKey to test
Return values
trueKey is valid

When the key is not marked as unusable

Definition at line 518 of file crypt_gpgme.c.

519 {
520  if (!key)
521  return 0;
522 
523  return !(key->flags & KEYFLAG_CANTUSE);
524 }
#define KEYFLAG_CANTUSE
Definition: lib.h:146
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.h:49
+ Here is the caller graph for this function:

◆ crypt_id_matches_addr()

static int crypt_id_matches_addr ( struct Address addr,
struct Address u_addr,
struct CryptKeyInfo key 
)
static

Does the key ID match the address.

Parameters
addrFirst email address
u_addrSecond email address
keyKey to use
Return values
numFlags, e.g. CRYPT_KV_VALID

Return a bit vector describing how well the addresses ADDR and U_ADDR match and whether KEY is valid.

Definition at line 536 of file crypt_gpgme.c.

538 {
539  int rc = 0;
540 
541  if (crypt_id_is_valid(key))
542  rc |= CRYPT_KV_VALID;
543 
544  if (crypt_id_is_strong(key))
545  rc |= CRYPT_KV_STRONGID;
546 
547  if (addr && u_addr)
548  {
549  if (addr->mailbox && u_addr->mailbox &&
550  mutt_istr_equal(addr->mailbox, u_addr->mailbox))
551  {
552  rc |= CRYPT_KV_ADDR;
553  }
554 
555  if (addr->personal && u_addr->personal &&
556  mutt_istr_equal(addr->personal, u_addr->personal))
557  {
558  rc |= CRYPT_KV_STRING;
559  }
560  }
561 
562  return rc;
563 }
#define CRYPT_KV_STRONGID
Definition: crypt_gpgme.c:78
#define CRYPT_KV_ADDR
Definition: crypt_gpgme.c:76
char * mailbox
Mailbox and host address.
Definition: address.h:37
#define CRYPT_KV_STRING
Definition: crypt_gpgme.c:77
int crypt_id_is_valid(struct CryptKeyInfo *key)
Is key ID valid.
Definition: crypt_gpgme.c:518
bool crypt_id_is_strong(struct CryptKeyInfo *key)
Is the key strong.
Definition: crypt_gpgme.c:483
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
char * personal
Real name of address.
Definition: address.h:36
#define CRYPT_KV_VALID
Definition: crypt_gpgme.c:75
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ create_gpgme_context()

gpgme_ctx_t create_gpgme_context ( bool  for_smime)

Create a new GPGME context.

Parameters
for_smimeIf true, protocol of the context is set to CMS
Return values
ptrNew GPGME context

Definition at line 570 of file crypt_gpgme.c.

571 {
572  gpgme_ctx_t ctx = NULL;
573 
574  gpgme_error_t err = gpgme_new(&ctx);
575 
576 #ifdef USE_AUTOCRYPT
577  if (!err && OptAutocryptGpgme)
578  err = gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_OpenPGP, NULL, C_AutocryptDir);
579 #endif
580 
581  if (err != 0)
582  {
583  mutt_error(_("error creating GPGME context: %s"), gpgme_strerror(err));
584  mutt_exit(1);
585  }
586 
587  if (for_smime)
588  {
589  err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS);
590  if (err != 0)
591  {
592  mutt_error(_("error enabling CMS protocol: %s"), gpgme_strerror(err));
593  mutt_exit(1);
594  }
595  }
596 
597  return ctx;
598 }
char * C_AutocryptDir
Config: Location of autocrypt files, including the GPG keyring and SQLite database.
Definition: config.c:40
#define _(a)
Definition: message.h:28
WHERE bool OptAutocryptGpgme
(pseudo) use Autocrypt context inside ncrypt/crypt_gpgme.c
Definition: options.h:33
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:134
#define mutt_error(...)
Definition: logging.h:84
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ create_gpgme_data()

static gpgme_data_t create_gpgme_data ( void  )
static

Create a new GPGME data object.

Return values
ptrGPGPE data object

This is a wrapper to die on error.

Note
Call gpgme_data_release() to free the data object

Definition at line 608 of file crypt_gpgme.c.

609 {
610  gpgme_data_t data = NULL;
611 
612  gpgme_error_t err = gpgme_data_new(&data);
613  if (err != 0)
614  {
615  mutt_error(_("error creating GPGME data object: %s"), gpgme_strerror(err));
616  mutt_exit(1);
617  }
618  return data;
619 }
#define _(a)
Definition: message.h:28
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:134
#define mutt_error(...)
Definition: logging.h:84
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ body_to_data_object()

static gpgme_data_t body_to_data_object ( struct Body a,
bool  convert 
)
static

Create GPGME object from the mail body.

Parameters
aBody to use
convertIf true, lines are converted to CR-LF if required
Return values
ptrNewly created GPGME data object

Definition at line 664 of file crypt_gpgme.c.

665 {
666  int err = 0;
667  gpgme_data_t data = NULL;
668 
669  struct Buffer *tempfile = mutt_buffer_pool_get();
670  mutt_buffer_mktemp(tempfile);
671  FILE *fp_tmp = mutt_file_fopen(mutt_b2s(tempfile), "w+");
672  if (!fp_tmp)
673  {
674  mutt_perror(mutt_b2s(tempfile));
675  goto cleanup;
676  }
677 
678  mutt_write_mime_header(a, fp_tmp, NeoMutt->sub);
679  fputc('\n', fp_tmp);
680  mutt_write_mime_body(a, fp_tmp, NeoMutt->sub);
681 
682  if (convert)
683  {
684  int c, hadcr = 0;
685  unsigned char buf[1];
686 
687  data = create_gpgme_data();
688  rewind(fp_tmp);
689  while ((c = fgetc(fp_tmp)) != EOF)
690  {
691  if (c == '\r')
692  hadcr = 1;
693  else
694  {
695  if ((c == '\n') && !hadcr)
696  {
697  buf[0] = '\r';
698  gpgme_data_write(data, buf, 1);
699  }
700 
701  hadcr = 0;
702  }
703  /* FIXME: This is quite suboptimal */
704  buf[0] = c;
705  gpgme_data_write(data, buf, 1);
706  }
707  mutt_file_fclose(&fp_tmp);
708  gpgme_data_seek(data, 0, SEEK_SET);
709  }
710  else
711  {
712  mutt_file_fclose(&fp_tmp);
713  err = gpgme_data_new_from_file(&data, mutt_b2s(tempfile), 1);
714  if (err != 0)
715  {
716  mutt_error(_("error allocating data object: %s"), gpgme_strerror(err));
717  gpgme_data_release(data);
718  data = NULL;
719  /* fall through to unlink the tempfile */
720  }
721  }
722  unlink(mutt_b2s(tempfile));
723 
724 cleanup:
725  mutt_buffer_pool_release(&tempfile);
726  return data;
727 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
int mutt_write_mime_body(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:314
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
Container for Accounts, Notifications.
Definition: neomutt.h:36
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
int mutt_write_mime_header(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition: header.c:760
#define mutt_b2s(buf)
Definition: buffer.h:41
char * data
Pointer to data.
Definition: buffer.h:35
static gpgme_data_t create_gpgme_data(void)
Create a new GPGME data object.
Definition: crypt_gpgme.c:608
#define mutt_error(...)
Definition: logging.h:84
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ file_to_data_object()

static gpgme_data_t file_to_data_object ( FILE *  fp,
long  offset,
size_t  length 
)
static

Create GPGME data object from file.

Parameters
fpFile to read from
offsetOffset to start reading from
lengthLength of data to read
Return values
ptrNewly created GPGME data object

Definition at line 736 of file crypt_gpgme.c.

737 {
738  gpgme_data_t data = NULL;
739 
740  int err = gpgme_data_new_from_filepart(&data, NULL, fp, offset, length);
741  if (err != 0)
742  {
743  mutt_error(_("error allocating data object: %s"), gpgme_strerror(err));
744  return NULL;
745  }
746 
747  return data;
748 }
#define _(a)
Definition: message.h:28
char * data
Pointer to data.
Definition: buffer.h:35
#define mutt_error(...)
Definition: logging.h:84
+ Here is the caller graph for this function:

◆ data_object_to_stream()

static int data_object_to_stream ( gpgme_data_t  data,
FILE *  fp 
)
static

Write a GPGME data object to a file.

Parameters
dataGPGME data object
fpFile to write to
Return values
0Success
-1Error

Definition at line 757 of file crypt_gpgme.c.

758 {
759  char buf[4096];
760  ssize_t nread;
761 
762  int err = ((gpgme_data_seek(data, 0, SEEK_SET) == -1) ? gpgme_error_from_errno(errno) : 0);
763  if (err != 0)
764  {
765  mutt_error(_("error rewinding data object: %s"), gpgme_strerror(err));
766  return -1;
767  }
768 
769  while ((nread = gpgme_data_read(data, buf, sizeof(buf))) > 0)
770  {
771  /* fixme: we are not really converting CRLF to LF but just
772  * skipping CR. Doing it correctly needs a more complex logic */
773  for (char *p = buf; nread; p++, nread--)
774  {
775  if (*p != '\r')
776  putc(*p, fp);
777  }
778 
779  if (ferror(fp))
780  {
781  mutt_perror(_("[tempfile]"));
782  return -1;
783  }
784  }
785  if (nread == -1)
786  {
787  mutt_error(_("error reading data object: %s"), strerror(errno));
788  return -1;
789  }
790  return 0;
791 }
#define mutt_perror(...)
Definition: logging.h:85
#define _(a)
Definition: message.h:28
char * data
Pointer to data.
Definition: buffer.h:35
#define mutt_error(...)
Definition: logging.h:84
+ Here is the caller graph for this function:

◆ data_object_to_tempfile()

static char* data_object_to_tempfile ( gpgme_data_t  data,
FILE **  fp_ret 
)
static

Copy a data object to a temporary file.

Parameters
[in]dataGPGME data object
[out]fp_retTemporary file
Return values
ptrName of temporary file

If fp_ret is passed in, the file will be rewound, left open, and returned via that parameter.

Note
The caller must free the returned file name

Definition at line 804 of file crypt_gpgme.c.

805 {
806  ssize_t nread = 0;
807  char *rv = NULL;
808  struct Buffer *tempf = mutt_buffer_pool_get();
809 
810  mutt_buffer_mktemp(tempf);
811 
812  FILE *fp = mutt_file_fopen(mutt_b2s(tempf), "w+");
813  if (!fp)
814  {
815  mutt_perror(_("Can't create temporary file"));
816  goto cleanup;
817  }
818 
819  int err = ((gpgme_data_seek(data, 0, SEEK_SET) == -1) ? gpgme_error_from_errno(errno) : 0);
820  if (err == 0)
821  {
822  char buf[4096];
823 
824  while ((nread = gpgme_data_read(data, buf, sizeof(buf))) > 0)
825  {
826  if (fwrite(buf, nread, 1, fp) != 1)
827  {
828  mutt_perror(mutt_b2s(tempf));
829  mutt_file_fclose(&fp);
830  unlink(mutt_b2s(tempf));
831  goto cleanup;
832  }
833  }
834  }
835  if (fp_ret)
836  rewind(fp);
837  else
838  mutt_file_fclose(&fp);
839  if (nread == -1)
840  {
841  mutt_error(_("error reading data object: %s"), gpgme_strerror(err));
842  unlink(mutt_b2s(tempf));
843  mutt_file_fclose(&fp);
844  goto cleanup;
845  }
846  if (fp_ret)
847  *fp_ret = fp;
848  rv = mutt_buffer_strdup(tempf);
849 
850 cleanup:
851  mutt_buffer_pool_release(&tempf);
852  return rv;
853 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define mutt_b2s(buf)
Definition: buffer.h:41
char * data
Pointer to data.
Definition: buffer.h:35
#define mutt_error(...)
Definition: logging.h:84
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ recipient_set_free()

static void recipient_set_free ( gpgme_key_t **  p_rset)
static

Free a set of recipients.

Parameters
p_rsetSet of GPGME keys

Definition at line 893 of file crypt_gpgme.c.

894 {
895  gpgme_key_t *rset = NULL;
896 
897  if (!p_rset)
898  return;
899 
900  rset = *p_rset;
901  if (!rset)
902  return;
903 
904  while (*rset)
905  {
906  gpgme_key_t k = *rset;
907  gpgme_key_unref(k);
908  rset++;
909  }
910 
911  FREE(p_rset);
912 }
#define FREE(x)
Definition: memory.h:40
+ Here is the caller graph for this function:

◆ create_recipient_set()

static gpgme_key_t* create_recipient_set ( const char *  keylist,
bool  use_smime 
)
static

Create a GpgmeRecipientSet from a string of keys.

Parameters
keylistKeys, space-separated
use_smimeUse SMIME
Return values
ptrGPGME key set

Definition at line 920 of file crypt_gpgme.c.

921 {
922  int err;
923  const char *s = NULL;
924  char buf[100];
925  gpgme_key_t *rset = NULL;
926  unsigned int rset_n = 0;
927  gpgme_key_t key = NULL;
928 
929  gpgme_ctx_t context = create_gpgme_context(use_smime);
930  s = keylist;
931  do
932  {
933  while (*s == ' ')
934  s++;
935  int i;
936  for (i = 0; *s && *s != ' ' && i < sizeof(buf) - 1;)
937  buf[i++] = *s++;
938  buf[i] = '\0';
939  if (*buf != '\0')
940  {
941  if ((i > 1) && (buf[i - 1] == '!'))
942  {
943  /* The user selected to override the validity of that key. */
944  buf[i - 1] = '\0';
945 
946  err = gpgme_get_key(context, buf, &key, 0);
947  if (err == 0)
948  key->uids->validity = GPGME_VALIDITY_FULL;
949  buf[i - 1] = '!';
950  }
951  else
952  err = gpgme_get_key(context, buf, &key, 0);
953  mutt_mem_realloc(&rset, sizeof(*rset) * (rset_n + 1));
954  if (err == 0)
955  rset[rset_n++] = key;
956  else
957  {
958  mutt_error(_("error adding recipient '%s': %s"), buf, gpgme_strerror(err));
959  rset[rset_n] = NULL;
960  recipient_set_free(&rset);
961  gpgme_release(context);
962  return NULL;
963  }
964  }
965  } while (*s);
966 
967  /* NULL terminate. */
968  mutt_mem_realloc(&rset, sizeof(*rset) * (rset_n + 1));
969  rset[rset_n++] = NULL;
970 
971  gpgme_release(context);
972 
973  return rset;
974 }
#define _(a)
Definition: message.h:28
static void recipient_set_free(gpgme_key_t **p_rset)
Free a set of recipients.
Definition: crypt_gpgme.c:893
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:570
#define mutt_error(...)
Definition: logging.h:84
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_signer_from_address()

static bool set_signer_from_address ( gpgme_ctx_t  ctx,
const char *  address,
bool  for_smime 
)
static

Try to set the context's signer from the address.

Parameters
ctxGPGME handle
addressAddress to try to set as a signer
for_smimeUse S/MIME
Return values
trueAddress was set as a signer
falseAddress could not be set as a signer

Definition at line 985 of file crypt_gpgme.c.

986 {
987  gpgme_error_t err;
988  gpgme_key_t key = NULL, key2 = NULL;
989  gpgme_ctx_t listctx = create_gpgme_context(for_smime);
990  err = gpgme_op_keylist_start(listctx, address, 1);
991  if (err == 0)
992  err = gpgme_op_keylist_next(listctx, &key);
993  if (err)
994  {
995  gpgme_release(listctx);
996  mutt_error(_("secret key '%s' not found: %s"), address, gpgme_strerror(err));
997  return false;
998  }
999 
1000  char *fpr = "fpr1";
1001  if (key->subkeys)
1002  fpr = key->subkeys->fpr ? key->subkeys->fpr : key->subkeys->keyid;
1003  while (gpgme_op_keylist_next(listctx, &key2) == 0)
1004  {
1005  char *fpr2 = "fpr2";
1006  if (key2->subkeys)
1007  fpr2 = key2->subkeys->fpr ? key2->subkeys->fpr : key2->subkeys->keyid;
1008  if (!mutt_str_equal(fpr, fpr2))
1009  {
1010  gpgme_key_unref(key);
1011  gpgme_key_unref(key2);
1012  gpgme_release(listctx);
1013  mutt_error(_("ambiguous specification of secret key '%s'\n"), address);
1014  return false;
1015  }
1016  else
1017  {
1018  gpgme_key_unref(key2);
1019  }
1020  }
1021  gpgme_op_keylist_end(listctx);
1022  gpgme_release(listctx);
1023 
1024  gpgme_signers_clear(ctx);
1025  err = gpgme_signers_add(ctx, key);
1026  gpgme_key_unref(key);
1027  if (err)
1028  {
1029  mutt_error(_("error setting secret key '%s': %s"), address, gpgme_strerror(err));
1030  return false;
1031  }
1032  return true;
1033 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
#define _(a)
Definition: message.h:28
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:570
#define mutt_error(...)
Definition: logging.h:84
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_signer()

static int set_signer ( gpgme_ctx_t  ctx,
const struct AddressList *  al,
bool  for_smime 
)
static

Make sure that the correct signer is set.

Parameters
ctxGPGME handle
alFrom AddressList
for_smimeUse S/MIME
Return values
0Success
-1Error

Definition at line 1043 of file crypt_gpgme.c.

1044 {
1045  char *signid = NULL;
1046 
1047  if (for_smime)
1049 #ifdef USE_AUTOCRYPT
1050  else if (OptAutocryptGpgme)
1051  signid = AutocryptSignAs;
1052 #endif
1053  else
1055 
1056  /* Try getting the signing key from config entries */
1057  if (signid && set_signer_from_address(ctx, signid, for_smime))
1058  {
1059  return 0;
1060  }
1061 
1062  /* Try getting the signing key from the From line */
1063  if (al)
1064  {
1065  struct Address *a;
1066  TAILQ_FOREACH(a, al, entries)
1067  {
1068  if (a->mailbox && set_signer_from_address(ctx, a->mailbox, for_smime))
1069  {
1070  return 0;
1071  }
1072  }
1073  }
1074 
1075  return (!signid && !al) ? 0 : -1;
1076 }
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
static bool set_signer_from_address(gpgme_ctx_t ctx, const char *address, bool for_smime)
Try to set the context&#39;s signer from the address.
Definition: crypt_gpgme.c:985
An email address.
Definition: address.h:34
WHERE bool OptAutocryptGpgme
(pseudo) use Autocrypt context inside ncrypt/crypt_gpgme.c
Definition: options.h:33
char * mailbox
Mailbox and host address.
Definition: address.h:37
char * AutocryptSignAs
Autocrypt Key id to sign as.
Definition: config.c:42
char * C_PgpSignAs
Config: Use this alternative key for signing messages.
Definition: config.c:67
char * C_PgpDefaultKey
Config: Default key to use for PGP operations.
Definition: config.c:66
char * C_SmimeDefaultKey
Config: Default key for SMIME operations.
Definition: config.c:69
char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: config.c:70
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_pka_sig_notation()

static gpgme_error_t set_pka_sig_notation ( gpgme_ctx_t  ctx)
static

Set the signature notation.

Parameters
ctxGPGME context
Return values
numGPGME error code, e.g. GPG_ERR_NO_ERROR

Definition at line 1083 of file crypt_gpgme.c.

1084 {
1085  gpgme_error_t err = gpgme_sig_notation_add(ctx, PKA_NOTATION_NAME, current_sender, 0);
1086  if (err)
1087  {
1088  mutt_error(_("error setting PKA signature notation: %s"), gpgme_strerror(err));
1089  }
1090 
1091  return err;
1092 }
#define PKA_NOTATION_NAME
Definition: crypt_gpgme.c:96
#define _(a)
Definition: message.h:28
static char * current_sender
Definition: crypt_gpgme.c:94
#define mutt_error(...)
Definition: logging.h:84
+ Here is the caller graph for this function:

◆ encrypt_gpgme_object()

static char* encrypt_gpgme_object ( gpgme_data_t  plaintext,
char *  keylist,
bool  use_smime,
bool  combined_signed,
const struct AddressList *  from 
)
static

Encrypt the GPGPME data object.

Parameters
plaintextGPGME data object with plain text message
keylistList of keys to encrypt to
use_smimeIf true, use SMIME
combined_signedIf true, sign and encrypt the message (PGP only)
fromThe From header line
Return values
ptrName of temporary file containing encrypted text

Definition at line 1103 of file crypt_gpgme.c.

1105 {
1106  gpgme_error_t err;
1107  gpgme_ctx_t ctx = NULL;
1108  gpgme_data_t ciphertext = NULL;
1109  char *outfile = NULL;
1110 
1111 #if GPGME_VERSION_NUMBER >= 0x010b00 /* GPGME >= 1.11.0 */
1112  struct Buffer *recpstring = mutt_buffer_pool_get();
1113  create_recipient_string(keylist, recpstring, use_smime);
1114  if (mutt_buffer_is_empty(recpstring))
1115  {
1116  mutt_buffer_pool_release(&recpstring);
1117  return NULL;
1118  }
1119 #else
1120  gpgme_key_t *rset = create_recipient_set(keylist, use_smime);
1121  if (!rset)
1122  return NULL;
1123 #endif /* GPGME_VERSION_NUMBER >= 0x010b00 */
1124 
1125  ctx = create_gpgme_context(use_smime);
1126  if (!use_smime)
1127  gpgme_set_armor(ctx, 1);
1128 
1129  ciphertext = create_gpgme_data();
1130 
1131  if (combined_signed)
1132  {
1133  if (set_signer(ctx, from, use_smime))
1134  goto cleanup;
1135 
1136  if (C_CryptUsePka)
1137  {
1138  err = set_pka_sig_notation(ctx);
1139  if (err != 0)
1140  goto cleanup;
1141  }
1142 
1143 #if (GPGME_VERSION_NUMBER >= 0x010b00) /* GPGME >= 1.11.0 */
1144  err = gpgme_op_encrypt_sign_ext(ctx, NULL, mutt_b2s(recpstring),
1145  GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
1146 #else
1147  err = gpgme_op_encrypt_sign(ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
1148 #endif
1149  }
1150  else
1151  {
1152 #if (GPGME_VERSION_NUMBER >= 0x010b00) /* GPGME >= 1.11.0 */
1153  err = gpgme_op_encrypt_ext(ctx, NULL, mutt_b2s(recpstring),
1154  GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
1155 #else
1156  err = gpgme_op_encrypt(ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
1157 #endif
1158  }
1159 
1160  redraw_if_needed(ctx);
1161  if (err != 0)
1162  {
1163  mutt_error(_("error encrypting data: %s"), gpgme_strerror(err));
1164  goto cleanup;
1165  }
1166 
1167  outfile = data_object_to_tempfile(ciphertext, NULL);
1168 
1169 cleanup:
1170 #if (GPGME_VERSION_NUMBER >= 0x010b00) /* GPGME >= 1.11.0 */
1171  mutt_buffer_pool_release(&recpstring);
1172 #else
1173  recipient_set_free(&rset);
1174 #endif
1175  gpgme_release(ctx);
1176  gpgme_data_release(ciphertext);
1177  return outfile;
1178 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
static char * data_object_to_tempfile(gpgme_data_t data, FILE **fp_ret)
Copy a data object to a temporary file.
Definition: crypt_gpgme.c:804
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
static void recipient_set_free(gpgme_key_t **p_rset)
Free a set of recipients.
Definition: crypt_gpgme.c:893
bool C_CryptUsePka
Config: Use GPGME to use PKA (lookup PGP keys using DNS)
Definition: config.c:53
#define mutt_b2s(buf)
Definition: buffer.h:41
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:570
static gpgme_key_t * create_recipient_set(const char *keylist, bool use_smime)
Create a GpgmeRecipientSet from a string of keys.
Definition: crypt_gpgme.c:920
static int set_signer(gpgme_ctx_t ctx, const struct AddressList *al, bool for_smime)
Make sure that the correct signer is set.
Definition: crypt_gpgme.c:1043
static gpgme_data_t create_gpgme_data(void)
Create a new GPGME data object.
Definition: crypt_gpgme.c:608
#define mutt_error(...)
Definition: logging.h:84
static gpgme_error_t set_pka_sig_notation(gpgme_ctx_t ctx)
Set the signature notation.
Definition: crypt_gpgme.c:1083
static void redraw_if_needed(gpgme_ctx_t ctx)
accommodate for a redraw if needed
Definition: crypt_gpgme.c:119
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_micalg()

static int get_micalg ( gpgme_ctx_t  ctx,
int  use_smime,
char *  buf,
size_t  buflen 
)
static

Find the "micalg" parameter from the last GPGME operation.

Parameters
ctxGPGME handle
use_smimeIf set, use SMIME instead of PGP
bufBuffer for the result
buflenLength of buffer
Return values
0Success
-1Error

Find the "Message Integrity Check algorithm" from the last GPGME operation. It is expected that this operation was a sign operation.

Definition at line 1192 of file crypt_gpgme.c.

1193 {
1194  gpgme_sign_result_t result = NULL;
1195  const char *algorithm_name = NULL;
1196 
1197  if (buflen < 5)
1198  return -1;
1199 
1200  *buf = '\0';
1201  result = gpgme_op_sign_result(ctx);
1202  if (result && result->signatures)
1203  {
1204  algorithm_name = gpgme_hash_algo_name(result->signatures->hash_algo);
1205  if (algorithm_name)
1206  {
1207  if (use_smime)
1208  {
1209  /* convert GPGME raw hash name to RFC2633 format */
1210  snprintf(buf, buflen, "%s", algorithm_name);
1211  mutt_str_lower(buf);
1212  }
1213  else
1214  {
1215  /* convert GPGME raw hash name to RFC3156 format */
1216  snprintf(buf, buflen, "pgp-%s", algorithm_name);
1217  mutt_str_lower(buf + 4);
1218  }
1219  }
1220  }
1221 
1222  return (buf[0] != '\0') ? 0 : -1;
1223 }
char * mutt_str_lower(char *s)
Convert all characters in the string to lowercase.
Definition: string.c:504
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_time()

static void print_time ( time_t  t,
struct State s 
)
static

Print the date/time according to the locale.

Parameters
tTimestamp
sState to write to

Definition at line 1230 of file crypt_gpgme.c.

1231 {
1232  char p[256];
1233  mutt_date_localtime_format(p, sizeof(p), nl_langinfo(D_T_FMT), t);
1234  state_puts(s, p);
1235 }
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:680
#define state_puts(STATE, STR)
Definition: state.h:55
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sign_message()

static struct Body* sign_message ( struct Body a,
const struct AddressList *  from,
bool  use_smime 
)
static

Sign a message.

Parameters
aMessage to sign
fromThe From header line
use_smimeIf set, use SMIME instead of PGP
Return values
ptrnew Body
NULLerror

Definition at line 1245 of file crypt_gpgme.c.

1246 {
1247  struct Body *t = NULL;
1248  char *sigfile = NULL;
1249  int err = 0;
1250  char buf[100];
1251  gpgme_ctx_t ctx = NULL;
1252  gpgme_data_t message = NULL, signature = NULL;
1253  gpgme_sign_result_t sigres = NULL;
1254 
1255  crypt_convert_to_7bit(a); /* Signed data _must_ be in 7-bit format. */
1256 
1257  message = body_to_data_object(a, true);
1258  if (!message)
1259  return NULL;
1260  signature = create_gpgme_data();
1261 
1262  ctx = create_gpgme_context(use_smime);
1263  if (!use_smime)
1264  gpgme_set_armor(ctx, 1);
1265 
1266  if (set_signer(ctx, from, use_smime))
1267  {
1268  gpgme_data_release(signature);
1269  gpgme_data_release(message);
1270  gpgme_release(ctx);
1271  return NULL;
1272  }
1273 
1274  if (C_CryptUsePka)
1275  {
1276  err = set_pka_sig_notation(ctx);
1277  if (err != 0)
1278  {
1279  gpgme_data_release(signature);
1280  gpgme_data_release(message);
1281  gpgme_release(ctx);
1282  return NULL;
1283  }
1284  }
1285 
1286  err = gpgme_op_sign(ctx, message, signature, GPGME_SIG_MODE_DETACH);
1287  redraw_if_needed(ctx);
1288  gpgme_data_release(message);
1289  if (err != 0)
1290  {
1291  gpgme_data_release(signature);
1292  gpgme_release(ctx);
1293  mutt_error(_("error signing data: %s"), gpgme_strerror(err));
1294  return NULL;
1295  }
1296  /* Check for zero signatures generated. This can occur when $pgp_sign_as is
1297  * unset and there is no default key specified in ~/.gnupg/gpg.conf */
1298  sigres = gpgme_op_sign_result(ctx);
1299  if (!sigres->signatures)
1300  {
1301  gpgme_data_release(signature);
1302  gpgme_release(ctx);
1303  mutt_error(_("$pgp_sign_as unset and no default key specified in "
1304  "~/.gnupg/gpg.conf"));
1305  return NULL;
1306  }
1307 
1308  sigfile = data_object_to_tempfile(signature, NULL);
1309  gpgme_data_release(signature);
1310  if (!sigfile)
1311  {
1312  gpgme_release(ctx);
1313  return NULL;
1314  }
1315 
1316  t = mutt_body_new();
1317  t->type = TYPE_MULTIPART;
1318  t->subtype = mutt_str_dup("signed");
1319  t->encoding = ENC_7BIT;
1320  t->use_disp = false;
1321  t->disposition = DISP_INLINE;
1322 
1324  mutt_param_set(&t->parameter, "protocol",
1325  use_smime ? "application/pkcs7-signature" : "application/pgp-signature");
1326  /* Get the micalg from GPGME. Old gpgme versions don't support this
1327  * for S/MIME so we assume sha-1 in this case. */
1328  if (get_micalg(ctx, use_smime, buf, sizeof(buf)) == 0)
1329  mutt_param_set(&t->parameter, "micalg", buf);
1330  else if (use_smime)
1331  mutt_param_set(&t->parameter, "micalg", "sha1");
1332  gpgme_release(ctx);
1333 
1334  t->parts = a;
1335  a = t;
1336 
1337  t->parts->next = mutt_body_new();
1338  t = t->parts->next;
1339  t->type = TYPE_APPLICATION;
1340  if (use_smime)
1341  {
1342  t->subtype = mutt_str_dup("pkcs7-signature");
1343  mutt_param_set(&t->parameter, "name", "smime.p7s");
1344  t->encoding = ENC_BASE64;
1345  t->use_disp = true;
1346  t->disposition = DISP_ATTACH;
1347  t->d_filename = mutt_str_dup("smime.p7s");
1348  }
1349  else
1350  {
1351  t->subtype = mutt_str_dup("pgp-signature");
1352  mutt_param_set(&t->parameter, "name", "signature.asc");
1353  t->use_disp = false;
1354  t->disposition = DISP_NONE;
1355  t->encoding = ENC_7BIT;
1356  }
1357  t->filename = sigfile;
1358  t->unlink = true; /* ok to remove this file after sending. */
1359 
1360  return a;
1361 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
static char * data_object_to_tempfile(gpgme_data_t data, FILE **fp_ret)
Copy a data object to a temporary file.
Definition: crypt_gpgme.c:804
7-bit text
Definition: mime.h:49
void crypt_convert_to_7bit(struct Body *a)
Convert an email to 7bit encoding.
Definition: crypt.c:801
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
The body of an email.
Definition: body.h:34
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
void mutt_generate_boundary(struct ParameterList *pl)
Create a unique boundary id for a MIME part.
Definition: multipart.c:86
Content is attached.
Definition: mime.h:63
static int get_micalg(gpgme_ctx_t ctx, int use_smime, char *buf, size_t buflen)
Find the "micalg" parameter from the last GPGME operation.
Definition: crypt_gpgme.c:1192
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
char * subtype
content-type subtype
Definition: body.h:37
bool C_CryptUsePka
Config: Use GPGME to use PKA (lookup PGP keys using DNS)
Definition: config.c:53
static gpgme_data_t body_to_data_object(struct Body *a, bool convert)
Create GPGME object from the mail body.
Definition: crypt_gpgme.c:664
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:570
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
static int set_signer(gpgme_ctx_t ctx, const struct AddressList *al, bool for_smime)
Make sure that the correct signer is set.
Definition: crypt_gpgme.c:1043
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
No preferred disposition.
Definition: mime.h:65
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
static gpgme_data_t create_gpgme_data(void)
Create a new GPGME data object.
Definition: crypt_gpgme.c:608
#define mutt_error(...)
Definition: logging.h:84
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
static gpgme_error_t set_pka_sig_notation(gpgme_ctx_t ctx)
Set the signature notation.
Definition: crypt_gpgme.c:1083
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
static void redraw_if_needed(gpgme_ctx_t ctx)
accommodate for a redraw if needed
Definition: crypt_gpgme.c:119
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
Type: &#39;application/*&#39;.
Definition: mime.h:33
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_gpgme_sign_message()

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

Implements CryptModuleSpecs::sign_message()

Definition at line 1366 of file crypt_gpgme.c.

1367 {
1368  return sign_message(a, from, false);
1369 }
static struct Body * sign_message(struct Body *a, const struct AddressList *from, bool use_smime)
Sign a message.
Definition: crypt_gpgme.c:1245
+ Here is the call graph for this function:

◆ smime_gpgme_sign_message()

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

Implements CryptModuleSpecs::sign_message()

Definition at line 1374 of file crypt_gpgme.c.

1375 {
1376  return sign_message(a, from, true);
1377 }
static struct Body * sign_message(struct Body *a, const struct AddressList *from, bool use_smime)
Sign a message.
Definition: crypt_gpgme.c:1245
+ Here is the call graph for this function:

◆ pgp_gpgme_encrypt_message()

struct Body* pgp_gpgme_encrypt_message ( struct Body a,
char *  keylist,
bool  sign,
const struct AddressList *  from 
)

Implements CryptModuleSpecs::pgp_encrypt_message()

Definition at line 1382 of file crypt_gpgme.c.

1384 {
1385  if (sign)
1387  gpgme_data_t plaintext = body_to_data_object(a, false);
1388  if (!plaintext)
1389  return NULL;
1390 
1391  char *outfile = encrypt_gpgme_object(plaintext, keylist, false, sign, from);
1392  gpgme_data_release(plaintext);
1393  if (!outfile)
1394  return NULL;
1395 
1396  struct Body *t = mutt_body_new();
1397  t->type = TYPE_MULTIPART;
1398  t->subtype = mutt_str_dup("encrypted");
1399  t->encoding = ENC_7BIT;
1400  t->use_disp = false;
1401  t->disposition = DISP_INLINE;
1402 
1404  mutt_param_set(&t->parameter, "protocol", "application/pgp-encrypted");
1405 
1406  t->parts = mutt_body_new();
1407  t->parts->type = TYPE_APPLICATION;
1408  t->parts->subtype = mutt_str_dup("pgp-encrypted");
1409  t->parts->encoding = ENC_7BIT;
1410 
1411  t->parts->next = mutt_body_new();
1413  t->parts->next->subtype = mutt_str_dup("octet-stream");
1414  t->parts->next->encoding = ENC_7BIT;
1415  t->parts->next->filename = outfile;
1416  t->parts->next->use_disp = true;
1418  t->parts->next->unlink = true; /* delete after sending the message */
1419  t->parts->next->d_filename = mutt_str_dup("msg.asc"); /* non pgp/mime
1420  can save */
1421 
1422  return t;
1423 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
7-bit text
Definition: mime.h:49
void crypt_convert_to_7bit(struct Body *a)
Convert an email to 7bit encoding.
Definition: crypt.c:801
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
static char * encrypt_gpgme_object(gpgme_data_t plaintext, char *keylist, bool use_smime, bool combined_signed, const struct AddressList *from)
Encrypt the GPGPME data object.
Definition: crypt_gpgme.c:1103
struct Body * next
next attachment in the list
Definition: body.h:53
The body of an email.
Definition: body.h:34
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
void mutt_generate_boundary(struct ParameterList *pl)
Create a unique boundary id for a MIME part.
Definition: multipart.c:86
Content is attached.
Definition: mime.h:63
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
char * subtype
content-type subtype
Definition: body.h:37
static gpgme_data_t body_to_data_object(struct Body *a, bool convert)
Create GPGME object from the mail body.
Definition: crypt_gpgme.c:664
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
Type: &#39;application/*&#39;.
Definition: mime.h:33
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_gpgme_build_smime_entity()

struct Body* smime_gpgme_build_smime_entity ( struct Body a,
char *  keylist 
)

Implements CryptModuleSpecs::smime_build_smime_entity()

Definition at line 1428 of file crypt_gpgme.c.

1429 {
1430  /* OpenSSL converts line endings to crlf when encrypting. Some clients
1431  * depend on this for signed+encrypted messages: they do not convert line
1432  * endings between decrypting and checking the signature. */
1433  gpgme_data_t plaintext = body_to_data_object(a, true);
1434  if (!plaintext)
1435  return NULL;
1436 
1437  char *outfile = encrypt_gpgme_object(plaintext, keylist, true, false, NULL);
1438  gpgme_data_release(plaintext);
1439  if (!outfile)
1440  return NULL;
1441 
1442  struct Body *t = mutt_body_new();
1443  t->type = TYPE_APPLICATION;
1444  t->subtype = mutt_str_dup("pkcs7-mime");
1445  mutt_param_set(&t->parameter, "name", "smime.p7m");
1446  mutt_param_set(&t->parameter, "smime-type", "enveloped-data");
1447  t->encoding = ENC_BASE64; /* The output of OpenSSL SHOULD be binary */
1448  t->use_disp = true;
1449  t->disposition = DISP_ATTACH;
1450  t->d_filename = mutt_str_dup("smime.p7m");
1451  t->filename = outfile;
1452  t->unlink = true; /* delete after sending the message */
1453  t->parts = 0;
1454  t->next = 0;
1455 
1456  return t;
1457 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
static char * encrypt_gpgme_object(gpgme_data_t plaintext, char *keylist, bool use_smime, bool combined_signed, const struct AddressList *from)
Encrypt the GPGPME data object.
Definition: crypt_gpgme.c:1103
struct Body * next
next attachment in the list
Definition: body.h:53
The body of an email.
Definition: body.h:34
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
Content is attached.
Definition: mime.h:63
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
char * subtype
content-type subtype
Definition: body.h:37
static gpgme_data_t body_to_data_object(struct Body *a, bool convert)
Create GPGME object from the mail body.
Definition: crypt_gpgme.c:664
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
Type: &#39;application/*&#39;.
Definition: mime.h:33
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
+ Here is the call graph for this function:

◆ show_sig_summary()

static int show_sig_summary ( unsigned long  sum,
gpgme_ctx_t  ctx,
gpgme_key_t  key,
int  idx,
struct State s,
gpgme_signature_t  sig 
)
static

Show a signature summary.

Parameters
sumFlags, e.g. GPGME_SIGSUM_KEY_REVOKED
ctxGPGME handle
keySet of keys
idxIndex into key set
sState to use
sigGPGME signature
Return values
0Success
1There is a severe warning

Display the common attributes of the signature summary SUM.

Definition at line 1472 of file crypt_gpgme.c.

1474 {
1475  if (!key)
1476  return 1;
1477 
1478  bool severe = false;
1479 
1480  if ((sum & GPGME_SIGSUM_KEY_REVOKED))
1481  {
1482  state_puts(s, _("Warning: One of the keys has been revoked\n"));
1483  severe = true;
1484  }
1485 
1486  if ((sum & GPGME_SIGSUM_KEY_EXPIRED))
1487  {
1488  time_t at = key->subkeys->expires ? key->subkeys->expires : 0;
1489  if (at)
1490  {
1491  state_puts(
1492  s, _("Warning: The key used to create the signature expired at: "));
1493  print_time(at, s);
1494  state_puts(s, "\n");
1495  }
1496  else
1497  {
1498  state_puts(s, _("Warning: At least one certification key has expired\n"));
1499  }
1500  }
1501 
1502  if ((sum & GPGME_SIGSUM_SIG_EXPIRED))
1503  {
1504  gpgme_signature_t sig2 = NULL;
1505  unsigned int i;
1506 
1507  gpgme_verify_result_t result = gpgme_op_verify_result(ctx);
1508 
1509  for (sig2 = result->signatures, i = 0; sig2 && (i < idx); sig2 = sig2->next, i++)
1510  ; // do nothing
1511 
1512  state_puts(s, _("Warning: The signature expired at: "));
1513  print_time(sig2 ? sig2->exp_timestamp : 0, s);
1514  state_puts(s, "\n");
1515  }
1516 
1517  if ((sum & GPGME_SIGSUM_KEY_MISSING))
1518  {
1519  state_puts(s, _("Can't verify due to a missing key or certificate\n"));
1520  }
1521 
1522  if ((sum & GPGME_SIGSUM_CRL_MISSING))
1523  {
1524  state_puts(s, _("The CRL is not available\n"));
1525  severe = true;
1526  }
1527 
1528  if ((sum & GPGME_SIGSUM_CRL_TOO_OLD))
1529  {
1530  state_puts(s, _("Available CRL is too old\n"));
1531  severe = true;
1532  }
1533 
1534  if ((sum & GPGME_SIGSUM_BAD_POLICY))
1535  state_puts(s, _("A policy requirement was not met\n"));
1536 
1537  if ((sum & GPGME_SIGSUM_SYS_ERROR))
1538  {
1539  const char *t0 = NULL, *t1 = NULL;
1540  gpgme_verify_result_t result = NULL;
1541  gpgme_signature_t sig2 = NULL;
1542  unsigned int i;
1543 
1544  state_puts(s, _("A system error occurred"));
1545 
1546  /* Try to figure out some more detailed system error information. */
1547  result = gpgme_op_verify_result(ctx);
1548  for (sig2 = result->signatures, i = 0; sig2 && (i < idx); sig2 = sig2->next, i++)
1549  ; // do nothing
1550 
1551  if (sig2)
1552  {
1553  t0 = "";
1554  t1 = sig2->wrong_key_usage ? "Wrong_Key_Usage" : "";
1555  }
1556 
1557  if (t0 || t1)
1558  {
1559  state_puts(s, ": ");
1560  if (t0)
1561  state_puts(s, t0);
1562  if (t1 && !(t0 && (strcmp(t0, t1) == 0)))
1563  {
1564  if (t0)
1565  state_puts(s, ",");
1566  state_puts(s, t1);
1567  }
1568  }
1569  state_puts(s, "\n");
1570  }
1571 
1572  if (C_CryptUsePka)
1573  {
1574  if ((sig->pka_trust == 1) && sig->pka_address)
1575  {
1576  state_puts(s, _("WARNING: PKA entry does not match signer's address: "));
1577  state_puts(s, sig->pka_address);
1578  state_puts(s, "\n");
1579  }
1580  else if ((sig->pka_trust == 2) && sig->pka_address)
1581  {
1582  state_puts(s, _("PKA verified signer's address is: "));
1583  state_puts(s, sig->pka_address);
1584  state_puts(s, "\n");
1585  }
1586  }
1587 
1588  return severe;
1589 }
static void print_time(time_t t, struct State *s)
Print the date/time according to the locale.
Definition: crypt_gpgme.c:1230
#define state_puts(STATE, STR)
Definition: state.h:55
#define _(a)
Definition: message.h:28
bool C_CryptUsePka
Config: Use GPGME to use PKA (lookup PGP keys using DNS)
Definition: config.c:53
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ show_fingerprint()

static void show_fingerprint ( gpgme_key_t  key,
struct State state 
)
static

Write a key's fingerprint.

Parameters
keyGPGME key
stateState to write to

Definition at line 1596 of file crypt_gpgme.c.

1597 {
1598  if (!key)
1599  return;
1600 
1601  const char *prefix = _("Fingerprint: ");
1602 
1603  const char *s = key->subkeys ? key->subkeys->fpr : NULL;
1604  if (!s)
1605  return;
1606  bool is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
1607 
1608  char *buf = mutt_mem_malloc(strlen(prefix) + strlen(s) * 4 + 2);
1609  strcpy(buf, prefix);
1610  char *p = buf + strlen(buf);
1611  if (is_pgp && (strlen(s) == 40))
1612  { /* PGP v4 style formatted. */
1613  for (int i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++)
1614  {
1615  *p++ = s[0];
1616  *p++ = s[1];
1617  *p++ = s[2];
1618  *p++ = s[3];
1619  *p++ = ' ';
1620  if (i == 4)
1621  *p++ = ' ';
1622  }
1623  }
1624  else
1625  {
1626  for (int i = 0; *s && s[1] && s[2]; s += 2, i++)
1627  {
1628  *p++ = s[0];
1629  *p++ = s[1];
1630  *p++ = is_pgp ? ' ' : ':';
1631  if (is_pgp && (i == 7))
1632  *p++ = ' ';
1633  }
1634  }
1635 
1636  /* just in case print remaining odd digits */
1637  for (; *s; s++)
1638  *p++ = *s;
1639  *p++ = '\n';
1640  *p = '\0';
1641  state_puts(state, buf);
1642  FREE(&buf);
1643 }
#define state_puts(STATE, STR)
Definition: state.h:55
#define _(a)
Definition: message.h:28
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ show_one_sig_validity()

static void show_one_sig_validity ( gpgme_ctx_t  ctx,
int  idx,
struct State s 
)
static

Show the validity of a key used for one signature.

Parameters
ctxGPGME handle
idxIndex of signature to check
sState to use

Definition at line 1651 of file crypt_gpgme.c.

1652 {
1653  gpgme_signature_t sig = NULL;
1654  const char *txt = NULL;
1655 
1656  gpgme_verify_result_t result = gpgme_op_verify_result(ctx);
1657  if (result)
1658  for (sig = result->signatures; sig && (idx > 0); sig = sig->next, idx--)
1659  ; // do nothing
1660 
1661  switch (sig ? sig->validity : 0)
1662  {
1663  case GPGME_VALIDITY_UNKNOWN:
1664  txt = _("WARNING: We have NO indication whether "
1665  "the key belongs to the person named "
1666  "as shown above\n");
1667  break;
1668  case GPGME_VALIDITY_UNDEFINED:
1669  break;
1670  case GPGME_VALIDITY_NEVER:
1671  txt = _("WARNING: The key does NOT BELONG to "
1672  "the person named as shown above\n");
1673  break;
1674  case GPGME_VALIDITY_MARGINAL:
1675  txt = _("WARNING: It is NOT certain that the key "
1676  "belongs to the person named as shown above\n");
1677  break;
1678  case GPGME_VALIDITY_FULL:
1679  case GPGME_VALIDITY_ULTIMATE:
1680  txt = NULL;
1681  break;
1682  }
1683  if (txt)
1684  state_puts(s, txt);
1685 }
#define state_puts(STATE, STR)
Definition: state.h:55
#define _(a)
Definition: message.h:28
+ Here is the caller graph for this function:

◆ print_smime_keyinfo()

static void print_smime_keyinfo ( const char *  msg,
gpgme_signature_t  sig,
gpgme_key_t  key,
struct State s 
)
static

Print key info about an SMIME key.

Parameters
msgPrefix message to write
sigGPGME signature
keyGPGME key
sState to write to

Definition at line 1694 of file crypt_gpgme.c.

1696 {
1697  int msgwid;
1698 
1699  state_puts(s, msg);
1700  state_puts(s, " ");
1701  /* key is NULL when not present in the user's keyring */
1702  if (key)
1703  {
1704  bool aka = false;
1705  for (gpgme_user_id_t uids = key->uids; uids; uids = uids->next)
1706  {
1707  if (uids->revoked)
1708  continue;
1709  if (aka)
1710  {
1711  msgwid = mutt_strwidth(msg) - mutt_strwidth(_("aka: ")) + 1;
1712  if (msgwid < 0)
1713  msgwid = 0;
1714  for (int i = 0; i < msgwid; i++)
1715  state_puts(s, " ");
1716  state_puts(s, _("aka: "));
1717  }
1718  state_puts(s, uids->uid);
1719  state_puts(s, "\n");
1720 
1721  aka = true;
1722  }
1723  }
1724  else
1725  {
1726  if (sig->fpr)
1727  {
1728  state_puts(s, _("KeyID "));
1729  state_puts(s, sig->fpr);
1730  }
1731  else
1732  {
1733  /* L10N: You will see this message in place of "KeyID "
1734  if the S/MIME key has no ID. This is quite an error. */
1735  state_puts(s, _("no signature fingerprint available"));
1736  }
1737  state_puts(s, "\n");
1738  }
1739 
1740  /* timestamp is 0 when verification failed.
1741  * "Jan 1 1970" is not the created date. */
1742  if (sig->timestamp)
1743  {
1744  msgwid = mutt_strwidth(msg) - mutt_strwidth(_("created: ")) + 1;
1745  if (msgwid < 0)
1746  msgwid = 0;
1747  for (int i = 0; i < msgwid; i++)
1748  state_puts(s, " ");
1749  state_puts(s, _("created: "));
1750  print_time(sig->timestamp, s);
1751  state_puts(s, "\n");
1752  }
1753 }
static void print_time(time_t t, struct State *s)
Print the date/time according to the locale.
Definition: crypt_gpgme.c:1230
#define state_puts(STATE, STR)
Definition: state.h:55
#define _(a)
Definition: message.h:28
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:1359
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ show_one_sig_status()

static int show_one_sig_status ( gpgme_ctx_t  ctx,
int  idx,
struct State s 
)
static

Show information about one signature.

Parameters
ctxGPGME handle of a successful verification
idxIndex
sState to use
Return values
0Normal procession
1A bad signature
2A signature with a warning
-1No more signature

The index should start at 0 and increment for each call/signature.

Definition at line 1767 of file crypt_gpgme.c.

1768 {
1769  const char *fpr = NULL;
1770  gpgme_key_t key = NULL;
1771  bool anybad = false, anywarn = false;
1772  gpgme_signature_t sig = NULL;
1773  gpgme_error_t err = GPG_ERR_NO_ERROR;
1774 
1775  gpgme_verify_result_t result = gpgme_op_verify_result(ctx);
1776  if (result)
1777  {
1778  /* FIXME: this code should use a static variable and remember
1779  * the current position in the list of signatures, IMHO.
1780  * -moritz. */
1781  int i;
1782  for (i = 0, sig = result->signatures; sig && (i < idx); i++, sig = sig->next)
1783  ; // do nothing
1784 
1785  if (!sig)
1786  return -1; /* Signature not found. */
1787 
1788  if (signature_key)
1789  {
1790  gpgme_key_unref(signature_key);
1791  signature_key = NULL;
1792  }
1793 
1794  fpr = sig->fpr;
1795  const unsigned int sum = sig->summary;
1796 
1797  if (gpg_err_code(sig->status) != GPG_ERR_NO_ERROR)
1798  anybad = true;
1799 
1800  if (gpg_err_code(sig->status) != GPG_ERR_NO_PUBKEY)
1801  {
1802  err = gpgme_get_key(ctx, fpr, &key, 0); /* secret key? */
1803  if (err == 0)
1804  {
1805  if (!signature_key)
1806  signature_key = key;
1807  }
1808  else
1809  {
1810  key = NULL; /* Old GPGME versions did not set KEY to NULL on
1811  error. Do it here to avoid a double free. */
1812  }
1813  }
1814  else
1815  {
1816  /* pubkey not present */
1817  }
1818 
1819  if (!s || !s->fp_out || !(s->flags & MUTT_DISPLAY))
1820  ; /* No state information so no way to print anything. */
1821  else if (err != 0)
1822  {
1823  char buf[1024];
1824  snprintf(buf, sizeof(buf), _("Error getting key information for KeyID %s: %s\n"),
1825  fpr, gpgme_strerror(err));
1826  state_puts(s, buf);
1827  anybad = true;
1828  }
1829  else if ((sum & GPGME_SIGSUM_GREEN))
1830  {
1831  print_smime_keyinfo(_("Good signature from:"), sig, key, s);
1832  if (show_sig_summary(sum, ctx, key, idx, s, sig))
1833  anywarn = true;
1834  show_one_sig_validity(ctx, idx, s);
1835  }
1836  else if ((sum & GPGME_SIGSUM_RED))
1837  {
1838  print_smime_keyinfo(_("*BAD* signature from:"), sig, key, s);
1839  show_sig_summary(sum, ctx, key, idx, s, sig);
1840  }
1841  else if (!anybad && key && (key->protocol == GPGME_PROTOCOL_OpenPGP))
1842  { /* We can't decide (yellow) but this is a PGP key with a good
1843  signature, so we display what a PGP user expects: The name,
1844  fingerprint and the key validity (which is neither fully or
1845  ultimate). */
1846  print_smime_keyinfo(_("Good signature from:"), sig, key, s);
1847  show_one_sig_validity(ctx, idx, s);
1848  show_fingerprint(key, s);
1849  if (show_sig_summary(sum, ctx, key, idx, s, sig))
1850  anywarn = true;
1851  }
1852  else /* can't decide (yellow) */
1853  {
1854  print_smime_keyinfo(_("Problem signature from:"), sig, key, s);
1855  /* 0 indicates no expiration */
1856  if (sig->exp_timestamp)
1857  {
1858  /* L10N: This is trying to match the width of the
1859  "Problem signature from:" translation just above. */
1860  state_puts(s, _(" expires: "));
1861  print_time(sig->exp_timestamp, s);
1862  state_puts(s, "\n");
1863  }
1864  show_sig_summary(sum, ctx, key, idx, s, sig);
1865  anywarn = true;
1866  }
1867 
1868  if (key != signature_key)
1869  gpgme_key_unref(key);
1870  }
1871 
1872  return anybad ? 1 : anywarn ? 2 : 0;
1873 }
static void print_time(time_t t, struct State *s)
Print the date/time according to the locale.
Definition: crypt_gpgme.c:1230
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
#define state_puts(STATE, STR)
Definition: state.h:55
static void show_one_sig_validity(gpgme_ctx_t ctx, int idx, struct State *s)
Show the validity of a key used for one signature.
Definition: crypt_gpgme.c:1651
static void print_smime_keyinfo(const char *msg, gpgme_signature_t sig, gpgme_key_t key, struct State *s)
Print key info about an SMIME key.
Definition: crypt_gpgme.c:1694
#define _(a)
Definition: message.h:28
FILE * fp_out
File to write to.
Definition: state.h:47
static int show_sig_summary(unsigned long sum, gpgme_ctx_t ctx, gpgme_key_t key, int idx, struct State *s, gpgme_signature_t sig)
Show a signature summary.
Definition: crypt_gpgme.c:1472
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
static void show_fingerprint(gpgme_key_t key, struct State *state)
Write a key&#39;s fingerprint.
Definition: crypt_gpgme.c:1596
static gpgme_key_t signature_key
Definition: crypt_gpgme.c:93
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ verify_one()

static int verify_one ( struct Body sigbdy,
struct State s,
const char *  tempfile,
bool  is_smime 
)
static

Do the actual verification step.

Parameters
sigbdyMime part containing signature
sState to read from
tempfileTemporary file to read
is_smimeIs the key S/MIME?
Return values
0Success
1Bad signature
2Warnings
-1Error

With is_smime set to true we assume S/MIME.

Definition at line 1888 of file crypt_gpgme.c.

1889 {
1890  int badsig = -1;
1891  int anywarn = 0;
1892  gpgme_ctx_t ctx = NULL;
1893  gpgme_data_t message = NULL;
1894 
1895  gpgme_data_t signature = file_to_data_object(s->fp_in, sigbdy->offset, sigbdy->length);
1896  if (!signature)
1897  return -1;
1898 
1899  /* We need to tell GPGME about the encoding because the backend can't
1900  * auto-detect plain base-64 encoding which is used by S/MIME. */
1901  if (is_smime)
1902  gpgme_data_set_encoding(signature, GPGME_DATA_ENCODING_BASE64);
1903 
1904  int err = gpgme_data_new_from_file(&message, tempfile, 1);
1905  if (err != 0)
1906  {
1907  gpgme_data_release(signature);
1908  mutt_error(_("error allocating data object: %s"), gpgme_strerror(err));
1909  return -1;
1910  }
1911  ctx = create_gpgme_context(is_smime);
1912 
1913  /* Note: We don't need a current time output because GPGME avoids
1914  * such an attack by separating the meta information from the data. */
1915  state_attach_puts(s, _("[-- Begin signature information --]\n"));
1916 
1917  err = gpgme_op_verify(ctx, signature, message, NULL);
1918  gpgme_data_release(message);
1919  gpgme_data_release(signature);
1920 
1921  redraw_if_needed(ctx);
1922  if (err != 0)
1923  {
1924  char buf[200];
1925 
1926  snprintf(buf, sizeof(buf) - 1, _("Error: verification failed: %s\n"),
1927  gpgme_strerror(err));
1928  state_puts(s, buf);
1929  }
1930  else
1931  { /* Verification succeeded, see what the result is. */
1932  gpgme_verify_result_t verify_result = NULL;
1933 
1934  if (signature_key)
1935  {
1936  gpgme_key_unref(signature_key);
1937  signature_key = NULL;
1938  }
1939 
1940  verify_result = gpgme_op_verify_result(ctx);
1941  if (verify_result && verify_result->signatures)
1942  {
1943  bool anybad = false;
1944  int res;
1945  for (int idx = 0; (res = show_one_sig_status(ctx, idx, s)) != -1; idx++)
1946  {
1947  if (res == 1)
1948  anybad = true;
1949  else if (res == 2)
1950  anywarn = 2;
1951  }
1952  if (!anybad)
1953  badsig = 0;
1954  }
1955  }
1956 
1957  if (badsig == 0)
1958  {
1959  gpgme_verify_result_t result = NULL;
1960  gpgme_sig_notation_t notation = NULL;
1961  gpgme_signature_t sig = NULL;
1962 
1963  result = gpgme_op_verify_result(ctx);
1964  if (result)
1965  {
1966  for (sig = result->signatures; sig; sig = sig->next)
1967  {
1968  int non_pka_notations = 0;
1969  for (notation = sig->notations; notation; notation = notation->next)
1970  if (!is_pka_notation(notation))
1971  non_pka_notations++;
1972 
1973  if (non_pka_notations)
1974  {
1975  char buf[128];
1976  snprintf(buf, sizeof(buf),
1977  _("*** Begin Notation (signature by: %s) ***\n"), sig->fpr);
1978  state_puts(s, buf);
1979  for (notation = sig->notations; notation; notation = notation->next)
1980  {
1981  if (is_pka_notation(notation))
1982  continue;
1983 
1984  if (notation->name)
1985  {
1986  state_puts(s, notation->name);
1987  state_puts(s, "=");
1988  }
1989  if (notation->value)
1990  {
1991  state_puts(s, notation->value);
1992  if (!(*notation->value && (notation->value[strlen(notation->value) - 1] == '\n')))
1993  state_puts(s, "\n");
1994  }
1995  }
1996  state_puts(s, _("*** End Notation ***\n"));
1997  }
1998  }
1999  }
2000  }
2001 
2002  gpgme_release(ctx);
2003 
2004  state_attach_puts(s, _("[-- End signature information --]\n\n"));
2005  mutt_debug(LL_DEBUG1, "returning %d\n", badsig);
2006 
2007  return badsig ? 1 : anywarn ? 2 : 0;
2008 }
static gpgme_data_t file_to_data_object(FILE *fp, long offset, size_t length)
Create GPGME data object from file.
Definition: crypt_gpgme.c:736
#define state_puts(STATE, STR)
Definition: state.h:55
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
FILE * fp_in
File to read from.
Definition: state.h:46
bool badsig
Bad cryptographic signature (needed to check encrypted s/mime-signatures)
Definition: body.h:77
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:570
static bool is_pka_notation(gpgme_sig_notation_t notation)
Is this the standard pka email address.
Definition: crypt_gpgme.c:110
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:70
Log at debug level 1.
Definition: logging.h:40
#define mutt_error(...)
Definition: logging.h:84
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
static void redraw_if_needed(gpgme_ctx_t ctx)
accommodate for a redraw if needed
Definition: crypt_gpgme.c:119
static gpgme_key_t signature_key
Definition: crypt_gpgme.c:93
static int show_one_sig_status(gpgme_ctx_t ctx, int idx, struct State *s)
Show information about one signature.
Definition: crypt_gpgme.c:1767
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_gpgme_verify_one()

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

Implements CryptModuleSpecs::verify_one()

Definition at line 2013 of file crypt_gpgme.c.

2014 {
2015  return verify_one(sigbdy, s, tempfile, false);
2016 }
static int verify_one(struct Body *sigbdy, struct State *s, const char *tempfile, bool is_smime)
Do the actual verification step.
Definition: crypt_gpgme.c:1888
+ Here is the call graph for this function:

◆ smime_gpgme_verify_one()

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

Implements CryptModuleSpecs::verify_one()

Definition at line 2021 of file crypt_gpgme.c.

2022 {
2023  return verify_one(sigbdy, s, tempfile, true);
2024 }
static int verify_one(struct Body *sigbdy, struct State *s, const char *tempfile, bool is_smime)
Do the actual verification step.
Definition: crypt_gpgme.c:1888
+ Here is the call graph for this function:

◆ decrypt_part()

static struct Body* decrypt_part ( struct Body a,
struct State s,
FILE *  fp_out,
bool  is_smime,
int *  r_is_signed 
)
static

Decrypt a PGP or SMIME message.

Parameters
[in]aBody of message
[in]sState to use
[in]fp_outFile to write to
[in]is_smimeTrue if an SMIME message
[out]r_is_signedFlag, R_IS_SIGNED (PGP only)
Return values
ptrNewly allocated Body

For PGP returns a flag in R_IS_SIGNED to indicate whether this is a combined encrypted and signed message, for S/MIME it returns true when it is not a encrypted but a signed message.

Definition at line 2039 of file crypt_gpgme.c.

2041 {
2042  if (!a || !s || !fp_out)
2043  return NULL;
2044 
2045  struct stat info;
2046  struct Body *tattach = NULL;
2047  int err = 0;
2048  gpgme_data_t ciphertext = NULL, plaintext = NULL;
2049  bool maybe_signed = false;
2050  bool anywarn = false;
2051  int sig_stat = 0;
2052 
2053  if (r_is_signed)
2054  *r_is_signed = 0;
2055 
2056  gpgme_ctx_t ctx = NULL;
2057 restart:
2058  ctx = create_gpgme_context(is_smime);
2059 
2060  if (a->length < 0)
2061  return NULL;
2062  /* Make a data object from the body, create context etc. */
2063  ciphertext = file_to_data_object(s->fp_in, a->offset, a->length);
2064  if (!ciphertext)
2065  goto cleanup;
2066  plaintext = create_gpgme_data();
2067 
2068  /* Do the decryption or the verification in case of the S/MIME hack. */
2069  if ((!is_smime) || maybe_signed)
2070  {
2071  if (!is_smime)
2072  err = gpgme_op_decrypt_verify(ctx, ciphertext, plaintext);
2073  else if (maybe_signed)
2074  err = gpgme_op_verify(ctx, ciphertext, NULL, plaintext);
2075 
2076  if (err == GPG_ERR_NO_ERROR)
2077  {
2078  /* Check whether signatures have been verified. */
2079  gpgme_verify_result_t verify_result = gpgme_op_verify_result(ctx);
2080  if (verify_result->signatures)
2081  sig_stat = 1;
2082  }
2083  }
2084  else
2085  err = gpgme_op_decrypt(ctx, ciphertext, plaintext);
2086  gpgme_data_release(ciphertext);
2087  ciphertext = NULL;
2088  if (err != 0)
2089  {
2090 #ifdef USE_AUTOCRYPT
2091  /* Abort right away and silently.
2092  * Autocrypt will retry on the normal keyring. */
2093  if (OptAutocryptGpgme)
2094  goto cleanup;
2095 #endif
2096  if (is_smime && !maybe_signed && (gpg_err_code(err) == GPG_ERR_NO_DATA))
2097  {
2098  /* Check whether this might be a signed message despite what the mime
2099  * header told us. Retry then. gpgsm returns the error information
2100  * "unsupported Algorithm '?'" but GPGME will not store this unknown
2101  * algorithm, thus we test that it has not been set. */
2102  gpgme_decrypt_result_t result;
2103 
2104  result = gpgme_op_decrypt_result(ctx);
2105  if (!result->unsupported_algorithm)
2106  {
2107  maybe_signed = true;
2108  gpgme_data_release(plaintext);
2109  plaintext = NULL;
2110  /* gpgsm ends the session after an error; restart it */
2111  gpgme_release(ctx);
2112  ctx = NULL;
2113  goto restart;
2114  }
2115  }
2116  redraw_if_needed(ctx);
2117  if ((s->flags & MUTT_DISPLAY))
2118  {
2119  char buf[200];
2120 
2121  snprintf(buf, sizeof(buf) - 1,
2122  _("[-- Error: decryption failed: %s --]\n\n"), gpgme_strerror(err));
2123  state_attach_puts(s, buf);
2124  }
2125  goto cleanup;
2126  }
2127  redraw_if_needed(ctx);
2128 
2129  /* Read the output from GPGME, and make sure to change CRLF to LF,
2130  * otherwise read_mime_header has a hard time parsing the message. */
2131  if (data_object_to_stream(plaintext, fp_out))
2132  {
2133  goto cleanup;
2134  }
2135  gpgme_data_release(plaintext);
2136  plaintext = NULL;
2137 
2138  if (sig_stat)
2139  {
2140  int res, idx;
2141  int anybad = 0;
2142 
2143  if (r_is_signed)
2144  *r_is_signed = -1; /* A signature exists. */
2145 
2146  if ((s->flags & MUTT_DISPLAY))
2147  {
2148  state_attach_puts(s, _("[-- Begin signature information --]\n"));
2149  }
2150  for (idx = 0; (res = show_one_sig_status(ctx, idx, s)) != -1; idx++)
2151  {
2152  if (res == 1)
2153  anybad = 1;
2154  else if (res == 2)
2155  anywarn = true;
2156  }
2157  if (!anybad && idx && r_is_signed && *r_is_signed)
2158  *r_is_signed = anywarn ? 2 : 1; /* Good signature. */
2159 
2160  if ((s->flags & MUTT_DISPLAY))
2161  {
2162  state_attach_puts(s, _("[-- End signature information --]\n\n"));
2163  }
2164  }
2165  gpgme_release(ctx);
2166  ctx = NULL;
2167 
2168  fflush(fp_out);
2169  rewind(fp_out);
2170  tattach = mutt_read_mime_header(fp_out, 0);
2171  if (tattach)
2172  {
2173  /* Need to set the length of this body part. */
2174  fstat(fileno(fp_out), &info);
2175  tattach->length = info.st_size - tattach->offset;
2176 
2177  tattach->warnsig = anywarn;
2178 
2179  /* See if we need to recurse on this MIME part. */
2180  mutt_parse_part(fp_out, tattach);
2181  }
2182 
2183 cleanup:
2184  gpgme_data_release(ciphertext);
2185  gpgme_data_release(plaintext);
2186  gpgme_release(ctx);
2187 
2188  return tattach;
2189 }
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
static gpgme_data_t file_to_data_object(FILE *fp, long offset, size_t length)
Create GPGME data object from file.
Definition: crypt_gpgme.c:736
static int data_object_to_stream(gpgme_data_t data, FILE *fp)
Write a GPGME data object to a file.
Definition: crypt_gpgme.c:757
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
WHERE bool OptAutocryptGpgme
(pseudo) use Autocrypt context inside ncrypt/crypt_gpgme.c
Definition: options.h:33
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:570
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:70
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1657
static gpgme_data_t create_gpgme_data(void)
Create a new GPGME data object.
Definition: crypt_gpgme.c:608
static void redraw_if_needed(gpgme_ctx_t ctx)
accommodate for a redraw if needed
Definition: crypt_gpgme.c:119
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1267
static int show_one_sig_status(gpgme_ctx_t ctx, int idx, struct State *s)
Show information about one signature.
Definition: crypt_gpgme.c:1767
bool warnsig
Maybe good signature.
Definition: body.h:76
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_gpgme_decrypt_mime()

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

Implements CryptModuleSpecs::decrypt_mime()

Definition at line 2194 of file crypt_gpgme.c.

2195 {
2196  struct State s = { 0 };
2197  struct Body *first_part = b;
2198  int is_signed = 0;
2199  bool need_decode = false;
2200  int saved_type = 0;
2201  LOFF_T saved_offset = 0;
2202  size_t saved_length = 0;
2203  FILE *fp_decoded = NULL;
2204  int rc = 0;
2205 
2206  first_part->goodsig = false;
2207  first_part->warnsig = false;
2208 
2210  {
2211  b = b->parts->next;
2212  /* Some clients improperly encode the octetstream part. */
2213  if (b->encoding != ENC_7BIT)
2214  need_decode = true;
2215  }
2217  {
2218  b = b->parts->next->next;
2219  need_decode = true;
2220  }
2221  else
2222  return -1;
2223 
2224  s.fp_in = fp_in;
2225 
2226  if (need_decode)
2227  {
2228  saved_type = b->type;
2229  saved_offset = b->offset;
2230  saved_length = b->length;
2231 
2232  fp_decoded = mutt_file_mkstemp();
2233  if (!fp_decoded)
2234  {
2235  mutt_perror(_("Can't create temporary file"));
2236  return -1;
2237  }
2238 
2239  fseeko(s.fp_in, b->offset, SEEK_SET);
2240  s.fp_out = fp_decoded;
2241 
2242  mutt_decode_attachment(b, &s);
2243 
2244  fflush(fp_decoded);
2245  b->length = ftello(fp_decoded);
2246  b->offset = 0;
2247  rewind(fp_decoded);
2248  s.fp_in = fp_decoded;
2249  s.fp_out = 0;
2250  }
2251 
2252  *fp_out = mutt_file_mkstemp();
2253  if (!*fp_out)
2254  {
2255  mutt_perror(_("Can't create temporary file"));
2256  rc = -1;
2257  goto bail;
2258  }
2259 
2260  *cur = decrypt_part(b, &s, *fp_out, false, &is_signed);
2261  if (*cur)
2262  {
2263  rewind(*fp_out);
2264  if (is_signed > 0)
2265  first_part->goodsig = true;
2266  }
2267  else
2268  {
2269  rc = -1;
2270  mutt_file_fclose(fp_out);
2271  }
2272 
2273 bail:
2274  if (need_decode)
2275  {
2276  b->type = saved_type;
2277  b->length = saved_length;
2278  b->offset = saved_offset;
2279  mutt_file_fclose(&fp_decoded);
2280  }
2281 
2282  return rc;
2283 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1843
#define mutt_perror(...)
Definition: logging.h:85
7-bit text
Definition: mime.h:49
int mutt_is_valid_multipart_pgp_encrypted(struct Body *b)
Is this a valid multi-part encrypted message?
Definition: crypt.c:471
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
FILE * fp_out
File to write to.
Definition: state.h:47
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
static struct Body * decrypt_part(struct Body *a, struct State *s, FILE *fp_out, bool is_smime, int *r_is_signed)
Decrypt a PGP or SMIME message.
Definition: crypt_gpgme.c:2039
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
bool goodsig
Good cryptographic signature.
Definition: body.h:75
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
#define mutt_file_mkstemp()
Definition: file.h:106
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:508
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Keep track when processing files.
Definition: state.h:44
bool warnsig
Maybe good signature.
Definition: body.h:76
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_gpgme_decrypt_mime()

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

Implements CryptModuleSpecs::decrypt_mime()

Definition at line 2288 of file crypt_gpgme.c.

2289 {
2290  struct State s = { 0 };
2291  int is_signed;
2292  LOFF_T saved_b_offset;
2293  size_t saved_b_length;
2294  int saved_b_type;
2295 
2297  return -1;
2298 
2299  if (b->parts)
2300  return -1;
2301 
2302  /* Decode the body - we need to pass binary CMS to the
2303  * backend. The backend allows for Base64 encoded data but it does
2304  * not allow for QP which I have seen in some messages. So better
2305  * do it here. */
2306  saved_b_type = b->type;
2307  saved_b_offset = b->offset;
2308  saved_b_length = b->length;
2309  s.fp_in = fp_in;
2310  fseeko(s.fp_in, b->offset, SEEK_SET);
2311  FILE *fp_tmp = mutt_file_mkstemp();
2312  if (!fp_tmp)
2313  {
2314  mutt_perror(_("Can't create temporary file"));
2315  return -1;
2316  }
2317 
2318  s.fp_out = fp_tmp;
2319  mutt_decode_attachment(b, &s);
2320  fflush(fp_tmp);
2321  b->length = ftello(s.fp_out);
2322  b->offset = 0;
2323  rewind(fp_tmp);
2324 
2325  memset(&s, 0, sizeof(s));
2326  s.fp_in = fp_tmp;
2327  s.fp_out = 0;
2329  if (!*fp_out)
2330  {
2331  mutt_perror(_("Can't create temporary file"));
2332  return -1;
2333  }
2334 
2335  *cur = decrypt_part(b, &s, *fp_out, true, &is_signed);
2336  if (*cur)
2337  (*cur)->goodsig = is_signed > 0;
2338  b->type = saved_b_type;
2339  b->length = saved_b_length;
2340  b->offset = saved_b_offset;
2341  mutt_file_fclose(&fp_tmp);
2342  rewind(*fp_out);
2343  if (*cur && !is_signed && !(*cur)->parts && mutt_is_application_smime(*cur))
2344  {
2345  /* Assume that this is a opaque signed s/mime message. This is an ugly way
2346  * of doing it but we have anyway a problem with arbitrary encoded S/MIME
2347  * messages: Only the outer part may be encrypted. The entire mime parsing
2348  * should be revamped, probably by keeping the temporary files so that we
2349  * don't need to decrypt them all the time. Inner parts of an encrypted
2350  * part can then point into this file and there won't ever be a need to
2351  * decrypt again. This needs a partial rewrite of the MIME engine. */
2352  struct Body *bb = *cur;
2353 
2354  saved_b_type = bb->type;
2355  saved_b_offset = bb->offset;
2356  saved_b_length = bb->length;
2357  memset(&s, 0, sizeof(s));
2358  s.fp_in = *fp_out;
2359  fseeko(s.fp_in, bb->offset, SEEK_SET);
2360  FILE *fp_tmp2 = mutt_file_mkstemp();
2361  if (!fp_tmp2)
2362  {
2363  mutt_perror(_("Can't create temporary file"));
2364  return -1;
2365  }
2366 
2367  s.fp_out = fp_tmp2;
2368  mutt_decode_attachment(bb, &s);
2369  fflush(fp_tmp2);
2370  bb->length = ftello(s.fp_out);
2371  bb->offset = 0;
2372  rewind(fp_tmp2);
2373  mutt_file_fclose(fp_out);
2374 
2375  memset(&s, 0, sizeof(s));
2376  s.fp_in = fp_tmp2;
2377  s.fp_out = 0;
2378  *fp_out = mutt_file_mkstemp();
2379  if (!*fp_out)
2380  {
2381  mutt_perror(_("Can't create temporary file"));
2382  return -1;
2383  }
2384 
2385  struct Body *b_tmp = decrypt_part(bb, &s, *fp_out, true, &is_signed);
2386  if (b_tmp)
2387  b_tmp->goodsig = is_signed > 0;
2388  bb->type = saved_b_type;
2389  bb->length = saved_b_length;
2390  bb->offset = saved_b_offset;
2391  mutt_file_fclose(&fp_tmp2);
2392  rewind(*fp_out);
2393  mutt_body_free(cur);
2394  *cur = b_tmp;
2395  }
2396  return *cur ? 0 : -1;
2397 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1843
#define mutt_perror(...)
Definition: logging.h:85
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:84
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
FILE * fp_out
File to write to.
Definition: state.h:47
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
static struct Body * decrypt_part(struct Body *a, struct State *s, FILE *fp_out, bool is_smime, int *r_is_signed)
Decrypt a PGP or SMIME message.
Definition: crypt_gpgme.c:2039
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
bool goodsig
Good cryptographic signature.
Definition: body.h:75
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
#define mutt_file_mkstemp()
Definition: file.h:106
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:610
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Keep track when processing files.
Definition: state.h:44
+ Here is the call graph for this function:

◆ pgp_gpgme_extract_keys()

static int pgp_gpgme_extract_keys ( gpgme_data_t  keydata,
FILE **  fp 
)
static

Write PGP keys to a file.

Parameters
[in]keydataGPGME key data
[out]fpTemporary file created with key info
Return values
0Success
-1Error

Definition at line 2406 of file crypt_gpgme.c.

2407 {
2408  /* Before GPGME 1.9.0 and gpg 2.1.14 there was no side-effect free
2409  * way to view key data in GPGME, so we import the key into a
2410  * temporary keyring if we detect an older system. */
2411  bool legacy_api;
2412  struct Buffer *tmpdir = NULL;
2413  gpgme_ctx_t tmpctx = NULL;
2414  gpgme_error_t err;
2415  gpgme_engine_info_t engineinfo = NULL;
2416  gpgme_key_t key = NULL;
2417  gpgme_user_id_t uid = NULL;
2418  gpgme_subkey_t subkey = NULL;
2419  const char *shortid = NULL;
2420  size_t len;
2421  char date[256];
2422  bool more;
2423  int rc = -1;
2424  time_t tt;
2425 
2426 #if GPGME_VERSION_NUMBER >= 0x010900 /* GPGME >= 1.9.0 */
2427  legacy_api = !have_gpg_version("2.1.14");
2428 #else /* GPGME < 1.9.0 */
2429  legacy_api = true;
2430 #endif
2431 
2432  tmpctx = create_gpgme_context(false);
2433 
2434  if (legacy_api)
2435  {
2436  tmpdir = mutt_buffer_pool_get();
2437  mutt_buffer_printf(tmpdir, "%s/neomutt-gpgme-XXXXXX", NONULL(C_Tmpdir));
2438  if (!mkdtemp(tmpdir->data))
2439  {
2440  mutt_debug(LL_DEBUG1, "Error creating temporary GPGME home\n");
2441  goto err_ctx;
2442  }
2443 
2444  engineinfo = gpgme_ctx_get_engine_info(tmpctx);
2445  while (engineinfo && (engineinfo->protocol != GPGME_PROTOCOL_OpenPGP))
2446  engineinfo = engineinfo->next;
2447  if (!engineinfo)
2448  {
2449  mutt_debug(LL_DEBUG1, "Error finding GPGME PGP engine\n");
2450  goto err_tmpdir;
2451  }
2452 
2453  err = gpgme_ctx_set_engine_info(tmpctx, GPGME_PROTOCOL_OpenPGP,
2454  engineinfo->file_name, mutt_b2s(tmpdir));
2455  if (err != GPG_ERR_NO_ERROR)
2456  {
2457  mutt_debug(LL_DEBUG1, "Error setting GPGME context home\n");
2458  goto err_tmpdir;
2459  }
2460  }
2461 
2462  *fp = mutt_file_mkstemp();
2463  if (!*fp)
2464  {
2465  mutt_perror(_("Can't create temporary file"));
2466  goto err_tmpdir;
2467  }
2468 
2469 #if GPGME_VERSION_NUMBER >= 0x010900 /* 1.9.0 */
2470  if (!legacy_api)
2471  err = gpgme_op_keylist_from_data_start(tmpctx, keydata, 0);
2472  else
2473 #endif /* GPGME >= 1.9.0 */
2474  {
2475  err = gpgme_op_keylist_start(tmpctx, NULL, 0);
2476  }
2477  while (err == 0)
2478  {
2479  err = gpgme_op_keylist_next(tmpctx, &key);
2480  if (err != 0)
2481  break;
2482  uid = key->uids;
2483  subkey = key->subkeys;
2484  more = false;
2485  while (subkey)
2486  {
2487  shortid = subkey->keyid;
2488  len = mutt_str_len(subkey->keyid);
2489  if (len > 8)
2490  shortid += len - 8;
2491  tt = subkey->timestamp;
2492  mutt_date_localtime_format(date, sizeof(date), "%Y-%m-%d", tt);
2493 
2494  if (more)
2495  {
2496  fprintf(*fp, "sub %5.5s %u/%8s %s\n", gpgme_pubkey_algo_name(subkey->pubkey_algo),
2497  subkey->length, shortid, date);
2498  }
2499  else
2500  {
2501  fprintf(*fp, "pub %5.5s %u/%8s %s %s\n", gpgme_pubkey_algo_name(subkey->pubkey_algo),
2502  subkey->length, shortid, date, uid->uid);
2503  }
2504  subkey = subkey->next;
2505  more = true;
2506  }
2507  gpgme_key_unref(key);
2508  }
2509  if (gpg_err_code(err) != GPG_ERR_EOF)
2510  {
2511  mutt_debug(LL_DEBUG1, "Error listing keys\n");
2512  goto err_fp;
2513  }
2514 
2515  rc = 0;
2516 
2517 err_fp:
2518  if (rc)
2519  mutt_file_fclose(fp);
2520 err_tmpdir:
2521  if (legacy_api)
2522  mutt_file_rmtree(mutt_b2s(tmpdir));
2523 err_ctx:
2524  gpgme_release(tmpctx);
2525 
2526  mutt_buffer_pool_release(&tmpdir);
2527 
2528  return rc;
2529 }
#define NONULL(x)
Definition: string2.h:37
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:680
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
int mutt_file_rmtree(const char *path)
Recursively remove a directory.
Definition: file.c:468
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define mutt_b2s(buf)
Definition: buffer.h:41
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:570
char * data
Pointer to data.
Definition: buffer.h:35
#define mutt_file_mkstemp()
Definition: file.h:106
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
Log at debug level 1.
Definition: logging.h:40
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:56
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ line_compare()

static int line_compare ( const char *  a,
size_t  n,
const char *  b 
)
static

Compare two strings ignore line endings.

Parameters
aString a
nMaximum length to compare
bString b
Return values
0Strings match
-1Strings differ

Check that b is a complete line containing a followed by either LF or CRLF.

Definition at line 2542 of file crypt_gpgme.c.

2543 {
2544  if (mutt_strn_equal(a, b, n))
2545  {
2546  /* at this point we know that 'b' is at least 'n' chars long */
2547  if ((b[n] == '\n') || ((b[n] == '\r') && (b[n + 1] == '\n')))
2548  return true;
2549  }
2550  return false;
2551 }
bool mutt_strn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
+ Here is the call graph for this function:

◆ pgp_check_traditional_one_body()

static int pgp_check_traditional_one_body ( FILE *  fp,
struct Body b 
)
static

Check one inline PGP body part.

Parameters
fpFile to read from
bBody of the email
Return values
1Success
0Error

Definition at line 2560 of file crypt_gpgme.c.

2561 {
2562  char buf[8192];
2563  int rv = 0;
2564 
2565  bool sgn = false;
2566  bool enc = false;
2567 
2568  if (b->type != TYPE_TEXT)
2569  return 0;
2570 
2571  struct Buffer *tempfile = mutt_buffer_pool_get();
2572  mutt_buffer_mktemp(tempfile);
2573  if (mutt_decode_save_attachment(fp, b, mutt_b2s(tempfile), 0, MUTT_SAVE_NO_FLAGS) != 0)
2574  {
2575  unlink(mutt_b2s(tempfile));
2576  goto cleanup;
2577  }
2578 
2579  FILE *fp_tmp = fopen(mutt_b2s(tempfile), "r");
2580  if (!fp_tmp)
2581  {
2582  unlink(mutt_b2s(tempfile));
2583  goto cleanup;
2584  }
2585 
2586  while (fgets(buf, sizeof(buf), fp_tmp))
2587  {
2588  size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
2589  if (plen != 0)
2590  {
2591  if (MESSAGE(buf + plen))
2592  {
2593  enc = true;
2594  break;
2595  }
2596  else if (SIGNED_MESSAGE(buf + plen))
2597  {
2598  sgn = true;
2599  break;
2600  }
2601  }
2602  }
2603  mutt_file_fclose(&fp_tmp);
2604  unlink(mutt_b2s(tempfile));
2605 
2606  if (!enc && !sgn)
2607  goto cleanup;
2608 
2609  /* fix the content type */
2610 
2611  mutt_param_set(&b->parameter, "format", "fixed");
2612  mutt_param_set(&b->parameter, "x-action", enc ? "pgp-encrypted" : "pgp-signed");
2613 
2614  rv = 1;
2615 
2616 cleanup:
2617  mutt_buffer_pool_release(&tempfile);
2618  return rv;
2619 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define SIGNED_MESSAGE(_y)
Definition: crypt_gpgme.c:100
No flags set.
Definition: mutt_attach.h:55
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
#define MESSAGE(_y)
Definition: crypt_gpgme.c:99
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define mutt_b2s(buf)
Definition: buffer.h:41
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
int mutt_decode_save_attachment(FILE *fp, struct Body *m, const char *path, int displaying, enum SaveAttach opt)
Decode, then save an attachment.
Definition: mutt_attach.c:1000
Type: &#39;text/*&#39;.
Definition: mime.h:38
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_gpgme_check_traditional()

int pgp_gpgme_check_traditional ( FILE *  fp,
struct Body b,
bool  just_one 
)

Implements CryptModuleSpecs::pgp_check_traditional()

Definition at line 2624 of file crypt_gpgme.c.

2625 {
2626  int rc = 0;
2627  for (; b; b = b->next)
2628  {
2629  if (!just_one && is_multipart(b))
2630  rc = (pgp_gpgme_check_traditional(fp, b->parts, false) || rc);
2631  else if (b->type == TYPE_TEXT)
2632  {
2634  if (r)
2635  rc = (rc || r);
2636  else
2637  rc = (pgp_check_traditional_one_body(fp, b) || rc);
2638  }
2639 
2640  if (just_one)
2641  break;
2642  }
2643  return rc;
2644 }
int pgp_gpgme_check_traditional(FILE *fp, struct Body *b, bool just_one)
Implements CryptModuleSpecs::pgp_check_traditional()
Definition: crypt_gpgme.c:2624
#define is_multipart(body)
Definition: mime.h:82
struct Body * next
next attachment in the list
Definition: body.h:53
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:83
static int pgp_check_traditional_one_body(FILE *fp, struct Body *b)
Check one inline PGP body part.
Definition: crypt_gpgme.c:2560
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:552
Type: &#39;text/*&#39;.
Definition: mime.h:38
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_gpgme_invoke_import()

void pgp_gpgme_invoke_import ( const char *  fname)

Implements CryptModuleSpecs::pgp_invoke_import()

Definition at line 2649 of file crypt_gpgme.c.

2650 {
2651  gpgme_ctx_t ctx = create_gpgme_context(false);
2652  gpgme_data_t keydata = NULL;
2653  gpgme_import_result_t impres;
2654  gpgme_import_status_t st;
2655  bool any;
2656 
2657  FILE *fp_in = mutt_file_fopen(fname, "r");
2658  if (!fp_in)
2659  {
2660  mutt_perror(fname);
2661  goto leave;
2662  }
2663  /* Note that the stream, "fp_in", needs to be kept open while the keydata
2664  * is used. */
2665  gpgme_error_t err = gpgme_data_new_from_stream(&keydata, fp_in);
2666  if (err != GPG_ERR_NO_ERROR)
2667  {
2668  mutt_error(_("error allocating data object: %s"), gpgme_strerror(err));
2669  goto leave;
2670  }
2671 
2672  err = gpgme_op_import(ctx, keydata);
2673  if (err != 0)
2674  {
2675  mutt_error(_("Error importing key: %s"), gpgme_strerror(err));
2676  goto leave;
2677  }
2678 
2679  /* Print infos about the imported keys to stdout. */
2680  impres = gpgme_op_import_result(ctx);
2681  if (!impres)
2682  {
2683  fputs("oops: no import result returned\n", stdout);
2684  goto leave;
2685  }
2686 
2687  for (st = impres->imports; st; st = st->next)
2688  {
2689  if (st->result)
2690  continue;
2691  printf("key %s imported (", NONULL(st->fpr));
2692  /* Note that we use the singular even if it is possible that
2693  * several uids etc are new. This simply looks better. */
2694  any = false;
2695  if (st->status & GPGME_IMPORT_SECRET)
2696  {
2697  printf("secret parts");
2698  any = true;
2699  }
2700  if ((st->status & GPGME_IMPORT_NEW))
2701  {
2702  printf("%snew key", any ? ", " : "");
2703  any = true;
2704  }
2705  if ((st->status & GPGME_IMPORT_UID))
2706  {
2707  printf("%snew uid", any ? ", " : "");
2708  any = true;
2709  }
2710  if ((st->status & GPGME_IMPORT_SIG))
2711  {
2712  printf("%snew sig", any ? ", " : "");
2713  any = true;
2714  }
2715  if ((st->status & GPGME_IMPORT_SUBKEY))
2716  {
2717  printf("%snew subkey", any ? ", " : "");
2718  any = true;
2719  }
2720  printf("%s)\n", any ? "" : "not changed");
2721  /* Fixme: Should we lookup each imported key and print more infos? */
2722  }
2723  /* Now print keys which failed the import. Unfortunately in most
2724  * cases gpg will bail out early and not tell GPGME about. */
2725  /* FIXME: We could instead use the new GPGME_AUDITLOG_DIAG to show
2726  * the actual gpg diagnostics. But I fear that would clutter the
2727  * output too much. Maybe a dedicated prompt or option to do this
2728  * would be helpful. */
2729  for (st = impres->imports; st; st = st->next)
2730  {
2731  if (st->result == 0)
2732  continue;
2733  printf("key %s import failed: %s\n", NONULL(st->fpr), gpgme_strerror(st->result));
2734  }
2735  fflush(stdout);
2736 
2737 leave:
2738  gpgme_release(ctx);
2739  gpgme_data_release(keydata);
2740  mutt_file_fclose(&fp_in);
2741 }
#define NONULL(x)
Definition: string2.h:37
#define mutt_perror(...)
Definition: logging.h:85
#define _(a)
Definition: message.h:28
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:570
#define mutt_error(...)
Definition: logging.h:84
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
+ Here is the call graph for this function:

◆ copy_clearsigned()

static void copy_clearsigned ( gpgme_data_t  data,
struct State s,
char *  charset 
)
static

Copy a clearsigned message.

Parameters
dataGPGME data object
sState to use
charsetCharset of message

strip the signature and PGP's dash-escaping.

XXX charset handling: We assume that it is safe to do character set decoding first, dash decoding second here, while we do it the other way around in the main handler.

(Note that we aren't worse than Outlook & Cie in this, and also note that we can successfully handle anything produced by any existing versions of neomutt.)

Definition at line 2758 of file crypt_gpgme.c.

2759 {
2760  char buf[8192];
2761  bool complete, armor_header;
2762  FILE *fp = NULL;
2763 
2764  char *fname = data_object_to_tempfile(data, &fp);
2765  if (!fname)
2766  {
2767  mutt_file_fclose(&fp);
2768  return;
2769  }
2770  unlink(fname);
2771  FREE(&fname);
2772 
2773  /* fromcode comes from the MIME Content-Type charset label. It might
2774  * be a wrong label, so we want the ability to do corrections via
2775  * charset-hooks. Therefore we set flags to MUTT_ICONV_HOOK_FROM. */
2776  struct FgetConv *fc = mutt_ch_fgetconv_open(fp, charset, C_Charset, MUTT_ICONV_HOOK_FROM);
2777 
2778  for (complete = true, armor_header = true;
2779  mutt_ch_fgetconvs(buf, sizeof(buf), fc); complete = (strchr(buf, '\n')))
2780  {
2781  if (!complete)
2782  {
2783  if (!armor_header)
2784  state_puts(s, buf);
2785  continue;
2786  }
2787 
2788  if (BEGIN_PGP_SIGNATURE(buf))
2789  break;
2790 
2791  if (armor_header)
2792  {
2793  if (buf[0] == '\n')
2794  armor_header = false;
2795  continue;
2796  }
2797 
2798  if (s->prefix)
2799  state_puts(s, s->prefix);
2800 
2801  if ((buf[0] == '-') && (buf[1] == ' '))
2802  state_puts(s, buf + 2);
2803  else
2804  state_puts(s, buf);
2805  }
2806 
2808  mutt_file_fclose(&fp);
2809 }
#define state_puts(STATE, STR)
Definition: state.h:55
static char * data_object_to_tempfile(gpgme_data_t data, FILE **fp_ret)
Copy a data object to a temporary file.
Definition: crypt_gpgme.c:804
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
char * mutt_ch_fgetconvs(char *buf, size_t buflen, struct FgetConv *fc)
Convert a file&#39;s charset into a string buffer.
Definition: charset.c:970
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
char * data
Pointer to data.
Definition: buffer.h:35
struct FgetConv * mutt_ch_fgetconv_open(FILE *fp, const char *from, const char *to, int flags)
Prepare a file for charset conversion.
Definition: charset.c:858
#define BEGIN_PGP_SIGNATURE(_y)
Definition: crypt_gpgme.c:102
void mutt_ch_fgetconv_close(struct FgetConv **fc)
Close an fgetconv handle.
Definition: charset.c:888
#define FREE(x)
Definition: memory.h:40
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
Cursor for converting a file&#39;s encoding.
Definition: charset.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_gpgme_application_handler()

int pgp_gpgme_application_handler ( struct Body m,
struct State s 
)

Implements CryptModuleSpecs::application_handler()

Definition at line 2814 of file crypt_gpgme.c.

2815 {
2816  int needpass = -1;
2817  bool pgp_keyblock = false;
2818  bool clearsign = false;
2819  long bytes;
2820  LOFF_T last_pos;
2821  char buf[8192];
2822  FILE *fp_out = NULL;
2823 
2824  gpgme_error_t err = 0;
2825  gpgme_data_t armored_data = NULL;
2826 
2827  bool maybe_goodsig = true;
2828  bool have_any_sigs = false;
2829 
2830  char body_charset[256]; /* Only used for clearsigned messages. */
2831 
2832  mutt_debug(LL_DEBUG2, "Entering handler\n");
2833 
2834  /* For clearsigned messages we won't be able to get a character set
2835  * but we know that this may only be text thus we assume Latin-1 here. */
2836  if (!mutt_body_get_charset(m, body_charset, sizeof(body_charset)))
2837  mutt_str_copy(body_charset, "iso-8859-1", sizeof(body_charset));
2838 
2839  fseeko(s->fp_in, m->offset, SEEK_SET);
2840  last_pos = m->offset;
2841 
2842  for (bytes = m->length; bytes > 0;)
2843  {
2844  if (!fgets(buf, sizeof(buf), s->fp_in))
2845  break;
2846 
2847  LOFF_T offset = ftello(s->fp_in);
2848  bytes -= (offset - last_pos); /* don't rely on mutt_str_len(buf) */
2849  last_pos = offset;
2850 
2851  size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
2852  if (plen != 0)
2853  {
2854  clearsign = false;
2855 
2856  if (MESSAGE(buf + plen))
2857  needpass = 1;
2858  else if (SIGNED_MESSAGE(buf + plen))
2859  {
2860  clearsign = true;
2861  needpass = 0;
2862  }
2863  else if (PUBLIC_KEY_BLOCK(buf + plen))
2864  {
2865  needpass = 0;
2866  pgp_keyblock = true;
2867  }
2868  else
2869  {
2870  /* XXX we may wish to recode here */
2871  if (s->prefix)
2872  state_puts(s, s->prefix);
2873  state_puts(s, buf);
2874  continue;
2875  }
2876 
2877  have_any_sigs = (have_any_sigs || (clearsign && (s->flags & MUTT_VERIFY)));
2878 
2879  /* Copy PGP material to an data container */
2880  armored_data = file_to_data_object(s->fp_in, m->offset, m->length);
2881  /* Invoke PGP if needed */
2882  if (pgp_keyblock)
2883  {
2884  pgp_gpgme_extract_keys(armored_data, &fp_out);
2885  }
2886  else if (!clearsign || (s->flags & MUTT_VERIFY))
2887  {
2888  gpgme_data_t plaintext = create_gpgme_data();
2889  gpgme_ctx_t ctx = create_gpgme_context(false);
2890 
2891  if (clearsign)
2892  err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
2893  else
2894  {
2895  err = gpgme_op_decrypt_verify(ctx, armored_data, plaintext);
2896  if (gpg_err_code(err) == GPG_ERR_NO_DATA)
2897  {
2898  /* Decrypt verify can't handle signed only messages. */
2899  gpgme_data_seek(armored_data, 0, SEEK_SET);
2900  /* Must release plaintext so that we supply an uninitialized object. */
2901  gpgme_data_release(plaintext);
2902  plaintext = create_gpgme_data();
2903  err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
2904  }
2905  }
2906  redraw_if_needed(ctx);
2907 
2908  if (err != 0)
2909  {
2910  char errbuf[200];
2911 
2912  snprintf(errbuf, sizeof(errbuf) - 1,
2913  _("Error: decryption/verification failed: %s\n"), gpgme_strerror(err));
2914  state_puts(s, errbuf);
2915  }
2916  else
2917  {
2918  /* Decryption/Verification succeeded */
2919 
2920  mutt_message(_("PGP message successfully decrypted"));
2921 
2922  bool sig_stat = false;
2923  char *tmpfname = NULL;
2924 
2925  {
2926  /* Check whether signatures have been verified. */
2927  gpgme_verify_result_t verify_result = gpgme_op_verify_result(ctx);
2928  if (verify_result->signatures)
2929  sig_stat = true;
2930  }
2931 
2932  have_any_sigs = false;
2933  maybe_goodsig = false;
2934  if ((s->flags & MUTT_DISPLAY) && sig_stat)
2935  {
2936  int res, idx;
2937  bool anybad = false;
2938 
2939  state_attach_puts(s, _("[-- Begin signature information --]\n"));
2940  have_any_sigs = true;
2941  for (idx = 0; (res = show_one_sig_status(ctx, idx, s)) != -1; idx++)
2942  {
2943  if (res == 1)
2944  anybad = true;
2945  }
2946  if (!anybad && idx)
2947  maybe_goodsig = true;
2948 
2949  state_attach_puts(s, _("[-- End signature information --]\n\n"));
2950  }
2951 
2952  tmpfname = data_object_to_tempfile(plaintext, &fp_out);
2953  if (tmpfname)
2954  {
2955  unlink(tmpfname);
2956  FREE(&tmpfname);
2957  }
2958  else
2959  {
2960  mutt_file_fclose(&fp_out);
2961  state_puts(s, _("Error: copy data failed\n"));
2962  }
2963  }
2964  gpgme_data_release(plaintext);
2965  gpgme_release(ctx);
2966  }
2967 
2968  /* Now, copy cleartext to the screen. NOTE - we expect that PGP
2969  * outputs utf-8 cleartext. This may not always be true, but it
2970  * seems to be a reasonable guess. */
2971  if (s->flags & MUTT_DISPLAY)
2972  {
2973  if (needpass)
2974  state_attach_puts(s, _("[-- BEGIN PGP MESSAGE --]\n\n"));
2975  else if (pgp_keyblock)
2976  state_attach_puts(s, _("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"));
2977  else
2978  state_attach_puts(s, _("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"));
2979  }
2980 
2981  if (clearsign)
2982  {
2983  copy_clearsigned(armored_data, s, body_charset);
2984  }
2985  else if (fp_out)
2986  {
2987  int c;
2988  rewind(fp_out);
2989  struct FgetConv *fc = mutt_ch_fgetconv_open(fp_out, "utf-8", C_Charset, 0);
2990  while ((c = mutt_ch_fgetconv(fc)) != EOF)
2991  {
2992  state_putc(s, c);
2993  if ((c == '\n') && s->prefix)
2994  state_puts(s, s->prefix);
2995  }
2997  }
2998 
2999  if (s->flags & MUTT_DISPLAY)
3000  {
3001  state_putc(s, '\n');
3002  if (needpass)
3003  state_attach_puts(s, _("[-- END PGP MESSAGE --]\n"));
3004  else if (pgp_keyblock)
3005  state_attach_puts(s, _("[-- END PGP PUBLIC KEY BLOCK --]\n"));
3006  else
3007  state_attach_puts(s, _("[-- END PGP SIGNED MESSAGE --]\n"));
3008  }
3009 
3010  gpgme_data_release(armored_data);
3011  mutt_file_fclose(&fp_out);
3012  }
3013  else
3014  {
3015  /* A traditional PGP part may mix signed and unsigned content */
3016  /* XXX we may wish to recode here */
3017  if (s->prefix)
3018  state_puts(s, s->prefix);
3019  state_puts(s, buf);
3020  }
3021  }
3022 
3023  m->goodsig = (maybe_goodsig && have_any_sigs);
3024 
3025  if (needpass == -1)
3026  {
3028  s, _("[-- Error: could not find beginning of PGP message --]\n\n"));
3029  return 1;
3030  }
3031  mutt_debug(LL_DEBUG2, "Leaving handler\n");
3032 
3033  return err;
3034 }
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
static gpgme_data_t file_to_data_object(FILE *fp, long offset, size_t length)
Create GPGME data object from file.
Definition: crypt_gpgme.c:736
#define state_puts(STATE, STR)
Definition: state.h:55
static char * data_object_to_tempfile(gpgme_data_t data, FILE **fp_ret)
Copy a data object to a temporary file.
Definition: crypt_gpgme.c:804
#define SIGNED_MESSAGE(_y)
Definition: crypt_gpgme.c:100
#define mutt_message(...)
Definition: logging.h:83
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
#define PUBLIC_KEY_BLOCK(_y)
Definition: crypt_gpgme.c:101
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
FILE * fp_in
File to read from.
Definition: state.h:46
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
#define MESSAGE(_y)
Definition: crypt_gpgme.c:99
Log at debug level 2.
Definition: logging.h:41
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: body.c:131
bool goodsig
Good cryptographic signature.
Definition: body.h:75
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:570
#define MUTT_VERIFY
Perform signature verification.
Definition: state.h:33
static int pgp_gpgme_extract_keys(gpgme_data_t keydata, FILE **fp)
Write PGP keys to a file.
Definition: crypt_gpgme.c:2406
struct FgetConv * mutt_ch_fgetconv_open(FILE *fp, const char *from, const char *to, int flags)
Prepare a file for charset conversion.
Definition: charset.c:858
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:70
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
void mutt_ch_fgetconv_close(struct FgetConv **fc)
Close an fgetconv handle.
Definition: charset.c:888
static gpgme_data_t create_gpgme_data(void)
Create a new GPGME data object.
Definition: crypt_gpgme.c:608
#define FREE(x)
Definition: memory.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
#define state_putc(STATE, STR)
Definition: state.h:56
static void redraw_if_needed(gpgme_ctx_t ctx)
accommodate for a redraw if needed
Definition: crypt_gpgme.c:119
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file&#39;s character set.
Definition: charset.c:908
Cursor for converting a file&#39;s encoding.
Definition: charset.h:41
static int show_one_sig_status(gpgme_ctx_t ctx, int idx, struct State *s)
Show information about one signature.
Definition: crypt_gpgme.c:1767
static void copy_clearsigned(gpgme_data_t data, struct State *s, char *charset)
Copy a clearsigned message.
Definition: crypt_gpgme.c:2758
+ Here is the call graph for this function:

◆ pgp_gpgme_encrypted_handler()

int pgp_gpgme_encrypted_handler ( struct Body a,
struct State s 
)

Implements CryptModuleSpecs::encrypted_handler()

This handler is passed the application/octet-stream directly. The caller must propagate a->goodsig to its parent.

Definition at line 3042 of file crypt_gpgme.c.

3043 {
3044  int is_signed;
3045  int rc = 0;
3046 
3047  mutt_debug(LL_DEBUG2, "Entering handler\n");
3048 
3049  FILE *fp_out = mutt_file_mkstemp();
3050  if (!fp_out)
3051  {
3052  mutt_perror(_("Can't create temporary file"));
3053  if (s->flags & MUTT_DISPLAY)
3054  {
3056  _("[-- Error: could not create temporary file --]\n"));
3057  }
3058  return -1;
3059  }
3060 
3061  struct Body *tattach = decrypt_part(a, s, fp_out, false, &is_signed);
3062  if (tattach)
3063  {
3064  tattach->goodsig = is_signed > 0;
3065 
3066  if (s->flags & MUTT_DISPLAY)
3067  {
3069  s, is_signed ?
3070  _("[-- The following data is PGP/MIME signed and encrypted "
3071  "--]\n\n") :
3072  _("[-- The following data is PGP/MIME encrypted --]\n\n"));
3073  mutt_protected_headers_handler(tattach, s);
3074  }
3075 
3076  /* Store any protected headers in the parent so they can be
3077  * accessed for index updates after the handler recursion is done.
3078  * This is done before the handler to prevent a nested encrypted
3079  * handler from freeing the headers. */
3081  a->mime_headers = tattach->mime_headers;
3082  tattach->mime_headers = NULL;
3083 
3084  {
3085  FILE *fp_save = s->fp_in;
3086  s->fp_in = fp_out;
3087  rc = mutt_body_handler(tattach, s);
3088  s->fp_in = fp_save;
3089  }
3090 
3091  /* Embedded multipart signed protected headers override the
3092  * encrypted headers. We need to do this after the handler so
3093  * they can be printed in the pager. */
3094  if (mutt_is_multipart_signed(tattach) && tattach->parts && tattach->parts->mime_headers)
3095  {
3097  a->mime_headers = tattach->parts->mime_headers;
3098  tattach->parts->mime_headers = NULL;
3099  }
3100 
3101  /* if a multipart/signed is the _only_ sub-part of a
3102  * multipart/encrypted, cache signature verification
3103  * status. */
3104  if (mutt_is_multipart_signed(tattach) && !tattach->next)
3105  a->goodsig |= tattach->goodsig;
3106 
3107  if (s->flags & MUTT_DISPLAY)
3108  {
3109  state_puts(s, "\n");
3111  s, is_signed ?
3112  _("[-- End of PGP/MIME signed and encrypted data --]\n") :
3113  _("[-- End of PGP/MIME encrypted data --]\n"));
3114  }
3115 
3116  mutt_body_free(&tattach);
3117  mutt_message(_("PGP message successfully decrypted"));
3118  }
3119  else
3120  {
3121 #ifdef USE_AUTOCRYPT
3122  if (!OptAutocryptGpgme)
3123 #endif
3124  {
3125  mutt_error(_("Could not decrypt PGP message"));
3126  }
3127  rc = -1;
3128  }
3129 
3130  mutt_file_fclose(&fp_out);
3131  mutt_debug(LL_DEBUG2, "Leaving handler\n");
3132 
3133  return rc;
3134 }
int mutt_protected_headers_handler(struct Body *a, struct State *s)
Process a protected header - Implements handler_t.
Definition: crypt.c:1087
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
#define state_puts(STATE, STR)
Definition: state.h:55
#define mutt_perror(...)
Definition: logging.h:85
#define mutt_message(...)
Definition: logging.h:83
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
WHERE bool OptAutocryptGpgme
(pseudo) use Autocrypt context inside ncrypt/crypt_gpgme.c
Definition: options.h:33
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
Log at debug level 2.
Definition: logging.h:41
static struct Body * decrypt_part(struct Body *a, struct State *s, FILE *fp_out, bool is_smime, int *r_is_signed)
Decrypt a PGP or SMIME message.
Definition: crypt_gpgme.c:2039
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:407
bool goodsig
Good cryptographic signature.
Definition: body.h:75
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
#define mutt_file_mkstemp()
Definition: file.h:106
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:70
#define mutt_error(...)
Definition: logging.h:84
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1593
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_gpgme_application_handler()

int smime_gpgme_application_handler ( struct Body a,
struct State s 
)

Implements CryptModuleSpecs::application_handler()

Definition at line 3139 of file crypt_gpgme.c.

3140 {
3141  int is_signed = 0;
3142  int rc = 0;
3143 
3144  mutt_debug(LL_DEBUG2, "Entering handler\n");
3145 
3146  /* clear out any mime headers before the handler, so they can't be spoofed. */
3148  a->warnsig = false;
3149  FILE *fp_out = mutt_file_mkstemp();
3150  if (!fp_out)
3151  {
3152  mutt_perror(_("Can't create temporary file"));
3153  if (s->flags & MUTT_DISPLAY)
3154  {
3156  _("[-- Error: could not create temporary file --]\n"));
3157  }
3158  return -1;
3159  }
3160 
3161  struct Body *tattach = decrypt_part(a, s, fp_out, true, &is_signed);
3162  if (tattach)
3163  {
3164  tattach->goodsig = is_signed > 0;
3165 
3166  if (s->flags & MUTT_DISPLAY)
3167  {
3169  s, is_signed ?
3170  _("[-- The following data is S/MIME signed --]\n\n") :
3171  _("[-- The following data is S/MIME encrypted --]\n\n"));
3172  mutt_protected_headers_handler(tattach, s);
3173  }
3174 
3175  /* Store any protected headers in the parent so they can be
3176  * accessed for index updates after the handler recursion is done.
3177  * This is done before the handler to prevent a nested encrypted
3178  * handler from freeing the headers. */
3180  a->mime_headers = tattach->mime_headers;
3181  tattach->mime_headers = NULL;
3182 
3183  {
3184  FILE *fp_save = s->fp_in;
3185  s->fp_in = fp_out;
3186  rc = mutt_body_handler(tattach, s);
3187  s->fp_in = fp_save;
3188  }
3189 
3190  /* Embedded multipart signed protected headers override the
3191  * encrypted headers. We need to do this after the handler so
3192  * they can be printed in the pager. */
3193  if (mutt_is_multipart_signed(tattach) && tattach->parts && tattach->parts->mime_headers)
3194  {
3196  a->mime_headers = tattach->parts->mime_headers;
3197  tattach->parts->mime_headers = NULL;
3198  }
3199 
3200  /* if a multipart/signed is the _only_ sub-part of a multipart/encrypted,
3201  * cache signature verification status. */
3202  if (mutt_is_multipart_signed(tattach) && !tattach->next)
3203  {
3204  a->goodsig = tattach->goodsig;
3205  if (!a->goodsig)
3206  a->warnsig = tattach->warnsig;
3207  }
3208  else if (tattach->goodsig)
3209  {
3210  a->goodsig = true;
3211  a->warnsig = tattach->warnsig;
3212  }
3213 
3214  if (s->flags & MUTT_DISPLAY)
3215  {
3216  state_puts(s, "\n");
3217  state_attach_puts(s, is_signed ?
3218  _("[-- End of S/MIME signed data --]\n") :
3219  _("[-- End of S/MIME encrypted data --]\n"));
3220  }
3221 
3222  mutt_body_free(&tattach);
3223  }
3224 
3225  mutt_file_fclose(&fp_out);
3226  mutt_debug(LL_DEBUG2, "Leaving handler\n");
3227 
3228  return rc;
3229 }
int mutt_protected_headers_handler(struct Body *a, struct State *s)
Process a protected header - Implements handler_t.
Definition: crypt.c:1087
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
#define state_puts(STATE, STR)
Definition: state.h:55
#define mutt_perror(...)
Definition: logging.h:85
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
Log at debug level 2.
Definition: logging.h:41
static struct Body * decrypt_part(struct Body *a, struct State *s, FILE *fp_out, bool is_smime, int *r_is_signed)
Decrypt a PGP or SMIME message.
Definition: crypt_gpgme.c:2039
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:407
bool goodsig
Good cryptographic signature.
Definition: body.h:75
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
#define mutt_file_mkstemp()
Definition: file.h:106
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:70
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1593
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
bool warnsig
Maybe good signature.
Definition: body.h:76
+ Here is the call graph for this function:

◆ key_check_cap()

unsigned int key_check_cap ( gpgme_key_t  key,
enum KeyCap  cap 
)

Check the capabilities of a key.

Parameters
keyGPGME key
capFlags, e.g. KEY_CAP_CAN_ENCRYPT
Return values
>0Key has the capabilities

Definition at line 3237 of file crypt_gpgme.c.

3238 {
3239  unsigned int ret = 0;
3240 
3241  switch (cap)
3242  {
3243  case KEY_CAP_CAN_ENCRYPT:
3244  ret = key->can_encrypt;
3245  if (ret == 0)
3246  {
3247  for (gpgme_subkey_t subkey = key->subkeys; subkey; subkey = subkey->next)
3248  {
3249  ret = subkey->can_encrypt;
3250  if (ret != 0)
3251  break;
3252  }
3253  }
3254  break;
3255  case KEY_CAP_CAN_SIGN:
3256  ret = key->can_sign;
3257  if (ret == 0)
3258  {
3259  for (gpgme_subkey_t subkey = key->subkeys; subkey; subkey = subkey->next)
3260  {
3261  ret = subkey->can_sign;
3262  if (ret != 0)
3263  break;
3264  }
3265  }
3266  break;
3267  case KEY_CAP_CAN_CERTIFY:
3268  ret = key->can_certify;
3269  if (ret == 0)
3270  {
3271  for (gpgme_subkey_t subkey = key->subkeys; subkey; subkey = subkey->next)
3272  {
3273  ret = subkey->can_certify;
3274  if (ret != 0)
3275  break;
3276  }
3277  }
3278  break;
3279  }
3280 
3281  return ret;
3282 }
Key can be used for encryption.
Definition: crypt_gpgme.h:76
Key can be used for signing.
Definition: crypt_gpgme.h:77
Key can be used to certify.
Definition: crypt_gpgme.h:78
+ Here is the caller graph for this function:

◆ list_to_pattern()

static char* list_to_pattern ( struct ListHead *  list)
static

Convert STailQ to GPGME-compatible pattern.

Parameters
listList of strings to convert
Return values
ptrGPGME-compatible pattern

We need to convert spaces in an item into a '+' and '' into "%25".

Note
The caller must free the returned pattern

Definition at line 3293 of file crypt_gpgme.c.

3294 {
3295  char *pattern = NULL, *p = NULL;
3296  const char *s = NULL;
3297  size_t n;
3298 
3299  n = 0;
3300  struct ListNode *np = NULL;
3301  STAILQ_FOREACH(np, list, entries)
3302  {
3303  for (s = np->data; *s; s++)
3304  {
3305  if ((*s == '%') || (*s == '+'))
3306  n += 2;
3307  n++;
3308  }
3309  n++; /* delimiter or end of string */
3310  }
3311  n++; /* make sure to allocate at least one byte */
3312  p = mutt_mem_calloc(1, n);
3313  pattern = p;
3314  STAILQ_FOREACH(np, list, entries)
3315  {
3316  s = np->data;
3317  if (*s)
3318  {
3319  if (np != STAILQ_FIRST(list))
3320  *p++ = ' ';
3321  for (s = np->data; *s; s++)
3322  {
3323  if (*s == '%')
3324  {
3325  *p++ = '%';
3326  *p++ = '2';
3327  *p++ = '5';
3328  }
3329  else if (*s == '+')
3330  {
3331  *p++ = '%';
3332  *p++ = '2';
3333  *p++ = 'B';
3334  }
3335  else if (*s == ' ')
3336  *p++ = '+';
3337  else
3338  *p++ = *s;
3339  }
3340  }
3341  }
3342  *p = '\0';
3343  return pattern;
3344 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
char * data
String.
Definition: list.h:36
A List node for strings.
Definition: list.h:34
#define STAILQ_FIRST(head)
Definition: queue.h:347
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_candidates()

static struct CryptKeyInfo* get_candidates ( struct ListHead *  hints,
SecurityFlags  app,
int  secret 
)
static

Get a list of keys which are candidates for the selection.

Parameters
hintsList of strings to match
appApplication type, e.g. APPLICATION_PGP
secretIf true, only match secret keys
Return values
ptrKey List
NULLError

Select by looking at the HINTS list.

Definition at line 3356 of file crypt_gpgme.c.

3357 {
3358  struct CryptKeyInfo *db = NULL, *k = NULL, **kend = NULL;
3359  gpgme_error_t err;
3360  gpgme_ctx_t ctx = NULL;
3361  gpgme_key_t key = NULL;
3362  int idx;
3363  gpgme_user_id_t uid = NULL;
3364 
3365  char *pattern = list_to_pattern(hints);
3366  if (!pattern)
3367  return NULL;
3368 
3369  ctx = create_gpgme_context(0);
3370  db = NULL;
3371  kend = &db;
3372 
3373  if ((app & APPLICATION_PGP))
3374  {
3375  /* It's all a mess. That old GPGME expects different things depending on
3376  * the protocol. For gpg we don't need percent escaped pappert but simple
3377  * strings passed in an array to the keylist_ext_start function. */
3378  size_t n = 0;
3379  struct ListNode *np = NULL;
3380  STAILQ_FOREACH(np, hints, entries)
3381  {
3382  if (np->data && *np->data)
3383  n++;
3384  }
3385  if (n == 0)
3386  goto no_pgphints;
3387 
3388  char **patarr = mutt_mem_calloc(n + 1, sizeof(*patarr));
3389  n = 0;
3390  STAILQ_FOREACH(np, hints, entries)
3391  {
3392  if (np->data && *np->data)
3393  patarr[n++] = mutt_str_dup(np->data);
3394  }
3395  patarr[n] = NULL;
3396  err = gpgme_op_keylist_ext_start(ctx, (const char **) patarr, secret, 0);
3397  for (n = 0; patarr[n]; n++)
3398  FREE(&patarr[n]);
3399  FREE(&patarr);
3400  if (err != 0)
3401  {
3402  mutt_error(_("gpgme_op_keylist_start failed: %s"), gpgme_strerror(err));
3403  gpgme_release(ctx);
3404  FREE(&pattern);
3405  return NULL;
3406  }
3407 
3408  while ((err = gpgme_op_keylist_next(ctx, &key)) == 0)
3409  {
3410  KeyFlags flags = KEYFLAG_NO_FLAGS;
3411 
3413  flags |= KEYFLAG_CANENCRYPT;
3414  if (key_check_cap(key, KEY_CAP_CAN_SIGN))
3415  flags |= KEYFLAG_CANSIGN;
3416 
3417  if (key->revoked)
3418  flags |= KEYFLAG_REVOKED;
3419  if (key->expired)
3420  flags |= KEYFLAG_EXPIRED;
3421  if (key->disabled)
3422  flags |= KEYFLAG_DISABLED;
3423 
3424  for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3425  {
3426  k = mutt_mem_calloc(1, sizeof(*k));
3427  k->kobj = key;
3428  gpgme_key_ref(k->kobj);
3429  k->idx = idx;
3430  k->uid = uid->uid;
3431  k->flags = flags;
3432  if (uid->revoked)
3433  k->flags |= KEYFLAG_REVOKED;
3434  k->validity = uid->validity;
3435  *kend = k;
3436  kend = &k->next;
3437  }
3438  gpgme_key_unref(key);
3439  }
3440  if (gpg_err_code(err) != GPG_ERR_EOF)
3441  mutt_error(_("gpgme_op_keylist_next failed: %s"), gpgme_strerror(err));
3442  gpgme_op_keylist_end(ctx);
3443  no_pgphints:;
3444  }
3445 
3446  if ((app & APPLICATION_SMIME))
3447  {
3448  /* and now look for x509 certificates */
3449  gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS);
3450  err = gpgme_op_keylist_start(ctx, pattern, 0);
3451  if (err != 0)
3452  {
3453  mutt_error(_("gpgme_op_keylist_start failed: %s"), gpgme_strerror(err));
3454  gpgme_release(ctx);
3455  FREE(&pattern);
3456  return NULL;
3457  }
3458 
3459  while ((err = gpgme_op_keylist_next(ctx, &key)) == 0)
3460  {
3461  KeyFlags flags = KEYFLAG_ISX509;
3462 
3464  flags |= KEYFLAG_CANENCRYPT;
3465  if (key_check_cap(key, KEY_CAP_CAN_SIGN))
3466  flags |= KEYFLAG_CANSIGN;
3467 
3468  for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3469  {
3470  k = mutt_mem_calloc(1, sizeof(*k));
3471  k->kobj = key;
3472  gpgme_key_ref(k->kobj);
3473  k->idx = idx;
3474  k->uid = uid->uid;
3475  k->flags = flags;
3476  k->validity = uid->validity;
3477  *kend = k;
3478  kend = &k->next;
3479  }
3480  gpgme_key_unref(key);
3481  }
3482  if (gpg_err_code(err) != GPG_ERR_EOF)
3483  mutt_error(_("gpgme_op_keylist_next failed: %s"), gpgme_strerror(err));
3484  gpgme_op_keylist_end(ctx);
3485  }
3486 
3487  gpgme_release(ctx);
3488  FREE(&pattern);
3489  return db;
3490 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
Key can be used for encryption.
Definition: crypt_gpgme.h:76
#define KEYFLAG_ISX509
Key is an X.509 key.
Definition: lib.h:136
Key can be used for signing.
Definition: crypt_gpgme.h:77
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition: lib.h:135
A stored PGP key.
Definition: crypt_gpgme.h:43
int idx
and the user ID at this index
Definition: crypt_gpgme.h:47
#define KEYFLAG_EXPIRED
Key is expired.
Definition: lib.h:138
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98
const char * uid
and for convenience point to this user ID
Definition: crypt_gpgme.h:48
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
#define KEYFLAG_NO_FLAGS
No flags are set.
Definition: lib.h:133
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:570
uint16_t KeyFlags
Flags describing PGP/SMIME keys, e.g. KEYFLAG_CANSIGN.
Definition: lib.h:132
unsigned int key_check_cap(gpgme_key_t key, enum KeyCap cap)
Check the capabilities of a key.
Definition: crypt_gpgme.c:3237
static char * list_to_pattern(struct ListHead *list)
Convert STailQ to GPGME-compatible pattern.
Definition: crypt_gpgme.c:3293
#define KEYFLAG_DISABLED
Key is marked disabled.
Definition: lib.h:140
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
#define KEYFLAG_CANSIGN
Key is suitable for signing.
Definition: lib.h:134
char * data
String.
Definition: list.h:36
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
A List node for strings.
Definition: list.h:34
#define KEYFLAG_REVOKED
Key is revoked.
Definition: lib.h:139
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_add_string_to_hints()

static void crypt_add_string_to_hints ( const char *  str,
struct ListHead *  hints 
)
static

Split a string and add the parts to a List.

Parameters
[in]strString to parse
[out]hintsList of string parts

The string str is split by whitespace and punctuation and the parts added to hints. This list is later used to match addresses.

Definition at line 3500 of file crypt_gpgme.c.

3501 {
3502  char *scratch = mutt_str_dup(str);
3503  if (!scratch)
3504  return;
3505 
3506  for (char *t = strtok(scratch, " ,.:\"()<>\n"); t;
3507  t = strtok(NULL, " ,.:\"()<>\n"))
3508  {
3509  if (strlen(t) > 3)
3511  }
3512 
3513  FREE(&scratch);
3514 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
#define FREE(x)
Definition: memory.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_getkeybyaddr()

static struct CryptKeyInfo* crypt_getkeybyaddr ( struct Address a,
KeyFlags  abilities,
unsigned int  app,
int *  forced_valid,
bool  oppenc_mode 
)
static

Find a key by email address.

Parameters
[in]aAddress to match
[in]abilitiesAbilities to match, see KeyFlags
[in]appApplication type, e.g. APPLICATION_PGP
[out]forced_validSet to true if user overrode key's validity
[in]oppenc_modeIf true, use opportunistic encryption
Return values
ptrMatching key

Definition at line 3525 of file crypt_gpgme.c.

3528 {
3529  struct ListHead hints = STAILQ_HEAD_INITIALIZER(hints);
3530 
3531  int multi = false;
3532  int this_key_has_strong = false;
3533  int this_key_has_addr_match = false;
3534  int match = false;
3535 
3536  struct CryptKeyInfo *keys = NULL, *k = NULL;
3537  struct CryptKeyInfo *the_strong_valid_key = NULL;
3538  struct CryptKeyInfo *a_valid_addrmatch_key = NULL;
3539  struct CryptKeyInfo *matches = NULL;
3540  struct CryptKeyInfo **matches_endp = &matches;
3541 
3542  *forced_valid = 0;
3543 
3544  if (a && a->mailbox)
3545  crypt_add_string_to_hints(a->mailbox, &hints);
3546  if (a && a->personal)
3547  crypt_add_string_to_hints(a->personal, &hints);
3548 
3549  if (!oppenc_mode)
3550  mutt_message(_("Looking for keys matching \"%s\"..."), a ? a->mailbox : "");
3551  keys = get_candidates(&hints, app, (abilities & KEYFLAG_CANSIGN));
3552 
3553  mutt_list_free(&hints);
3554 
3555  if (!keys)
3556  return NULL;
3557 
3558  mutt_debug(LL_DEBUG5, "looking for %s <%s>\n", a ? a->personal : "", a ? a->mailbox : "");
3559 
3560  for (k = keys; k; k = k->next)
3561  {
3562  mutt_debug(LL_DEBUG5, " looking at key: %s '%.15s'\n", crypt_keyid(k), k->uid);
3563 
3564  if (abilities && !(k->flags & abilities))
3565  {
3566  mutt_debug(LL_DEBUG2, " insufficient abilities: Has %x, want %x\n", k->flags, abilities);
3567  continue;
3568  }
3569 
3570  this_key_has_strong = false; /* strong and valid match */
3571  this_key_has_addr_match = false;
3572  match = false; /* any match */
3573 
3574  struct AddressList alist = TAILQ_HEAD_INITIALIZER(alist);
3575  mutt_addrlist_parse(&alist, k->uid);
3576  struct Address *ka = NULL;
3577  TAILQ_FOREACH(ka, &alist, entries)
3578  {
3579  int validity = crypt_id_matches_addr(a, ka, k);
3580 
3581  if (validity & CRYPT_KV_MATCH) /* something matches */
3582  {
3583  match = true;
3584 
3585  if ((validity & CRYPT_KV_VALID) && (validity & CRYPT_KV_ADDR))
3586  {
3587  if (validity & CRYPT_KV_STRONGID)
3588  {
3589  if (the_strong_valid_key && (the_strong_valid_key->kobj != k->kobj))
3590  multi = true;
3591  this_key_has_strong = true;
3592  }
3593  else
3594  this_key_has_addr_match = true;
3595  }
3596  }
3597  }
3598  mutt_addrlist_clear(&alist);
3599 
3600  if (match)
3601  {
3602  struct CryptKeyInfo *tmp = crypt_copy_key(k);
3603  *matches_endp = tmp;
3604  matches_endp = &tmp->next;
3605 
3606  if (this_key_has_strong)
3607  the_strong_valid_key = tmp;
3608  else if (this_key_has_addr_match)
3609  a_valid_addrmatch_key = tmp;
3610  }
3611  }
3612 
3613  crypt_key_free(&keys);
3614 
3615  if (matches)
3616  {
3617  if (oppenc_mode)
3618  {
3619  if (the_strong_valid_key)
3620  k = crypt_copy_key(the_strong_valid_key);
3621  else if (a_valid_addrmatch_key && !C_CryptOpportunisticEncryptStrongKeys)
3622  k = crypt_copy_key(a_valid_addrmatch_key);
3623  else
3624  k = NULL;
3625  }
3626  else if (the_strong_valid_key && !multi)
3627  {
3628  /* There was precisely one strong match on a valid ID.
3629  * Proceed without asking the user. */
3630  k = crypt_copy_key(the_strong_valid_key);
3631  }
3632  else
3633  {
3634  /* Else: Ask the user. */
3635  k = dlg_select_gpgme_key(matches, a, NULL, app, forced_valid);
3636  }
3637 
3638  crypt_key_free(&matches);
3639  }
3640  else
3641  k = NULL;
3642 
3643  return k;
3644 }
#define CRYPT_KV_STRONGID
Definition: crypt_gpgme.c:78
static void crypt_key_free(struct CryptKeyInfo **keylist)
Release all the keys in a list.
Definition: crypt_gpgme.c:461
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
#define CRYPT_KV_ADDR
Definition: crypt_gpgme.c:76
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
#define mutt_message(...)
Definition: logging.h:83
struct CryptKeyInfo * dlg_select_gpgme_key(struct CryptKeyInfo *keys, struct Address *p, const char *s, unsigned int app, int *forced_valid)
Get the user to select a key.
Definition: dlggpgme.c:1196
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1468
const char * crypt_keyid(struct CryptKeyInfo *k)
Find the ID for the key.
Definition: crypt_gpgme.c:347
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
struct CryptKeyInfo * next
Definition: crypt_gpgme.h:45
bool C_CryptOpportunisticEncryptStrongKeys
Config: Enable encryption only when strong a key is available.
Definition: config.c:57
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
static void crypt_add_string_to_hints(const char *str, struct ListHead *hints)
Split a string and add the parts to a List.
Definition: crypt_gpgme.c:3500
A stored PGP key.
Definition: crypt_gpgme.h:43
static int crypt_id_matches_addr(struct Address *addr, struct Address *u_addr, struct CryptKeyInfo *key)
Does the key ID match the address.
Definition: crypt_gpgme.c:536
Log at debug level 2.
Definition: logging.h:41
struct CryptKeyInfo * crypt_copy_key(struct CryptKeyInfo *key)
Return a copy of KEY.
Definition: crypt_gpgme.c:442
#define CRYPT_KV_MATCH
Definition: crypt_gpgme.c:79
gpgme_key_t kobj
Definition: crypt_gpgme.h:46
#define KEYFLAG_CANSIGN
Key is suitable for signing.
Definition: lib.h:134
char * personal
Real name of address.
Definition: address.h:36
#define CRYPT_KV_VALID
Definition: crypt_gpgme.c:75
static struct CryptKeyInfo * get_candidates(struct ListHead *hints, SecurityFlags app, int secret)
Get a list of keys which are candidates for the selection.
Definition: crypt_gpgme.c:3356
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Log at debug level 5.
Definition: logging.h:44
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_getkeybystr()

static struct CryptKeyInfo* crypt_getkeybystr ( const char *  p,
KeyFlags  abilities,
unsigned int  app,
int *  forced_valid 
)
static

Find a key by string.

Parameters
[in]pString to match
[in]abilitiesAbilities to match, see KeyFlags
[in]appApplication type, e.g. APPLICATION_PGP
[out]forced_validSet to true if user overrode key's validity
Return values
ptrMatching key

Definition at line 3654 of file crypt_gpgme.c.

3656 {
3657  struct ListHead hints = STAILQ_HEAD_INITIALIZER(hints);
3658  struct CryptKeyInfo *matches = NULL;
3659  struct CryptKeyInfo **matches_endp = &matches;
3660  struct CryptKeyInfo *k = NULL;
3661  const char *ps = NULL, *pl = NULL, *phint = NULL;
3662 
3663  mutt_message(_("Looking for keys matching \"%s\"..."), p);
3664 
3665  *forced_valid = 0;
3666 
3667  const char *pfcopy = crypt_get_fingerprint_or_id(p, &phint, &pl, &ps);
3668  crypt_add_string_to_hints(phint, &hints);
3669  struct CryptKeyInfo *keys = get_candidates(&hints, app, (abilities & KEYFLAG_CANSIGN));
3670  mutt_list_free(&hints);
3671 
3672  if (!keys)
3673  {
3674  FREE(&pfcopy);
3675  return NULL;
3676  }
3677 
3678  for (k = keys; k; k = k->next)
3679  {
3680  if (abilities && !(k->flags & abilities))
3681  continue;
3682 
3683  mutt_debug(LL_DEBUG5, "matching \"%s\" against key %s, \"%s\": ", p,
3684  crypt_long_keyid(k), k->uid);
3685 
3686  if ((*p == '\0') || (pfcopy && mutt_istr_equal(pfcopy, crypt_fpr(k))) ||
3687  (pl && mutt_istr_equal(pl, crypt_long_keyid(k))) ||
3688  (ps && mutt_istr_equal(ps, crypt_short_keyid(k))) || mutt_istr_find(k->uid, p))
3689  {
3690  mutt_debug(LL_DEBUG5, "match\n");
3691 
3692  struct CryptKeyInfo *tmp = crypt_copy_key(k);
3693  *matches_endp = tmp;
3694  matches_endp = &tmp->next;
3695  }
3696  else
3697  {
3698  mutt_debug(LL_DEBUG5, "no match\n");
3699  }
3700  }
3701 
3702  FREE(&pfcopy);
3703  crypt_key_free(&keys);
3704 
3705  if (matches)
3706  {
3707  k = dlg_select_gpgme_key(matches, NULL, p, app, forced_valid);
3708  crypt_key_free(&matches);
3709  return k;
3710  }
3711 
3712  return NULL;
3713 }
const char * crypt_get_fingerprint_or_id(const char *p, const char **pphint, const char **ppl, const char **pps)
Get the fingerprint or long key ID.
Definition: crypt.c:1258
static void crypt_key_free(struct CryptKeyInfo **keylist)
Release all the keys in a list.
Definition: crypt_gpgme.c:461
#define mutt_message(...)
Definition: logging.h:83
struct CryptKeyInfo * dlg_select_gpgme_key(struct CryptKeyInfo *keys, struct Address *p, const char *s, unsigned int app, int *forced_valid)
Get the user to select a key.
Definition: dlggpgme.c:1196
#define _(a)
Definition: message.h:28
struct CryptKeyInfo * next
Definition: crypt_gpgme.h:45
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
static void crypt_add_string_to_hints(const char *str, struct ListHead *hints)
Split a string and add the parts to a List.
Definition: crypt_gpgme.c:3500
A stored PGP key.
Definition: crypt_gpgme.h:43
static const char * crypt_fpr(struct CryptKeyInfo *k)
Get the hexstring fingerprint from a key.
Definition: crypt_gpgme.c:407
struct CryptKeyInfo * crypt_copy_key(struct CryptKeyInfo *key)
Return a copy of KEY.
Definition: crypt_gpgme.c:442
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
const char * uid
and for convenience point to this user ID
Definition: crypt_gpgme.h:48
#define KEYFLAG_CANSIGN
Key is suitable for signing.
Definition: lib.h:134
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:656
static const char * crypt_long_keyid(struct CryptKeyInfo *k)
Find the Long ID for the key.
Definition: crypt_gpgme.c:371
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.h:49
static const char * crypt_short_keyid(struct CryptKeyInfo *k)
Get the short keyID for a key.
Definition: crypt_gpgme.c:388
#define FREE(x)
Definition: memory.h:40
static struct CryptKeyInfo * get_candidates(struct ListHead *hints, SecurityFlags app, int secret)
Get a list of keys which are candidates for the selection.
Definition: crypt_gpgme.c:3356
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Log at debug level 5.
Definition: logging.h:44
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_ask_for_key()

static struct CryptKeyInfo* crypt_ask_for_key ( char *  tag,
char *  whatfor,
KeyFlags  abilities,
unsigned int  app,
int *  forced_valid 
)
static

Ask the user for a key.

Parameters
[in]tagPrompt to display
[in]whatforLabel to use (OPTIONAL)
[in]abilitiesFlags, see KeyFlags
[in]appApplication type, e.g. APPLICATION_PGP
[out]forced_validSet to true if user overrode key's validity
Return values
ptrCopy of the selected key

If whatfor is not null use it as default and store it under that label as the next default.

Definition at line 3727 of file crypt_gpgme.c.

3729 {
3730  struct CryptKeyInfo *key = NULL;
3731  char resp[128];
3732  struct CryptCache *l = NULL;
3733  int dummy;
3734 
3735  if (!forced_valid)
3736  forced_valid = &dummy;
3737 
3738  mutt_clear_error();
3739 
3740  *forced_valid = 0;
3741  resp[0] = '\0';
3742  if (whatfor)
3743  {
3744  for (l = id_defaults; l; l = l->next)
3745  {
3746  if (mutt_istr_equal(whatfor, l->what))
3747  {
3748  mutt_str_copy(resp, l->dflt, sizeof(resp));
3749  break;
3750  }
3751  }
3752  }
3753 
3754  while (true)
3755  {
3756  resp[0] = '\0';
3757  if (mutt_get_field(tag, resp, sizeof(resp), MUTT_COMP_NO_FLAGS) != 0)
3758  return NULL;
3759 
3760  if (whatfor)
3761  {
3762  if (l)
3763  mutt_str_replace(&l->dflt, resp);
3764  else
3765  {
3766  l = mutt_mem_malloc(sizeof(struct CryptCache));
3767  l->next = id_defaults;
3768  id_defaults = l;
3769  l->what = mutt_str_dup(whatfor);
3770  l->dflt = mutt_str_dup(resp);
3771  }
3772  }
3773 
3774  key = crypt_getkeybystr(resp, abilities, app, forced_valid);
3775  if (key)
3776  return key;
3777 
3778  mutt_error(_("No matching keys found for \"%s\""), resp);
3779  }
3780  /* not reached */
3781 }
static struct CryptKeyInfo * crypt_getkeybystr(const char *p, KeyFlags abilities, unsigned int app, int *forced_valid)
Find a key by string.
Definition: crypt_gpgme.c:3654
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
Internal cache for GPGME.
Definition: crypt_gpgme.c:85
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:91
A stored PGP key.
Definition: crypt_gpgme.h:43
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
static struct CryptCache * id_defaults
Definition: crypt_gpgme.c:92
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
#define mutt_error(...)
Definition: logging.h:84
struct CryptCache * next
Definition: crypt_gpgme.c:89
char * dflt
Definition: crypt_gpgme.c:88
char * what
Definition: crypt_gpgme.c:87
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ find_keys()

static char* find_keys ( struct AddressList *  addrlist,
unsigned int  app,
bool  oppenc_mode 
)
static

Find keys of the recipients of the message.

Parameters
addrlistAddress List
appApplication type, e.g. APPLICATION_PGP
oppenc_modeIf true, use opportunistic encryption
Return values
ptrSpace-separated string of keys
NULLAt least one of the keys can't be found

If oppenc_mode is true, only keys that can be determined without prompting will be used.

Definition at line 3794 of file crypt_gpgme.c.

3795 {
3796  struct ListHead crypt_hook_list = STAILQ_HEAD_INITIALIZER(crypt_hook_list);
3797  struct ListNode *crypt_hook = NULL;
3798  const char *keyid = NULL;
3799  char *keylist = NULL;
3800  size_t keylist_size = 0;
3801  size_t keylist_used = 0;
3802  struct Address *p = NULL;
3803  struct CryptKeyInfo *k_info = NULL;
3804  const char *fqdn = mutt_fqdn(true, NeoMutt->sub);
3805  char buf[1024];
3806  int forced_valid;
3807  bool key_selected;
3808  struct AddressList hookal = TAILQ_HEAD_INITIALIZER(hookal);
3809 
3810  struct Address *a = NULL;
3811  TAILQ_FOREACH(a, addrlist, entries)
3812  {
3813  key_selected = false;
3814  mutt_crypt_hook(&crypt_hook_list, a);
3815  crypt_hook = STAILQ_FIRST(&crypt_hook_list);
3816  do
3817  {
3818  p = a;
3819  forced_valid = 0;
3820  k_info = NULL;
3821 
3822  if (crypt_hook)
3823  {
3824  keyid = crypt_hook->data;
3825  enum QuadOption ans = MUTT_YES;
3826  if (!oppenc_mode && C_CryptConfirmhook)
3827  {
3828  snprintf(buf, sizeof(buf), _("Use keyID = \"%s\" for %s?"), keyid, p->mailbox);
3829  ans = mutt_yesorno(buf, MUTT_YES);
3830  }
3831  if (ans == MUTT_YES)
3832  {
3833  if (crypt_is_numerical_keyid(keyid))
3834  {
3835  if (mutt_strn_equal(keyid, "0x", 2))
3836  keyid += 2;
3837  goto bypass_selection; /* you don't see this. */
3838  }
3839 
3840  /* check for e-mail address */
3841  mutt_addrlist_clear(&hookal);
3842  if (strchr(keyid, '@') && (mutt_addrlist_parse(&hookal, keyid) != 0))
3843  {
3844  mutt_addrlist_qualify(&hookal, fqdn);
3845  p = TAILQ_FIRST(&hookal);
3846  }
3847  else if (!oppenc_mode)
3848  {
3849  k_info = crypt_getkeybystr(keyid, KEYFLAG_CANENCRYPT, app, &forced_valid);
3850  }
3851  }
3852  else if (ans == MUTT_NO)
3853  {
3854  if (key_selected || STAILQ_NEXT(crypt_hook, entries))
3855  {
3856  crypt_hook = STAILQ_NEXT(crypt_hook, entries);
3857  continue;
3858  }
3859  }
3860  else if (ans == MUTT_ABORT)
3861  {
3862  FREE(&keylist);
3863  mutt_addrlist_clear(&hookal);
3864  mutt_list_free(&crypt_hook_list);
3865  return NULL;
3866  }
3867  }
3868 
3869  if (!k_info)
3870  {
3871  k_info = crypt_getkeybyaddr(p, KEYFLAG_CANENCRYPT, app, &forced_valid, oppenc_mode);
3872  }
3873 
3874  if (!k_info && !oppenc_mode)
3875  {
3876  snprintf(buf, sizeof(buf), _("Enter keyID for %s: "), p->mailbox);
3877 
3878  k_info = crypt_ask_for_key(buf, p->mailbox, KEYFLAG_CANENCRYPT, app, &forced_valid);
3879  }
3880 
3881  if (!k_info)
3882  {
3883  FREE(&keylist);
3884  mutt_addrlist_clear(&hookal);
3885  mutt_list_free(&crypt_hook_list);
3886  return NULL;
3887  }
3888 
3889  keyid = crypt_fpr_or_lkeyid(k_info);
3890 
3891  bypass_selection:
3892  keylist_size += mutt_str_len(keyid) + 4 + 1;
3893  mutt_mem_realloc(&keylist, keylist_size);
3894  sprintf(keylist + keylist_used, "%s0x%s%s", keylist_used ? " " : "",
3895  keyid, forced_valid ? "!" : "");
3896  keylist_used = mutt_str_len(keylist);
3897 
3898  key_selected = true;
3899 
3900  crypt_key_free(&k_info);
3901  mutt_addrlist_clear(&hookal);
3902 
3903  if (crypt_hook)
3904  crypt_hook = STAILQ_NEXT(crypt_hook, entries);
3905 
3906  } while (crypt_hook);
3907 
3908  mutt_list_free(&crypt_hook_list);
3909  }
3910  return keylist;
3911 }
#define TAILQ_FIRST(head)
Definition: queue.h:716
static void crypt_key_free(struct CryptKeyInfo **keylist)
Release all the keys in a list.
Definition: crypt_gpgme.c:461
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1468
static struct CryptKeyInfo * crypt_getkeybystr(const char *p, KeyFlags abilities, unsigned int app, int *forced_valid)
Find a key by string.
Definition: crypt_gpgme.c:3654
bool crypt_is_numerical_keyid(const char *s)
Is this a numerical keyid.
Definition: crypt.c:1347
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition: lib.h:135
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
static struct CryptKeyInfo * crypt_getkeybyaddr(struct Address *a, KeyFlags abilities, unsigned int app, int *forced_valid, bool oppenc_mode)
Find a key by email address.
Definition: crypt_gpgme.c:3525
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
A stored PGP key.
Definition: crypt_gpgme.h:43
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:379
void mutt_crypt_hook(struct ListHead *list, struct Address *addr)
Find crypto hooks for an Address.
Definition: hook.c:746
User aborted the question (with Ctrl-G)
Definition: quad.h:38
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
const char * crypt_fpr_or_lkeyid(struct CryptKeyInfo *k)
Find the fingerprint of a key.
Definition: crypt_gpgme.c:422
static struct CryptKeyInfo * crypt_ask_for_key(char *tag, char *whatfor, KeyFlags abilities, unsigned int app, int *forced_valid)
Ask the user for a key.
Definition: crypt_gpgme.c:3727
#define STAILQ_NEXT(elm, field)
Definition: queue.h:397
bool mutt_strn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:650
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:1181
char * data
String.
Definition: list.h:36
bool C_CryptConfirmhook
Config: Prompt the user to confirm keys before use.
Definition: config.c:55
#define FREE(x)
Definition: memory.h:40
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:39
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
A List node for strings.
Definition: list.h:34
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
#define STAILQ_FIRST(head)
Definition: queue.h:347
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_gpgme_find_keys()

char* pgp_gpgme_find_keys ( struct AddressList *  addrlist,
bool  oppenc_mode 
)

Implements CryptModuleSpecs::find_keys()

Definition at line 3916 of file crypt_gpgme.c.

3917 {
3918  return find_keys(addrlist, APPLICATION_PGP, oppenc_mode);
3919 }
static char * find_keys(struct AddressList *addrlist, unsigned int app, bool oppenc_mode)
Find keys of the recipients of the message.
Definition: crypt_gpgme.c:3794
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
+ Here is the call graph for this function:

◆ smime_gpgme_find_keys()

char* smime_gpgme_find_keys ( struct AddressList *  addrlist,
bool  oppenc_mode 
)

Implements CryptModuleSpecs::find_keys()

Definition at line 3924 of file crypt_gpgme.c.

3925 {
3926  return find_keys(addrlist, APPLICATION_SMIME, oppenc_mode);
3927 }
static char * find_keys(struct AddressList *addrlist, unsigned int app, bool oppenc_mode)
Find keys of the recipients of the message.
Definition: crypt_gpgme.c:3794
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98
+ Here is the call graph for this function:

◆ mutt_gpgme_select_secret_key()

int mutt_gpgme_select_secret_key ( struct Buffer keyid)

Select a private Autocrypt key for a new account.

Parameters
keyidAutocrypt Key id
Return values
0Success
-1Error

Unfortunately, the internal ncrypt/crypt_gpgme.c functions use CryptKeyInfo, and so aren't exportable.

This function queries all private keys, provides the crypt_select_keys() menu, and returns the selected key fingerprint in keyid.

Definition at line 3942 of file crypt_gpgme.c.

3943 {
3944  int rc = -1, junk;
3945  gpgme_error_t err;
3946  gpgme_key_t key = NULL;
3947  gpgme_user_id_t uid = NULL;
3948  struct CryptKeyInfo *results = NULL, *k = NULL;
3949  struct CryptKeyInfo **kend = NULL;
3950  struct CryptKeyInfo *choice = NULL;
3951 
3952  gpgme_ctx_t ctx = create_gpgme_context(false);
3953 
3954  /* list all secret keys */
3955  if (gpgme_op_keylist_start(ctx, NULL, 1))
3956  goto cleanup;
3957 
3958  kend = &results;
3959 
3960  while (!(err = gpgme_op_keylist_next(ctx, &key)))
3961  {
3963 
3965  flags |= KEYFLAG_CANENCRYPT;
3966  if (key_check_cap(key, KEY_CAP_CAN_SIGN))
3967  flags |= KEYFLAG_CANSIGN;
3968 
3969  if (key->revoked)
3970  flags |= KEYFLAG_REVOKED;
3971  if (key->expired)
3972  flags |= KEYFLAG_EXPIRED;
3973  if (key->disabled)
3974  flags |= KEYFLAG_DISABLED;
3975 
3976  int idx;
3977  for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
3978  {
3979  k = mutt_mem_calloc(1, sizeof(*k));
3980  k->kobj = key;
3981  gpgme_key_ref(k->kobj);
3982  k->idx = idx;
3983  k->uid = uid->uid;
3984  k->flags = flags;
3985  if (uid->revoked)
3986  k->flags |= KEYFLAG_REVOKED;
3987  k->validity = uid->validity;
3988  *kend = k;
3989  kend = &k->next;
3990  }
3991  gpgme_key_unref(key);
3992  }
3993  if (gpg_err_code(err) != GPG_ERR_EOF)
3994  mutt_error(_("gpgme_op_keylist_next failed: %s"), gpgme_strerror(err));
3995  gpgme_op_keylist_end(ctx);
3996 
3997  if (!results)
3998  {
3999  /* L10N: mutt_gpgme_select_secret_key() tries to list all secret keys to choose
4000  from. This error is displayed if no results were found. */
4001  mutt_error(_("No secret keys found"));
4002  goto cleanup;
4003  }
4004 
4005  choice = dlg_select_gpgme_key(results, NULL, "*", APPLICATION_PGP, &junk);
4006  if (!(choice && choice->kobj && choice->kobj->subkeys && choice->kobj->subkeys->fpr))
4007  goto cleanup;
4008  mutt_buffer_strcpy(keyid, choice->kobj->subkeys->fpr);
4009 
4010  rc = 0;
4011 
4012 cleanup:
4013  crypt_key_free(&choice);
4014  crypt_key_free(&results);
4015  gpgme_release(ctx);
4016  return rc;
4017 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
static void crypt_key_free(struct CryptKeyInfo **keylist)
Release all the keys in a list.
Definition: crypt_gpgme.c:461
struct CryptKeyInfo * dlg_select_gpgme_key(struct CryptKeyInfo *keys, struct Address *p, const char *s, unsigned int app, int *forced_valid)
Get the user to select a key.
Definition: dlggpgme.c:1196
#define _(a)
Definition: message.h:28
Key can be used for encryption.
Definition: crypt_gpgme.h:76
Key can be used for signing.
Definition: crypt_gpgme.h:77
struct CryptKeyInfo * next
Definition: crypt_gpgme.h:45
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition: lib.h:135
A stored PGP key.
Definition: crypt_gpgme.h:43
int idx
and the user ID at this index
Definition: crypt_gpgme.h:47
#define KEYFLAG_EXPIRED
Key is expired.
Definition: lib.h:138
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
#define KEYFLAG_NO_FLAGS
No flags are set.
Definition: lib.h:133
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:570
uint16_t KeyFlags
Flags describing PGP/SMIME keys, e.g. KEYFLAG_CANSIGN.
Definition: lib.h:132
gpgme_key_t kobj
Definition: crypt_gpgme.h:46
unsigned int key_check_cap(gpgme_key_t key, enum KeyCap cap)
Check the capabilities of a key.
Definition: crypt_gpgme.c:3237
#define KEYFLAG_DISABLED
Key is marked disabled.
Definition: lib.h:140
#define KEYFLAG_CANSIGN
Key is suitable for signing.
Definition: lib.h:134
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.h:49
#define mutt_error(...)
Definition: logging.h:84
#define KEYFLAG_REVOKED
Key is revoked.
Definition: lib.h:139
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_gpgme_make_key_attachment()

struct Body* pgp_gpgme_make_key_attachment ( void  )

Implements CryptModuleSpecs::pgp_make_key_attachment()

Definition at line 4023 of file crypt_gpgme.c.

4024 {
4025 #ifdef HAVE_GPGME_OP_EXPORT_KEYS
4026  gpgme_ctx_t context = NULL;
4027  gpgme_key_t export_keys[2] = { 0 };
4028  gpgme_data_t keydata = NULL;
4029  gpgme_error_t err;
4030  struct Body *att = NULL;
4031  char buf[1024];
4032  struct stat sb;
4033 
4034  OptPgpCheckTrust = false;
4035 
4036  struct CryptKeyInfo *key = crypt_ask_for_key(_("Please enter the key ID: "), NULL,
4038  if (!key)
4039  goto bail;
4040  export_keys[0] = key->kobj;
4041  export_keys[1] = NULL;
4042 
4043  context = create_gpgme_context(false);
4044  gpgme_set_armor(context, 1);
4045  keydata = create_gpgme_data();
4046  err = gpgme_op_export_keys(context, export_keys, 0, keydata);
4047  if (err != GPG_ERR_NO_ERROR)
4048  {
4049  mutt_error(_("Error exporting key: %s"), gpgme_strerror(err));
4050  goto bail;
4051  }
4052 
4053  char *tempf = data_object_to_tempfile(keydata, NULL);
4054  if (!tempf)
4055  goto bail;
4056 
4057  att = mutt_body_new();
4058  /* tempf is a newly allocated string, so this is correct: */
4059  att->filename = tempf;
4060  att->unlink = true;
4061  att->use_disp = false;
4062  att->type = TYPE_APPLICATION;
4063  att->subtype = mutt_str_dup("pgp-keys");
4064  /* L10N: MIME description for exported (attached) keys.
4065  You can translate this entry to a non-ASCII string (it will be encoded),
4066  but it may be safer to keep it untranslated. */
4067  snprintf(buf, sizeof(buf), _("PGP Key 0x%s"), crypt_keyid(key));
4068  att->description = mutt_str_dup(buf);
4070 
4071  stat(tempf, &sb);
4072  att->length = sb.st_size;
4073 
4074 bail:
4075  crypt_key_free(&key);
4076  gpgme_data_release(keydata);
4077  gpgme_release(context);
4078 
4079  return att;
4080 #else
4081  mutt_error("gpgme_op_export_keys not supported");
4082  return NULL;
4083 #endif
4084 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
static char * data_object_to_tempfile(gpgme_data_t data, FILE **fp_ret)
Copy a data object to a temporary file.
Definition: crypt_gpgme.c:804
static void crypt_key_free(struct CryptKeyInfo **keylist)
Release all the keys in a list.
Definition: crypt_gpgme.c:461
void mutt_update_encoding(struct Body *a, struct ConfigSubset *sub)
Update the encoding type.
Definition: sendlib.c:903
const char * crypt_keyid(struct CryptKeyInfo *k)
Find the ID for the key.
Definition: crypt_gpgme.c:347
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
Container for Accounts, Notifications.
Definition: neomutt.h:36
The body of an email.
Definition: body.h:34
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
A stored PGP key.
Definition: crypt_gpgme.h:43
char * subtype
content-type subtype
Definition: body.h:37
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define KEYFLAG_NO_FLAGS
No flags are set.
Definition: lib.h:133
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:570
gpgme_key_t kobj
Definition: crypt_gpgme.h:46
static struct CryptKeyInfo * crypt_ask_for_key(char *tag, char *whatfor, KeyFlags abilities, unsigned int app, int *forced_valid)
Ask the user for a key.
Definition: crypt_gpgme.c:3727
WHERE bool OptPgpCheckTrust
(pseudo) used by dlg_select_pgp_key()
Definition: options.h:49
char * description
content-description
Definition: body.h:40
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
static gpgme_data_t create_gpgme_data(void)
Create a new GPGME data object.
Definition: crypt_gpgme.c:608
#define mutt_error(...)
Definition: logging.h:84
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Type: &#39;application/*&#39;.
Definition: mime.h:33
+ Here is the call graph for this function:

◆ init_common()

static void init_common ( void  )
static

Initialise code common to PGP and SMIME parts of GPGME.

Definition at line 4089 of file crypt_gpgme.c.

4090 {
4091  /* this initialization should only run one time, but it may be called by
4092  * either pgp_gpgme_init or smime_gpgme_init */
4093  static bool has_run = false;
4094  if (has_run)
4095  return;
4096 
4097  gpgme_check_version(NULL);
4098  gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
4099 #ifdef ENABLE_NLS
4100  gpgme_set_locale(NULL, LC_MESSAGES, setlocale(LC_MESSAGES, NULL));
4101 #endif
4102  has_run = true;
4103 }
+ Here is the caller graph for this function:

◆ init_pgp()

static void init_pgp ( void  )
static

Initialise the PGP crypto backend.

Definition at line 4108 of file crypt_gpgme.c.

4109 {
4110  if (gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP) != GPG_ERR_NO_ERROR)
4111  {
4112  mutt_error(_("GPGME: OpenPGP protocol not available"));
4113  }
4114 }
#define _(a)
Definition: message.h:28
#define mutt_error(...)
Definition: logging.h:84
+ Here is the caller graph for this function:

◆ init_smime()

static void init_smime ( void  )
static

Initialise the SMIME crypto backend.

Definition at line 4119 of file crypt_gpgme.c.

4120 {
4121  if (gpgme_engine_check_version(GPGME_PROTOCOL_CMS) != GPG_ERR_NO_ERROR)
4122  {
4123  mutt_error(_("GPGME: CMS protocol not available"));
4124  }
4125 }
#define _(a)
Definition: message.h:28
#define mutt_error(...)
Definition: logging.h:84
+ Here is the caller graph for this function:

◆ pgp_gpgme_init()

void pgp_gpgme_init ( void  )

Implements CryptModuleSpecs::init()

Definition at line 4130 of file crypt_gpgme.c.

4131 {
4132  init_common();
4133  init_pgp();
4134 }
static void init_common(void)
Initialise code common to PGP and SMIME parts of GPGME.
Definition: crypt_gpgme.c:4089
static void init_pgp(void)
Initialise the PGP crypto backend.
Definition: crypt_gpgme.c:4108
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_gpgme_init()

void smime_gpgme_init ( void  )

Implements CryptModuleSpecs::init()

Definition at line 4139 of file crypt_gpgme.c.

4140 {
4141  init_common();
4142  init_smime();
4143 }
static void init_smime(void)
Initialise the SMIME crypto backend.
Definition: crypt_gpgme.c:4119
static void init_common(void)
Initialise code common to PGP and SMIME parts of GPGME.
Definition: crypt_gpgme.c:4089
+ Here is the call graph for this function:

◆ gpgme_send_menu()

static int gpgme_send_menu ( struct Email e,
bool  is_smime 
)
static

Show the user the encryption/signing menu.

Parameters
eEmail
is_smimeTrue if an SMIME message
Return values
numFlags, e.g. APPLICATION_SMIME | SEC_ENCRYPT

Definition at line 4151 of file crypt_gpgme.c.

4152 {
4153  struct CryptKeyInfo *p = NULL;
4154  const char *prompt = NULL;
4155  const char *letters = NULL;
4156  const char *choices = NULL;
4157  int choice;
4158 
4159  if (is_smime)
4161  else
4162  e->security |= APPLICATION_PGP;
4163 
4164  /* Opportunistic encrypt is controlling encryption.
4165  * NOTE: "Signing" and "Clearing" only adjust the sign bit, so we have different
4166  * letter choices for those.
4167  */
4169  {
4170  if (is_smime)
4171  {
4172  /* L10N: S/MIME options (opportunistic encryption is on) */
4173  prompt =
4174  _("S/MIME (s)ign, sign (a)s, (p)gp, (c)lear, or (o)ppenc mode off?");
4175  /* L10N: S/MIME options (opportunistic encryption is on) */
4176  letters = _("sapco");
4177  choices = "SapCo";
4178  }
4179  else
4180  {
4181  /* L10N: PGP options (opportunistic encryption is on) */
4182  prompt =
4183  _("PGP (s)ign, sign (a)s, s/(m)ime, (c)lear, or (o)ppenc mode off?");
4184  /* L10N: PGP options (opportunistic encryption is on) */
4185  letters = _("samco");
4186  choices = "SamCo";
4187  }
4188  }
4189  /* Opportunistic encryption option is set, but is toggled off for this message. */
4190  else if (C_CryptOpportunisticEncrypt)
4191  {
4192  if (is_smime)
4193  {
4194  /* L10N: S/MIME options (opportunistic encryption is off) */
4195  prompt = _("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp, (c)lear, "
4196  "or (o)ppenc mode?");
4197  /* L10N: S/MIME options (opportunistic encryption is off) */
4198  letters = _("esabpco");
4199  choices = "esabpcO";
4200  }
4201  else
4202  {
4203  /* L10N: PGP options (opportunistic encryption is off) */
4204  prompt = _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime, (c)lear, "
4205  "or (o)ppenc mode?");
4206  /* L10N: PGP options (opportunistic encryption is off) */
4207  letters = _("esabmco");
4208  choices = "esabmcO";
4209  }
4210  }
4211  /* Opportunistic encryption is unset */
4212  else
4213  {
4214  if (is_smime)
4215  {
4216  /* L10N: S/MIME options */
4217  prompt =
4218  _("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?");
4219  /* L10N: S/MIME options */
4220  letters = _("esabpc");
4221  choices = "esabpc";
4222  }
4223  else
4224  {
4225  /* L10N: PGP options */
4226  prompt =
4227  _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?");
4228  /* L10N: PGP options */
4229  letters = _("esabmc");
4230  choices = "esabmc";
4231  }
4232  }
4233 
4234  choice = mutt_multi_choice(prompt, letters);
4235  if (choice > 0)
4236  {
4237  switch (choices[choice - 1])
4238  {
4239  case 'a': /* sign (a)s */
4240  p = crypt_ask_for_key(_("Sign as: "), NULL, KEYFLAG_CANSIGN,
4241  is_smime ? APPLICATION_SMIME : APPLICATION_PGP, NULL);
4242  if (p)
4243  {
4244  char input_signas[128];
4245  snprintf(input_signas, sizeof(input_signas), "0x%s", crypt_fpr_or_lkeyid(p));
4246  mutt_str_replace(is_smime ? &C_SmimeDefaultKey : &C_PgpSignAs, input_signas);
4247  crypt_key_free(&p);
4248 
4249  e->security |= SEC_SIGN;
4250  }
4251  break;
4252 
4253  case 'b': /* (b)oth */
4254  e->security |= (SEC_ENCRYPT | SEC_SIGN);
4255  break;
4256 
4257  case 'C':
4258  e->security &= ~SEC_SIGN;
4259  break;
4260 
4261  case 'c': /* (c)lear */
4262  e->security &= ~(SEC_ENCRYPT | SEC_SIGN);
4263  break;
4264 
4265  case 'e': /* (e)ncrypt */
4266  e->security |= SEC_ENCRYPT;
4267  e->security &= ~SEC_SIGN;
4268  break;
4269 
4270  case 'm': /* (p)gp or s/(m)ime */
4271  case 'p':
4272  is_smime = !is_smime;
4273  if (is_smime)
4274  {
4275  e->security &= ~APPLICATION_PGP;
4277  }
4278  else
4279  {
4280  e->security &= ~APPLICATION_SMIME;
4281  e->security |= APPLICATION_PGP;
4282  }
4284  break;
4285 
4286  case 'O': /* oppenc mode on */
4287  e->security |= SEC_OPPENCRYPT;
4289  break;
4290 
4291  case 'o': /* oppenc mode off */
4292  e->security &= ~SEC_OPPENCRYPT;
4293  break;
4294 
4295  case 'S': /* (s)ign in oppenc mode */
4296  e->security |= SEC_SIGN;
4297  break;
4298 
4299  case 's': /* (s)ign */
4300  e->security &= ~SEC_ENCRYPT;
4301  e->security |= SEC_SIGN;
4302  break;
4303  }
4304  }
4305 
4306  return e->security;
4307 }
static void crypt_key_free(struct CryptKeyInfo **keylist)
Release all the keys in a list.
Definition: crypt_gpgme.c:461
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:85
#define _(a)
Definition: message.h:28
A stored PGP key.
Definition: crypt_gpgme.h:43
bool C_CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: config.c:56
char * C_PgpSignAs
Config: Use this alternative key for signing messages.
Definition: config.c:67
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98