NeoMutt  2020-06-26-89-g172cd3
Teaching an old dog new tricks
DOXYGEN
crypt_gpgme.c File Reference

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

#include "config.h"
#include <ctype.h>
#include <errno.h>
#include <gpg-error.h>
#include <gpgme.h>
#include <langinfo.h>
#include <limits.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 "crypt.h"
#include "format_flags.h"
#include "handler.h"
#include "hook.h"
#include "keymap.h"
#include "mutt_attach.h"
#include "mutt_globals.h"
#include "mutt_logging.h"
#include "mutt_menu.h"
#include "muttlib.h"
#include "opcodes.h"
#include "options.h"
#include "pager.h"
#include "protos.h"
#include "recvattach.h"
#include "state.h"
#include "autocrypt/lib.h"
#include "ncrypt/lib.h"
#include "send/lib.h"
#include <libintl.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...
 
struct  DnArray
 An X500 Distinguished Name. More...
 
struct  CryptKeyInfo
 A stored PGP key. More...
 
struct  CryptEntry
 An entry in the Select-Key menu. 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)
 

Enumerations

enum  KeyCap { KEY_CAP_CAN_ENCRYPT, KEY_CAP_CAN_SIGN, KEY_CAP_CAN_CERTIFY }
 PGP/SMIME Key Capabilities. More...
 
enum  KeyInfo {
  KIP_NAME = 0, KIP_AKA, KIP_VALID_FROM, KIP_VALID_TO,
  KIP_KEY_TYPE, KIP_KEY_USAGE, KIP_FINGERPRINT, KIP_SERIAL_NO,
  KIP_ISSUED_BY, KIP_SUBKEY, KIP_MAX
}
 PGP Key info. More...
 

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...
 
static int digit (const char *s)
 Is the character a number. More...
 
static int digit_or_letter (const char *s)
 Is the character a number or letter. More...
 
static void print_utf8 (FILE *fp, const char *buf, size_t len)
 Write a UTF-8 string to a file. More...
 
static 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...
 
static const char * crypt_fpr_or_lkeyid (struct CryptKeyInfo *k)
 Find the fingerprint of a key. More...
 
static char * crypt_key_abilities (KeyFlags flags)
 Parse key flags into a string. More...
 
static char crypt_flags (KeyFlags flags)
 Parse the key flags into a single character. More...
 
static 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...
 
static bool crypt_key_is_valid (struct CryptKeyInfo *k)
 Is the key valid. More...
 
static bool crypt_id_is_strong (struct CryptKeyInfo *key)
 Is the key strong. More...
 
static 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...
 
static 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...
 
static const char * crypt_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the key selection menu - Implements format_t. More...
 
static void crypt_make_entry (char *buf, size_t buflen, struct Menu *menu, int line)
 Format a menu item for the key selection list - Implements Menu::make_entry() More...
 
static int compare_key_address (const void *a, const void *b)
 Compare Key addresses and IDs for sorting. More...
 
static int crypt_compare_address (const void *a, const void *b)
 Compare the addresses of two keys. More...
 
static int compare_keyid (const void *a, const void *b)
 Compare Key IDs and addresses for sorting. More...
 
static int crypt_compare_keyid (const void *a, const void *b)
 Compare the IDs of two keys. More...
 
static int compare_key_date (const void *a, const void *b)
 Compare Key creation dates and addresses for sorting. More...
 
static int crypt_compare_date (const void *a, const void *b)
 Compare the dates of two keys. More...
 
static int compare_key_trust (const void *a, const void *b)
 Compare the trust of keys for sorting. More...
 
static int crypt_compare_trust (const void *a, const void *b)
 Compare the trust levels of two keys. More...
 
static bool print_dn_part (FILE *fp, struct DnArray *dn, const char *key)
 Print the X.500 Distinguished Name. More...
 
static void print_dn_parts (FILE *fp, struct DnArray *dn)
 Print all parts of a DN in a standard sequence. More...
 
static const char * parse_dn_part (struct DnArray *array, const char *str)
 Parse an RDN. More...
 
static struct DnArrayparse_dn (const char *str)
 Parse a DN and return an array-ized one. More...
 
static void parse_and_print_user_id (FILE *fp, const char *userid)
 Print a nice representation of the userid. More...
 
static unsigned int key_check_cap (gpgme_key_t key, enum KeyCap cap)
 Check the capabilities of a key. More...
 
static void print_key_info (gpgme_key_t key, FILE *fp)
 Verbose information about a key or certificate to a file. More...
 
static void verify_key (struct CryptKeyInfo *key)
 Show detailed information about the selected 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_select_key (struct CryptKeyInfo *keys, struct Address *p, const char *s, unsigned int app, int *forced_valid)
 Get the user to select a key. 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
 
static const char *const KeyInfoPrompts []
 
int KeyInfoPadding [KIP_MAX] = { 0 }
 

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 86 of file crypt_gpgme.c.

◆ CRYPT_KV_ADDR

#define CRYPT_KV_ADDR   (1 << 1)

Definition at line 87 of file crypt_gpgme.c.

◆ CRYPT_KV_STRING

#define CRYPT_KV_STRING   (1 << 2)

Definition at line 88 of file crypt_gpgme.c.

◆ CRYPT_KV_STRONGID

#define CRYPT_KV_STRONGID   (1 << 3)

Definition at line 89 of file crypt_gpgme.c.

◆ CRYPT_KV_MATCH

#define CRYPT_KV_MATCH   (CRYPT_KV_ADDR | CRYPT_KV_STRING)

Definition at line 90 of file crypt_gpgme.c.

◆ PKA_NOTATION_NAME

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

Definition at line 140 of file crypt_gpgme.c.

◆ _LINE_COMPARE

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

Definition at line 142 of file crypt_gpgme.c.

◆ MESSAGE

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

Definition at line 143 of file crypt_gpgme.c.

◆ SIGNED_MESSAGE

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

Definition at line 144 of file crypt_gpgme.c.

◆ PUBLIC_KEY_BLOCK

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

Definition at line 145 of file crypt_gpgme.c.

◆ BEGIN_PGP_SIGNATURE

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

Definition at line 146 of file crypt_gpgme.c.

Enumeration Type Documentation

◆ KeyCap

enum KeyCap

PGP/SMIME Key Capabilities.

Enumerator
KEY_CAP_CAN_ENCRYPT 

Key can be used for encryption.

KEY_CAP_CAN_SIGN 

Key can be used for signing.

KEY_CAP_CAN_CERTIFY 

Key can be used to certify.

Definition at line 152 of file crypt_gpgme.c.

153 {
157 };
Key can be used to certify.
Definition: crypt_gpgme.c:156
Key can be used for signing.
Definition: crypt_gpgme.c:155
Key can be used for encryption.
Definition: crypt_gpgme.c:154

◆ KeyInfo

enum KeyInfo

PGP Key info.

Enumerator
KIP_NAME 

PGP Key field: Name.

KIP_AKA 

PGP Key field: aka (Also Known As)

KIP_VALID_FROM 

PGP Key field: Valid From date.

KIP_VALID_TO 

PGP Key field: Valid To date.

KIP_KEY_TYPE 

PGP Key field: Key Type.

KIP_KEY_USAGE 

PGP Key field: Key Usage.

KIP_FINGERPRINT 

PGP Key field: Fingerprint.

KIP_SERIAL_NO 

PGP Key field: Serial number.

KIP_ISSUED_BY 

PGP Key field: Issued By.

KIP_SUBKEY 

PGP Key field: Subkey.

KIP_MAX 

Definition at line 162 of file crypt_gpgme.c.

163 {
164  KIP_NAME = 0,
165  KIP_AKA,
167  KIP_VALID_TO,
168  KIP_KEY_TYPE,
169  KIP_KEY_USAGE,
171  KIP_SERIAL_NO,
172  KIP_ISSUED_BY,
173  KIP_SUBKEY,
174  KIP_MAX,
175 };
PGP Key field: aka (Also Known As)
Definition: crypt_gpgme.c:165
PGP Key field: Subkey.
Definition: crypt_gpgme.c:173
PGP Key field: Valid To date.
Definition: crypt_gpgme.c:167
PGP Key field: Issued By.
Definition: crypt_gpgme.c:172
PGP Key field: Key Usage.
Definition: crypt_gpgme.c:169
PGP Key field: Key Type.
Definition: crypt_gpgme.c:168
PGP Key field: Serial number.
Definition: crypt_gpgme.c:171
PGP Key field: Name.
Definition: crypt_gpgme.c:164
PGP Key field: Valid From date.
Definition: crypt_gpgme.c:166
PGP Key field: Fingerprint.
Definition: crypt_gpgme.c:170

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 193 of file crypt_gpgme.c.

194 {
195  return mutt_str_equal(notation->name, PKA_NOTATION_NAME);
196 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
#define PKA_NOTATION_NAME
Definition: crypt_gpgme.c:140
+ 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 202 of file crypt_gpgme.c.

203 {
204 #if (GPGME_VERSION_NUMBER < 0x010800)
205  /* gpgme_get_ctx_flag is not available in GPGME < 1.8.0. In this case, stay
206  * on the safe side and always redraw. */
207  (void) ctx;
209 #else
210  const char *s = gpgme_get_ctx_flag(ctx, "redraw");
211  if (!s /* flag not known */ || *s /* flag true */)
212  {
214  }
215 #endif
216 }
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:128
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ digit()

static int digit ( const char *  s)
static

Is the character a number.

Parameters
sOnly the first character of this string is tested
Return values
truewhen s points to a digit

Definition at line 223 of file crypt_gpgme.c.

224 {
225  return (*s >= '0' && *s <= '9');
226 }
+ Here is the caller graph for this function:

◆ digit_or_letter()

static int digit_or_letter ( const char *  s)
static

Is the character a number or letter.

Parameters
sOnly the first character of this string is tested
Return values
truewhen s points to a digit or letter

Definition at line 233 of file crypt_gpgme.c.

234 {
235  return digit(s) || (*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z');
236 }
static int digit(const char *s)
Is the character a number.
Definition: crypt_gpgme.c:223
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_utf8()

static void print_utf8 ( FILE *  fp,
const char *  buf,
size_t  len 
)
static

Write a UTF-8 string to a file.

Parameters
fpFile to write to
bufBuffer to read from
lenLength to read

Convert the character set.

Definition at line 246 of file crypt_gpgme.c.

247 {
248  char *tstr = mutt_mem_malloc(len + 1);
249  memcpy(tstr, buf, len);
250  tstr[len] = 0;
251 
252  /* fromcode "utf-8" is sure, so we don't want
253  * charset-hook corrections: flags must be 0. */
254  mutt_ch_convert_string(&tstr, "utf-8", C_Charset, 0);
255  fputs(tstr, fp);
256  FREE(&tstr);
257 }
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
Definition: charset.c:754
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:40
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_keyid()

static const char* crypt_keyid ( struct CryptKeyInfo k)
static

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 471 of file crypt_gpgme.c.

472 {
473  const char *s = "????????";
474 
475  if (k->kobj && k->kobj->subkeys)
476  {
477  s = k->kobj->subkeys->keyid;
478  if ((!C_PgpLongIds) && (strlen(s) == 16))
479  {
480  /* Return only the short keyID. */
481  s += 8;
482  }
483  }
484 
485  return s;
486 }
gpgme_key_t kobj
Definition: crypt_gpgme.c:120
bool C_PgpLongIds
Config: Display long PGP key IDs to the user.
Definition: config.c:48
+ 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 495 of file crypt_gpgme.c.

496 {
497  const char *s = "????????????????";
498 
499  if (k->kobj && k->kobj->subkeys)
500  {
501  s = k->kobj->subkeys->keyid;
502  }
503 
504  return s;
505 }
gpgme_key_t kobj
Definition: crypt_gpgme.c:120
+ 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 512 of file crypt_gpgme.c.

513 {
514  const char *s = "????????";
515 
516  if (k->kobj && k->kobj->subkeys)
517  {
518  s = k->kobj->subkeys->keyid;
519  if (strlen(s) == 16)
520  s += 8;
521  }
522 
523  return s;
524 }
gpgme_key_t kobj
Definition: crypt_gpgme.c:120
+ 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 531 of file crypt_gpgme.c.

532 {
533  const char *s = "";
534 
535  if (k->kobj && k->kobj->subkeys)
536  s = k->kobj->subkeys->fpr;
537 
538  return s;
539 }
gpgme_key_t kobj
Definition: crypt_gpgme.c:120
+ Here is the caller graph for this function:

◆ crypt_fpr_or_lkeyid()

static const char* crypt_fpr_or_lkeyid ( struct CryptKeyInfo k)
static

Find the fingerprint of a key.

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

Definition at line 546 of file crypt_gpgme.c.

547 {
548  const char *s = "????????????????";
549 
550  if (k->kobj && k->kobj->subkeys)
551  {
552  if (k->kobj->subkeys->fpr)
553  s = k->kobj->subkeys->fpr;
554  else
555  s = k->kobj->subkeys->keyid;
556  }
557 
558  return s;
559 }
gpgme_key_t kobj
Definition: crypt_gpgme.c:120
+ Here is the caller graph for this function:

◆ crypt_key_abilities()

static char* crypt_key_abilities ( KeyFlags  flags)
static

Parse key flags into a string.

Parameters
flagsFlags, see KeyFlags
Return values
ptrFlag string
Note
The string is statically allocated.

Definition at line 568 of file crypt_gpgme.c.

569 {
570  static char buf[3];
571 
572  if (!(flags & KEYFLAG_CANENCRYPT))
573  buf[0] = '-';
574  else if (flags & KEYFLAG_PREFER_SIGNING)
575  buf[0] = '.';
576  else
577  buf[0] = 'e';
578 
579  if (!(flags & KEYFLAG_CANSIGN))
580  buf[1] = '-';
581  else if (flags & KEYFLAG_PREFER_ENCRYPTION)
582  buf[1] = '.';
583  else
584  buf[1] = 's';
585 
586  buf[2] = '\0';
587 
588  return buf;
589 }
#define KEYFLAG_PREFER_ENCRYPTION
Key&#39;s owner prefers encryption.
Definition: lib.h:138
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition: lib.h:130
#define KEYFLAG_PREFER_SIGNING
Key&#39;s owner prefers signing.
Definition: lib.h:139
#define KEYFLAG_CANSIGN
Key is suitable for signing.
Definition: lib.h:129
+ Here is the caller graph for this function:

◆ crypt_flags()

static char crypt_flags ( KeyFlags  flags)
static

Parse the key flags into a single character.

Parameters
flagsFlags, see KeyFlags
Return values
charFlag character

The returned character describes the most important flag.

Definition at line 598 of file crypt_gpgme.c.

599 {
600  if (flags & KEYFLAG_REVOKED)
601  return 'R';
602  if (flags & KEYFLAG_EXPIRED)
603  return 'X';
604  if (flags & KEYFLAG_DISABLED)
605  return 'd';
606  if (flags & KEYFLAG_CRITICAL)
607  return 'c';
608 
609  return ' ';
610 }
#define KEYFLAG_EXPIRED
Key is expired.
Definition: lib.h:133
#define KEYFLAG_DISABLED
Key is marked disabled.
Definition: lib.h:135
#define KEYFLAG_CRITICAL
Key is marked critical.
Definition: lib.h:137
#define KEYFLAG_REVOKED
Key is revoked.
Definition: lib.h:134
+ Here is the caller graph for this function:

◆ crypt_copy_key()

static struct CryptKeyInfo* crypt_copy_key ( struct CryptKeyInfo key)
static

Return a copy of KEY.

Parameters
keyKey to copy
Return values
ptrCopy of key

Definition at line 617 of file crypt_gpgme.c.

618 {
619  struct CryptKeyInfo *k = NULL;
620 
621  k = mutt_mem_calloc(1, sizeof(*k));
622  k->kobj = key->kobj;
623  gpgme_key_ref(key->kobj);
624  k->idx = key->idx;
625  k->uid = key->uid;
626  k->flags = key->flags;
627  k->validity = key->validity;
628 
629  return k;
630 }
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.c:117
int idx
and the user ID at this index
Definition: crypt_gpgme.c:121
const char * uid
and for convenience point to this user ID
Definition: crypt_gpgme.c:122
gpgme_key_t kobj
Definition: crypt_gpgme.c:120
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.c:123
gpgme_validity_t validity
uid validity (cached for convenience)
Definition: crypt_gpgme.c:124
+ 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 636 of file crypt_gpgme.c.

637 {
638  if (!keylist)
639  return;
640 
641  struct CryptKeyInfo *k = NULL;
642 
643  while (*keylist)
644  {
645  k = *keylist;
646  *keylist = (*keylist)->next;
647 
648  gpgme_key_unref(k->kobj);
649  FREE(&k);
650  }
651 }
struct CryptKeyInfo * next
Definition: crypt_gpgme.c:119
A stored PGP key.
Definition: crypt_gpgme.c:117
gpgme_key_t kobj
Definition: crypt_gpgme.c:120
#define FREE(x)
Definition: memory.h:40
+ Here is the caller graph for this function:

◆ crypt_key_is_valid()

static bool crypt_key_is_valid ( struct CryptKeyInfo k)
static

Is the key valid.

Parameters
kKey to test
Return values
trueIf key is valid

Definition at line 658 of file crypt_gpgme.c.

659 {
660  if (k->flags & KEYFLAG_CANTUSE)
661  return false;
662  return true;
663 }
#define KEYFLAG_CANTUSE
Definition: lib.h:141
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.c:123
+ Here is the caller graph for this function:

◆ crypt_id_is_strong()

static bool crypt_id_is_strong ( struct CryptKeyInfo key)
static

Is the key strong.

Parameters
keyKey to test
Return values
trueValidity of key is sufficient

Definition at line 670 of file crypt_gpgme.c.

671 {
672  if (!key)
673  return false;
674 
675  bool is_strong = false;
676 
677  if ((key->flags & KEYFLAG_ISX509))
678  return true;
679 
680  switch (key->validity)
681  {
682  case GPGME_VALIDITY_MARGINAL:
683  case GPGME_VALIDITY_NEVER:
684  case GPGME_VALIDITY_UNDEFINED:
685  case GPGME_VALIDITY_UNKNOWN:
686  is_strong = false;
687  break;
688 
689  case GPGME_VALIDITY_FULL:
690  case GPGME_VALIDITY_ULTIMATE:
691  is_strong = true;
692  break;
693  }
694 
695  return is_strong;
696 }
#define KEYFLAG_ISX509
Key is an X.509 key.
Definition: lib.h:131
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.c:123
gpgme_validity_t validity
uid validity (cached for convenience)
Definition: crypt_gpgme.c:124
+ Here is the caller graph for this function:

◆ crypt_id_is_valid()

static int crypt_id_is_valid ( struct CryptKeyInfo key)
static

Is key ID valid.

Parameters
keyKey to test
Return values
trueKey is valid

When the key is not marked as unusable

Definition at line 705 of file crypt_gpgme.c.

706 {
707  if (!key)
708  return 0;
709 
710  return !(key->flags & KEYFLAG_CANTUSE);
711 }
#define KEYFLAG_CANTUSE
Definition: lib.h:141
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.c:123
+ 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 723 of file crypt_gpgme.c.

725 {
726  int rc = 0;
727 
728  if (crypt_id_is_valid(key))
729  rc |= CRYPT_KV_VALID;
730 
731  if (crypt_id_is_strong(key))
732  rc |= CRYPT_KV_STRONGID;
733 
734  if (addr && u_addr)
735  {
736  if (addr->mailbox && u_addr->mailbox &&
737  mutt_istr_equal(addr->mailbox, u_addr->mailbox))
738  {
739  rc |= CRYPT_KV_ADDR;
740  }
741 
742  if (addr->personal && u_addr->personal &&
743  mutt_istr_equal(addr->personal, u_addr->personal))
744  {
745  rc |= CRYPT_KV_STRING;
746  }
747  }
748 
749  return rc;
750 }
static int crypt_id_is_valid(struct CryptKeyInfo *key)
Is key ID valid.
Definition: crypt_gpgme.c:705
#define CRYPT_KV_STRONGID
Definition: crypt_gpgme.c:89
#define CRYPT_KV_ADDR
Definition: crypt_gpgme.c:87
char * mailbox
Mailbox and host address.
Definition: address.h:37
#define CRYPT_KV_STRING
Definition: crypt_gpgme.c:88
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
char * personal
Real name of address.
Definition: address.h:36
#define CRYPT_KV_VALID
Definition: crypt_gpgme.c:86
static bool crypt_id_is_strong(struct CryptKeyInfo *key)
Is the key strong.
Definition: crypt_gpgme.c:670
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ create_gpgme_context()

static gpgme_ctx_t create_gpgme_context ( bool  for_smime)
static

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 757 of file crypt_gpgme.c.

758 {
759  gpgme_ctx_t ctx = NULL;
760 
761  gpgme_error_t err = gpgme_new(&ctx);
762 
763 #ifdef USE_AUTOCRYPT
764  if (!err && OptAutocryptGpgme)
765  err = gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_OpenPGP, NULL, C_AutocryptDir);
766 #endif
767 
768  if (err != 0)
769  {
770  mutt_error(_("error creating GPGME context: %s"), gpgme_strerror(err));
771  mutt_exit(1);
772  }
773 
774  if (for_smime)
775  {
776  err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS);
777  if (err != 0)
778  {
779  mutt_error(_("error enabling CMS protocol: %s"), gpgme_strerror(err));
780  mutt_exit(1);
781  }
782  }
783 
784  return ctx;
785 }
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:137
#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 795 of file crypt_gpgme.c.

796 {
797  gpgme_data_t data = NULL;
798 
799  gpgme_error_t err = gpgme_data_new(&data);
800  if (err != 0)
801  {
802  mutt_error(_("error creating GPGME data object: %s"), gpgme_strerror(err));
803  mutt_exit(1);
804  }
805  return data;
806 }
#define _(a)
Definition: message.h:28
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:137
#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 851 of file crypt_gpgme.c.

852 {
853  int err = 0;
854  gpgme_data_t data = NULL;
855 
856  struct Buffer *tempfile = mutt_buffer_pool_get();
857  mutt_buffer_mktemp(tempfile);
858  FILE *fp_tmp = mutt_file_fopen(mutt_b2s(tempfile), "w+");
859  if (!fp_tmp)
860  {
861  mutt_perror(mutt_b2s(tempfile));
862  goto cleanup;
863  }
864 
865  mutt_write_mime_header(a, fp_tmp, NeoMutt->sub);
866  fputc('\n', fp_tmp);
867  mutt_write_mime_body(a, fp_tmp, NeoMutt->sub);
868 
869  if (convert)
870  {
871  int c, hadcr = 0;
872  unsigned char buf[1];
873 
874  data = create_gpgme_data();
875  rewind(fp_tmp);
876  while ((c = fgetc(fp_tmp)) != EOF)
877  {
878  if (c == '\r')
879  hadcr = 1;
880  else
881  {
882  if ((c == '\n') && !hadcr)
883  {
884  buf[0] = '\r';
885  gpgme_data_write(data, buf, 1);
886  }
887 
888  hadcr = 0;
889  }
890  /* FIXME: This is quite suboptimal */
891  buf[0] = c;
892  gpgme_data_write(data, buf, 1);
893  }
894  mutt_file_fclose(&fp_tmp);
895  gpgme_data_seek(data, 0, SEEK_SET);
896  }
897  else
898  {
899  mutt_file_fclose(&fp_tmp);
900  err = gpgme_data_new_from_file(&data, mutt_b2s(tempfile), 1);
901  if (err != 0)
902  {
903  mutt_error(_("error allocating data object: %s"), gpgme_strerror(err));
904  gpgme_data_release(data);
905  data = NULL;
906  /* fall through to unlink the tempfile */
907  }
908  }
909  unlink(mutt_b2s(tempfile));
910 
911 cleanup:
912  mutt_buffer_pool_release(&tempfile);
913  return data;
914 }
#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:755
#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:795
#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 923 of file crypt_gpgme.c.

924 {
925  gpgme_data_t data = NULL;
926 
927  int err = gpgme_data_new_from_filepart(&data, NULL, fp, offset, length);
928  if (err != 0)
929  {
930  mutt_error(_("error allocating data object: %s"), gpgme_strerror(err));
931  return NULL;
932  }
933 
934  return data;
935 }
#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 944 of file crypt_gpgme.c.

945 {
946  char buf[4096];
947  ssize_t nread;
948 
949  int err = ((gpgme_data_seek(data, 0, SEEK_SET) == -1) ? gpgme_error_from_errno(errno) : 0);
950  if (err != 0)
951  {
952  mutt_error(_("error rewinding data object: %s"), gpgme_strerror(err));
953  return -1;
954  }
955 
956  while ((nread = gpgme_data_read(data, buf, sizeof(buf))) > 0)
957  {
958  /* fixme: we are not really converting CRLF to LF but just
959  * skipping CR. Doing it correctly needs a more complex logic */
960  for (char *p = buf; nread; p++, nread--)
961  {
962  if (*p != '\r')
963  putc(*p, fp);
964  }
965 
966  if (ferror(fp))
967  {
968  mutt_perror(_("[tempfile]"));
969  return -1;
970  }
971  }
972  if (nread == -1)
973  {
974  mutt_error(_("error reading data object: %s"), strerror(errno));
975  return -1;
976  }
977  return 0;
978 }
#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 991 of file crypt_gpgme.c.

992 {
993  ssize_t nread = 0;
994  char *rv = NULL;
995  struct Buffer *tempf = mutt_buffer_pool_get();
996 
997  mutt_buffer_mktemp(tempf);
998 
999  FILE *fp = mutt_file_fopen(mutt_b2s(tempf), "w+");
1000  if (!fp)
1001  {
1002  mutt_perror(_("Can't create temporary file"));
1003  goto cleanup;
1004  }
1005 
1006  int err = ((gpgme_data_seek(data, 0, SEEK_SET) == -1) ? gpgme_error_from_errno(errno) : 0);
1007  if (err == 0)
1008  {
1009  char buf[4096];
1010 
1011  while ((nread = gpgme_data_read(data, buf, sizeof(buf))) > 0)
1012  {
1013  if (fwrite(buf, nread, 1, fp) != 1)
1014  {
1015  mutt_perror(mutt_b2s(tempf));
1016  mutt_file_fclose(&fp);
1017  unlink(mutt_b2s(tempf));
1018  goto cleanup;
1019  }
1020  }
1021  }
1022  if (fp_ret)
1023  rewind(fp);
1024  else
1025  mutt_file_fclose(&fp);
1026  if (nread == -1)
1027  {
1028  mutt_error(_("error reading data object: %s"), gpgme_strerror(err));
1029  unlink(mutt_b2s(tempf));
1030  mutt_file_fclose(&fp);
1031  goto cleanup;
1032  }
1033  if (fp_ret)
1034  *fp_ret = fp;
1035  rv = mutt_buffer_strdup(tempf);
1036 
1037 cleanup:
1038  mutt_buffer_pool_release(&tempf);
1039  return rv;
1040 }
#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 1080 of file crypt_gpgme.c.

1081 {
1082  gpgme_key_t *rset = NULL;
1083 
1084  if (!p_rset)
1085  return;
1086 
1087  rset = *p_rset;
1088  if (!rset)
1089  return;
1090 
1091  while (*rset)
1092  {
1093  gpgme_key_t k = *rset;
1094  gpgme_key_unref(k);
1095  rset++;
1096  }
1097 
1098  FREE(p_rset);
1099 }
#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 1107 of file crypt_gpgme.c.

1108 {
1109  int err;
1110  const char *s = NULL;
1111  char buf[100];
1112  gpgme_key_t *rset = NULL;
1113  unsigned int rset_n = 0;
1114  gpgme_key_t key = NULL;
1115 
1116  gpgme_ctx_t context = create_gpgme_context(use_smime);
1117  s = keylist;
1118  do
1119  {
1120  while (*s == ' ')
1121  s++;
1122  int i;
1123  for (i = 0; *s && *s != ' ' && i < sizeof(buf) - 1;)
1124  buf[i++] = *s++;
1125  buf[i] = '\0';
1126  if (*buf != '\0')
1127  {
1128  if ((i > 1) && (buf[i - 1] == '!'))
1129  {
1130  /* The user selected to override the validity of that key. */
1131  buf[i - 1] = '\0';
1132 
1133  err = gpgme_get_key(context, buf, &key, 0);
1134  if (err == 0)
1135  key->uids->validity = GPGME_VALIDITY_FULL;
1136  buf[i - 1] = '!';
1137  }
1138  else
1139  err = gpgme_get_key(context, buf, &key, 0);
1140  mutt_mem_realloc(&rset, sizeof(*rset) * (rset_n + 1));
1141  if (err == 0)
1142  rset[rset_n++] = key;
1143  else
1144  {
1145  mutt_error(_("error adding recipient '%s': %s"), buf, gpgme_strerror(err));
1146  rset[rset_n] = NULL;
1147  recipient_set_free(&rset);
1148  gpgme_release(context);
1149  return NULL;
1150  }
1151  }
1152  } while (*s);
1153 
1154  /* NULL terminate. */
1155  mutt_mem_realloc(&rset, sizeof(*rset) * (rset_n + 1));
1156  rset[rset_n++] = NULL;
1157 
1158  gpgme_release(context);
1159 
1160  return rset;
1161 }
#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:1080
static gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:757
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
#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 1172 of file crypt_gpgme.c.

1173 {
1174  gpgme_error_t err;
1175  gpgme_key_t key = NULL, key2 = NULL;
1176  gpgme_ctx_t listctx = create_gpgme_context(for_smime);
1177  err = gpgme_op_keylist_start(listctx, address, 1);
1178  if (err == 0)
1179  err = gpgme_op_keylist_next(listctx, &key);
1180  if (err)
1181  {
1182  gpgme_release(listctx);
1183  mutt_error(_("secret key '%s' not found: %s"), address, gpgme_strerror(err));
1184  return false;
1185  }
1186 
1187  char *fpr = "fpr1";
1188  if (key->subkeys)
1189  fpr = key->subkeys->fpr ? key->subkeys->fpr : key->subkeys->keyid;
1190  while (gpgme_op_keylist_next(listctx, &key2) == 0)
1191  {
1192  char *fpr2 = "fpr2";
1193  if (key2->subkeys)
1194  fpr2 = key2->subkeys->fpr ? key2->subkeys->fpr : key2->subkeys->keyid;
1195  if (!mutt_str_equal(fpr, fpr2))
1196  {
1197  gpgme_key_unref(key);
1198  gpgme_key_unref(key2);
1199  gpgme_release(listctx);
1200  mutt_error(_("ambiguous specification of secret key '%s'\n"), address);
1201  return false;
1202  }
1203  else
1204  {
1205  gpgme_key_unref(key2);
1206  }
1207  }
1208  gpgme_op_keylist_end(listctx);
1209  gpgme_release(listctx);
1210 
1211  gpgme_signers_clear(ctx);
1212  err = gpgme_signers_add(ctx, key);
1213  gpgme_key_unref(key);
1214  if (err)
1215  {
1216  mutt_error(_("error setting secret key '%s': %s"), address, gpgme_strerror(err));
1217  return false;
1218  }
1219  return true;
1220 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
#define _(a)
Definition: message.h:28
static gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:757
#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 1230 of file crypt_gpgme.c.

1231 {
1232  char *signid = NULL;
1233 
1234  if (for_smime)
1236 #ifdef USE_AUTOCRYPT
1237  else if (OptAutocryptGpgme)
1238  signid = AutocryptSignAs;
1239 #endif
1240  else
1242 
1243  /* Try getting the signing key from config entries */
1244  if (signid && set_signer_from_address(ctx, signid, for_smime))
1245  {
1246  return 0;
1247  }
1248 
1249  /* Try getting the signing key from the From line */
1250  if (al)
1251  {
1252  struct Address *a;
1253  TAILQ_FOREACH(a, al, entries)
1254  {
1255  if (a->mailbox && set_signer_from_address(ctx, a->mailbox, for_smime))
1256  {
1257  return 0;
1258  }
1259  }
1260  }
1261 
1262  return (!signid && !al) ? 0 : -1;
1263 }
#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:1172
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:52
char * C_PgpDefaultKey
Config: Default key to use for PGP operations.
Definition: config.c:51
char * C_SmimeDefaultKey
Config: Default key for SMIME operations.
Definition: config.c:54
char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: config.c:55
+ 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 1270 of file crypt_gpgme.c.

1271 {
1272  gpgme_error_t err = gpgme_sig_notation_add(ctx, PKA_NOTATION_NAME, current_sender, 0);
1273  if (err)
1274  {
1275  mutt_error(_("error setting PKA signature notation: %s"), gpgme_strerror(err));
1276  }
1277 
1278  return err;
1279 }
#define PKA_NOTATION_NAME
Definition: crypt_gpgme.c:140
#define _(a)
Definition: message.h:28
static char * current_sender
Definition: crypt_gpgme.c:138
#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 1290 of file crypt_gpgme.c.

1292 {
1293  gpgme_error_t err;
1294  gpgme_ctx_t ctx = NULL;
1295  gpgme_data_t ciphertext = NULL;
1296  char *outfile = NULL;
1297 
1298 #if GPGME_VERSION_NUMBER >= 0x010b00 /* GPGME >= 1.11.0 */
1299  struct Buffer *recpstring = mutt_buffer_pool_get();
1300  create_recipient_string(keylist, recpstring, use_smime);
1301  if (mutt_buffer_is_empty(recpstring))
1302  {
1303  mutt_buffer_pool_release(&recpstring);
1304  return NULL;
1305  }
1306 #else
1307  gpgme_key_t *rset = create_recipient_set(keylist, use_smime);
1308  if (!rset)
1309  return NULL;
1310 #endif /* GPGME_VERSION_NUMBER >= 0x010b00 */
1311 
1312  ctx = create_gpgme_context(use_smime);
1313  if (!use_smime)
1314  gpgme_set_armor(ctx, 1);
1315 
1316  ciphertext = create_gpgme_data();
1317 
1318  if (combined_signed)
1319  {
1320  if (set_signer(ctx, from, use_smime))
1321  goto cleanup;
1322 
1323  if (C_CryptUsePka)
1324  {
1325  err = set_pka_sig_notation(ctx);
1326  if (err != 0)
1327  goto cleanup;
1328  }
1329 
1330 #if (GPGME_VERSION_NUMBER >= 0x010b00) /* GPGME >= 1.11.0 */
1331  err = gpgme_op_encrypt_sign_ext(ctx, NULL, mutt_b2s(recpstring),
1332  GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
1333 #else
1334  err = gpgme_op_encrypt_sign(ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
1335 #endif
1336  }
1337  else
1338  {
1339 #if (GPGME_VERSION_NUMBER >= 0x010b00) /* GPGME >= 1.11.0 */
1340  err = gpgme_op_encrypt_ext(ctx, NULL, mutt_b2s(recpstring),
1341  GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
1342 #else
1343  err = gpgme_op_encrypt(ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext);
1344 #endif
1345  }
1346 
1347  redraw_if_needed(ctx);
1348  if (err != 0)
1349  {
1350  mutt_error(_("error encrypting data: %s"), gpgme_strerror(err));
1351  goto cleanup;
1352  }
1353 
1354  outfile = data_object_to_tempfile(ciphertext, NULL);
1355 
1356 cleanup:
1357 #if (GPGME_VERSION_NUMBER >= 0x010b00) /* GPGME >= 1.11.0 */
1358  mutt_buffer_pool_release(&recpstring);
1359 #else
1360  recipient_set_free(&rset);
1361 #endif
1362  gpgme_release(ctx);
1363  gpgme_data_release(ciphertext);
1364  return outfile;
1365 }
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:991
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:1080
static gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:757
bool C_CryptUsePka
Config: Use GPGME to use PKA (lookup PGP keys using DNS)
Definition: config.c:38
#define mutt_b2s(buf)
Definition: buffer.h:41
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:1107
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:1230
static gpgme_data_t create_gpgme_data(void)
Create a new GPGME data object.
Definition: crypt_gpgme.c:795
#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:1270
static void redraw_if_needed(gpgme_ctx_t ctx)
accommodate for a redraw if needed
Definition: crypt_gpgme.c:202
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 1379 of file crypt_gpgme.c.

1380 {
1381  gpgme_sign_result_t result = NULL;
1382  const char *algorithm_name = NULL;
1383 
1384  if (buflen < 5)
1385  return -1;
1386 
1387  *buf = '\0';
1388  result = gpgme_op_sign_result(ctx);
1389  if (result && result->signatures)
1390  {
1391  algorithm_name = gpgme_hash_algo_name(result->signatures->hash_algo);
1392  if (algorithm_name)
1393  {
1394  if (use_smime)
1395  {
1396  /* convert GPGME raw hash name to RFC2633 format */
1397  snprintf(buf, buflen, "%s", algorithm_name);
1398  mutt_str_lower(buf);
1399  }
1400  else
1401  {
1402  /* convert GPGME raw hash name to RFC3156 format */
1403  snprintf(buf, buflen, "pgp-%s", algorithm_name);
1404  mutt_str_lower(buf + 4);
1405  }
1406  }
1407  }
1408 
1409  return (buf[0] != '\0') ? 0 : -1;
1410 }
char * mutt_str_lower(char *s)
Convert all characters in the string to lowercase.
Definition: string.c:509
+ 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 1417 of file crypt_gpgme.c.

1418 {
1419  char p[256];
1420  mutt_date_localtime_format(p, sizeof(p), nl_langinfo(D_T_FMT), t);
1421  state_puts(s, p);
1422 }
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:678
#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 1432 of file crypt_gpgme.c.

1433 {
1434  struct Body *t = NULL;
1435  char *sigfile = NULL;
1436  int err = 0;
1437  char buf[100];
1438  gpgme_ctx_t ctx = NULL;
1439  gpgme_data_t message = NULL, signature = NULL;
1440  gpgme_sign_result_t sigres = NULL;
1441 
1442  crypt_convert_to_7bit(a); /* Signed data _must_ be in 7-bit format. */
1443 
1444  message = body_to_data_object(a, true);
1445  if (!message)
1446  return NULL;
1447  signature = create_gpgme_data();
1448 
1449  ctx = create_gpgme_context(use_smime);
1450  if (!use_smime)
1451  gpgme_set_armor(ctx, 1);
1452 
1453  if (set_signer(ctx, from, use_smime))
1454  {
1455  gpgme_data_release(signature);
1456  gpgme_data_release(message);
1457  gpgme_release(ctx);
1458  return NULL;
1459  }
1460 
1461  if (C_CryptUsePka)
1462  {
1463  err = set_pka_sig_notation(ctx);
1464  if (err != 0)
1465  {
1466  gpgme_data_release(signature);
1467  gpgme_data_release(message);
1468  gpgme_release(ctx);
1469  return NULL;
1470  }
1471  }
1472 
1473  err = gpgme_op_sign(ctx, message, signature, GPGME_SIG_MODE_DETACH);
1474  redraw_if_needed(ctx);
1475  gpgme_data_release(message);
1476  if (err != 0)
1477  {
1478  gpgme_data_release(signature);
1479  gpgme_release(ctx);
1480  mutt_error(_("error signing data: %s"), gpgme_strerror(err));
1481  return NULL;
1482  }
1483  /* Check for zero signatures generated. This can occur when $pgp_sign_as is
1484  * unset and there is no default key specified in ~/.gnupg/gpg.conf */
1485  sigres = gpgme_op_sign_result(ctx);
1486  if (!sigres->signatures)
1487  {
1488  gpgme_data_release(signature);
1489  gpgme_release(ctx);
1490  mutt_error(_("$pgp_sign_as unset and no default key specified in "
1491  "~/.gnupg/gpg.conf"));
1492  return NULL;
1493  }
1494 
1495  sigfile = data_object_to_tempfile(signature, NULL);
1496  gpgme_data_release(signature);
1497  if (!sigfile)
1498  {
1499  gpgme_release(ctx);
1500  return NULL;
1501  }
1502 
1503  t = mutt_body_new();
1504  t->type = TYPE_MULTIPART;
1505  t->subtype = mutt_str_dup("signed");
1506  t->encoding = ENC_7BIT;
1507  t->use_disp = false;
1508  t->disposition = DISP_INLINE;
1509 
1511  mutt_param_set(&t->parameter, "protocol",
1512  use_smime ? "application/pkcs7-signature" : "application/pgp-signature");
1513  /* Get the micalg from GPGME. Old gpgme versions don't support this
1514  * for S/MIME so we assume sha-1 in this case. */
1515  if (get_micalg(ctx, use_smime, buf, sizeof(buf)) == 0)
1516  mutt_param_set(&t->parameter, "micalg", buf);
1517  else if (use_smime)
1518  mutt_param_set(&t->parameter, "micalg", "sha1");
1519  gpgme_release(ctx);
1520 
1521  t->parts = a;
1522  a = t;
1523 
1524  t->parts->next = mutt_body_new();
1525  t = t->parts->next;
1526  t->type = TYPE_APPLICATION;
1527  if (use_smime)
1528  {
1529  t->subtype = mutt_str_dup("pkcs7-signature");
1530  mutt_param_set(&t->parameter, "name", "smime.p7s");
1531  t->encoding = ENC_BASE64;
1532  t->use_disp = true;
1533  t->disposition = DISP_ATTACH;
1534  t->d_filename = mutt_str_dup("smime.p7s");
1535  }
1536  else
1537  {
1538  t->subtype = mutt_str_dup("pgp-signature");
1539  mutt_param_set(&t->parameter, "name", "signature.asc");
1540  t->use_disp = false;
1541  t->disposition = DISP_NONE;
1542  t->encoding = ENC_7BIT;
1543  }
1544  t->filename = sigfile;
1545  t->unlink = true; /* ok to remove this file after sending. */
1546 
1547  return a;
1548 }
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:991
7-bit text
Definition: mime.h:49
void crypt_convert_to_7bit(struct Body *a)
Convert an email to 7bit encoding.
Definition: crypt.c:799
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
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:85
Content is attached.
Definition: mime.h:63
static gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:757
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:1379
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:38
static gpgme_data_t body_to_data_object(struct Body *a, bool convert)
Create GPGME object from the mail body.
Definition: crypt_gpgme.c:851
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:1230
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:795
#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:1270
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:202
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 1553 of file crypt_gpgme.c.

1554 {
1555  return sign_message(a, from, false);
1556 }
static struct Body * sign_message(struct Body *a, const struct AddressList *from, bool use_smime)
Sign a message.
Definition: crypt_gpgme.c:1432
+ 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 1561 of file crypt_gpgme.c.

1562 {
1563  return sign_message(a, from, true);
1564 }
static struct Body * sign_message(struct Body *a, const struct AddressList *from, bool use_smime)
Sign a message.
Definition: crypt_gpgme.c:1432
+ 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 1569 of file crypt_gpgme.c.

1571 {
1572  if (sign)
1574  gpgme_data_t plaintext = body_to_data_object(a, false);
1575  if (!plaintext)
1576  return NULL;
1577 
1578  char *outfile = encrypt_gpgme_object(plaintext, keylist, false, sign, from);
1579  gpgme_data_release(plaintext);
1580  if (!outfile)
1581  return NULL;
1582 
1583  struct Body *t = mutt_body_new();
1584  t->type = TYPE_MULTIPART;
1585  t->subtype = mutt_str_dup("encrypted");
1586  t->encoding = ENC_7BIT;
1587  t->use_disp = false;
1588  t->disposition = DISP_INLINE;
1589 
1591  mutt_param_set(&t->parameter, "protocol", "application/pgp-encrypted");
1592 
1593  t->parts = mutt_body_new();
1594  t->parts->type = TYPE_APPLICATION;
1595  t->parts->subtype = mutt_str_dup("pgp-encrypted");
1596  t->parts->encoding = ENC_7BIT;
1597 
1598  t->parts->next = mutt_body_new();
1600  t->parts->next->subtype = mutt_str_dup("octet-stream");
1601  t->parts->next->encoding = ENC_7BIT;
1602  t->parts->next->filename = outfile;
1603  t->parts->next->use_disp = true;
1605  t->parts->next->unlink = true; /* delete after sending the message */
1606  t->parts->next->d_filename = mutt_str_dup("msg.asc"); /* non pgp/mime
1607  can save */
1608 
1609  return t;
1610 }
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:799
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
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:1290
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:85
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:851
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 1615 of file crypt_gpgme.c.

1616 {
1617  /* OpenSSL converts line endings to crlf when encrypting. Some clients
1618  * depend on this for signed+encrypted messages: they do not convert line
1619  * endings between decrypting and checking the signature. */
1620  gpgme_data_t plaintext = body_to_data_object(a, true);
1621  if (!plaintext)
1622  return NULL;
1623 
1624  char *outfile = encrypt_gpgme_object(plaintext, keylist, true, false, NULL);
1625  gpgme_data_release(plaintext);
1626  if (!outfile)
1627  return NULL;
1628 
1629  struct Body *t = mutt_body_new();
1630  t->type = TYPE_APPLICATION;
1631  t->subtype = mutt_str_dup("pkcs7-mime");
1632  mutt_param_set(&t->parameter, "name", "smime.p7m");
1633  mutt_param_set(&t->parameter, "smime-type", "enveloped-data");
1634  t->encoding = ENC_BASE64; /* The output of OpenSSL SHOULD be binary */
1635  t->use_disp = true;
1636  t->disposition = DISP_ATTACH;
1637  t->d_filename = mutt_str_dup("smime.p7m");
1638  t->filename = outfile;
1639  t->unlink = true; /* delete after sending the message */
1640  t->parts = 0;
1641  t->next = 0;
1642 
1643  return t;
1644 }
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:375
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:1290
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:851
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 1659 of file crypt_gpgme.c.

1661 {
1662  if (!key)
1663  return 1;
1664 
1665  bool severe = false;
1666 
1667  if ((sum & GPGME_SIGSUM_KEY_REVOKED))
1668  {
1669  state_puts(s, _("Warning: One of the keys has been revoked\n"));
1670  severe = true;
1671  }
1672 
1673  if ((sum & GPGME_SIGSUM_KEY_EXPIRED))
1674  {
1675  time_t at = key->subkeys->expires ? key->subkeys->expires : 0;
1676  if (at)
1677  {
1678  state_puts(
1679  s, _("Warning: The key used to create the signature expired at: "));
1680  print_time(at, s);
1681  state_puts(s, "\n");
1682  }
1683  else
1684  {
1685  state_puts(s, _("Warning: At least one certification key has expired\n"));
1686  }
1687  }
1688 
1689  if ((sum & GPGME_SIGSUM_SIG_EXPIRED))
1690  {
1691  gpgme_signature_t sig2 = NULL;
1692  unsigned int i;
1693 
1694  gpgme_verify_result_t result = gpgme_op_verify_result(ctx);
1695 
1696  for (sig2 = result->signatures, i = 0; sig2 && (i < idx); sig2 = sig2->next, i++)
1697  ; // do nothing
1698 
1699  state_puts(s, _("Warning: The signature expired at: "));
1700  print_time(sig2 ? sig2->exp_timestamp : 0, s);
1701  state_puts(s, "\n");
1702  }
1703 
1704  if ((sum & GPGME_SIGSUM_KEY_MISSING))
1705  {
1706  state_puts(s, _("Can't verify due to a missing key or certificate\n"));
1707  }
1708 
1709  if ((sum & GPGME_SIGSUM_CRL_MISSING))
1710  {
1711  state_puts(s, _("The CRL is not available\n"));
1712  severe = true;
1713  }
1714 
1715  if ((sum & GPGME_SIGSUM_CRL_TOO_OLD))
1716  {
1717  state_puts(s, _("Available CRL is too old\n"));
1718  severe = true;
1719  }
1720 
1721  if ((sum & GPGME_SIGSUM_BAD_POLICY))
1722  state_puts(s, _("A policy requirement was not met\n"));
1723 
1724  if ((sum & GPGME_SIGSUM_SYS_ERROR))
1725  {
1726  const char *t0 = NULL, *t1 = NULL;
1727  gpgme_verify_result_t result = NULL;
1728  gpgme_signature_t sig2 = NULL;
1729  unsigned int i;
1730 
1731  state_puts(s, _("A system error occurred"));
1732 
1733  /* Try to figure out some more detailed system error information. */
1734  result = gpgme_op_verify_result(ctx);
1735  for (sig2 = result->signatures, i = 0; sig2 && (i < idx); sig2 = sig2->next, i++)
1736  ; // do nothing
1737 
1738  if (sig2)
1739  {
1740  t0 = "";
1741  t1 = sig2->wrong_key_usage ? "Wrong_Key_Usage" : "";
1742  }
1743 
1744  if (t0 || t1)
1745  {
1746  state_puts(s, ": ");
1747  if (t0)
1748  state_puts(s, t0);
1749  if (t1 && !(t0 && (strcmp(t0, t1) == 0)))
1750  {
1751  if (t0)
1752  state_puts(s, ",");
1753  state_puts(s, t1);
1754  }
1755  }
1756  state_puts(s, "\n");
1757  }
1758 
1759  if (C_CryptUsePka)
1760  {
1761  if ((sig->pka_trust == 1) && sig->pka_address)
1762  {
1763  state_puts(s, _("WARNING: PKA entry does not match signer's address: "));
1764  state_puts(s, sig->pka_address);
1765  state_puts(s, "\n");
1766  }
1767  else if ((sig->pka_trust == 2) && sig->pka_address)
1768  {
1769  state_puts(s, _("PKA verified signer's address is: "));
1770  state_puts(s, sig->pka_address);
1771  state_puts(s, "\n");
1772  }
1773  }
1774 
1775  return severe;
1776 }
static void print_time(time_t t, struct State *s)
Print the date/time according to the locale.
Definition: crypt_gpgme.c:1417
#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:38
+ 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 1783 of file crypt_gpgme.c.

1784 {
1785  if (!key)
1786  return;
1787 
1788  const char *prefix = _("Fingerprint: ");
1789 
1790  const char *s = key->subkeys ? key->subkeys->fpr : NULL;
1791  if (!s)
1792  return;
1793  bool is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
1794 
1795  char *buf = mutt_mem_malloc(strlen(prefix) + strlen(s) * 4 + 2);
1796  strcpy(buf, prefix);
1797  char *p = buf + strlen(buf);
1798  if (is_pgp && (strlen(s) == 40))
1799  { /* PGP v4 style formatted. */
1800  for (int i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++)
1801  {
1802  *p++ = s[0];
1803  *p++ = s[1];
1804  *p++ = s[2];
1805  *p++ = s[3];
1806  *p++ = ' ';
1807  if (i == 4)
1808  *p++ = ' ';
1809  }
1810  }
1811  else
1812  {
1813  for (int i = 0; *s && s[1] && s[2]; s += 2, i++)
1814  {
1815  *p++ = s[0];
1816  *p++ = s[1];
1817  *p++ = is_pgp ? ' ' : ':';
1818  if (is_pgp && (i == 7))
1819  *p++ = ' ';
1820  }
1821  }
1822 
1823  /* just in case print remaining odd digits */
1824  for (; *s; s++)
1825  *p++ = *s;
1826  *p++ = '\n';
1827  *p = '\0';
1828  state_puts(state, buf);
1829  FREE(&buf);
1830 }
#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 1838 of file crypt_gpgme.c.

1839 {
1840  gpgme_signature_t sig = NULL;
1841  const char *txt = NULL;
1842 
1843  gpgme_verify_result_t result = gpgme_op_verify_result(ctx);
1844  if (result)
1845  for (sig = result->signatures; sig && (idx > 0); sig = sig->next, idx--)
1846  ; // do nothing
1847 
1848  switch (sig ? sig->validity : 0)
1849  {
1850  case GPGME_VALIDITY_UNKNOWN:
1851  txt = _("WARNING: We have NO indication whether "
1852  "the key belongs to the person named "
1853  "as shown above\n");
1854  break;
1855  case GPGME_VALIDITY_UNDEFINED:
1856  break;
1857  case GPGME_VALIDITY_NEVER:
1858  txt = _("WARNING: The key does NOT BELONG to "
1859  "the person named as shown above\n");
1860  break;
1861  case GPGME_VALIDITY_MARGINAL:
1862  txt = _("WARNING: It is NOT certain that the key "
1863  "belongs to the person named as shown above\n");
1864  break;
1865  case GPGME_VALIDITY_FULL:
1866  case GPGME_VALIDITY_ULTIMATE:
1867  txt = NULL;
1868  break;
1869  }
1870  if (txt)
1871  state_puts(s, txt);
1872 }
#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 1881 of file crypt_gpgme.c.

1883 {
1884  int msgwid;
1885 
1886  state_puts(s, msg);
1887  state_puts(s, " ");
1888  /* key is NULL when not present in the user's keyring */
1889  if (key)
1890  {
1891  bool aka = false;
1892  for (gpgme_user_id_t uids = key->uids; uids; uids = uids->next)
1893  {
1894  if (uids->revoked)
1895  continue;
1896  if (aka)
1897  {
1898  msgwid = mutt_strwidth(msg) - mutt_strwidth(_("aka: ")) + 1;
1899  if (msgwid < 0)
1900  msgwid = 0;
1901  for (int i = 0; i < msgwid; i++)
1902  state_puts(s, " ");
1903  state_puts(s, _("aka: "));
1904  }
1905  state_puts(s, uids->uid);
1906  state_puts(s, "\n");
1907 
1908  aka = true;
1909  }
1910  }
1911  else
1912  {
1913  if (sig->fpr)
1914  {
1915  state_puts(s, _("KeyID "));
1916  state_puts(s, sig->fpr);
1917  }
1918  else
1919  {
1920  /* L10N: You will see this message in place of "KeyID "
1921  if the S/MIME key has no ID. This is quite an error. */
1922  state_puts(s, _("no signature fingerprint available"));
1923  }
1924  state_puts(s, "\n");
1925  }
1926 
1927  /* timestamp is 0 when verification failed.
1928  * "Jan 1 1970" is not the created date. */
1929  if (sig->timestamp)
1930  {
1931  msgwid = mutt_strwidth(msg) - mutt_strwidth(_("created: ")) + 1;
1932  if (msgwid < 0)
1933  msgwid = 0;
1934  for (int i = 0; i < msgwid; i++)
1935  state_puts(s, " ");
1936  state_puts(s, _("created: "));
1937  print_time(sig->timestamp, s);
1938  state_puts(s, "\n");
1939  }
1940 }
static void print_time(time_t t, struct State *s)
Print the date/time according to the locale.
Definition: crypt_gpgme.c:1417
#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:1356
+ 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 1954 of file crypt_gpgme.c.

1955 {
1956  const char *fpr = NULL;
1957  gpgme_key_t key = NULL;
1958  bool anybad = false, anywarn = false;
1959  gpgme_signature_t sig = NULL;
1960  gpgme_error_t err = GPG_ERR_NO_ERROR;
1961 
1962  gpgme_verify_result_t result = gpgme_op_verify_result(ctx);
1963  if (result)
1964  {
1965  /* FIXME: this code should use a static variable and remember
1966  * the current position in the list of signatures, IMHO.
1967  * -moritz. */
1968  int i;
1969  for (i = 0, sig = result->signatures; sig && (i < idx); i++, sig = sig->next)
1970  ; // do nothing
1971 
1972  if (!sig)
1973  return -1; /* Signature not found. */
1974 
1975  if (signature_key)
1976  {
1977  gpgme_key_unref(signature_key);
1978  signature_key = NULL;
1979  }
1980 
1981  fpr = sig->fpr;
1982  const unsigned int sum = sig->summary;
1983 
1984  if (gpg_err_code(sig->status) != GPG_ERR_NO_ERROR)
1985  anybad = true;
1986 
1987  if (gpg_err_code(sig->status) != GPG_ERR_NO_PUBKEY)
1988  {
1989  err = gpgme_get_key(ctx, fpr, &key, 0); /* secret key? */
1990  if (err == 0)
1991  {
1992  if (!signature_key)
1993  signature_key = key;
1994  }
1995  else
1996  {
1997  key = NULL; /* Old GPGME versions did not set KEY to NULL on
1998  error. Do it here to avoid a double free. */
1999  }
2000  }
2001  else
2002  {
2003  /* pubkey not present */
2004  }
2005 
2006  if (!s || !s->fp_out || !(s->flags & MUTT_DISPLAY))
2007  ; /* No state information so no way to print anything. */
2008  else if (err != 0)
2009  {
2010  char buf[1024];
2011  snprintf(buf, sizeof(buf), _("Error getting key information for KeyID %s: %s\n"),
2012  fpr, gpgme_strerror(err));
2013  state_puts(s, buf);
2014  anybad = true;
2015  }
2016  else if ((sum & GPGME_SIGSUM_GREEN))
2017  {
2018  print_smime_keyinfo(_("Good signature from:"), sig, key, s);
2019  if (show_sig_summary(sum, ctx, key, idx, s, sig))
2020  anywarn = true;
2021  show_one_sig_validity(ctx, idx, s);
2022  }
2023  else if ((sum & GPGME_SIGSUM_RED))
2024  {
2025  print_smime_keyinfo(_("*BAD* signature from:"), sig, key, s);
2026  show_sig_summary(sum, ctx, key, idx, s, sig);
2027  }
2028  else if (!anybad && key && (key->protocol == GPGME_PROTOCOL_OpenPGP))
2029  { /* We can't decide (yellow) but this is a PGP key with a good
2030  signature, so we display what a PGP user expects: The name,
2031  fingerprint and the key validity (which is neither fully or
2032  ultimate). */
2033  print_smime_keyinfo(_("Good signature from:"), sig, key, s);
2034  show_one_sig_validity(ctx, idx, s);
2035  show_fingerprint(key, s);
2036  if (show_sig_summary(sum, ctx, key, idx, s, sig))
2037  anywarn = true;
2038  }
2039  else /* can't decide (yellow) */
2040  {
2041  print_smime_keyinfo(_("Problem signature from:"), sig, key, s);
2042  /* 0 indicates no expiration */
2043  if (sig->exp_timestamp)
2044  {
2045  /* L10N: This is trying to match the width of the
2046  "Problem signature from:" translation just above. */
2047  state_puts(s, _(" expires: "));
2048  print_time(sig->exp_timestamp, s);
2049  state_puts(s, "\n");
2050  }
2051  show_sig_summary(sum, ctx, key, idx, s, sig);
2052  anywarn = true;
2053  }
2054 
2055  if (key != signature_key)
2056  gpgme_key_unref(key);
2057  }
2058 
2059  return anybad ? 1 : anywarn ? 2 : 0;
2060 }
static void print_time(time_t t, struct State *s)
Print the date/time according to the locale.
Definition: crypt_gpgme.c:1417
#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:1838
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:1881
#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:1659
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:1783
static gpgme_key_t signature_key
Definition: crypt_gpgme.c:137
+ 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 2075 of file crypt_gpgme.c.

2076 {
2077  int badsig = -1;
2078  int anywarn = 0;
2079  gpgme_ctx_t ctx = NULL;
2080  gpgme_data_t message = NULL;
2081 
2082  gpgme_data_t signature = file_to_data_object(s->fp_in, sigbdy->offset, sigbdy->length);
2083  if (!signature)
2084  return -1;
2085 
2086  /* We need to tell GPGME about the encoding because the backend can't
2087  * auto-detect plain base-64 encoding which is used by S/MIME. */
2088  if (is_smime)
2089  gpgme_data_set_encoding(signature, GPGME_DATA_ENCODING_BASE64);
2090 
2091  int err = gpgme_data_new_from_file(&message, tempfile, 1);
2092  if (err != 0)
2093  {
2094  gpgme_data_release(signature);
2095  mutt_error(_("error allocating data object: %s"), gpgme_strerror(err));
2096  return -1;
2097  }
2098  ctx = create_gpgme_context(is_smime);
2099 
2100  /* Note: We don't need a current time output because GPGME avoids
2101  * such an attack by separating the meta information from the data. */
2102  state_attach_puts(s, _("[-- Begin signature information --]\n"));
2103 
2104  err = gpgme_op_verify(ctx, signature, message, NULL);
2105  gpgme_data_release(message);
2106  gpgme_data_release(signature);
2107 
2108  redraw_if_needed(ctx);
2109  if (err != 0)
2110  {
2111  char buf[200];
2112 
2113  snprintf(buf, sizeof(buf) - 1, _("Error: verification failed: %s\n"),
2114  gpgme_strerror(err));
2115  state_puts(s, buf);
2116  }
2117  else
2118  { /* Verification succeeded, see what the result is. */
2119  gpgme_verify_result_t verify_result = NULL;
2120 
2121  if (signature_key)
2122  {
2123  gpgme_key_unref(signature_key);
2124  signature_key = NULL;
2125  }
2126 
2127  verify_result = gpgme_op_verify_result(ctx);
2128  if (verify_result && verify_result->signatures)
2129  {
2130  bool anybad = false;
2131  int res;
2132  for (int idx = 0; (res = show_one_sig_status(ctx, idx, s)) != -1; idx++)
2133  {
2134  if (res == 1)
2135  anybad = true;
2136  else if (res == 2)
2137  anywarn = 2;
2138  }
2139  if (!anybad)
2140  badsig = 0;
2141  }
2142  }
2143 
2144  if (badsig == 0)
2145  {
2146  gpgme_verify_result_t result = NULL;
2147  gpgme_sig_notation_t notation = NULL;
2148  gpgme_signature_t sig = NULL;
2149 
2150  result = gpgme_op_verify_result(ctx);
2151  if (result)
2152  {
2153  for (sig = result->signatures; sig; sig = sig->next)
2154  {
2155  int non_pka_notations = 0;
2156  for (notation = sig->notations; notation; notation = notation->next)
2157  if (!is_pka_notation(notation))
2158  non_pka_notations++;
2159 
2160  if (non_pka_notations)
2161  {
2162  char buf[128];
2163  snprintf(buf, sizeof(buf),
2164  _("*** Begin Notation (signature by: %s) ***\n"), sig->fpr);
2165  state_puts(s, buf);
2166  for (notation = sig->notations; notation; notation = notation->next)
2167  {
2168  if (is_pka_notation(notation))
2169  continue;
2170 
2171  if (notation->name)
2172  {
2173  state_puts(s, notation->name);
2174  state_puts(s, "=");
2175  }
2176  if (notation->value)
2177  {
2178  state_puts(s, notation->value);
2179  if (!(*notation->value && (notation->value[strlen(notation->value) - 1] == '\n')))
2180  state_puts(s, "\n");
2181  }
2182  }
2183  state_puts(s, _("*** End Notation ***\n"));
2184  }
2185  }
2186  }
2187  }
2188 
2189  gpgme_release(ctx);
2190 
2191  state_attach_puts(s, _("[-- End signature information --]\n\n"));
2192  mutt_debug(LL_DEBUG1, "returning %d\n", badsig);
2193 
2194  return badsig ? 1 : anywarn ? 2 : 0;
2195 }
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:923
#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
static gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:757
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
static bool is_pka_notation(gpgme_sig_notation_t notation)
Is this the standard pka email address.
Definition: crypt_gpgme.c:193
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:202
static gpgme_key_t signature_key
Definition: crypt_gpgme.c:137
static int show_one_sig_status(gpgme_ctx_t ctx, int idx, struct State *s)
Show information about one signature.
Definition: crypt_gpgme.c:1954
+ 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 2200 of file crypt_gpgme.c.

2201 {
2202  return verify_one(sigbdy, s, tempfile, false);
2203 }
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:2075
+ 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 2208 of file crypt_gpgme.c.

2209 {
2210  return verify_one(sigbdy, s, tempfile, true);
2211 }
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:2075
+ 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 2226 of file crypt_gpgme.c.

2228 {
2229  if (!a || !s || !fp_out)
2230  return NULL;
2231 
2232  struct stat info;
2233  struct Body *tattach = NULL;
2234  int err = 0;
2235  gpgme_data_t ciphertext = NULL, plaintext = NULL;
2236  bool maybe_signed = false;
2237  bool anywarn = false;
2238  int sig_stat = 0;
2239 
2240  if (r_is_signed)
2241  *r_is_signed = 0;
2242 
2243  gpgme_ctx_t ctx = NULL;
2244 restart:
2245  ctx = create_gpgme_context(is_smime);
2246 
2247  if (a->length < 0)
2248  return NULL;
2249  /* Make a data object from the body, create context etc. */
2250  ciphertext = file_to_data_object(s->fp_in, a->offset, a->length);
2251  if (!ciphertext)
2252  goto cleanup;
2253  plaintext = create_gpgme_data();
2254 
2255  /* Do the decryption or the verification in case of the S/MIME hack. */
2256  if ((!is_smime) || maybe_signed)
2257  {
2258  if (!is_smime)
2259  err = gpgme_op_decrypt_verify(ctx, ciphertext, plaintext);
2260  else if (maybe_signed)
2261  err = gpgme_op_verify(ctx, ciphertext, NULL, plaintext);
2262 
2263  if (err == GPG_ERR_NO_ERROR)
2264  {
2265  /* Check whether signatures have been verified. */
2266  gpgme_verify_result_t verify_result = gpgme_op_verify_result(ctx);
2267  if (verify_result->signatures)
2268  sig_stat = 1;
2269  }
2270  }
2271  else
2272  err = gpgme_op_decrypt(ctx, ciphertext, plaintext);
2273  gpgme_data_release(ciphertext);
2274  ciphertext = NULL;
2275  if (err != 0)
2276  {
2277 #ifdef USE_AUTOCRYPT
2278  /* Abort right away and silently.
2279  * Autocrypt will retry on the normal keyring. */
2280  if (OptAutocryptGpgme)
2281  goto cleanup;
2282 #endif
2283  if (is_smime && !maybe_signed && (gpg_err_code(err) == GPG_ERR_NO_DATA))
2284  {
2285  /* Check whether this might be a signed message despite what the mime
2286  * header told us. Retry then. gpgsm returns the error information
2287  * "unsupported Algorithm '?'" but GPGME will not store this unknown
2288  * algorithm, thus we test that it has not been set. */
2289  gpgme_decrypt_result_t result;
2290 
2291  result = gpgme_op_decrypt_result(ctx);
2292  if (!result->unsupported_algorithm)
2293  {
2294  maybe_signed = true;
2295  gpgme_data_release(plaintext);
2296  plaintext = NULL;
2297  /* gpgsm ends the session after an error; restart it */
2298  gpgme_release(ctx);
2299  ctx = NULL;
2300  goto restart;
2301  }
2302  }
2303  redraw_if_needed(ctx);
2304  if ((s->flags & MUTT_DISPLAY))
2305  {
2306  char buf[200];
2307 
2308  snprintf(buf, sizeof(buf) - 1,
2309  _("[-- Error: decryption failed: %s --]\n\n"), gpgme_strerror(err));
2310  state_attach_puts(s, buf);
2311  }
2312  goto cleanup;
2313  }
2314  redraw_if_needed(ctx);
2315 
2316  /* Read the output from GPGME, and make sure to change CRLF to LF,
2317  * otherwise read_mime_header has a hard time parsing the message. */
2318  if (data_object_to_stream(plaintext, fp_out))
2319  {
2320  goto cleanup;
2321  }
2322  gpgme_data_release(plaintext);
2323  plaintext = NULL;
2324 
2325  if (sig_stat)
2326  {
2327  int res, idx;
2328  int anybad = 0;
2329 
2330  if (r_is_signed)
2331  *r_is_signed = -1; /* A signature exists. */
2332 
2333  if ((s->flags & MUTT_DISPLAY))
2334  {
2335  state_attach_puts(s, _("[-- Begin signature information --]\n"));
2336  }
2337  for (idx = 0; (res = show_one_sig_status(ctx, idx, s)) != -1; idx++)
2338  {
2339  if (res == 1)
2340  anybad = 1;
2341  else if (res == 2)
2342  anywarn = true;
2343  }
2344  if (!anybad && idx && r_is_signed && *r_is_signed)
2345  *r_is_signed = anywarn ? 2 : 1; /* Good signature. */
2346 
2347  if ((s->flags & MUTT_DISPLAY))
2348  {
2349  state_attach_puts(s, _("[-- End signature information --]\n\n"));
2350  }
2351  }
2352  gpgme_release(ctx);
2353  ctx = NULL;
2354 
2355  fflush(fp_out);
2356  rewind(fp_out);
2357  tattach = mutt_read_mime_header(fp_out, 0);
2358  if (tattach)
2359  {
2360  /* Need to set the length of this body part. */
2361  fstat(fileno(fp_out), &info);
2362  tattach->length = info.st_size - tattach->offset;
2363 
2364  tattach->warnsig = anywarn;
2365 
2366  /* See if we need to recurse on this MIME part. */
2367  mutt_parse_part(fp_out, tattach);
2368  }
2369 
2370 cleanup:
2371  gpgme_data_release(ciphertext);
2372  gpgme_data_release(plaintext);
2373  gpgme_release(ctx);
2374 
2375  return tattach;
2376 }
#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:923
static int data_object_to_stream(gpgme_data_t data, FILE *fp)
Write a GPGME data object to a file.
Definition: crypt_gpgme.c:944
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
static gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:757
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
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:1375
static gpgme_data_t create_gpgme_data(void)
Create a new GPGME data object.
Definition: crypt_gpgme.c:795
static void redraw_if_needed(gpgme_ctx_t ctx)
accommodate for a redraw if needed
Definition: crypt_gpgme.c:202
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1262
static int show_one_sig_status(gpgme_ctx_t ctx, int idx, struct State *s)
Show information about one signature.
Definition: crypt_gpgme.c:1954
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 2381 of file crypt_gpgme.c.

2382 {
2383  struct State s = { 0 };
2384  struct Body *first_part = b;
2385  int is_signed = 0;
2386  bool need_decode = false;
2387  int saved_type = 0;
2388  LOFF_T saved_offset = 0;
2389  size_t saved_length = 0;
2390  FILE *fp_decoded = NULL;
2391  int rc = 0;
2392 
2393  first_part->goodsig = false;
2394  first_part->warnsig = false;
2395 
2397  {
2398  b = b->parts->next;
2399  /* Some clients improperly encode the octetstream part. */
2400  if (b->encoding != ENC_7BIT)
2401  need_decode = true;
2402  }
2404  {
2405  b = b->parts->next->next;
2406  need_decode = true;
2407  }
2408  else
2409  return -1;
2410 
2411  s.fp_in = fp_in;
2412 
2413  if (need_decode)
2414  {
2415  saved_type = b->type;
2416  saved_offset = b->offset;
2417  saved_length = b->length;
2418 
2419  fp_decoded = mutt_file_mkstemp();
2420  if (!fp_decoded)
2421  {
2422  mutt_perror(_("Can't create temporary file"));
2423  return -1;
2424  }
2425 
2426  fseeko(s.fp_in, b->offset, SEEK_SET);
2427  s.fp_out = fp_decoded;
2428 
2429  mutt_decode_attachment(b, &s);
2430 
2431  fflush(fp_decoded);
2432  b->length = ftello(fp_decoded);
2433  b->offset = 0;
2434  rewind(fp_decoded);
2435  s.fp_in = fp_decoded;
2436  s.fp_out = 0;
2437  }
2438 
2439  *fp_out = mutt_file_mkstemp();
2440  if (!*fp_out)
2441  {
2442  mutt_perror(_("Can't create temporary file"));
2443  rc = -1;
2444  goto bail;
2445  }
2446 
2447  *cur = decrypt_part(b, &s, *fp_out, false, &is_signed);
2448  if (*cur)
2449  {
2450  rewind(*fp_out);
2451  if (is_signed > 0)
2452  first_part->goodsig = true;
2453  }
2454  else
2455  {
2456  rc = -1;
2457  mutt_file_fclose(fp_out);
2458  }
2459 
2460 bail:
2461  if (need_decode)
2462  {
2463  b->type = saved_type;
2464  b->length = saved_length;
2465  b->offset = saved_offset;
2466  mutt_file_fclose(&fp_decoded);
2467  }
2468 
2469  return rc;
2470 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1835
#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:469
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:2226
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:506
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 2475 of file crypt_gpgme.c.

2476 {
2477  struct State s = { 0 };
2478  int is_signed;
2479  LOFF_T saved_b_offset;
2480  size_t saved_b_length;
2481  int saved_b_type;
2482 
2484  return -1;
2485 
2486  if (b->parts)
2487  return -1;
2488 
2489  /* Decode the body - we need to pass binary CMS to the
2490  * backend. The backend allows for Base64 encoded data but it does
2491  * not allow for QP which I have seen in some messages. So better
2492  * do it here. */
2493  saved_b_type = b->type;
2494  saved_b_offset = b->offset;
2495  saved_b_length = b->length;
2496  s.fp_in = fp_in;
2497  fseeko(s.fp_in, b->offset, SEEK_SET);
2498  FILE *fp_tmp = mutt_file_mkstemp();
2499  if (!fp_tmp)
2500  {
2501  mutt_perror(_("Can't create temporary file"));
2502  return -1;
2503  }
2504 
2505  s.fp_out = fp_tmp;
2506  mutt_decode_attachment(b, &s);
2507  fflush(fp_tmp);
2508  b->length = ftello(s.fp_out);
2509  b->offset = 0;
2510  rewind(fp_tmp);
2511 
2512  memset(&s, 0, sizeof(s));
2513  s.fp_in = fp_tmp;
2514  s.fp_out = 0;
2516  if (!*fp_out)
2517  {
2518  mutt_perror(_("Can't create temporary file"));
2519  return -1;
2520  }
2521 
2522  *cur = decrypt_part(b, &s, *fp_out, true, &is_signed);
2523  if (*cur)
2524  (*cur)->goodsig = is_signed > 0;
2525  b->type = saved_b_type;
2526  b->length = saved_b_length;
2527  b->offset = saved_b_offset;
2528  mutt_file_fclose(&fp_tmp);
2529  rewind(*fp_out);
2530  if (*cur && !is_signed && !(*cur)->parts && mutt_is_application_smime(*cur))
2531  {
2532  /* Assume that this is a opaque signed s/mime message. This is an ugly way
2533  * of doing it but we have anyway a problem with arbitrary encoded S/MIME
2534  * messages: Only the outer part may be encrypted. The entire mime parsing
2535  * should be revamped, probably by keeping the temporary files so that we
2536  * don't need to decrypt them all the time. Inner parts of an encrypted
2537  * part can then point into this file and there won't ever be a need to
2538  * decrypt again. This needs a partial rewrite of the MIME engine. */
2539  struct Body *bb = *cur;
2540 
2541  saved_b_type = bb->type;
2542  saved_b_offset = bb->offset;
2543  saved_b_length = bb->length;
2544  memset(&s, 0, sizeof(s));
2545  s.fp_in = *fp_out;
2546  fseeko(s.fp_in, bb->offset, SEEK_SET);
2547  FILE *fp_tmp2 = mutt_file_mkstemp();
2548  if (!fp_tmp2)
2549  {
2550  mutt_perror(_("Can't create temporary file"));
2551  return -1;
2552  }
2553 
2554  s.fp_out = fp_tmp2;
2555  mutt_decode_attachment(bb, &s);
2556  fflush(fp_tmp2);
2557  bb->length = ftello(s.fp_out);
2558  bb->offset = 0;
2559  rewind(fp_tmp2);
2560  mutt_file_fclose(fp_out);
2561 
2562  memset(&s, 0, sizeof(s));
2563  s.fp_in = fp_tmp2;
2564  s.fp_out = 0;
2565  *fp_out = mutt_file_mkstemp();
2566  if (!*fp_out)
2567  {
2568  mutt_perror(_("Can't create temporary file"));
2569  return -1;
2570  }
2571 
2572  struct Body *b_tmp = decrypt_part(bb, &s, *fp_out, true, &is_signed);
2573  if (b_tmp)
2574  b_tmp->goodsig = is_signed > 0;
2575  bb->type = saved_b_type;
2576  bb->length = saved_b_length;
2577  bb->offset = saved_b_offset;
2578  mutt_file_fclose(&fp_tmp2);
2579  rewind(*fp_out);
2580  mutt_body_free(cur);
2581  *cur = b_tmp;
2582  }
2583  return *cur ? 0 : -1;
2584 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1835
#define mutt_perror(...)
Definition: logging.h:85
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:79
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:2226
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:608
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 2593 of file crypt_gpgme.c.

2594 {
2595  /* Before GPGME 1.9.0 and gpg 2.1.14 there was no side-effect free
2596  * way to view key data in GPGME, so we import the key into a
2597  * temporary keyring if we detect an older system. */
2598  bool legacy_api;
2599  struct Buffer *tmpdir = NULL;
2600  gpgme_ctx_t tmpctx = NULL;
2601  gpgme_error_t err;
2602  gpgme_engine_info_t engineinfo = NULL;
2603  gpgme_key_t key = NULL;
2604  gpgme_user_id_t uid = NULL;
2605  gpgme_subkey_t subkey = NULL;
2606  const char *shortid = NULL;
2607  size_t len;
2608  char date[256];
2609  bool more;
2610  int rc = -1;
2611  time_t tt;
2612 
2613 #if GPGME_VERSION_NUMBER >= 0x010900 /* GPGME >= 1.9.0 */
2614  legacy_api = !have_gpg_version("2.1.14");
2615 #else /* GPGME < 1.9.0 */
2616  legacy_api = true;
2617 #endif
2618 
2619  tmpctx = create_gpgme_context(false);
2620 
2621  if (legacy_api)
2622  {
2623  tmpdir = mutt_buffer_pool_get();
2624  mutt_buffer_printf(tmpdir, "%s/neomutt-gpgme-XXXXXX", NONULL(C_Tmpdir));
2625  if (!mkdtemp(tmpdir->data))
2626  {
2627  mutt_debug(LL_DEBUG1, "Error creating temporary GPGME home\n");
2628  goto err_ctx;
2629  }
2630 
2631  engineinfo = gpgme_ctx_get_engine_info(tmpctx);
2632  while (engineinfo && (engineinfo->protocol != GPGME_PROTOCOL_OpenPGP))
2633  engineinfo = engineinfo->next;
2634  if (!engineinfo)
2635  {
2636  mutt_debug(LL_DEBUG1, "Error finding GPGME PGP engine\n");
2637  goto err_tmpdir;
2638  }
2639 
2640  err = gpgme_ctx_set_engine_info(tmpctx, GPGME_PROTOCOL_OpenPGP,
2641  engineinfo->file_name, mutt_b2s(tmpdir));
2642  if (err != GPG_ERR_NO_ERROR)
2643  {
2644  mutt_debug(LL_DEBUG1, "Error setting GPGME context home\n");
2645  goto err_tmpdir;
2646  }
2647  }
2648 
2649  *fp = mutt_file_mkstemp();
2650  if (!*fp)
2651  {
2652  mutt_perror(_("Can't create temporary file"));
2653  goto err_tmpdir;
2654  }
2655 
2656 #if GPGME_VERSION_NUMBER >= 0x010900 /* 1.9.0 */
2657  if (!legacy_api)
2658  err = gpgme_op_keylist_from_data_start(tmpctx, keydata, 0);
2659  else
2660 #endif /* GPGME >= 1.9.0 */
2661  {
2662  err = gpgme_op_keylist_start(tmpctx, NULL, 0);
2663  }
2664  while (err == 0)
2665  {
2666  err = gpgme_op_keylist_next(tmpctx, &key);
2667  if (err != 0)
2668  break;
2669  uid = key->uids;
2670  subkey = key->subkeys;
2671  more = false;
2672  while (subkey)
2673  {
2674  shortid = subkey->keyid;
2675  len = mutt_str_len(subkey->keyid);
2676  if (len > 8)
2677  shortid += len - 8;
2678  tt = subkey->timestamp;
2679  mutt_date_localtime_format(date, sizeof(date), "%Y-%m-%d", tt);
2680 
2681  if (more)
2682  {
2683  fprintf(*fp, "sub %5.5s %u/%8s %s\n", gpgme_pubkey_algo_name(subkey->pubkey_algo),
2684  subkey->length, shortid, date);
2685  }
2686  else
2687  {
2688  fprintf(*fp, "pub %5.5s %u/%8s %s %s\n", gpgme_pubkey_algo_name(subkey->pubkey_algo),
2689  subkey->length, shortid, date, uid->uid);
2690  }
2691  subkey = subkey->next;
2692  more = true;
2693  }
2694  gpgme_key_unref(key);
2695  }
2696  if (gpg_err_code(err) != GPG_ERR_EOF)
2697  {
2698  mutt_debug(LL_DEBUG1, "Error listing keys\n");
2699  goto err_fp;
2700  }
2701 
2702  rc = 0;
2703 
2704 err_fp:
2705  if (rc)
2706  mutt_file_fclose(fp);
2707 err_tmpdir:
2708  if (legacy_api)
2709  mutt_file_rmtree(mutt_b2s(tmpdir));
2710 err_ctx:
2711  gpgme_release(tmpctx);
2712 
2713  mutt_buffer_pool_release(&tmpdir);
2714 
2715  return rc;
2716 }
#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:678
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
static gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:757
#define mutt_b2s(buf)
Definition: buffer.h:41
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:636
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 2729 of file crypt_gpgme.c.

2730 {
2731  if (mutt_strn_equal(a, b, n))
2732  {
2733  /* at this point we know that 'b' is at least 'n' chars long */
2734  if ((b[n] == '\n') || ((b[n] == '\r') && (b[n + 1] == '\n')))
2735  return true;
2736  }
2737  return false;
2738 }
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:598
int n
Definition: acutest.h:492
+ 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 2747 of file crypt_gpgme.c.

2748 {
2749  char buf[8192];
2750  int rv = 0;
2751 
2752  bool sgn = false;
2753  bool enc = false;
2754 
2755  if (b->type != TYPE_TEXT)
2756  return 0;
2757 
2758  struct Buffer *tempfile = mutt_buffer_pool_get();
2759  mutt_buffer_mktemp(tempfile);
2760  if (mutt_decode_save_attachment(fp, b, mutt_b2s(tempfile), 0, MUTT_SAVE_NO_FLAGS) != 0)
2761  {
2762  unlink(mutt_b2s(tempfile));
2763  goto cleanup;
2764  }
2765 
2766  FILE *fp_tmp = fopen(mutt_b2s(tempfile), "r");
2767  if (!fp_tmp)
2768  {
2769  unlink(mutt_b2s(tempfile));
2770  goto cleanup;
2771  }
2772 
2773  while (fgets(buf, sizeof(buf), fp_tmp))
2774  {
2775  size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
2776  if (plen != 0)
2777  {
2778  if (MESSAGE(buf + plen))
2779  {
2780  enc = true;
2781  break;
2782  }
2783  else if (SIGNED_MESSAGE(buf + plen))
2784  {
2785  sgn = true;
2786  break;
2787  }
2788  }
2789  }
2790  mutt_file_fclose(&fp_tmp);
2791  unlink(mutt_b2s(tempfile));
2792 
2793  if (!enc && !sgn)
2794  goto cleanup;
2795 
2796  /* fix the content type */
2797 
2798  mutt_param_set(&b->parameter, "format", "fixed");
2799  mutt_param_set(&b->parameter, "x-action", enc ? "pgp-encrypted" : "pgp-signed");
2800 
2801  rv = 1;
2802 
2803 cleanup:
2804  mutt_buffer_pool_release(&tempfile);
2805  return rv;
2806 }
#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:144
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:143
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:165
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:961
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 2811 of file crypt_gpgme.c.

2812 {
2813  int rc = 0;
2814  for (; b; b = b->next)
2815  {
2816  if (!just_one && is_multipart(b))
2817  rc = (pgp_gpgme_check_traditional(fp, b->parts, false) || rc);
2818  else if (b->type == TYPE_TEXT)
2819  {
2821  if (r)
2822  rc = (rc || r);
2823  else
2824  rc = (pgp_check_traditional_one_body(fp, b) || rc);
2825  }
2826 
2827  if (just_one)
2828  break;
2829  }
2830  return rc;
2831 }
int pgp_gpgme_check_traditional(FILE *fp, struct Body *b, bool just_one)
Implements CryptModuleSpecs::pgp_check_traditional()
Definition: crypt_gpgme.c:2811
#define is_multipart(body)
Definition: mime.h:77
struct Body * next
next attachment in the list
Definition: body.h:53
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:78
static int pgp_check_traditional_one_body(FILE *fp, struct Body *b)
Check one inline PGP body part.
Definition: crypt_gpgme.c:2747
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:550
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 2836 of file crypt_gpgme.c.

2837 {
2838  gpgme_ctx_t ctx = create_gpgme_context(false);
2839  gpgme_data_t keydata = NULL;
2840  gpgme_import_result_t impres;
2841  gpgme_import_status_t st;
2842  bool any;
2843 
2844  FILE *fp_in = mutt_file_fopen(fname, "r");
2845  if (!fp_in)
2846  {
2847  mutt_perror(fname);
2848  goto leave;
2849  }
2850  /* Note that the stream, "fp_in", needs to be kept open while the keydata
2851  * is used. */
2852  gpgme_error_t err = gpgme_data_new_from_stream(&keydata, fp_in);
2853  if (err != GPG_ERR_NO_ERROR)
2854  {
2855  mutt_error(_("error allocating data object: %s"), gpgme_strerror(err));
2856  goto leave;
2857  }
2858 
2859  err = gpgme_op_import(ctx, keydata);
2860  if (err != 0)
2861  {
2862  mutt_error(_("Error importing key: %s"), gpgme_strerror(err));
2863  goto leave;
2864  }
2865 
2866  /* Print infos about the imported keys to stdout. */
2867  impres = gpgme_op_import_result(ctx);
2868  if (!impres)
2869  {
2870  fputs("oops: no import result returned\n", stdout);
2871  goto leave;
2872  }
2873 
2874  for (st = impres->imports; st; st = st->next)
2875  {
2876  if (st->result)
2877  continue;
2878  printf("key %s imported (", NONULL(st->fpr));
2879  /* Note that we use the singular even if it is possible that
2880  * several uids etc are new. This simply looks better. */
2881  any = false;
2882  if (st->status & GPGME_IMPORT_SECRET)
2883  {
2884  printf("secret parts");
2885  any = true;
2886  }
2887  if ((st->status & GPGME_IMPORT_NEW))
2888  {
2889  printf("%snew key", any ? ", " : "");
2890  any = true;
2891  }
2892  if ((st->status & GPGME_IMPORT_UID))
2893  {
2894  printf("%snew uid", any ? ", " : "");
2895  any = true;
2896  }
2897  if ((st->status & GPGME_IMPORT_SIG))
2898  {
2899  printf("%snew sig", any ? ", " : "");
2900  any = true;
2901  }
2902  if ((st->status & GPGME_IMPORT_SUBKEY))
2903  {
2904  printf("%snew subkey", any ? ", " : "");
2905  any = true;
2906  }
2907  printf("%s)\n", any ? "" : "not changed");
2908  /* Fixme: Should we lookup each imported key and print more infos? */
2909  }
2910  /* Now print keys which failed the import. Unfortunately in most
2911  * cases gpg will bail out early and not tell GPGME about. */
2912  /* FIXME: We could instead use the new GPGME_AUDITLOG_DIAG to show
2913  * the actual gpg diagnostics. But I fear that would clutter the
2914  * output too much. Maybe a dedicated prompt or option to do this
2915  * would be helpful. */
2916  for (st = impres->imports; st; st = st->next)
2917  {
2918  if (st->result == 0)
2919  continue;
2920  printf("key %s import failed: %s\n", NONULL(st->fpr), gpgme_strerror(st->result));
2921  }
2922  fflush(stdout);
2923 
2924 leave:
2925  gpgme_release(ctx);
2926  gpgme_data_release(keydata);
2927  mutt_file_fclose(&fp_in);
2928 }
#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
static gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:757
#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 2945 of file crypt_gpgme.c.

2946 {
2947  char buf[8192];
2948  bool complete, armor_header;
2949  FILE *fp = NULL;
2950 
2951  char *fname = data_object_to_tempfile(data, &fp);
2952  if (!fname)
2953  {
2954  mutt_file_fclose(&fp);
2955  return;
2956  }
2957  unlink(fname);
2958  FREE(&fname);
2959 
2960  /* fromcode comes from the MIME Content-Type charset label. It might
2961  * be a wrong label, so we want the ability to do corrections via
2962  * charset-hooks. Therefore we set flags to MUTT_ICONV_HOOK_FROM. */
2963  struct FgetConv *fc = mutt_ch_fgetconv_open(fp, charset, C_Charset, MUTT_ICONV_HOOK_FROM);
2964 
2965  for (complete = true, armor_header = true;
2966  mutt_ch_fgetconvs(buf, sizeof(buf), fc); complete = (strchr(buf, '\n')))
2967  {
2968  if (!complete)
2969  {
2970  if (!armor_header)
2971  state_puts(s, buf);
2972  continue;
2973  }
2974 
2975  if (BEGIN_PGP_SIGNATURE(buf))
2976  break;
2977 
2978  if (armor_header)
2979  {
2980  if (buf[0] == '\n')
2981  armor_header = false;
2982  continue;
2983  }
2984 
2985  if (s->prefix)
2986  state_puts(s, s->prefix);
2987 
2988  if ((buf[0] == '-') && (buf[1] == ' '))
2989  state_puts(s, buf + 2);
2990  else
2991  state_puts(s, buf);
2992  }
2993 
2995  mutt_file_fclose(&fp);
2996 }
#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:991
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
char * data
Pointer to data.
Definition: buffer.h:35
#define BEGIN_PGP_SIGNATURE(_y)
Definition: crypt_gpgme.c:146
void mutt_ch_fgetconv_close(struct FgetConv **fc)
Close an fgetconv handle.
Definition: charset.c:888
#define FREE(x)
Definition: memory.h:40
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
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
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
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 3001 of file crypt_gpgme.c.

3002 {
3003  int needpass = -1;
3004  bool pgp_keyblock = false;
3005  bool clearsign = false;
3006  long bytes;
3007  LOFF_T last_pos;
3008  char buf[8192];
3009  FILE *fp_out = NULL;
3010 
3011  gpgme_error_t err = 0;
3012  gpgme_data_t armored_data = NULL;
3013 
3014  bool maybe_goodsig = true;
3015  bool have_any_sigs = false;
3016 
3017  char body_charset[256]; /* Only used for clearsigned messages. */
3018 
3019  mutt_debug(LL_DEBUG2, "Entering handler\n");
3020 
3021  /* For clearsigned messages we won't be able to get a character set
3022  * but we know that this may only be text thus we assume Latin-1 here. */
3023  if (!mutt_body_get_charset(m, body_charset, sizeof(body_charset)))
3024  mutt_str_copy(body_charset, "iso-8859-1", sizeof(body_charset));
3025 
3026  fseeko(s->fp_in, m->offset, SEEK_SET);
3027  last_pos = m->offset;
3028 
3029  for (bytes = m->length; bytes > 0;)
3030  {
3031  if (!fgets(buf, sizeof(buf), s->fp_in))
3032  break;
3033 
3034  LOFF_T offset = ftello(s->fp_in);
3035  bytes -= (offset - last_pos); /* don't rely on mutt_str_len(buf) */
3036  last_pos = offset;
3037 
3038  size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
3039  if (plen != 0)
3040  {
3041  clearsign = false;
3042 
3043  if (MESSAGE(buf + plen))
3044  needpass = 1;
3045  else if (SIGNED_MESSAGE(buf + plen))
3046  {
3047  clearsign = true;
3048  needpass = 0;
3049  }
3050  else if (PUBLIC_KEY_BLOCK(buf + plen))
3051  {
3052  needpass = 0;
3053  pgp_keyblock = true;
3054  }
3055  else
3056  {
3057  /* XXX we may wish to recode here */
3058  if (s->prefix)
3059  state_puts(s, s->prefix);
3060  state_puts(s, buf);
3061  continue;
3062  }
3063 
3064  have_any_sigs = (have_any_sigs || (clearsign && (s->flags & MUTT_VERIFY)));
3065 
3066  /* Copy PGP material to an data container */
3067  armored_data = file_to_data_object(s->fp_in, m->offset, m->length);
3068  /* Invoke PGP if needed */
3069  if (pgp_keyblock)
3070  {
3071  pgp_gpgme_extract_keys(armored_data, &fp_out);
3072  }
3073  else if (!clearsign || (s->flags & MUTT_VERIFY))
3074  {
3075  gpgme_data_t plaintext = create_gpgme_data();
3076  gpgme_ctx_t ctx = create_gpgme_context(false);
3077 
3078  if (clearsign)
3079  err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
3080  else
3081  {
3082  err = gpgme_op_decrypt_verify(ctx, armored_data, plaintext);
3083  if (gpg_err_code(err) == GPG_ERR_NO_DATA)
3084  {
3085  /* Decrypt verify can't handle signed only messages. */
3086  gpgme_data_seek(armored_data, 0, SEEK_SET);
3087  /* Must release plaintext so that we supply an uninitialized object. */
3088  gpgme_data_release(plaintext);
3089  plaintext = create_gpgme_data();
3090  err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
3091  }
3092  }
3093  redraw_if_needed(ctx);
3094 
3095  if (err != 0)
3096  {
3097  char errbuf[200];
3098 
3099  snprintf(errbuf, sizeof(errbuf) - 1,
3100  _("Error: decryption/verification failed: %s\n"), gpgme_strerror(err));
3101  state_puts(s, errbuf);
3102  }
3103  else
3104  {
3105  /* Decryption/Verification succeeded */
3106 
3107  mutt_message(_("PGP message successfully decrypted"));
3108 
3109  bool sig_stat = false;
3110  char *tmpfname = NULL;
3111 
3112  {
3113  /* Check whether signatures have been verified. */
3114  gpgme_verify_result_t verify_result = gpgme_op_verify_result(ctx);
3115  if (verify_result->signatures)
3116  sig_stat = true;
3117  }
3118 
3119  have_any_sigs = false;
3120  maybe_goodsig = false;
3121  if ((s->flags & MUTT_DISPLAY) && sig_stat)
3122  {
3123  int res, idx;
3124  bool anybad = false;
3125 
3126  state_attach_puts(s, _("[-- Begin signature information --]\n"));
3127  have_any_sigs = true;
3128  for (idx = 0; (res = show_one_sig_status(ctx, idx, s)) != -1; idx++)
3129  {
3130  if (res == 1)
3131  anybad = true;
3132  }
3133  if (!anybad && idx)
3134  maybe_goodsig = true;
3135 
3136  state_attach_puts(s, _("[-- End signature information --]\n\n"));
3137  }
3138 
3139  tmpfname = data_object_to_tempfile(plaintext, &fp_out);
3140  if (tmpfname)
3141  {
3142  unlink(tmpfname);
3143  FREE(&tmpfname);
3144  }
3145  else
3146  {
3147  mutt_file_fclose(&fp_out);
3148  state_puts(s, _("Error: copy data failed\n"));
3149  }
3150  }
3151  gpgme_data_release(plaintext);
3152  gpgme_release(ctx);
3153  }
3154 
3155  /* Now, copy cleartext to the screen. NOTE - we expect that PGP
3156  * outputs utf-8 cleartext. This may not always be true, but it
3157  * seems to be a reasonable guess. */
3158  if (s->flags & MUTT_DISPLAY)
3159  {
3160  if (needpass)
3161  state_attach_puts(s, _("[-- BEGIN PGP MESSAGE --]\n\n"));
3162  else if (pgp_keyblock)
3163  state_attach_puts(s, _("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"));
3164  else
3165  state_attach_puts(s, _("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"));
3166  }
3167 
3168  if (clearsign)
3169  {
3170  copy_clearsigned(armored_data, s, body_charset);
3171  }
3172  else if (fp_out)
3173  {
3174  int c;
3175  rewind(fp_out);
3176  struct FgetConv *fc = mutt_ch_fgetconv_open(fp_out, "utf-8", C_Charset, 0);
3177  while ((c = mutt_ch_fgetconv(fc)) != EOF)
3178  {
3179  state_putc(s, c);
3180  if ((c == '\n') && s->prefix)
3181  state_puts(s, s->prefix);
3182  }
3184  }
3185 
3186  if (s->flags & MUTT_DISPLAY)
3187  {
3188  state_putc(s, '\n');
3189  if (needpass)
3190  state_attach_puts(s, _("[-- END PGP MESSAGE --]\n"));
3191  else if (pgp_keyblock)
3192  state_attach_puts(s, _("[-- END PGP PUBLIC KEY BLOCK --]\n"));
3193  else
3194  state_attach_puts(s, _("[-- END PGP SIGNED MESSAGE --]\n"));
3195  }
3196 
3197  gpgme_data_release(armored_data);
3198  mutt_file_fclose(&fp_out);
3199  }
3200  else
3201  {
3202  /* A traditional PGP part may mix signed and unsigned content */
3203  /* XXX we may wish to recode here */
3204  if (s->prefix)
3205  state_puts(s, s->prefix);
3206  state_puts(s, buf);
3207  }
3208  }
3209 
3210  m->goodsig = (maybe_goodsig && have_any_sigs);
3211 
3212  if (needpass == -1)
3213  {
3215  s, _("[-- Error: could not find beginning of PGP message --]\n\n"));
3216  return 1;
3217  }
3218  mutt_debug(LL_DEBUG2, "Leaving handler\n");
3219 
3220  return err;
3221 }
#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:923
#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:991
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file&#39;s character set.
Definition: charset.c:908
#define SIGNED_MESSAGE(_y)
Definition: crypt_gpgme.c:144
#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:145
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:143
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
static gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:757
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:165
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#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:2593
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:70
void mutt_ch_fgetconv_close(struct FgetConv **fc)
Close an fgetconv handle.
Definition: charset.c:888
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:721
static gpgme_data_t create_gpgme_data(void)
Create a new GPGME data object.
Definition: crypt_gpgme.c:795
#define FREE(x)
Definition: memory.h:40
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
#define state_putc(STATE, STR)
Definition: state.h:56
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
static void redraw_if_needed(gpgme_ctx_t ctx)
accommodate for a redraw if needed
Definition: crypt_gpgme.c:202
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:1954
static void copy_clearsigned(gpgme_data_t data, struct State *s, char *charset)
Copy a clearsigned message.
Definition: crypt_gpgme.c:2945
+ 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 3229 of file crypt_gpgme.c.

3230 {
3231  int is_signed;
3232  int rc = 0;
3233 
3234  mutt_debug(LL_DEBUG2, "Entering handler\n");
3235 
3236  FILE *fp_out = mutt_file_mkstemp();
3237  if (!fp_out)
3238  {
3239  mutt_perror(_("Can't create temporary file"));
3240  if (s->flags & MUTT_DISPLAY)
3241  {
3243  _("[-- Error: could not create temporary file --]\n"));
3244  }
3245  return -1;
3246  }
3247 
3248  struct Body *tattach = decrypt_part(a, s, fp_out, false, &is_signed);
3249  if (tattach)
3250  {
3251  tattach->goodsig = is_signed > 0;
3252 
3253  if (s->flags & MUTT_DISPLAY)
3254  {
3256  s, is_signed ?
3257  _("[-- The following data is PGP/MIME signed and encrypted "
3258  "--]\n\n") :
3259  _("[-- The following data is PGP/MIME encrypted --]\n\n"));
3260  mutt_protected_headers_handler(tattach, s);
3261  }
3262 
3263  /* Store any protected headers in the parent so they can be
3264  * accessed for index updates after the handler recursion is done.
3265  * This is done before the handler to prevent a nested encrypted
3266  * handler from freeing the headers. */
3268  a->mime_headers = tattach->mime_headers;
3269  tattach->mime_headers = NULL;
3270 
3271  {
3272  FILE *fp_save = s->fp_in;
3273  s->fp_in = fp_out;
3274  rc = mutt_body_handler(tattach, s);
3275  s->fp_in = fp_save;
3276  }
3277 
3278  /* Embedded multipart signed protected headers override the
3279  * encrypted headers. We need to do this after the handler so
3280  * they can be printed in the pager. */
3281  if (mutt_is_multipart_signed(tattach) && tattach->parts && tattach->parts->mime_headers)
3282  {
3284  a->mime_headers = tattach->parts->mime_headers;
3285  tattach->parts->mime_headers = NULL;
3286  }
3287 
3288  /* if a multipart/signed is the _only_ sub-part of a
3289  * multipart/encrypted, cache signature verification
3290  * status. */
3291  if (mutt_is_multipart_signed(tattach) && !tattach->next)
3292  a->goodsig |= tattach->goodsig;
3293 
3294  if (s->flags & MUTT_DISPLAY)
3295  {
3296  state_puts(s, "\n");
3298  s, is_signed ?
3299  _("[-- End of PGP/MIME signed and encrypted data --]\n") :
3300  _("[-- End of PGP/MIME encrypted data --]\n"));
3301  }
3302 
3303  mutt_body_free(&tattach);
3304  mutt_message(_("PGP message successfully decrypted"));
3305  }
3306  else
3307  {
3308 #ifdef USE_AUTOCRYPT
3309  if (!OptAutocryptGpgme)
3310 #endif
3311  {
3312  mutt_error(_("Could not decrypt PGP message"));
3313  }
3314  rc = -1;
3315  }
3316 
3317  mutt_file_fclose(&fp_out);
3318  mutt_debug(LL_DEBUG2, "Leaving handler\n");
3319 
3320  return rc;
3321 }
int mutt_protected_headers_handler(struct Body *a, struct State *s)
Process a protected header - Implements handler_t.
Definition: crypt.c:1085
#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:2226
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:405
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:1585
#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 3326 of file crypt_gpgme.c.

3327 {
3328  int is_signed = 0;
3329  int rc = 0;
3330 
3331  mutt_debug(LL_DEBUG2, "Entering handler\n");
3332 
3333  /* clear out any mime headers before the handler, so they can't be spoofed. */
3335  a->warnsig = false;
3336  FILE *fp_out = mutt_file_mkstemp();
3337  if (!fp_out)
3338  {
3339  mutt_perror(_("Can't create temporary file"));
3340  if (s->flags & MUTT_DISPLAY)
3341  {
3343  _("[-- Error: could not create temporary file --]\n"));
3344  }
3345  return -1;
3346  }
3347 
3348  struct Body *tattach = decrypt_part(a, s, fp_out, true, &is_signed);
3349  if (tattach)
3350  {
3351  tattach->goodsig = is_signed > 0;
3352 
3353  if (s->flags & MUTT_DISPLAY)
3354  {
3356  s, is_signed ?
3357  _("[-- The following data is S/MIME signed --]\n\n") :
3358  _("[-- The following data is S/MIME encrypted --]\n\n"));
3359  mutt_protected_headers_handler(tattach, s);
3360  }
3361 
3362  /* Store any protected headers in the parent so they can be
3363  * accessed for index updates after the handler recursion is done.
3364  * This is done before the handler to prevent a nested encrypted
3365  * handler from freeing the headers. */
3367  a->mime_headers = tattach->mime_headers;
3368  tattach->mime_headers = NULL;
3369 
3370  {
3371  FILE *fp_save = s->fp_in;
3372  s->fp_in = fp_out;
3373  rc = mutt_body_handler(tattach, s);
3374  s->fp_in = fp_save;
3375  }
3376 
3377  /* Embedded multipart signed protected headers override the
3378  * encrypted headers. We need to do this after the handler so
3379  * they can be printed in the pager. */
3380  if (mutt_is_multipart_signed(tattach) && tattach->parts && tattach->parts->mime_headers)
3381  {
3383  a->mime_headers = tattach->parts->mime_headers;
3384  tattach->parts->mime_headers = NULL;
3385  }
3386 
3387  /* if a multipart/signed is the _only_ sub-part of a multipart/encrypted,
3388  * cache signature verification status. */
3389  if (mutt_is_multipart_signed(tattach) && !tattach->next)
3390  {
3391  a->goodsig = tattach->goodsig;
3392  if (!a->goodsig)
3393  a->warnsig = tattach->warnsig;
3394  }
3395  else if (tattach->goodsig)
3396  {
3397  a->goodsig = true;
3398  a->warnsig = tattach->warnsig;
3399  }
3400 
3401  if (s->flags & MUTT_DISPLAY)
3402  {
3403  state_puts(s, "\n");
3404  state_attach_puts(s, is_signed ?
3405  _("[-- End of S/MIME signed data --]\n") :
3406  _("[-- End of S/MIME encrypted data --]\n"));
3407  }
3408 
3409  mutt_body_free(&tattach);
3410  }
3411 
3412  mutt_file_fclose(&fp_out);
3413  mutt_debug(LL_DEBUG2, "Leaving handler\n");
3414 
3415  return rc;
3416 }
int mutt_protected_headers_handler(struct Body *a, struct State *s)
Process a protected header - Implements handler_t.
Definition: crypt.c:1085
#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:2226
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:405
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:1585
#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:

◆ crypt_format_str()

static const char* crypt_format_str ( char *  buf,
size_t  buflen,
size_t  col,
int  cols,
char  op,
const char *  src,
const char *  prec,
const char *  if_str,
const char *  else_str,
intptr_t  data,
MuttFormatFlags  flags 
)
static

Format a string for the key selection menu - Implements format_t.

Expando Description
%n Number
%p Protocol
%t Trust/validity of the key-uid association
%u User id
%[fmt] Date of key using strftime(3)

| | | %a | Algorithm | %c | Capabilities | %f | Flags | %k | Key id | %l | Length | | | %A | Algorithm of the principal key | %C | Capabilities of the principal key | %F | Flags of the principal key | %K | Key id of the principal key | %L | Length of the principal key

Definition at line 3441 of file crypt_gpgme.c.

3445 {
3446  char fmt[128];
3447  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
3448 
3449  struct CryptEntry *entry = (struct CryptEntry *) data;
3450  struct CryptKeyInfo *key = entry->key;
3451 
3452  /* if (isupper ((unsigned char) op)) */
3453  /* key = pkey; */
3454 
3455  KeyFlags kflags = (key->flags /* | (pkey->flags & KEYFLAG_RESTRICTIONS)
3456  | uid->flags */);
3457 
3458  switch (tolower(op))
3459  {
3460  case 'a':
3461  if (!optional)
3462  {
3463  const char *s = NULL;
3464  snprintf(fmt, sizeof(fmt), "%%%s.3s", prec);
3465  if (key->kobj->subkeys)
3466  s = gpgme_pubkey_algo_name(key->kobj->subkeys->pubkey_algo);
3467  else
3468  s = "?";
3469  snprintf(buf, buflen, fmt, s);
3470  }
3471  break;
3472 
3473  case 'c':
3474  if (!optional)
3475  {
3476  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
3477  snprintf(buf, buflen, fmt, crypt_key_abilities(kflags));
3478  }
3479  else if (!(kflags & KEYFLAG_ABILITIES))
3480  optional = false;
3481  break;
3482 
3483  case 'f':
3484  if (!optional)
3485  {
3486  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
3487  snprintf(buf, buflen, fmt, crypt_flags(kflags));
3488  }
3489  else if (!(kflags & KEYFLAG_RESTRICTIONS))
3490  optional = false;
3491  break;
3492 
3493  case 'k':
3494  if (!optional)
3495  {
3496  /* fixme: we need a way to distinguish between main and subkeys.
3497  * Store the idx in entry? */
3498  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
3499  snprintf(buf, buflen, fmt, crypt_keyid(key));
3500  }
3501  break;
3502 
3503  case 'l':
3504  if (!optional)
3505  {
3506  snprintf(fmt, sizeof(fmt), "%%%slu", prec);
3507  unsigned long val;
3508  if (key->kobj->subkeys)
3509  val = key->kobj->subkeys->length;
3510  else
3511  val = 0;
3512  snprintf(buf, buflen, fmt, val);
3513  }
3514  break;
3515 
3516  case 'n':
3517  if (!optional)
3518  {
3519  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
3520  snprintf(buf, buflen, fmt, entry->num);
3521  }
3522  break;
3523 
3524  case 'p':
3525  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
3526  snprintf(buf, buflen, fmt, gpgme_get_protocol_name(key->kobj->protocol));
3527  break;
3528 
3529  case 't':
3530  {
3531  char *s = NULL;
3532  if ((kflags & KEYFLAG_ISX509))
3533  s = "x";
3534  else
3535  {
3536  switch (key->validity)
3537  {
3538  case GPGME_VALIDITY_FULL:
3539  s = "f";
3540  break;
3541  case GPGME_VALIDITY_MARGINAL:
3542  s = "m";
3543  break;
3544  case GPGME_VALIDITY_NEVER:
3545  s = "n";
3546  break;
3547  case GPGME_VALIDITY_ULTIMATE:
3548  s = "u";
3549  break;
3550  case GPGME_VALIDITY_UNDEFINED:
3551  s = "q";
3552  break;
3553  case GPGME_VALIDITY_UNKNOWN:
3554  default:
3555  s = "?";
3556  break;
3557  }
3558  }
3559  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
3560  snprintf(buf, buflen, fmt, *s);
3561  break;
3562  }
3563 
3564  case 'u':
3565  if (!optional)
3566  {
3567  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
3568  snprintf(buf, buflen, fmt, key->uid);
3569  }
3570  break;
3571 
3572  case '[':
3573  {
3574  char buf2[128];
3575  bool do_locales = true;
3576  struct tm tm = { 0 };
3577 
3578  char *p = buf;
3579 
3580  const char *cp = src;
3581  if (*cp == '!')
3582  {
3583  do_locales = false;
3584  cp++;
3585  }
3586 
3587  size_t len = buflen - 1;
3588  while ((len > 0) && (*cp != ']'))
3589  {
3590  if (*cp == '%')
3591  {
3592  cp++;
3593  if (len >= 2)
3594  {
3595  *p++ = '%';
3596  *p++ = *cp;
3597  len -= 2;
3598  }
3599  else
3600  break; /* not enough space */
3601  cp++;
3602  }
3603  else
3604  {
3605  *p++ = *cp++;
3606  len--;
3607  }
3608  }
3609  *p = '\0';
3610 
3611  if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
3612  tm = mutt_date_localtime(key->kobj->subkeys->timestamp);
3613  else
3614  tm = mutt_date_localtime(0); // Default to 1970-01-01
3615 
3616  if (!do_locales)
3617  setlocale(LC_TIME, "C");
3618  strftime(buf2, sizeof(buf2), buf, &tm);
3619  if (!do_locales)
3620  setlocale(LC_TIME, "");
3621 
3622  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
3623  snprintf(buf, buflen, fmt, buf2);
3624  if (len > 0)
3625  src = cp + 1;
3626  break;
3627  }
3628 
3629  default:
3630  *buf = '\0';
3631  }
3632 
3633  if (optional)
3634  {
3635  mutt_expando_format(buf, buflen, col, cols, if_str, crypt_format_str, data,
3637  }
3638  else if (flags & MUTT_FORMAT_OPTIONAL)
3639  {
3640  mutt_expando_format(buf, buflen, col, cols, else_str, crypt_format_str,
3641  data, MUTT_FORMAT_NO_FLAGS);
3642  }
3643  return src;
3644 }
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:641
static char crypt_flags(KeyFlags flags)
Parse the key flags into a single character.
Definition: crypt_gpgme.c:598
static int const char * fmt
Definition: acutest.h:488
static const char * crypt_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the key selection menu - Implements format_t.
Definition: crypt_gpgme.c:3441
#define KEYFLAG_ISX509
Key is an X.509 key.
Definition: lib.h:131
size_t num
Definition: crypt_gpgme.c:132
#define KEYFLAG_ABILITIES
Definition: lib.h:144
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
A stored PGP key.
Definition: crypt_gpgme.c:117
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string.
Definition: muttlib.c:772
const char * uid
and for convenience point to this user ID
Definition: crypt_gpgme.c:122
uint16_t KeyFlags
Flags describing PGP/SMIME keys, e.g. KEYFLAG_CANSIGN.
Definition: lib.h:127
static char * crypt_key_abilities(KeyFlags flags)
Parse key flags into a string.
Definition: crypt_gpgme.c:568
gpgme_key_t kobj
Definition: crypt_gpgme.c:120
#define KEYFLAG_RESTRICTIONS
Definition: lib.h:142
An entry in the Select-Key menu.
Definition: crypt_gpgme.c:130
struct CryptKeyInfo * key
Definition: crypt_gpgme.c:133
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.c:123
gpgme_validity_t validity
uid validity (cached for convenience)
Definition: crypt_gpgme.c:124
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
static const char * crypt_keyid(struct CryptKeyInfo *k)
Find the ID for the key.
Definition: crypt_gpgme.c:471
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_make_entry()

static void crypt_make_entry ( char *  buf,
size_t  buflen,
struct Menu menu,
int  line 
)
static

Format a menu item for the key selection list - Implements Menu::make_entry()

Definition at line 3649 of file crypt_gpgme.c.

3650 {
3651  struct CryptKeyInfo **key_table = menu->mdata;
3652  struct CryptEntry entry;
3653 
3654  entry.key = key_table[line];
3655  entry.num = line + 1;
3656 
3657  mutt_expando_format(buf, buflen, 0, menu->win_index->state.cols,
3659  (intptr_t) &entry, MUTT_FORMAT_ARROWCURSOR);
3660 }
#define NONULL(x)
Definition: string2.h:37
#define MUTT_FORMAT_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
static const char * crypt_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the key selection menu - Implements format_t.
Definition: crypt_gpgme.c:3441
A stored PGP key.
Definition: crypt_gpgme.c:117
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string.
Definition: muttlib.c:772
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:57
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:119
void * mdata
Extra data for the current menu.
Definition: mutt_menu.h:84
An entry in the Select-Key menu.
Definition: crypt_gpgme.c:130
struct CryptKeyInfo * key
Definition: crypt_gpgme.c:133
char * C_PgpEntryFormat
Config: printf-like format string for the PGP key selection menu.
Definition: config.c:53
int const char int line
Definition: acutest.h:617
struct MuttWindow * win_index
Definition: mutt_menu.h:92
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compare_key_address()

static int compare_key_address ( const void *  a,
const void *  b 
)
static

Compare Key addresses and IDs for sorting.

Parameters
aFirst key
bSecond key
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 3670 of file crypt_gpgme.c.

3671 {
3672  struct CryptKeyInfo **s = (struct CryptKeyInfo **) a;
3673  struct CryptKeyInfo **t = (struct CryptKeyInfo **) b;
3674  int r;
3675 
3676  r = mutt_istr_cmp((*s)->uid, (*t)->uid);
3677  if (r != 0)
3678  return r > 0;
3680 }
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:585
A stored PGP key.
Definition: crypt_gpgme.c:117
static const char * crypt_fpr_or_lkeyid(struct CryptKeyInfo *k)
Find the fingerprint of a key.
Definition: crypt_gpgme.c:546
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_compare_address()

static int crypt_compare_address ( const void *  a,
const void *  b 
)
static

Compare the addresses of two keys.

Parameters
aFirst key
bSecond key
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 3690 of file crypt_gpgme.c.

3691 {
3692  return (C_PgpSortKeys & SORT_REVERSE) ? !compare_key_address(a, b) :
3693  compare_key_address(a, b);
3694 }
static int compare_key_address(const void *a, const void *b)
Compare Key addresses and IDs for sorting.
Definition: crypt_gpgme.c:3670
short C_PgpSortKeys
Config: Sort order for PGP keys.
Definition: config.c:89
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:86
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compare_keyid()

static int compare_keyid ( const void *  a,
const void *  b 
)
static

Compare Key IDs and addresses for sorting.

Parameters
aFirst key ID
bSecond key ID
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 3704 of file crypt_gpgme.c.

3705 {
3706  struct CryptKeyInfo **s = (struct CryptKeyInfo **) a;
3707  struct CryptKeyInfo **t = (struct CryptKeyInfo **) b;
3708  int r;
3709 
3711  if (r != 0)
3712  return r > 0;
3713  return mutt_istr_cmp((*s)->uid, (*t)->uid) > 0;
3714 }
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:585
A stored PGP key.
Definition: crypt_gpgme.c:117
static const char * crypt_fpr_or_lkeyid(struct CryptKeyInfo *k)
Find the fingerprint of a key.
Definition: crypt_gpgme.c:546
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_compare_keyid()

static int crypt_compare_keyid ( const void *  a,
const void *  b 
)
static

Compare the IDs of two keys.

Parameters
aFirst key ID
bSecond key ID
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 3724 of file crypt_gpgme.c.

3725 {
3726  return (C_PgpSortKeys & SORT_REVERSE) ? !compare_keyid(a, b) : compare_keyid(a, b);
3727 }
static int compare_keyid(const void *a, const void *b)
Compare Key IDs and addresses for sorting.
Definition: crypt_gpgme.c:3704
short C_PgpSortKeys
Config: Sort order for PGP keys.
Definition: config.c:89
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:86
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compare_key_date()

static int compare_key_date ( const void *  a,
const void *  b 
)
static

Compare Key creation dates and addresses for sorting.

Parameters
aFirst key
bSecond key
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 3737 of file crypt_gpgme.c.

3738 {
3739  struct CryptKeyInfo **s = (struct CryptKeyInfo **) a;
3740  struct CryptKeyInfo **t = (struct CryptKeyInfo **) b;
3741  unsigned long ts = 0, tt = 0;
3742 
3743  if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
3744  ts = (*s)->kobj->subkeys->timestamp;
3745  if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
3746  tt = (*t)->kobj->subkeys->timestamp;
3747 
3748  if (ts > tt)
3749  return 1;
3750  if (ts < tt)
3751  return 0;
3752 
3753  return mutt_istr_cmp((*s)->uid, (*t)->uid) > 0;
3754 }
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:585
if(!test_colorize_)
Definition: acutest.h:499
A stored PGP key.
Definition: crypt_gpgme.c:117
gpgme_key_t kobj
Definition: crypt_gpgme.c:120
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_compare_date()

static int crypt_compare_date ( const void *  a,
const void *  b 
)
static

Compare the dates of two keys.

Parameters
aFirst key
bSecond key
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 3764 of file crypt_gpgme.c.

3765 {
3766  return (C_PgpSortKeys & SORT_REVERSE) ? !compare_key_date(a, b) :
3767  compare_key_date(a, b);
3768 }
short C_PgpSortKeys
Config: Sort order for PGP keys.
Definition: config.c:89
static int compare_key_date(const void *a, const void *b)
Compare Key creation dates and addresses for sorting.
Definition: crypt_gpgme.c:3737
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:86
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compare_key_trust()

static int compare_key_trust ( const void *  a,
const void *  b 
)
static

Compare the trust of keys for sorting.

Parameters
aFirst key
bSecond key
Return values
-1a precedes b
0a and b are identical
1b precedes a

Compare two trust values, the key length, the creation dates. the addresses and the key IDs.

Definition at line 3781 of file crypt_gpgme.c.

3782 {
3783  struct CryptKeyInfo **s = (struct CryptKeyInfo **) a;
3784  struct CryptKeyInfo **t = (struct CryptKeyInfo **) b;
3785  unsigned long ts = 0, tt = 0;
3786  int r;
3787 
3788  r = (((*s)->flags & KEYFLAG_RESTRICTIONS) - ((*t)->flags & KEYFLAG_RESTRICTIONS));
3789  if (r != 0)
3790  return r > 0;
3791 
3792  ts = (*s)->validity;
3793  tt = (*t)->validity;
3794  r = (tt - ts);
3795  if (r != 0)
3796  return r < 0;
3797 
3798  if ((*s)->kobj->subkeys)
3799  ts = (*s)->kobj->subkeys->length;
3800  if ((*t)->kobj->subkeys)
3801  tt = (*t)->kobj->subkeys->length;
3802  if (ts != tt)
3803  return ts > tt;
3804 
3805  if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
3806  ts = (*s)->kobj->subkeys->timestamp;
3807  if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
3808  tt = (*t)->kobj->subkeys->timestamp;
3809  if (ts > tt)
3810  return 1;
3811  if (ts < tt)
3812  return 0;
3813 
3814  r = mutt_istr_cmp((*s)->uid, (*t)->uid);
3815  if (r != 0)
3816  return r > 0;
3817  return mutt_istr_cmp(crypt_fpr_or_lkeyid((*s)), crypt_fpr_or_lkeyid((*t))) > 0;
3818 }
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:585
if(!test_colorize_)
Definition: acutest.h:499
A stored PGP key.
Definition: crypt_gpgme.c:117
#define KEYFLAG_RESTRICTIONS
Definition: lib.h:142
static const char * crypt_fpr_or_lkeyid(struct CryptKeyInfo *k)
Find the fingerprint of a key.
Definition: crypt_gpgme.c:546
gpgme_validity_t validity
uid validity (cached for convenience)
Definition: crypt_gpgme.c:124
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_compare_trust()

static int crypt_compare_trust ( const void *  a,
const void *  b 
)
static

Compare the trust levels of two keys.

Parameters
aFirst key
bSecond key
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 3828 of file crypt_gpgme.c.

3829 {
3830  return (C_PgpSortKeys & SORT_REVERSE) ? !compare_key_trust(a, b) :
3831  compare_key_trust(a, b);
3832 }
short C_PgpSortKeys
Config: Sort order for PGP keys.
Definition: config.c:89
static int compare_key_trust(const void *a, const void *b)
Compare the trust of keys for sorting.
Definition: crypt_gpgme.c:3781
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:86
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_dn_part()

static bool print_dn_part ( FILE *  fp,
struct DnArray dn,
const char *  key 
)
static

Print the X.500 Distinguished Name.

Parameters
fpFile to write to
dnDistinguished Name
keyKey string
Return values
trueIf any DN keys match the given key string
falseOtherwise

Print the X.500 Distinguished Name part KEY from the array of parts DN to FP.

Definition at line 3844 of file crypt_gpgme.c.

3845 {
3846  bool any = false;
3847 
3848  for (; dn->key; dn++)
3849  {
3850  if (strcmp(dn->key, key) == 0)
3851  {
3852  if (any)
3853  fputs(" + ", fp);
3854  print_utf8(fp, dn->value, strlen(dn->value));
3855  any = true;
3856  }
3857  }
3858  return any;
3859 }
char * key
Definition: crypt_gpgme.c:108
static void print_utf8(FILE *fp, const char *buf, size_t len)
Write a UTF-8 string to a file.
Definition: crypt_gpgme.c:246
char * value
Definition: crypt_gpgme.c:109
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_dn_parts()

static void print_dn_parts ( FILE *  fp,
struct DnArray dn 
)
static

Print all parts of a DN in a standard sequence.

Parameters
fpFile to write to
dnArray of Distinguished Names

Definition at line 3866 of file crypt_gpgme.c.

3867 {
3868  static const char *const stdpart[] = {
3869  "CN", "OU", "O", "STREET", "L", "ST", "C", NULL,
3870  };
3871  bool any = false;
3872  bool any2 = false;
3873 
3874  for (int i = 0; stdpart[i]; i++)
3875  {
3876  if (any)
3877  fputs(", ", fp);
3878  any = print_dn_part(fp, dn, stdpart[i]);
3879  }
3880  /* now print the rest without any specific ordering */
3881  for (; dn->key; dn++)
3882  {
3883  int i;
3884  for (i = 0; stdpart[i]; i++)
3885  {
3886  if (strcmp(dn->key, stdpart[i]) == 0)
3887  break;
3888  }
3889  if (!stdpart[i])
3890  {
3891  if (any)
3892  fputs(", ", fp);
3893  if (!any2)
3894  fputs("(", fp);
3895  any = print_dn_part(fp, dn, dn->key);
3896  any2 = true;
3897  }
3898  }
3899  if (any2)
3900  fputs(")", fp);
3901 }
static bool print_dn_part(FILE *fp, struct DnArray *dn, const char *key)
Print the X.500 Distinguished Name.
Definition: crypt_gpgme.c:3844
char * key
Definition: crypt_gpgme.c:108
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_dn_part()

static const char* parse_dn_part ( struct DnArray array,
const char *  str 
)
static

Parse an RDN.

Parameters
arrayArray for results
strString to parse
Return values
ptrFirst character after Distinguished Name

This is a helper to parse_dn()

Definition at line 3911 of file crypt_gpgme.c.

3912 {
3913  const char *s = NULL, *s1 = NULL;
3914  size_t n;
3915  char *p = NULL;
3916 
3917  /* parse attribute type */
3918  for (s = str + 1; (s[0] != '\0') && (s[0] != '='); s++)
3919  ; // do nothing
3920 
3921  if (s[0] == '\0')
3922  return NULL; /* error */
3923  n = s - str;
3924  if (n == 0)
3925  return NULL; /* empty key */
3926  array->key = mutt_mem_malloc(n + 1);
3927  p = array->key;
3928  memcpy(p, str, n); /* fixme: trim trailing spaces */
3929  p[n] = 0;
3930  str = s + 1;
3931 
3932  if (*str == '#')
3933  { /* hexstring */
3934  str++;
3935  for (s = str; isxdigit(*s); s++)
3936  s++;
3937  n = s - str;
3938  if ((n == 0) || (n & 1))
3939  return NULL; /* empty or odd number of digits */
3940  n /= 2;
3941  p = mutt_mem_malloc(n + 1);
3942  array->value = (char *) p;
3943  for (s1 = str; n; s1 += 2, n--)
3944  sscanf(s1, "%2hhx", (unsigned char *) p++);
3945  *p = '\0';
3946  }
3947  else
3948  { /* regular v3 quoted string */
3949  for (n = 0, s = str; *s; s++)
3950  {
3951  if (*s == '\\')
3952  { /* pair */
3953  s++;
3954  if ((*s == ',') || (*s == '=') || (*s == '+') || (*s == '<') || (*s == '>') ||
3955  (*s == '#') || (*s == ';') || (*s == '\\') || (*s == '\"') || (*s == ' '))
3956  {
3957  n++;
3958  }
3959  else if (isxdigit(s[0]) && isxdigit(s[1]))
3960  {
3961  s++;
3962  n++;
3963  }
3964  else
3965  return NULL; /* invalid escape sequence */
3966  }
3967  else if (*s == '\"')
3968  return NULL; /* invalid encoding */
3969  else if ((*s == ',') || (*s == '=') || (*s == '+') || (*s == '<') ||
3970  (*s == '>') || (*s == '#') || (*s == ';'))
3971  {
3972  break;
3973  }
3974  else
3975  n++;
3976  }
3977 
3978  p = mutt_mem_malloc(n + 1);
3979  array->value = (char *) p;
3980  for (s = str; n; s++, n--)
3981  {
3982  if (*s == '\\')
3983  {
3984  s++;
3985  if (isxdigit(*s))
3986  {
3987  sscanf(s, "%2hhx", (unsigned char *) p++);
3988  s++;
3989  }
3990  else
3991  *p++ = *s;
3992  }
3993  else
3994  *p++ = *s;
3995  }
3996  *p = '\0';
3997  }
3998  return s;
3999 }
char * key
Definition: crypt_gpgme.c:108
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
int n
Definition: acutest.h:492
char * value
Definition: crypt_gpgme.c:109
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_dn()

static struct DnArray* parse_dn ( const char *  str)
static

Parse a DN and return an array-ized one.

Parameters
strString to parse
Return values
ptrArray of Distinguished Names

This is not a validating parser and it does not support any old-stylish syntax; GPGME is expected to return only rfc2253 compatible strings.

Definition at line 4009 of file crypt_gpgme.c.

4010 {
4011  struct DnArray *array = NULL;
4012  size_t arrayidx, arraysize;
4013 
4014  arraysize = 7; /* C,ST,L,O,OU,CN,email */
4015  array = mutt_mem_malloc((arraysize + 1) * sizeof(*array));
4016  arrayidx = 0;
4017  while (*str)
4018  {
4019  while (str[0] == ' ')
4020  str++;
4021  if (str[0] == '\0')
4022  break; /* ready */
4023  if (arrayidx >= arraysize)
4024  {
4025  /* neomutt lacks a real mutt_mem_realloc - so we need to copy */
4026  arraysize += 5;
4027  struct DnArray *a2 = mutt_mem_malloc((arraysize + 1) * sizeof(*array));
4028  for (int i = 0; i < arrayidx; i++)
4029  {
4030  a2[i].key = array[i].key;
4031  a2[i].value = array[i].value;
4032  }
4033  FREE(&array);
4034  array = a2;
4035  }
4036  array[arrayidx].key = NULL;
4037  array[arrayidx].value = NULL;
4038  str = parse_dn_part(array + arrayidx, str);
4039  arrayidx++;
4040  if (!str)
4041  goto failure;
4042  while (str[0] == ' ')
4043  str++;
4044  if ((str[0] != '\0') && (str[0] != ',') && (str[0] != ';') && (str[0] != '+'))
4045  goto failure; /* invalid delimiter */
4046  if (str[0] != '\0')
4047  str++;
4048  }
4049  array[arrayidx].key = NULL;
4050  array[arrayidx].value = NULL;
4051  return array;
4052 
4053 failure:
4054  for (int i = 0; i < arrayidx; i++)
4055  {
4056  FREE(&array[i].key);
4057  FREE(&array[i].value);
4058  }
4059  FREE(&array);
4060  return NULL;
4061 }
static const char * parse_dn_part(struct DnArray *array, const char *str)
Parse an RDN.
Definition: crypt_gpgme.c:3911
char * key
Definition: crypt_gpgme.c:108
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:40
char * value
Definition: crypt_gpgme.c:109
An X500 Distinguished Name.
Definition: crypt_gpgme.c:106
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_and_print_user_id()

static void parse_and_print_user_id ( FILE *  fp,
const char *  userid 
)
static

Print a nice representation of the userid.

Parameters
fpFile to write to
useridString returned by GPGME key functions (utf-8 encoded)

Make sure it is displayed in a proper way, which does mean to reorder some parts for S/MIME's DNs.

Definition at line 4071 of file crypt_gpgme.c.

4072 {
4073  const char *s = NULL;
4074 
4075  if (*userid == '<')
4076  {
4077  s = strchr(userid + 1, '>');
4078  if (s)
4079  print_utf8(fp, userid + 1, s - userid - 1);
4080  }
4081  else if (*userid == '(')
4082  fputs(_("[Can't display this user ID (unknown encoding)]"), fp);
4083  else if (!digit_or_letter(userid))
4084  fputs(_("[Can't display this user ID (invalid encoding)]"), fp);
4085  else
4086  {
4087  struct DnArray *dn = parse_dn(userid);
4088  if (!dn)
4089  fputs(_("[Can't display this user ID (invalid DN)]"), fp);
4090  else
4091  {
4092  print_dn_parts(fp, dn);
4093  for (int i = 0; dn[i].key; i++)
4094  {
4095  FREE(&dn[i].key);
4096  FREE(&dn[i].value);
4097  }
4098  FREE(&dn);
4099  }
4100  }
4101 }
#define _(a)
Definition: message.h:28
char * key
Definition: crypt_gpgme.c:108
static int digit_or_letter(const char *s)
Is the character a number or letter.
Definition: crypt_gpgme.c:233
static void print_utf8(FILE *fp, const char *buf, size_t len)
Write a UTF-8 string to a file.
Definition: crypt_gpgme.c:246
static void print_dn_parts(FILE *fp, struct DnArray *dn)
Print all parts of a DN in a standard sequence.
Definition: crypt_gpgme.c:3866
static struct DnArray * parse_dn(const char *str)
Parse a DN and return an array-ized one.
Definition: crypt_gpgme.c:4009
#define FREE(x)
Definition: memory.h:40
char * value
Definition: crypt_gpgme.c:109
An X500 Distinguished Name.
Definition: crypt_gpgme.c:106
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ key_check_cap()

static unsigned int key_check_cap ( gpgme_key_t  key,
enum KeyCap  cap 
)
static

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 4109 of file crypt_gpgme.c.

4110 {
4111  unsigned int ret = 0;
4112 
4113  switch (cap)
4114  {
4115  case KEY_CAP_CAN_ENCRYPT:
4116  ret = key->can_encrypt;
4117  if (ret == 0)
4118  {
4119  for (gpgme_subkey_t subkey = key->subkeys; subkey; subkey = subkey->next)
4120  {
4121  ret = subkey->can_encrypt;
4122  if (ret != 0)
4123  break;
4124  }
4125  }
4126  break;
4127  case KEY_CAP_CAN_SIGN:
4128  ret = key->can_sign;
4129  if (ret == 0)
4130  {
4131  for (gpgme_subkey_t subkey = key->subkeys; subkey; subkey = subkey->next)
4132  {
4133  ret = subkey->can_sign;
4134  if (ret != 0)
4135  break;
4136  }
4137  }
4138  break;
4139  case KEY_CAP_CAN_CERTIFY:
4140  ret = key->can_certify;
4141  if (ret == 0)
4142  {
4143  for (gpgme_subkey_t subkey = key->subkeys; subkey; subkey = subkey->next)
4144  {
4145  ret = subkey->can_certify;
4146  if (ret != 0)
4147  break;
4148  }
4149  }
4150  break;
4151  }
4152 
4153  return ret;
4154 }
Key can be used to certify.
Definition: crypt_gpgme.c:156
char * key
Definition: crypt_gpgme.c:108
Key can be used for signing.
Definition: crypt_gpgme.c:155
Key can be used for encryption.
Definition: crypt_gpgme.c:154
+ Here is the caller graph for this function:

◆ print_key_info()

static void print_key_info ( gpgme_key_t  key,
FILE *  fp 
)
static

Verbose information about a key or certificate to a file.

Parameters
keyKey to use
fpFile to write to

Definition at line 4161 of file crypt_gpgme.c.

4162 {
4163  int idx;
4164  const char *s = NULL, *s2 = NULL;
4165  time_t tt = 0;
4166  char shortbuf[128];
4167  unsigned long aval = 0;
4168  const char *delim = NULL;
4169  gpgme_user_id_t uid = NULL;
4170  static int max_header_width = 0;
4171 
4172  if (max_header_width == 0)
4173  {
4174  for (int i = 0; i < KIP_MAX; i++)
4175  {
4177  const int width = mutt_strwidth(_(KeyInfoPrompts[i]));
4178  if (max_header_width < width)
4179  max_header_width = width;
4180  KeyInfoPadding[i] -= width;
4181  }
4182  for (int i = 0; i < KIP_MAX; i++)
4183  KeyInfoPadding[i] += max_header_width;
4184  }
4185 
4186  bool is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
4187 
4188  for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
4189  {
4190  if (uid->revoked)
4191  continue;
4192 
4193  s = uid->uid;
4194  /* L10N: DOTFILL */
4195 
4196  if (idx == 0)
4197  fprintf(fp, "%*s", KeyInfoPadding[KIP_NAME], _(KeyInfoPrompts[KIP_NAME]));
4198  else
4199  fprintf(fp, "%*s", KeyInfoPadding[KIP_AKA], _(KeyInfoPrompts[KIP_AKA]));
4200  if (uid->invalid)
4201  {
4202  /* L10N: comes after the Name or aka if the key is invalid */
4203  fputs(_("[Invalid]"), fp);
4204  putc(' ', fp);
4205  }
4206  if (is_pgp)
4207  print_utf8(fp, s, strlen(s));
4208  else
4209  parse_and_print_user_id(fp, s);
4210  putc('\n', fp);
4211  }
4212 
4213  if (key->subkeys && (key->subkeys->timestamp > 0))
4214  {
4215  tt = key->subkeys->timestamp;
4216 
4217  mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
4218  fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_FROM],
4219  _(KeyInfoPrompts[KIP_VALID_FROM]), shortbuf);
4220  }
4221 
4222  if (key->subkeys && (key->subkeys->expires > 0))
4223  {
4224  tt = key->subkeys->expires;
4225 
4226  mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
4227  fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_TO],
4228  _(KeyInfoPrompts[KIP_VALID_TO]), shortbuf);
4229  }
4230 
4231  if (key->subkeys)
4232  s = gpgme_pubkey_algo_name(key->subkeys->pubkey_algo);
4233  else
4234  s = "?";
4235 
4236  s2 = is_pgp ? "PGP" : "X.509";
4237 
4238  if (key->subkeys)
4239  aval = key->subkeys->length;
4240 
4241  fprintf(fp, "%*s", KeyInfoPadding[KIP_KEY_TYPE], _(KeyInfoPrompts[KIP_KEY_TYPE]));
4242  /* L10N: This is printed after "Key Type: " and looks like this: PGP, 2048 bit RSA */
4243  fprintf(fp, ngettext("%s, %lu bit %s\n", "%s, %lu bit %s\n", aval), s2, aval, s);
4244 
4245  fprintf(fp, "%*s", KeyInfoPadding[KIP_KEY_USAGE], _(KeyInfoPrompts[KIP_KEY_USAGE]));
4246  delim = "";
4247 
4249  {
4250  /* L10N: value in Key Usage: field */
4251  fprintf(fp, "%s%s", delim, _("encryption"));
4252  delim = _(", ");
4253  }
4255  {
4256  /* L10N: value in Key Usage: field */
4257  fprintf(fp, "%s%s", delim, _("signing"));
4258  delim = _(", ");
4259  }
4261  {
4262  /* L10N: value in Key Usage: field */
4263  fprintf(fp, "%s%s", delim, _("certification"));
4264  }
4265  putc('\n', fp);
4266 
4267  if (key->subkeys)
4268  {
4269  s = key->subkeys->fpr;
4270  fprintf(fp, "%*s", KeyInfoPadding[KIP_FINGERPRINT], _(KeyInfoPrompts[KIP_FINGERPRINT]));
4271  if (is_pgp && (strlen(s) == 40))
4272  {
4273  for (int i = 0; (s[0] != '\0') && (s[1] != '\0') && (s[2] != '\0') &&
4274  (s[3] != '\0') && (s[4] != '\0');
4275  s += 4, i++)
4276  {
4277  putc(*s, fp);
4278  putc(s[1], fp);
4279  putc(s[2], fp);
4280  putc(s[3], fp);
4281  putc(' ', fp);
4282  if (i == 4)
4283  putc(' ', fp);
4284  }
4285  }
4286  else
4287  {
4288  for (int i = 0; (s[0] != '\0') && (s[1] != '\0') && (s[2] != '\0'); s += 2, i++)
4289  {
4290  putc(*s, fp);
4291  putc(s[1], fp);
4292  putc(is_pgp ? ' ' : ':', fp);
4293  if (is_pgp && (i == 7))
4294  putc(' ', fp);
4295  }
4296  }
4297  fprintf(fp, "%s\n", s);
4298  }
4299 
4300  if (key->issuer_serial)
4301  {
4302  s = key->issuer_serial;
4303  if (s)
4304  {
4305  fprintf(fp, "%*s0x%s\n", KeyInfoPadding[KIP_SERIAL_NO],
4306  _(KeyInfoPrompts[KIP_SERIAL_NO]), s);
4307  }
4308  }
4309 
4310  if (key->issuer_name)
4311  {
4312  s = key->issuer_name;
4313  if (s)
4314  {
4315  fprintf(fp, "%*s", KeyInfoPadding[KIP_ISSUED_BY], _(KeyInfoPrompts[KIP_ISSUED_BY]));
4316  parse_and_print_user_id(fp, s);
4317  putc('\n', fp);
4318  }
4319  }
4320 
4321  /* For PGP we list all subkeys. */
4322  if (is_pgp)
4323  {
4324  gpgme_subkey_t subkey = NULL;
4325 
4326  for (idx = 1, subkey = key->subkeys; subkey; idx++, subkey = subkey->next)
4327  {
4328  s = subkey->keyid;
4329 
4330  putc('\n', fp);
4331  if (strlen(s) == 16)
4332  s += 8; /* display only the short keyID */
4333  fprintf(fp, "%*s0x%s", KeyInfoPadding[KIP_SUBKEY], _(KeyInfoPrompts[KIP_SUBKEY]), s);
4334  if (subkey->revoked)
4335  {
4336  putc(' ', fp);
4337  /* L10N: describes a subkey */
4338  fputs(_("[Revoked]"), fp);
4339  }
4340  if (subkey->invalid)
4341  {
4342  putc(' ', fp);
4343  /* L10N: describes a subkey */
4344  fputs(_("[Invalid]"), fp);
4345  }
4346  if (subkey->expired)
4347  {
4348  putc(' ', fp);
4349  /* L10N: describes a subkey */
4350  fputs(_("[Expired]"), fp);
4351  }
4352  if (subkey->disabled)
4353  {
4354  putc(' ', fp);
4355  /* L10N: describes a subkey */
4356  fputs(_("[Disabled]"), fp);
4357  }
4358  putc('\n', fp);
4359 
4360  if (subkey->timestamp > 0)
4361  {
4362  tt = subkey->timestamp;
4363 
4364  mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
4365  fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_FROM],
4366  _(KeyInfoPrompts[KIP_VALID_FROM]), shortbuf);
4367  }
4368