NeoMutt  2019-12-07-168-gc45f47
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 "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "crypt_gpgme.h"
#include "lib.h"
#include "alias.h"
#include "crypt.h"
#include "format_flags.h"
#include "globals.h"
#include "handler.h"
#include "hook.h"
#include "keymap.h"
#include "mutt_attach.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 "sendlib.h"
#include "sort.h"
#include "state.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, unsigned long 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::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, int 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/.

crypt_gpgme.c - GPGME based crypto operations

Definition in file crypt_gpgme.c.

Macro Definition Documentation

◆ CRYPT_KV_VALID

#define CRYPT_KV_VALID   (1 << 0)

Definition at line 88 of file crypt_gpgme.c.

◆ CRYPT_KV_ADDR

#define CRYPT_KV_ADDR   (1 << 1)

Definition at line 89 of file crypt_gpgme.c.

◆ CRYPT_KV_STRING

#define CRYPT_KV_STRING   (1 << 2)

Definition at line 90 of file crypt_gpgme.c.

◆ CRYPT_KV_STRONGID

#define CRYPT_KV_STRONGID   (1 << 3)

Definition at line 91 of file crypt_gpgme.c.

◆ CRYPT_KV_MATCH

#define CRYPT_KV_MATCH   (CRYPT_KV_ADDR | CRYPT_KV_STRING)

Definition at line 92 of file crypt_gpgme.c.

◆ PKA_NOTATION_NAME

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

Definition at line 142 of file crypt_gpgme.c.

◆ _LINE_COMPARE

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

Definition at line 144 of file crypt_gpgme.c.

◆ MESSAGE

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

Definition at line 145 of file crypt_gpgme.c.

◆ SIGNED_MESSAGE

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

Definition at line 146 of file crypt_gpgme.c.

◆ PUBLIC_KEY_BLOCK

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

Definition at line 147 of file crypt_gpgme.c.

◆ BEGIN_PGP_SIGNATURE

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

Definition at line 148 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 154 of file crypt_gpgme.c.

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

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

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

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

196 {
197  return mutt_str_strcmp(notation->name, PKA_NOTATION_NAME) == 0;
198 }
#define PKA_NOTATION_NAME
Definition: crypt_gpgme.c:142
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:638
+ 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 204 of file crypt_gpgme.c.

205 {
206 #if (GPGME_VERSION_NUMBER < 0x010800)
207  /* gpgme_get_ctx_flag is not available in gpgme < 1.8.0. In this case, stay
208  * on the safe side and always redraw. */
209  (void) ctx;
211 #else
212  const char *s = gpgme_get_ctx_flag(ctx, "redraw");
213  if (!s /* flag not known */ || *s /* flag true */)
214  {
216  }
217 #endif
218 }
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 225 of file crypt_gpgme.c.

226 {
227  return (*s >= '0' && *s <= '9');
228 }
+ 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 235 of file crypt_gpgme.c.

236 {
237  return digit(s) || (*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z');
238 }
static int digit(const char *s)
Is the character a number.
Definition: crypt_gpgme.c:225
+ 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 248 of file crypt_gpgme.c.

249 {
250  char *tstr = mutt_mem_malloc(len + 1);
251  memcpy(tstr, buf, len);
252  tstr[len] = 0;
253 
254  /* fromcode "utf-8" is sure, so we don't want
255  * charset-hook corrections: flags must be 0. */
256  mutt_ch_convert_string(&tstr, "utf-8", C_Charset, 0);
257  fputs(tstr, fp);
258  FREE(&tstr);
259 }
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
Definition: charset.c:748
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:54
+ 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 473 of file crypt_gpgme.c.

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

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

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

534 {
535  const char *s = "";
536 
537  if (k->kobj && k->kobj->subkeys)
538  s = k->kobj->subkeys->fpr;
539 
540  return s;
541 }
gpgme_key_t kobj
Definition: crypt_gpgme.c:122
+ 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
ptrOtherwise the long keyid

Definition at line 549 of file crypt_gpgme.c.

550 {
551  const char *s = "????????????????";
552 
553  if (k->kobj && k->kobj->subkeys)
554  {
555  if (k->kobj->subkeys->fpr)
556  s = k->kobj->subkeys->fpr;
557  else
558  s = k->kobj->subkeys->keyid;
559  }
560 
561  return s;
562 }
gpgme_key_t kobj
Definition: crypt_gpgme.c:122
+ 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 571 of file crypt_gpgme.c.

572 {
573  static char buf[3];
574 
575  if (!(flags & KEYFLAG_CANENCRYPT))
576  buf[0] = '-';
577  else if (flags & KEYFLAG_PREFER_SIGNING)
578  buf[0] = '.';
579  else
580  buf[0] = 'e';
581 
582  if (!(flags & KEYFLAG_CANSIGN))
583  buf[1] = '-';
584  else if (flags & KEYFLAG_PREFER_ENCRYPTION)
585  buf[1] = '.';
586  else
587  buf[1] = 's';
588 
589  buf[2] = '\0';
590 
591  return buf;
592 }
#define KEYFLAG_PREFER_ENCRYPTION
Key&#39;s owner prefers encryption.
Definition: lib.h:181
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition: lib.h:173
#define KEYFLAG_PREFER_SIGNING
Key&#39;s owner prefers signing.
Definition: lib.h:182
#define KEYFLAG_CANSIGN
Key is suitable for signing.
Definition: lib.h:172
+ 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 601 of file crypt_gpgme.c.

602 {
603  if (flags & KEYFLAG_REVOKED)
604  return 'R';
605  if (flags & KEYFLAG_EXPIRED)
606  return 'X';
607  if (flags & KEYFLAG_DISABLED)
608  return 'd';
609  if (flags & KEYFLAG_CRITICAL)
610  return 'c';
611 
612  return ' ';
613 }
#define KEYFLAG_EXPIRED
Key is expired.
Definition: lib.h:176
#define KEYFLAG_DISABLED
Key is marked disabled.
Definition: lib.h:178
#define KEYFLAG_CRITICAL
Key is marked critical.
Definition: lib.h:180
#define KEYFLAG_REVOKED
Key is revoked.
Definition: lib.h:177
+ 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 620 of file crypt_gpgme.c.

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

640 {
641  if (!keylist)
642  return;
643 
644  struct CryptKeyInfo *k = NULL;
645 
646  while (*keylist)
647  {
648  k = *keylist;
649  *keylist = (*keylist)->next;
650 
651  gpgme_key_unref(k->kobj);
652  FREE(&k);
653  }
654 }
struct CryptKeyInfo * next
Definition: crypt_gpgme.c:121
A stored PGP key.
Definition: crypt_gpgme.c:119
gpgme_key_t kobj
Definition: crypt_gpgme.c:122
#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 661 of file crypt_gpgme.c.

662 {
663  if (k->flags & KEYFLAG_CANTUSE)
664  return false;
665  return true;
666 }
#define KEYFLAG_CANTUSE
Definition: lib.h:184
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.c:125
+ 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 673 of file crypt_gpgme.c.

674 {
675  if (!key)
676  return false;
677 
678  bool is_strong = false;
679 
680  if ((key->flags & KEYFLAG_ISX509))
681  return true;
682 
683  switch (key->validity)
684  {
685  case GPGME_VALIDITY_MARGINAL:
686  case GPGME_VALIDITY_NEVER:
687  case GPGME_VALIDITY_UNDEFINED:
688  case GPGME_VALIDITY_UNKNOWN:
689  is_strong = false;
690  break;
691 
692  case GPGME_VALIDITY_FULL:
693  case GPGME_VALIDITY_ULTIMATE:
694  is_strong = true;
695  break;
696  }
697 
698  return is_strong;
699 }
#define KEYFLAG_ISX509
Key is an X.509 key.
Definition: lib.h:174
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.c:125
gpgme_validity_t validity
uid validity (cached for convenience)
Definition: crypt_gpgme.c:126
+ 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 708 of file crypt_gpgme.c.

709 {
710  if (!key)
711  return 0;
712 
713  return !(key->flags & KEYFLAG_CANTUSE);
714 }
#define KEYFLAG_CANTUSE
Definition: lib.h:184
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.c:125
+ 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 726 of file crypt_gpgme.c.

728 {
729  int rc = 0;
730 
731  if (crypt_id_is_valid(key))
732  rc |= CRYPT_KV_VALID;
733 
734  if (crypt_id_is_strong(key))
735  rc |= CRYPT_KV_STRONGID;
736 
737  if (addr && u_addr)
738  {
739  if (addr->mailbox && u_addr->mailbox &&
740  (mutt_str_strcasecmp(addr->mailbox, u_addr->mailbox) == 0))
741  {
742  rc |= CRYPT_KV_ADDR;
743  }
744 
745  if (addr->personal && u_addr->personal &&
746  (mutt_str_strcasecmp(addr->personal, u_addr->personal) == 0))
747  {
748  rc |= CRYPT_KV_STRING;
749  }
750  }
751 
752  return rc;
753 }
static int crypt_id_is_valid(struct CryptKeyInfo *key)
Is key ID valid.
Definition: crypt_gpgme.c:708
#define CRYPT_KV_STRONGID
Definition: crypt_gpgme.c:91
#define CRYPT_KV_ADDR
Definition: crypt_gpgme.c:89
char * mailbox
Mailbox and host address.
Definition: address.h:37
#define CRYPT_KV_STRING
Definition: crypt_gpgme.c:90
char * personal
Real name of address.
Definition: address.h:36
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
#define CRYPT_KV_VALID
Definition: crypt_gpgme.c:88
static bool crypt_id_is_strong(struct CryptKeyInfo *key)
Is the key strong.
Definition: crypt_gpgme.c:673
+ 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 760 of file crypt_gpgme.c.

761 {
762  gpgme_ctx_t ctx = NULL;
763 
764  gpgme_error_t err = gpgme_new(&ctx);
765 
766 #ifdef USE_AUTOCRYPT
767  if (!err && OptAutocryptGpgme)
768  err = gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_OpenPGP, NULL, C_AutocryptDir);
769 #endif
770 
771  if (err != 0)
772  {
773  mutt_error(_("error creating gpgme context: %s"), gpgme_strerror(err));
774  mutt_exit(1);
775  }
776 
777  if (for_smime)
778  {
779  err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS);
780  if (err != 0)
781  {
782  mutt_error(_("error enabling CMS protocol: %s"), gpgme_strerror(err));
783  mutt_exit(1);
784  }
785  }
786 
787  return ctx;
788 }
#define _(a)
Definition: message.h:28
WHERE bool OptAutocryptGpgme
(pseudo) use Autocrypt context inside ncrypt/crypt_gpgme.c
Definition: options.h:32
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:143
#define mutt_error(...)
Definition: logging.h:84
WHERE char * C_AutocryptDir
Config: Location of autocrypt files, including the GPG keyring and sqlite database.
Definition: globals.h:102
+ 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 798 of file crypt_gpgme.c.

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

855 {
856  int err = 0;
857  gpgme_data_t data = NULL;
858 
859  struct Buffer *tempfile = mutt_buffer_pool_get();
860  mutt_buffer_mktemp(tempfile);
861  FILE *fp_tmp = mutt_file_fopen(mutt_b2s(tempfile), "w+");
862  if (!fp_tmp)
863  {
864  mutt_perror(mutt_b2s(tempfile));
865  goto cleanup;
866  }
867 
868  mutt_write_mime_header(a, fp_tmp);
869  fputc('\n', fp_tmp);
870  mutt_write_mime_body(a, fp_tmp);
871 
872  if (convert)
873  {
874  int c, hadcr = 0;
875  unsigned char buf[1];
876 
877  data = create_gpgme_data();
878  rewind(fp_tmp);
879  while ((c = fgetc(fp_tmp)) != EOF)
880  {
881  if (c == '\r')
882  hadcr = 1;
883  else
884  {
885  if ((c == '\n') && !hadcr)
886  {
887  buf[0] = '\r';
888  gpgme_data_write(data, buf, 1);
889  }
890 
891  hadcr = 0;
892  }
893  /* FIXME: This is quite suboptimal */
894  buf[0] = c;
895  gpgme_data_write(data, buf, 1);
896  }
897  mutt_file_fclose(&fp_tmp);
898  gpgme_data_seek(data, 0, SEEK_SET);
899  }
900  else
901  {
902  mutt_file_fclose(&fp_tmp);
903  err = gpgme_data_new_from_file(&data, mutt_b2s(tempfile), 1);
904  if (err != 0)
905  {
906  mutt_error(_("error allocating data object: %s"), gpgme_strerror(err));
907  gpgme_data_release(data);
908  data = NULL;
909  /* fall through to unlink the tempfile */
910  }
911  }
912  unlink(mutt_b2s(tempfile));
913 
914 cleanup:
915  mutt_buffer_pool_release(&tempfile);
916  return data;
917 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:81
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
#define mutt_b2s(buf)
Definition: buffer.h:41
int mutt_write_mime_body(struct Body *a, FILE *fp)
Write a MIME part.
Definition: sendlib.c:554
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:798
#define mutt_error(...)
Definition: logging.h:84
int mutt_write_mime_header(struct Body *a, FILE *fp)
Create a MIME header.
Definition: sendlib.c:395
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:585
+ 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 926 of file crypt_gpgme.c.

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

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

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

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

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

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

1234 {
1235  char *signid = NULL;
1236 
1237  if (for_smime)
1239 #ifdef USE_AUTOCRYPT
1240  else if (OptAutocryptGpgme)
1241  signid = AutocryptSignAs;
1242 #endif
1243  else
1245 
1246  /* Try getting the signing key from config entries */
1247  if (signid && set_signer_from_address(ctx, signid, for_smime))
1248  {
1249  return 0;
1250  }
1251 
1252  /* Try getting the signing key from the From line */
1253  if (al)
1254  {
1255  struct Address *a;
1256  TAILQ_FOREACH(a, al, entries)
1257  {
1258  if (a->mailbox && set_signer_from_address(ctx, a->mailbox, for_smime))
1259  {
1260  return 0;
1261  }
1262  }
1263  }
1264 
1265  return (!signid && !al) ? 0 : -1;
1266 }
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
WHERE char * C_SmimeDefaultKey
Config: Default key for SMIME operations.
Definition: globals.h:163
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:1175
An email address.
Definition: address.h:34
WHERE bool OptAutocryptGpgme
(pseudo) use Autocrypt context inside ncrypt/crypt_gpgme.c
Definition: options.h:32
char * mailbox
Mailbox and host address.
Definition: address.h:37
WHERE char * C_PgpDefaultKey
Config: Default key to use for PGP operations.
Definition: globals.h:159
WHERE char * C_PgpSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:160
WHERE char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:164
WHERE char * AutocryptSignAs
Autocrypt Key id to sign as.
Definition: globals.h:87
+ 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 1273 of file crypt_gpgme.c.

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

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

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

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

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

1557 {
1558  return sign_message(a, from, false);
1559 }
static struct Body * sign_message(struct Body *a, const struct AddressList *from, bool use_smime)
Sign a message.
Definition: crypt_gpgme.c:1435
+ 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 1564 of file crypt_gpgme.c.

1565 {
1566  return sign_message(a, from, true);
1567 }
static struct Body * sign_message(struct Body *a, const struct AddressList *from, bool use_smime)
Sign a message.
Definition: crypt_gpgme.c:1435
+ 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 1572 of file crypt_gpgme.c.

1574 {
1575  if (sign)
1577  gpgme_data_t plaintext = body_to_data_object(a, false);
1578  if (!plaintext)
1579  return NULL;
1580 
1581  char *outfile = encrypt_gpgme_object(plaintext, keylist, false, sign, from);
1582  gpgme_data_release(plaintext);
1583  if (!outfile)
1584  return NULL;
1585 
1586  struct Body *t = mutt_body_new();
1587  t->type = TYPE_MULTIPART;
1588  t->subtype = mutt_str_strdup("encrypted");
1589  t->encoding = ENC_7BIT;
1590  t->use_disp = false;
1591  t->disposition = DISP_INLINE;
1592 
1594  mutt_param_set(&t->parameter, "protocol", "application/pgp-encrypted");
1595 
1596  t->parts = mutt_body_new();
1597  t->parts->type = TYPE_APPLICATION;
1598  t->parts->subtype = mutt_str_strdup("pgp-encrypted");
1599  t->parts->encoding = ENC_7BIT;
1600 
1601  t->parts->next = mutt_body_new();
1603  t->parts->next->subtype = mutt_str_strdup("octet-stream");
1604  t->parts->next->encoding = ENC_7BIT;
1605  t->parts->next->filename = outfile;
1606  t->parts->next->use_disp = true;
1608  t->parts->next->unlink = true; /* delete after sending the message */
1609  t->parts->next->d_filename = mutt_str_strdup("msg.asc"); /* non pgp/mime
1610  can save */
1611 
1612  return t;
1613 }
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:814
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:1293
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
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: sendlib.c:637
Content is attached.
Definition: mime.h:63
unsigned int encoding
content-transfer-encoding
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:854
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
unsigned int type
content-type primary type
Definition: body.h:65
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
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 1618 of file crypt_gpgme.c.

1619 {
1620  /* OpenSSL converts line endings to crlf when encrypting. Some clients
1621  * depend on this for signed+encrypted messages: they do not convert line
1622  * endings between decrypting and checking the signature. */
1623  gpgme_data_t plaintext = body_to_data_object(a, true);
1624  if (!plaintext)
1625  return NULL;
1626 
1627  char *outfile = encrypt_gpgme_object(plaintext, keylist, true, false, NULL);
1628  gpgme_data_release(plaintext);
1629  if (!outfile)
1630  return NULL;
1631 
1632  struct Body *t = mutt_body_new();
1633  t->type = TYPE_APPLICATION;
1634  t->subtype = mutt_str_strdup("pkcs7-mime");
1635  mutt_param_set(&t->parameter, "name", "smime.p7m");
1636  mutt_param_set(&t->parameter, "smime-type", "enveloped-data");
1637  t->encoding = ENC_BASE64; /* The output of OpenSSL SHOULD be binary */
1638  t->use_disp = true;
1639  t->disposition = DISP_ATTACH;
1640  t->d_filename = mutt_str_strdup("smime.p7m");
1641  t->filename = outfile;
1642  t->unlink = true; /* delete after sending the message */
1643  t->parts = 0;
1644  t->next = 0;
1645 
1646  return t;
1647 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
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:1293
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
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
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:854
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
unsigned int type
content-type primary type
Definition: body.h:65
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
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 1662 of file crypt_gpgme.c.

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

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

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

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

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

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

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

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

2229 {
2230  if (!a || !s || !fp_out)
2231  return NULL;
2232 
2233  struct stat info;
2234  struct Body *tattach = NULL;
2235  int err = 0;
2236  gpgme_data_t ciphertext = NULL, plaintext = NULL;
2237  bool maybe_signed = false;
2238  bool anywarn = false;
2239  int sig_stat = 0;
2240 
2241  if (r_is_signed)
2242  *r_is_signed = 0;
2243 
2244  gpgme_ctx_t ctx = create_gpgme_context(is_smime);
2245 
2246 restart:
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  /* Abort right away and silently.
2278  * Autocrypt will retry on the normal keyring. */
2279  if (OptAutocryptGpgme)
2280  goto cleanup;
2281  if (is_smime && !maybe_signed && (gpg_err_code(err) == GPG_ERR_NO_DATA))
2282  {
2283  /* Check whether this might be a signed message despite what the mime
2284  * header told us. Retry then. gpgsm returns the error information
2285  * "unsupported Algorithm '?'" but gpgme will not store this unknown
2286  * algorithm, thus we test that it has not been set. */
2287  gpgme_decrypt_result_t result;
2288 
2289  result = gpgme_op_decrypt_result(ctx);
2290  if (!result->unsupported_algorithm)
2291  {
2292  maybe_signed = true;
2293  gpgme_data_release(plaintext);
2294  plaintext = NULL;
2295  /* gpgsm ends the session after an error; restart it */
2296  gpgme_release(ctx);
2297  ctx = NULL;
2298  goto restart;
2299  }
2300  }
2301  redraw_if_needed(ctx);
2302  if ((s->flags & MUTT_DISPLAY))
2303  {
2304  char buf[200];
2305 
2306  snprintf(buf, sizeof(buf) - 1,
2307  _("[-- Error: decryption failed: %s --]\n\n"), gpgme_strerror(err));
2308  state_attach_puts(s, buf);
2309  }
2310  goto cleanup;
2311  }
2312  redraw_if_needed(ctx);
2313 
2314  /* Read the output from GPGME, and make sure to change CRLF to LF,
2315  * otherwise read_mime_header has a hard time parsing the message. */
2316  if (data_object_to_stream(plaintext, fp_out))
2317  {
2318  goto cleanup;
2319  }
2320  gpgme_data_release(plaintext);
2321  plaintext = NULL;
2322 
2323  if (sig_stat)
2324  {
2325  int res, idx;
2326  int anybad = 0;
2327 
2328  if (r_is_signed)
2329  *r_is_signed = -1; /* A signature exists. */
2330 
2331  if ((s->flags & MUTT_DISPLAY))
2332  {
2333  state_attach_puts(s, _("[-- Begin signature information --]\n"));
2334  }
2335  for (idx = 0; (res = show_one_sig_status(ctx, idx, s)) != -1; idx++)
2336  {
2337  if (res == 1)
2338  anybad = 1;
2339  else if (res == 2)
2340  anywarn = true;
2341  }
2342  if (!anybad && idx && r_is_signed && *r_is_signed)
2343  *r_is_signed = anywarn ? 2 : 1; /* Good signature. */
2344 
2345  if ((s->flags & MUTT_DISPLAY))
2346  {
2347  state_attach_puts(s, _("[-- End signature information --]\n\n"));
2348  }
2349  }
2350  gpgme_release(ctx);
2351  ctx = NULL;
2352 
2353  fflush(fp_out);
2354  rewind(fp_out);
2355  tattach = mutt_read_mime_header(fp_out, 0);
2356  if (tattach)
2357  {
2358  /* Need to set the length of this body part. */
2359  fstat(fileno(fp_out), &info);
2360  tattach->length = info.st_size - tattach->offset;
2361 
2362  tattach->warnsig = anywarn;
2363 
2364  /* See if we need to recurse on this MIME part. */
2365  mutt_parse_part(fp_out, tattach);
2366  }
2367 
2368 cleanup:
2369  gpgme_data_release(ciphertext);
2370  gpgme_data_release(plaintext);
2371  gpgme_release(ctx);
2372 
2373  return tattach;
2374 }
#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:926
static int data_object_to_stream(gpgme_data_t data, FILE *fp)
Write a GPGME data object to a file.
Definition: crypt_gpgme.c:947
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:32
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:760
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:1406
static gpgme_data_t create_gpgme_data(void)
Create a new GPGME data object.
Definition: crypt_gpgme.c:798
static void redraw_if_needed(gpgme_ctx_t ctx)
accommodate for a redraw if needed
Definition: crypt_gpgme.c:204
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1292
static int show_one_sig_status(gpgme_ctx_t ctx, int idx, struct State *s)
Show information about one signature.
Definition: crypt_gpgme.c:1956
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 2379 of file crypt_gpgme.c.

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

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

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

2728 {
2729  if (mutt_str_strncmp(a, b, n) == 0)
2730  {
2731  /* at this point we know that 'b' is at least 'n' chars long */
2732  if ((b[n] == '\n') || ((b[n] == '\r') && (b[n + 1] == '\n')))
2733  return true;
2734  }
2735  return false;
2736 }
int mutt_str_strncmp(const char *a, const char *b, size_t l)
Compare two strings (to a maximum), safely.
Definition: string.c:665
+ 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 2745 of file crypt_gpgme.c.

2746 {
2747  char buf[8192];
2748  int rv = 0;
2749 
2750  bool sgn = false;
2751  bool enc = false;
2752 
2753  if (b->type != TYPE_TEXT)
2754  return 0;
2755 
2756  struct Buffer *tempfile = mutt_buffer_pool_get();
2757  mutt_buffer_mktemp(tempfile);
2758  if (mutt_decode_save_attachment(fp, b, mutt_b2s(tempfile), 0, MUTT_SAVE_NO_FLAGS) != 0)
2759  {
2760  unlink(mutt_b2s(tempfile));
2761  goto cleanup;
2762  }
2763 
2764  FILE *fp_tmp = fopen(mutt_b2s(tempfile), "r");
2765  if (!fp_tmp)
2766  {
2767  unlink(mutt_b2s(tempfile));
2768  goto cleanup;
2769  }
2770 
2771  while (fgets(buf, sizeof(buf), fp_tmp))
2772  {
2773  size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ", CASE_MATCH);
2774  if (plen != 0)
2775  {
2776  if (MESSAGE(buf + plen))
2777  {
2778  enc = true;
2779  break;
2780  }
2781  else if (SIGNED_MESSAGE(buf + plen))
2782  {
2783  sgn = true;
2784  break;
2785  }
2786  }
2787  }
2788  mutt_file_fclose(&fp_tmp);
2789  unlink(mutt_b2s(tempfile));
2790 
2791  if (!enc && !sgn)
2792  goto cleanup;
2793 
2794  /* fix the content type */
2795 
2796  mutt_param_set(&b->parameter, "format", "fixed");
2797  mutt_param_set(&b->parameter, "x-action", enc ? "pgp-encrypted" : "pgp-signed");
2798 
2799  rv = 1;
2800 
2801 cleanup:
2802  mutt_buffer_pool_release(&tempfile);
2803  return rv;
2804 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:81
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:146
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
Match case when comparing strings.
Definition: string2.h:67
#define MESSAGE(_y)
Definition: crypt_gpgme.c:145
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
#define mutt_b2s(buf)
Definition: buffer.h:41
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
Definition: body.h:65
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
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 2809 of file crypt_gpgme.c.

2810 {
2811  int rc = 0;
2812  for (; b; b = b->next)
2813  {
2814  if (!just_one && is_multipart(b))
2815  rc = (pgp_gpgme_check_traditional(fp, b->parts, false) || rc);
2816  else if (b->type == TYPE_TEXT)
2817  {
2819  if (r)
2820  rc = (rc || r);
2821  else
2822  rc = (pgp_check_traditional_one_body(fp, b) || rc);
2823  }
2824 
2825  if (just_one)
2826  break;
2827  }
2828  return rc;
2829 }
int pgp_gpgme_check_traditional(FILE *fp, struct Body *b, bool just_one)
Implements CryptModuleSpecs::pgp_check_traditional()
Definition: crypt_gpgme.c:2809
#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:121
static int pgp_check_traditional_one_body(FILE *fp, struct Body *b)
Check one inline PGP body part.
Definition: crypt_gpgme.c:2745
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:563
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
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 2834 of file crypt_gpgme.c.

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

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

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

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

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

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

Definition at line 3645 of file crypt_gpgme.c.

3646 {
3647  struct CryptKeyInfo **key_table = menu->data;
3648  struct CryptEntry entry;
3649 
3650  entry.key = key_table[line];
3651  entry.num = line + 1;
3652 
3653  mutt_expando_format(buf, buflen, 0, menu->win_index->state.cols,
3655  (unsigned long) &entry, MUTT_FORMAT_ARROWCURSOR);
3656 }
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, unsigned long data, MuttFormatFlags flags)
Expand expandos (x) in a string.
Definition: muttlib.c:876
#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, unsigned long data, MuttFormatFlags flags)
Format a string for the key selection menu - Implements format_t.
Definition: crypt_gpgme.c:3437
A stored PGP key.
Definition: crypt_gpgme.c:119
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:56
const char * line
Definition: common.c:36
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:91
WHERE char * C_PgpEntryFormat
Config: printf-like format string for the PGP key selection menu.
Definition: globals.h:161
An entry in the Select-Key menu.
Definition: crypt_gpgme.c:132
struct CryptKeyInfo * key
Definition: crypt_gpgme.c:135
void * data
Extra data for the current menu.
Definition: mutt_menu.h:86
struct MuttWindow * win_index
Definition: mutt_menu.h:95
+ 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 3666 of file crypt_gpgme.c.

3667 {
3668  struct CryptKeyInfo **s = (struct CryptKeyInfo **) a;
3669  struct CryptKeyInfo **t = (struct CryptKeyInfo **) b;
3670  int r;
3671 
3672  r = mutt_str_strcasecmp((*s)->uid, (*t)->uid);
3673  if (r != 0)
3674  return r > 0;
3676 }
A stored PGP key.
Definition: crypt_gpgme.c:119
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
static const char * crypt_fpr_or_lkeyid(struct CryptKeyInfo *k)
Find the fingerprint of a key.
Definition: crypt_gpgme.c:549
+ 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 3686 of file crypt_gpgme.c.

3687 {
3688  return (C_PgpSortKeys & SORT_REVERSE) ? !compare_key_address(a, b) :
3689  compare_key_address(a, b);
3690 }
static int compare_key_address(const void *a, const void *b)
Compare Key addresses and IDs for sorting.
Definition: crypt_gpgme.c:3666
WHERE short C_PgpSortKeys
Config: Sort order for PGP keys.
Definition: sort.h:62
#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 3700 of file crypt_gpgme.c.

3701 {
3702  struct CryptKeyInfo **s = (struct CryptKeyInfo **) a;
3703  struct CryptKeyInfo **t = (struct CryptKeyInfo **) b;
3704  int r;
3705 
3707  if (r != 0)
3708  return r > 0;
3709  return mutt_str_strcasecmp((*s)->uid, (*t)->uid) > 0;
3710 }
A stored PGP key.
Definition: crypt_gpgme.c:119
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
static const char * crypt_fpr_or_lkeyid(struct CryptKeyInfo *k)
Find the fingerprint of a key.
Definition: crypt_gpgme.c:549
+ 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 3720 of file crypt_gpgme.c.

3721 {
3722  return (C_PgpSortKeys & SORT_REVERSE) ? !compare_keyid(a, b) : compare_keyid(a, b);
3723 }
static int compare_keyid(const void *a, const void *b)
Compare Key IDs and addresses for sorting.
Definition: crypt_gpgme.c:3700
WHERE short C_PgpSortKeys
Config: Sort order for PGP keys.
Definition: sort.h:62
#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 3733 of file crypt_gpgme.c.

3734 {
3735  struct CryptKeyInfo **s = (struct CryptKeyInfo **) a;
3736  struct CryptKeyInfo **t = (struct CryptKeyInfo **) b;
3737  unsigned long ts = 0, tt = 0;
3738 
3739  if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
3740  ts = (*s)->kobj->subkeys->timestamp;
3741  if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
3742  tt = (*t)->kobj->subkeys->timestamp;
3743 
3744  if (ts > tt)
3745  return 1;
3746  if (ts < tt)
3747  return 0;
3748 
3749  return mutt_str_strcasecmp((*s)->uid, (*t)->uid) > 0;
3750 }
A stored PGP key.
Definition: crypt_gpgme.c:119
gpgme_key_t kobj
Definition: crypt_gpgme.c:122
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
+ 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 3760 of file crypt_gpgme.c.

3761 {
3762  return (C_PgpSortKeys & SORT_REVERSE) ? !compare_key_date(a, b) :
3763  compare_key_date(a, b);
3764 }
WHERE short C_PgpSortKeys
Config: Sort order for PGP keys.
Definition: sort.h:62
static int compare_key_date(const void *a, const void *b)
Compare Key creation dates and addresses for sorting.
Definition: crypt_gpgme.c:3733
#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 3777 of file crypt_gpgme.c.

3778 {
3779  struct CryptKeyInfo **s = (struct CryptKeyInfo **) a;
3780  struct CryptKeyInfo **t = (struct CryptKeyInfo **) b;
3781  unsigned long ts = 0, tt = 0;
3782  int r;
3783 
3784  r = (((*s)->flags & KEYFLAG_RESTRICTIONS) - ((*t)->flags & KEYFLAG_RESTRICTIONS));
3785  if (r != 0)
3786  return r > 0;
3787 
3788  ts = (*s)->validity;
3789  tt = (*t)->validity;
3790  r = (tt - ts);
3791  if (r != 0)
3792  return r < 0;
3793 
3794  if ((*s)->kobj->subkeys)
3795  ts = (*s)->kobj->subkeys->length;
3796  if ((*t)->kobj->subkeys)
3797  tt = (*t)->kobj->subkeys->length;
3798  if (ts != tt)
3799  return ts > tt;
3800 
3801  if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
3802  ts = (*s)->kobj->subkeys->timestamp;
3803  if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
3804  tt = (*t)->kobj->subkeys->timestamp;
3805  if (ts > tt)
3806  return 1;
3807  if (ts < tt)
3808  return 0;
3809 
3810  r = mutt_str_strcasecmp((*s)->uid, (*t)->uid);
3811  if (r != 0)
3812  return r > 0;
3814 }
A stored PGP key.
Definition: crypt_gpgme.c:119
#define KEYFLAG_RESTRICTIONS
Definition: lib.h:185
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
static const char * crypt_fpr_or_lkeyid(struct CryptKeyInfo *k)
Find the fingerprint of a key.
Definition: crypt_gpgme.c:549
gpgme_validity_t validity
uid validity (cached for convenience)
Definition: crypt_gpgme.c:126
+ 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 3824 of file crypt_gpgme.c.

3825 {
3826  return (C_PgpSortKeys & SORT_REVERSE) ? !compare_key_trust(a, b) :
3827  compare_key_trust(a, b);
3828 }
WHERE short C_PgpSortKeys
Config: Sort order for PGP keys.
Definition: sort.h:62
static int compare_key_trust(const void *a, const void *b)
Compare the trust of keys for sorting.
Definition: crypt_gpgme.c:3777
#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 3840 of file crypt_gpgme.c.

3841 {
3842  bool any = false;
3843 
3844  for (; dn->key; dn++)
3845  {
3846  if (strcmp(dn->key, key) == 0)
3847  {
3848  if (any)
3849  fputs(" + ", fp);
3850  print_utf8(fp, dn->value, strlen(dn->value));
3851  any = true;
3852  }
3853  }
3854  return any;
3855 }
char * key
Definition: crypt_gpgme.c:110
static void print_utf8(FILE *fp, const char *buf, size_t len)
Write a UTF-8 string to a file.
Definition: crypt_gpgme.c:248
char * value
Definition: crypt_gpgme.c:111
+ 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 3862 of file crypt_gpgme.c.

3863 {
3864  static const char *const stdpart[] = {
3865  "CN", "OU", "O", "STREET", "L", "ST", "C", NULL,
3866  };
3867  bool any = false;
3868  bool any2 = false;
3869 
3870  for (int i = 0; stdpart[i]; i++)
3871  {
3872  if (any)
3873  fputs(", ", fp);
3874  any = print_dn_part(fp, dn, stdpart[i]);
3875  }
3876  /* now print the rest without any specific ordering */
3877  for (; dn->key; dn++)
3878  {
3879  int i;
3880  for (i = 0; stdpart[i]; i++)
3881  {
3882  if (strcmp(dn->key, stdpart[i]) == 0)
3883  break;
3884  }
3885  if (!stdpart[i])
3886  {
3887  if (any)
3888  fputs(", ", fp);
3889  if (!any2)
3890  fputs("(", fp);
3891  any = print_dn_part(fp, dn, dn->key);
3892  any2 = true;
3893  }
3894  }
3895  if (any2)
3896  fputs(")", fp);
3897 }
static bool print_dn_part(FILE *fp, struct DnArray *dn, const char *key)
Print the X.500 Distinguished Name.
Definition: crypt_gpgme.c:3840
char * key
Definition: crypt_gpgme.c:110
+ 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 3907 of file crypt_gpgme.c.

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

4005 {
4006  struct DnArray *array = NULL;
4007  size_t arrayidx, arraysize;
4008 
4009  arraysize = 7; /* C,ST,L,O,OU,CN,email */
4010  array = mutt_mem_malloc((arraysize + 1) * sizeof(*array));
4011  arrayidx = 0;
4012  while (*str)
4013  {
4014  while (str[0] == ' ')
4015  str++;
4016  if (str[0] == '\0')
4017  break; /* ready */
4018  if (arrayidx >= arraysize)
4019  {
4020  /* neomutt lacks a real mutt_mem_realloc - so we need to copy */
4021  arraysize += 5;
4022  struct DnArray *a2 = mutt_mem_malloc((arraysize + 1) * sizeof(*array));
4023  for (int i = 0; i < arrayidx; i++)
4024  {
4025  a2[i].key = array[i].key;
4026  a2[i].value = array[i].value;
4027  }
4028  FREE(&array);
4029  array = a2;
4030  }
4031  array[arrayidx].key = NULL;
4032  array[arrayidx].value = NULL;
4033  str = parse_dn_part(array + arrayidx, str);
4034  arrayidx++;
4035  if (!str)
4036  goto failure;
4037  while (str[0] == ' ')
4038  str++;
4039  if ((str[0] != '\0') && (str[0] != ',') && (str[0] != ';') && (str[0] != '+'))
4040  goto failure; /* invalid delimiter */
4041  if (str[0] != '\0')
4042  str++;
4043  }
4044  array[arrayidx].key = NULL;
4045  array[arrayidx].value = NULL;
4046  return array;
4047 
4048 failure:
4049  for (int i = 0; i < arrayidx; i++)
4050  {
4051  FREE(&array[i].key);
4052  FREE(&array[i].value);
4053  }
4054  FREE(&array);
4055  return NULL;
4056 }
static const char * parse_dn_part(struct DnArray *array, const char *str)
Parse an RDN.
Definition: crypt_gpgme.c:3907
char * key
Definition: crypt_gpgme.c:110
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:111
An X500 Distinguished Name.
Definition: crypt_gpgme.c:108
+ 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 4066 of file crypt_gpgme.c.

4067 {
4068  const char *s = NULL;
4069 
4070  if (*userid == '<')
4071  {
4072  s = strchr(userid + 1, '>');
4073  if (s)
4074  print_utf8(fp, userid + 1, s - userid - 1);
4075  }
4076  else if (*userid == '(')
4077  fputs(_("[Can't display this user ID (unknown encoding)]"), fp);
4078  else if (!digit_or_letter(userid))
4079  fputs(_("[Can't display this user ID (invalid encoding)]"), fp);
4080  else
4081  {
4082  struct DnArray *dn = parse_dn(userid);
4083  if (!dn)
4084  fputs(_("[Can't display this user ID (invalid DN)]"), fp);
4085  else
4086  {
4087  print_dn_parts(fp, dn);
4088  for (int i = 0; dn[i].key; i++)
4089  {
4090  FREE(&dn[i].key);
4091  FREE(&dn[i].value);
4092  }
4093  FREE(&dn);
4094  }
4095  }
4096 }
#define _(a)
Definition: message.h:28
char * key
Definition: crypt_gpgme.c:110
static int digit_or_letter(const char *s)
Is the character a number or letter.
Definition: crypt_gpgme.c:235
static void print_utf8(FILE *fp, const char *buf, size_t len)
Write a UTF-8 string to a file.
Definition: crypt_gpgme.c:248
static void print_dn_parts(FILE *fp, struct DnArray *dn)
Print all parts of a DN in a standard sequence.
Definition: crypt_gpgme.c:3862
static struct DnArray * parse_dn(const char *str)
Parse a DN and return an array-ized one.
Definition: crypt_gpgme.c:4004
#define FREE(x)
Definition: memory.h:40
char * value
Definition: crypt_gpgme.c:111
An X500 Distinguished Name.
Definition: crypt_gpgme.c:108
+ 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 4104 of file crypt_gpgme.c.

4105 {
4106  unsigned int ret = 0;
4107 
4108  switch (cap)
4109  {
4110  case KEY_CAP_CAN_ENCRYPT:
4111  ret = key->can_encrypt;
4112  if (ret == 0)
4113  {
4114  for (gpgme_subkey_t subkey = key->subkeys; subkey; subkey = subkey->next)
4115  {
4116  ret = subkey->can_encrypt;
4117  if (ret != 0)
4118  break;
4119  }
4120  }
4121  break;
4122  case KEY_CAP_CAN_SIGN:
4123  ret = key->can_sign;
4124  if (ret == 0)
4125  {
4126  for (gpgme_subkey_t subkey = key->subkeys; subkey; subkey = subkey->next)
4127  {
4128  ret = subkey->can_sign;
4129  if (ret != 0)
4130  break;
4131  }
4132  }
4133  break;
4134  case KEY_CAP_CAN_CERTIFY:
4135  ret = key->can_certify;
4136  if (ret == 0)
4137  {
4138  for (gpgme_subkey_t subkey = key->subkeys; subkey; subkey = subkey->next)
4139  {
4140  ret = subkey->can_certify;
4141  if (ret != 0)
4142  break;
4143  }
4144  }
4145  break;
4146  }
4147 
4148  return ret;
4149 }
Key can be used to certify.
Definition: crypt_gpgme.c:158
char * key
Definition: crypt_gpgme.c:110
Key can be used for signing.
Definition: crypt_gpgme.c:157
Key can be used for encryption.
Definition: crypt_gpgme.c:156
+ 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 4156 of file crypt_gpgme.c.

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