NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
dlggpgme.c File Reference

GPGME Key Selection Dialog. More...

#include "config.h"
#include <ctype.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 <time.h>
#include <unistd.h>
#include "private.h"
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "lib.h"
#include "menu/lib.h"
#include "pager/lib.h"
#include "question/lib.h"
#include "crypt_gpgme.h"
#include "format_flags.h"
#include "mutt_logging.h"
#include "muttlib.h"
#include "opcodes.h"
#include "options.h"
#include <libintl.h>
+ Include dependency graph for dlggpgme.c:

Go to the source code of this file.

Data Structures

struct  CryptEntry
 An entry in the Select-Key menu. More...
 
struct  DnArray
 An X500 Distinguished Name. More...
 

Functions

static void print_utf8 (FILE *fp, const char *buf, size_t len)
 Write a UTF-8 string to a file. More...
 
static bool crypt_key_is_valid (struct CryptKeyInfo *k)
 Is the key valid. More...
 
static int crypt_compare_key_address (const void *a, const void *b)
 Compare Key addresses and IDs for sorting. More...
 
static int crypt_compare_address_qsort (const void *a, const void *b)
 Compare the addresses of two keys. More...
 
static int crypt_compare_keyid (const void *a, const void *b)
 Compare Key IDs and addresses for sorting. More...
 
static int crypt_crypt_compare_keyid_qsort (const void *a, const void *b)
 Compare the IDs of two keys. More...
 
static int crypt_compare_key_date (const void *a, const void *b)
 Compare Key creation dates and addresses for sorting. More...
 
static int crypt_compare_date_qsort (const void *a, const void *b)
 Compare the dates of two keys. More...
 
static int crypt_compare_key_trust (const void *a, const void *b)
 Compare the trust of keys for sorting. More...
 
static int crypt_compare_trust_qsort (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 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 * 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 const char * crypt_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the key selection menu - Implements format_t -
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. More...

 
static void crypt_make_entry (struct Menu *menu, char *buf, size_t buflen, int line)
 Format a menu item for the key selection list - Implements Menu::make_entry() -. More...
 
static void gpgme_key_table_free (struct Menu *menu, void **ptr)
 Free the key table - Implements Menu::mdata_free() -. More...
 
static int gpgme_key_config_observer (struct NotifyCallback *nc)
 Notification that a Config Variable has changed - Implements observer_t. More...
 
static int gpgme_key_window_observer (struct NotifyCallback *nc)
 Notification that a Window has changed - Implements observer_t. More...
 
struct CryptKeyInfodlg_select_gpgme_key (struct CryptKeyInfo *keys, struct Address *p, const char *s, unsigned int app, int *forced_valid)
 Get the user to select a key. More...
 

Variables

static const struct Mapping GpgmeHelp []
 Help Bar for the GPGME key selection dialog. More...
 
static const char *const KeyInfoPrompts []
 
int KeyInfoPadding [KIP_MAX] = { 0 }
 

Detailed Description

GPGME Key Selection Dialog.

Authors
  • Richard Russon

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

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

Definition in file dlggpgme.c.

Function Documentation

◆ 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 150 of file dlggpgme.c.

151 {
152  char *tstr = mutt_mem_malloc(len + 1);
153  memcpy(tstr, buf, len);
154  tstr[len] = 0;
155 
156  /* fromcode "utf-8" is sure, so we don't want
157  * charset-hook corrections: flags must be 0. */
158  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
159  mutt_ch_convert_string(&tstr, "utf-8", c_charset, MUTT_ICONV_NO_FLAGS);
160  fputs(tstr, fp);
161  FREE(&tstr);
162 }
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:758
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
Container for Accounts, Notifications.
Definition: neomutt.h:36
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define FREE(x)
Definition: memory.h:40
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ 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
trueKey is valid

Definition at line 169 of file dlggpgme.c.

170 {
171  if (k->flags & KEYFLAG_CANTUSE)
172  return false;
173  return true;
174 }
#define KEYFLAG_CANTUSE
Definition: lib.h:136
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.h:50
+ Here is the caller graph for this function:

◆ crypt_compare_key_address()

static int crypt_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 184 of file dlggpgme.c.

185 {
186  struct CryptKeyInfo **s = (struct CryptKeyInfo **) a;
187  struct CryptKeyInfo **t = (struct CryptKeyInfo **) b;
188 
189  int r = mutt_istr_cmp((*s)->uid, (*t)->uid);
190  if (r != 0)
191  return r > 0;
193 }
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:580
A stored PGP key.
Definition: crypt_gpgme.h:44
const char * crypt_fpr_or_lkeyid(struct CryptKeyInfo *k)
Find the fingerprint of a key.
Definition: crypt_gpgme.c:423
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_compare_address_qsort()

static int crypt_compare_address_qsort ( 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 203 of file dlggpgme.c.

204 {
205  const short c_pgp_sort_keys = cs_subset_sort(NeoMutt->sub, "pgp_sort_keys");
206  return (c_pgp_sort_keys & SORT_REVERSE) ? !crypt_compare_key_address(a, b) :
208 }
Container for Accounts, Notifications.
Definition: neomutt.h:36
static int crypt_compare_key_address(const void *a, const void *b)
Compare Key addresses and IDs for sorting.
Definition: dlggpgme.c:184
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:79
+ 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 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 218 of file dlggpgme.c.

219 {
220  struct CryptKeyInfo **s = (struct CryptKeyInfo **) a;
221  struct CryptKeyInfo **t = (struct CryptKeyInfo **) b;
222 
224  if (r != 0)
225  return r > 0;
226  return mutt_istr_cmp((*s)->uid, (*t)->uid) > 0;
227 }
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:580
A stored PGP key.
Definition: crypt_gpgme.h:44
const char * crypt_fpr_or_lkeyid(struct CryptKeyInfo *k)
Find the fingerprint of a key.
Definition: crypt_gpgme.c:423
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_crypt_compare_keyid_qsort()

static int crypt_crypt_compare_keyid_qsort ( 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 237 of file dlggpgme.c.

238 {
239  const short c_pgp_sort_keys = cs_subset_sort(NeoMutt->sub, "pgp_sort_keys");
240  return (c_pgp_sort_keys & SORT_REVERSE) ? !crypt_compare_keyid(a, b) :
241  crypt_compare_keyid(a, b);
242 }
Container for Accounts, Notifications.
Definition: neomutt.h:36
static int crypt_compare_keyid(const void *a, const void *b)
Compare Key IDs and addresses for sorting.
Definition: dlggpgme.c:218
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:79
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_compare_key_date()

static int crypt_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 252 of file dlggpgme.c.

253 {
254  struct CryptKeyInfo **s = (struct CryptKeyInfo **) a;
255  struct CryptKeyInfo **t = (struct CryptKeyInfo **) b;
256  unsigned long ts = 0, tt = 0;
257 
258  if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
259  ts = (*s)->kobj->subkeys->timestamp;
260  if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
261  tt = (*t)->kobj->subkeys->timestamp;
262 
263  if (ts > tt)
264  return 1;
265  if (ts < tt)
266  return 0;
267 
268  return mutt_istr_cmp((*s)->uid, (*t)->uid) > 0;
269 }
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:580
A stored PGP key.
Definition: crypt_gpgme.h:44
gpgme_key_t kobj
Definition: crypt_gpgme.h:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_compare_date_qsort()

static int crypt_compare_date_qsort ( 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 279 of file dlggpgme.c.

280 {
281  const short c_pgp_sort_keys = cs_subset_sort(NeoMutt->sub, "pgp_sort_keys");
282  return (c_pgp_sort_keys & SORT_REVERSE) ? !crypt_compare_key_date(a, b) :
284 }
Container for Accounts, Notifications.
Definition: neomutt.h:36
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
static int crypt_compare_key_date(const void *a, const void *b)
Compare Key creation dates and addresses for sorting.
Definition: dlggpgme.c:252
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:79
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_compare_key_trust()

static int crypt_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 297 of file dlggpgme.c.

298 {
299  struct CryptKeyInfo **s = (struct CryptKeyInfo **) a;
300  struct CryptKeyInfo **t = (struct CryptKeyInfo **) b;
301  unsigned long ts = 0, tt = 0;
302 
303  int r = (((*s)->flags & KEYFLAG_RESTRICTIONS) - ((*t)->flags & KEYFLAG_RESTRICTIONS));
304  if (r != 0)
305  return r > 0;
306 
307  ts = (*s)->validity;
308  tt = (*t)->validity;
309  r = (tt - ts);
310  if (r != 0)
311  return r < 0;
312 
313  if ((*s)->kobj->subkeys)
314  ts = (*s)->kobj->subkeys->length;
315  if ((*t)->kobj->subkeys)
316  tt = (*t)->kobj->subkeys->length;
317  if (ts != tt)
318  return ts > tt;
319 
320  if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
321  ts = (*s)->kobj->subkeys->timestamp;
322  if ((*t)->kobj->subkeys && ((*t)->kobj->subkeys->timestamp > 0))
323  tt = (*t)->kobj->subkeys->timestamp;
324  if (ts > tt)
325  return 1;
326  if (ts < tt)
327  return 0;
328 
329  r = mutt_istr_cmp((*s)->uid, (*t)->uid);
330  if (r != 0)
331  return r > 0;
332  return mutt_istr_cmp(crypt_fpr_or_lkeyid((*s)), crypt_fpr_or_lkeyid((*t))) > 0;
333 }
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:580
A stored PGP key.
Definition: crypt_gpgme.h:44
const char * crypt_fpr_or_lkeyid(struct CryptKeyInfo *k)
Find the fingerprint of a key.
Definition: crypt_gpgme.c:423
#define KEYFLAG_RESTRICTIONS
Definition: lib.h:137
gpgme_validity_t validity
uid validity (cached for convenience)
Definition: crypt_gpgme.h:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_compare_trust_qsort()

static int crypt_compare_trust_qsort ( 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 343 of file dlggpgme.c.

344 {
345  const short c_pgp_sort_keys = cs_subset_sort(NeoMutt->sub, "pgp_sort_keys");
346  return (c_pgp_sort_keys & SORT_REVERSE) ? !crypt_compare_key_trust(a, b) :
348 }
Container for Accounts, Notifications.
Definition: neomutt.h:36
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
static int crypt_compare_key_trust(const void *a, const void *b)
Compare the trust of keys for sorting.
Definition: dlggpgme.c:297
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:79
+ 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
trueAny 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 360 of file dlggpgme.c.

361 {
362  bool any = false;
363 
364  for (; dn->key; dn++)
365  {
366  if (strcmp(dn->key, key) == 0)
367  {
368  if (any)
369  fputs(" + ", fp);
370  print_utf8(fp, dn->value, strlen(dn->value));
371  any = true;
372  }
373  }
374  return any;
375 }
char * key
Definition: dlggpgme.c:127
static void print_utf8(FILE *fp, const char *buf, size_t len)
Write a UTF-8 string to a file.
Definition: dlggpgme.c:150
char * value
Definition: dlggpgme.c:128
+ 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 382 of file dlggpgme.c.

383 {
384  static const char *const stdpart[] = {
385  "CN", "OU", "O", "STREET", "L", "ST", "C", NULL,
386  };
387  bool any = false;
388  bool any2 = false;
389 
390  for (int i = 0; stdpart[i]; i++)
391  {
392  if (any)
393  fputs(", ", fp);
394  any = print_dn_part(fp, dn, stdpart[i]);
395  }
396  /* now print the rest without any specific ordering */
397  for (; dn->key; dn++)
398  {
399  int i;
400  for (i = 0; stdpart[i]; i++)
401  {
402  if (strcmp(dn->key, stdpart[i]) == 0)
403  break;
404  }
405  if (!stdpart[i])
406  {
407  if (any)
408  fputs(", ", fp);
409  if (!any2)
410  fputs("(", fp);
411  any = print_dn_part(fp, dn, dn->key);
412  any2 = true;
413  }
414  }
415  if (any2)
416  fputs(")", fp);
417 }
static bool print_dn_part(FILE *fp, struct DnArray *dn, const char *key)
Print the X.500 Distinguished Name.
Definition: dlggpgme.c:360
char * key
Definition: dlggpgme.c:127
+ 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 427 of file dlggpgme.c.

428 {
429  const char *s = NULL, *s1 = NULL;
430  size_t n;
431  char *p = NULL;
432 
433  /* parse attribute type */
434  for (s = str + 1; (s[0] != '\0') && (s[0] != '='); s++)
435  ; // do nothing
436 
437  if (s[0] == '\0')
438  return NULL; /* error */
439  n = s - str;
440  if (n == 0)
441  return NULL; /* empty key */
442  array->key = mutt_mem_malloc(n + 1);
443  p = array->key;
444  memcpy(p, str, n); /* fixme: trim trailing spaces */
445  p[n] = 0;
446  str = s + 1;
447 
448  if (*str == '#')
449  { /* hexstring */
450  str++;
451  for (s = str; isxdigit(*s); s++)
452  s++;
453  n = s - str;
454  if ((n == 0) || (n & 1))
455  return NULL; /* empty or odd number of digits */
456  n /= 2;
457  p = mutt_mem_malloc(n + 1);
458  array->value = (char *) p;
459  for (s1 = str; n; s1 += 2, n--)
460  sscanf(s1, "%2hhx", (unsigned char *) p++);
461  *p = '\0';
462  }
463  else
464  { /* regular v3 quoted string */
465  for (n = 0, s = str; *s; s++)
466  {
467  if (*s == '\\')
468  { /* pair */
469  s++;
470  if ((*s == ',') || (*s == '=') || (*s == '+') || (*s == '<') || (*s == '>') ||
471  (*s == '#') || (*s == ';') || (*s == '\\') || (*s == '\"') || (*s == ' '))
472  {
473  n++;
474  }
475  else if (isxdigit(s[0]) && isxdigit(s[1]))
476  {
477  s++;
478  n++;
479  }
480  else
481  return NULL; /* invalid escape sequence */
482  }
483  else if (*s == '\"')
484  return NULL; /* invalid encoding */
485  else if ((*s == ',') || (*s == '=') || (*s == '+') || (*s == '<') ||
486  (*s == '>') || (*s == '#') || (*s == ';'))
487  {
488  break;
489  }
490  else
491  n++;
492  }
493 
494  p = mutt_mem_malloc(n + 1);
495  array->value = (char *) p;
496  for (s = str; n; s++, n--)
497  {
498  if (*s == '\\')
499  {
500  s++;
501  if (isxdigit(*s))
502  {
503  sscanf(s, "%2hhx", (unsigned char *) p++);
504  s++;
505  }
506  else
507  *p++ = *s;
508  }
509  else
510  *p++ = *s;
511  }
512  *p = '\0';
513  }
514  return s;
515 }
char * key
Definition: dlggpgme.c:127
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
char * value
Definition: dlggpgme.c:128
+ 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 525 of file dlggpgme.c.

526 {
527  struct DnArray *array = NULL;
528  size_t arrayidx, arraysize;
529 
530  arraysize = 7; /* C,ST,L,O,OU,CN,email */
531  array = mutt_mem_malloc((arraysize + 1) * sizeof(*array));
532  arrayidx = 0;
533  while (*str)
534  {
535  while (str[0] == ' ')
536  str++;
537  if (str[0] == '\0')
538  break; /* ready */
539  if (arrayidx >= arraysize)
540  {
541  /* neomutt lacks a real mutt_mem_realloc - so we need to copy */
542  arraysize += 5;
543  struct DnArray *a2 = mutt_mem_malloc((arraysize + 1) * sizeof(*array));
544  for (int i = 0; i < arrayidx; i++)
545  {
546  a2[i].key = array[i].key;
547  a2[i].value = array[i].value;
548  }
549  FREE(&array);
550  array = a2;
551  }
552  array[arrayidx].key = NULL;
553  array[arrayidx].value = NULL;
554  str = parse_dn_part(array + arrayidx, str);
555  arrayidx++;
556  if (!str)
557  goto failure;
558  while (str[0] == ' ')
559  str++;
560  if ((str[0] != '\0') && (str[0] != ',') && (str[0] != ';') && (str[0] != '+'))
561  goto failure; /* invalid delimiter */
562  if (str[0] != '\0')
563  str++;
564  }
565  array[arrayidx].key = NULL;
566  array[arrayidx].value = NULL;
567  return array;
568 
569 failure:
570  for (int i = 0; i < arrayidx; i++)
571  {
572  FREE(&array[i].key);
573  FREE(&array[i].value);
574  }
575  FREE(&array);
576  return NULL;
577 }
char * key
Definition: dlggpgme.c:127
static const char * parse_dn_part(struct DnArray *array, const char *str)
Parse an RDN.
Definition: dlggpgme.c:427
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: dlggpgme.c:128
An X500 Distinguished Name.
Definition: dlggpgme.c:125
+ 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 587 of file dlggpgme.c.

588 {
589  const char *s = NULL;
590 
591  if (*userid == '<')
592  {
593  s = strchr(userid + 1, '>');
594  if (s)
595  print_utf8(fp, userid + 1, s - userid - 1);
596  }
597  else if (*userid == '(')
598  fputs(_("[Can't display this user ID (unknown encoding)]"), fp);
599  else if (!isalnum(userid[0]))
600  fputs(_("[Can't display this user ID (invalid encoding)]"), fp);
601  else
602  {
603  struct DnArray *dn = parse_dn(userid);
604  if (!dn)
605  fputs(_("[Can't display this user ID (invalid DN)]"), fp);
606  else
607  {
608  print_dn_parts(fp, dn);
609  for (int i = 0; dn[i].key; i++)
610  {
611  FREE(&dn[i].key);
612  FREE(&dn[i].value);
613  }
614  FREE(&dn);
615  }
616  }
617 }
#define _(a)
Definition: message.h:28
char * key
Definition: dlggpgme.c:127
static struct DnArray * parse_dn(const char *str)
Parse a DN and return an array-ized one.
Definition: dlggpgme.c:525
static void print_utf8(FILE *fp, const char *buf, size_t len)
Write a UTF-8 string to a file.
Definition: dlggpgme.c:150
#define FREE(x)
Definition: memory.h:40
char * value
Definition: dlggpgme.c:128
static void print_dn_parts(FILE *fp, struct DnArray *dn)
Print all parts of a DN in a standard sequence.
Definition: dlggpgme.c:382
An X500 Distinguished Name.
Definition: dlggpgme.c:125
+ Here is the call graph for this function:
+ 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 624 of file dlggpgme.c.

625 {
626  int idx;
627  const char *s = NULL, *s2 = NULL;
628  time_t tt = 0;
629  char shortbuf[128];
630  unsigned long aval = 0;
631  const char *delim = NULL;
632  gpgme_user_id_t uid = NULL;
633  static int max_header_width = 0;
634 
635  if (max_header_width == 0)
636  {
637  for (int i = 0; i < KIP_MAX; i++)
638  {
640  const int width = mutt_strwidth(_(KeyInfoPrompts[i]));
641  if (max_header_width < width)
642  max_header_width = width;
643  KeyInfoPadding[i] -= width;
644  }
645  for (int i = 0; i < KIP_MAX; i++)
646  KeyInfoPadding[i] += max_header_width;
647  }
648 
649  bool is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
650 
651  for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
652  {
653  if (uid->revoked)
654  continue;
655 
656  s = uid->uid;
657  /* L10N: DOTFILL */
658 
659  if (idx == 0)
660  fprintf(fp, "%*s", KeyInfoPadding[KIP_NAME], _(KeyInfoPrompts[KIP_NAME]));
661  else
662  fprintf(fp, "%*s", KeyInfoPadding[KIP_AKA], _(KeyInfoPrompts[KIP_AKA]));
663  if (uid->invalid)
664  {
665  /* L10N: comes after the Name or aka if the key is invalid */
666  fputs(_("[Invalid]"), fp);
667  putc(' ', fp);
668  }
669  if (is_pgp)
670  print_utf8(fp, s, strlen(s));
671  else
673  putc('\n', fp);
674  }
675 
676  if (key->subkeys && (key->subkeys->timestamp > 0))
677  {
678  tt = key->subkeys->timestamp;
679 
680  mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
681  fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_FROM],
682  _(KeyInfoPrompts[KIP_VALID_FROM]), shortbuf);
683  }
684 
685  if (key->subkeys && (key->subkeys->expires > 0))
686  {
687  tt = key->subkeys->expires;
688 
689  mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
690  fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_TO],
691  _(KeyInfoPrompts[KIP_VALID_TO]), shortbuf);
692  }
693 
694  if (key->subkeys)
695  s = gpgme_pubkey_algo_name(key->subkeys->pubkey_algo);
696  else
697  s = "?";
698 
699  s2 = is_pgp ? "PGP" : "X.509";
700 
701  if (key->subkeys)
702  aval = key->subkeys->length;
703 
704  fprintf(fp, "%*s", KeyInfoPadding[KIP_KEY_TYPE], _(KeyInfoPrompts[KIP_KEY_TYPE]));
705  /* L10N: This is printed after "Key Type: " and looks like this: PGP, 2048 bit RSA */
706  fprintf(fp, ngettext("%s, %lu bit %s\n", "%s, %lu bit %s\n", aval), s2, aval, s);
707 
708  fprintf(fp, "%*s", KeyInfoPadding[KIP_KEY_USAGE], _(KeyInfoPrompts[KIP_KEY_USAGE]));
709  delim = "";
710 
712  {
713  /* L10N: value in Key Usage: field */
714  fprintf(fp, "%s%s", delim, _("encryption"));
715  delim = _(", ");
716  }
718  {
719  /* L10N: value in Key Usage: field */
720  fprintf(fp, "%s%s", delim, _("signing"));
721  delim = _(", ");
722  }
724  {
725  /* L10N: value in Key Usage: field */
726  fprintf(fp, "%s%s", delim, _("certification"));
727  }
728  putc('\n', fp);
729 
730  if (key->subkeys)
731  {
732  s = key->subkeys->fpr;
733  fprintf(fp, "%*s", KeyInfoPadding[KIP_FINGERPRINT], _(KeyInfoPrompts[KIP_FINGERPRINT]));
734  if (is_pgp && (strlen(s) == 40))
735  {
736  for (int i = 0; (s[0] != '\0') && (s[1] != '\0') && (s[2] != '\0') &&
737  (s[3] != '\0') && (s[4] != '\0');
738  s += 4, i++)
739  {
740  putc(*s, fp);
741  putc(s[1], fp);
742  putc(s[2], fp);
743  putc(s[3], fp);
744  putc(' ', fp);
745  if (i == 4)
746  putc(' ', fp);
747  }
748  }
749  else
750  {
751  for (int i = 0; (s[0] != '\0') && (s[1] != '\0') && (s[2] != '\0'); s += 2, i++)
752  {
753  putc(*s, fp);
754  putc(s[1], fp);
755  putc(is_pgp ? ' ' : ':', fp);
756  if (is_pgp && (i == 7))
757  putc(' ', fp);
758  }
759  }
760  fprintf(fp, "%s\n", s);
761  }
762 
763  if (key->issuer_serial)
764  {
765  s = key->issuer_serial;
766  if (s)
767  {
768  fprintf(fp, "%*s0x%s\n", KeyInfoPadding[KIP_SERIAL_NO],
769  _(KeyInfoPrompts[KIP_SERIAL_NO]), s);
770  }
771  }
772 
773  if (key->issuer_name)
774  {
775  s = key->issuer_name;
776  if (s)
777  {
778  fprintf(fp, "%*s", KeyInfoPadding[KIP_ISSUED_BY], _(KeyInfoPrompts[KIP_ISSUED_BY]));
780  putc('\n', fp);
781  }
782  }
783 
784  /* For PGP we list all subkeys. */
785  if (is_pgp)
786  {
787  gpgme_subkey_t subkey = NULL;
788 
789  for (idx = 1, subkey = key->subkeys; subkey; idx++, subkey = subkey->next)
790  {
791  s = subkey->keyid;
792 
793  putc('\n', fp);
794  if (strlen(s) == 16)
795  s += 8; /* display only the short keyID */
796  fprintf(fp, "%*s0x%s", KeyInfoPadding[KIP_SUBKEY], _(KeyInfoPrompts[KIP_SUBKEY]), s);
797  if (subkey->revoked)
798  {
799  putc(' ', fp);
800  /* L10N: describes a subkey */
801  fputs(_("[Revoked]"), fp);
802  }
803  if (subkey->invalid)
804  {
805  putc(' ', fp);
806  /* L10N: describes a subkey */
807  fputs(_("[Invalid]"), fp);
808  }
809  if (subkey->expired)
810  {
811  putc(' ', fp);
812  /* L10N: describes a subkey */
813  fputs(_("[Expired]"), fp);
814  }
815  if (subkey->disabled)
816  {
817  putc(' ', fp);
818  /* L10N: describes a subkey */
819  fputs(_("[Disabled]"), fp);
820  }
821  putc('\n', fp);
822 
823  if (subkey->timestamp > 0)
824  {
825  tt = subkey->timestamp;
826 
827  mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
828  fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_FROM],
829  _(KeyInfoPrompts[KIP_VALID_FROM]), shortbuf);
830  }
831 
832  if (subkey->expires > 0)
833  {
834  tt = subkey->expires;
835 
836  mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
837  fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_TO],
838  _(KeyInfoPrompts[KIP_VALID_TO]), shortbuf);
839  }
840 
841  s = gpgme_pubkey_algo_name(subkey->pubkey_algo);
842 
843  aval = subkey->length;
844 
845  fprintf(fp, "%*s", KeyInfoPadding[KIP_KEY_TYPE], _(KeyInfoPrompts[KIP_KEY_TYPE]));
846  /* L10N: This is printed after "Key Type: " and looks like this: PGP, 2048 bit RSA */
847  fprintf(fp, ngettext("%s, %lu bit %s\n", "%s, %lu bit %s\n", aval), "PGP", aval, s);
848 
849  fprintf(fp, "%*s", KeyInfoPadding[KIP_KEY_USAGE], _(KeyInfoPrompts[KIP_KEY_USAGE]));
850  delim = "";
851 
852  if (subkey->can_encrypt)
853  {
854  fprintf(fp, "%s%s", delim, _("encryption"));
855  delim = _(", ");
856  }
857  if (subkey->can_sign)
858  {
859  fprintf(fp, "%s%s", delim, _("signing"));
860  delim = _(", ");
861  }
862  if (subkey->can_certify)
863  {
864  fprintf(fp, "%s%s", delim, _("certification"));
865  }
866  putc('\n', fp);
867  }
868  }
869 }
PGP Key field: Valid To date.
Definition: crypt_gpgme.h:62
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:691
PGP Key field: Serial number.
Definition: crypt_gpgme.h:66
size_t idx
Definition: mailbox.c:257
#define _(a)
Definition: message.h:28
Key can be used for encryption.
Definition: crypt_gpgme.h:77
Key can be used for signing.
Definition: crypt_gpgme.h:78
PGP Key field: Key Usage.
Definition: crypt_gpgme.h:64
char * key
Definition: dlggpgme.c:127
PGP Key field: Key Type.
Definition: crypt_gpgme.h:63
PGP Key field: Valid From date.
Definition: crypt_gpgme.h:61
static const char *const KeyInfoPrompts[]
Definition: dlggpgme.c:131
PGP Key field: Name.
Definition: crypt_gpgme.h:59
static void parse_and_print_user_id(FILE *fp, const char *userid)
Print a nice representation of the userid.
Definition: dlggpgme.c:587
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:983
Key can be used to certify.
Definition: crypt_gpgme.h:79
unsigned int key_check_cap(gpgme_key_t key, enum KeyCap cap)
Check the capabilities of a key.
Definition: crypt_gpgme.c:3256
PGP Key field: Fingerprint.
Definition: crypt_gpgme.h:65
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
static void print_utf8(FILE *fp, const char *buf, size_t len)
Write a UTF-8 string to a file.
Definition: dlggpgme.c:150
PGP Key field: aka (Also Known As)
Definition: crypt_gpgme.h:60
PGP Key field: Issued By.
Definition: crypt_gpgme.h:67
int KeyInfoPadding[KIP_MAX]
Definition: dlggpgme.c:140
PGP Key field: Subkey.
Definition: crypt_gpgme.h:68
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ verify_key()

static void verify_key ( struct CryptKeyInfo key)
static

Show detailed information about the selected key.

Parameters
keyKey to show

Definition at line 875 of file dlggpgme.c.

876 {
877  const char *s = NULL;
878  gpgme_ctx_t listctx = NULL;
879  gpgme_error_t err;
880  gpgme_key_t k = NULL;
881  int maxdepth = 100;
882 
883  struct Buffer tempfile = mutt_buffer_make(PATH_MAX);
884  mutt_buffer_mktemp(&tempfile);
885  FILE *fp = mutt_file_fopen(mutt_buffer_string(&tempfile), "w");
886  if (!fp)
887  {
888  mutt_perror(_("Can't create temporary file"));
889  goto cleanup;
890  }
891  mutt_message(_("Collecting data..."));
892 
893  print_key_info(key->kobj, fp);
894 
895  listctx = create_gpgme_context(key->flags & KEYFLAG_ISX509);
896 
897  k = key->kobj;
898  gpgme_key_ref(k);
899  while ((s = k->chain_id) && k->subkeys && (strcmp(s, k->subkeys->fpr) != 0))
900  {
901  putc('\n', fp);
902  err = gpgme_op_keylist_start(listctx, s, 0);
903  gpgme_key_unref(k);
904  k = NULL;
905  if (err == 0)
906  err = gpgme_op_keylist_next(listctx, &k);
907  if (err != 0)
908  {
909  fprintf(fp, _("Error finding issuer key: %s\n"), gpgme_strerror(err));
910  goto leave;
911  }
912  gpgme_op_keylist_end(listctx);
913 
914  print_key_info(k, fp);
915  if (!--maxdepth)
916  {
917  putc('\n', fp);
918  fputs(_("Error: certification chain too long - stopping here\n"), fp);
919  break;
920  }
921  }
922 
923 leave:
924  gpgme_key_unref(k);
925  gpgme_release(listctx);
926  mutt_file_fclose(&fp);
928  char title[1024];
929  snprintf(title, sizeof(title), _("Key ID: 0x%s"), crypt_keyid(key));
930 
931  struct PagerData pdata = { 0 };
932  struct PagerView pview = { &pdata };
933 
934  pdata.fname = mutt_buffer_string(&tempfile);
935 
936  pview.banner = title;
937  pview.flags = MUTT_PAGER_NO_FLAGS;
938  pview.mode = PAGER_MODE_OTHER;
939 
940  mutt_do_pager(&pview, NULL);
941 
942 cleanup:
943  mutt_buffer_dealloc(&tempfile);
944 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
const char * crypt_keyid(struct CryptKeyInfo *k)
Find the ID for the key.
Definition: crypt_gpgme.c:347
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
Paged view into some data.
Definition: lib.h:154
#define _(a)
Definition: message.h:28
#define KEYFLAG_ISX509
Key is an X.509 key.
Definition: lib.h:126
#define mutt_perror(...)
Definition: logging.h:89
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Data to be displayed by PagerView.
Definition: lib.h:143
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
static int create_gpgme_context(gpgme_ctx_t *ctx)
Create a GPGME context.
Definition: gpgme.c:48
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:112
enum PagerMode mode
Pager mode.
Definition: lib.h:157
#define PATH_MAX
Definition: mutt.h:40
gpgme_key_t kobj
Definition: crypt_gpgme.h:47
int mutt_do_pager(struct PagerView *pview, struct Email *e)
Display some page-able text to the user (help or attachment)
Definition: do_pager.c:120
PagerFlags flags
Additional settings to tweak pager&#39;s function.
Definition: lib.h:158
static void print_key_info(gpgme_key_t key, FILE *fp)
Verbose information about a key or certificate to a file.
Definition: dlggpgme.c:624
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.h:50
#define mutt_message(...)
Definition: logging.h:87
const char * fname
Name of the file to read.
Definition: lib.h:148
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
#define MUTT_PAGER_NO_FLAGS
No flags are set.
Definition: lib.h:54
const char * banner
Title to display in status bar.
Definition: lib.h:159
Pager is invoked via 3rd path. Non-email content is likely to be shown.
Definition: lib.h:135
+ Here is the call graph for this function:
+ 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 953 of file dlggpgme.c.

954 {
955  static char buf[3];
956 
957  if (!(flags & KEYFLAG_CANENCRYPT))
958  buf[0] = '-';
959  else if (flags & KEYFLAG_PREFER_SIGNING)
960  buf[0] = '.';
961  else
962  buf[0] = 'e';
963 
964  if (!(flags & KEYFLAG_CANSIGN))
965  buf[1] = '-';
966  else if (flags & KEYFLAG_PREFER_ENCRYPTION)
967  buf[1] = '.';
968  else
969  buf[1] = 's';
970 
971  buf[2] = '\0';
972 
973  return buf;
974 }
#define KEYFLAG_PREFER_ENCRYPTION
Key&#39;s owner prefers encryption.
Definition: lib.h:133
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition: lib.h:125
#define KEYFLAG_PREFER_SIGNING
Key&#39;s owner prefers signing.
Definition: lib.h:134
PagerFlags flags
Additional settings to tweak pager&#39;s function.
Definition: lib.h:158
#define KEYFLAG_CANSIGN
Key is suitable for signing.
Definition: lib.h:124
+ 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 983 of file dlggpgme.c.

984 {
985  if (flags & KEYFLAG_REVOKED)
986  return 'R';
987  if (flags & KEYFLAG_EXPIRED)
988  return 'X';
989  if (flags & KEYFLAG_DISABLED)
990  return 'd';
991  if (flags & KEYFLAG_CRITICAL)
992  return 'c';
993 
994  return ' ';
995 }
#define KEYFLAG_EXPIRED
Key is expired.
Definition: lib.h:128
#define KEYFLAG_DISABLED
Key is marked disabled.
Definition: lib.h:130
PagerFlags flags
Additional settings to tweak pager&#39;s function.
Definition: lib.h:158
#define KEYFLAG_CRITICAL
Key is marked critical.
Definition: lib.h:132
#define KEYFLAG_REVOKED
Key is revoked.
Definition: lib.h:129
+ Here is the caller graph for this function:

◆ gpgme_key_config_observer()

static int gpgme_key_config_observer ( struct NotifyCallback nc)
static

Notification that a Config Variable has changed - Implements observer_t.

Definition at line 1257 of file dlggpgme.c.

1258 {
1259  if ((nc->event_type != NT_CONFIG) || !nc->global_data || !nc->event_data)
1260  return -1;
1261 
1262  struct EventConfig *ev_c = nc->event_data;
1263 
1264  if (!mutt_str_equal(ev_c->name, "pgp_entry_format") &&
1265  !mutt_str_equal(ev_c->name, "pgp_sort_keys"))
1266  {
1267  return 0;
1268  }
1269 
1270  struct Menu *menu = nc->global_data;
1272  mutt_debug(LL_DEBUG5, "config done, request WA_RECALC, MENU_REDRAW_FULL\n");
1273 
1274  return 0;
1275 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
Definition: lib.h:67
A config-change event.
Definition: subset.h:69
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:42
void * global_data
Data from notify_observer_add()
Definition: observer.h:45
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
void * event_data
Data from notify_send()
Definition: observer.h:44
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:42
Log at debug level 5.
Definition: logging.h:44
const char * name
Name of config item that changed.
Definition: subset.h:72
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ gpgme_key_window_observer()

static int gpgme_key_window_observer ( struct NotifyCallback nc)
static

Notification that a Window has changed - Implements observer_t.

This function is triggered by changes to the windows.

  • Delete (this window): clean up the resources held by the Help Bar

Definition at line 1284 of file dlggpgme.c.

1285 {
1286  if ((nc->event_type != NT_WINDOW) || !nc->global_data || !nc->event_data)
1287  return -1;
1288 
1289  if (nc->event_subtype != NT_WINDOW_DELETE)
1290  return 0;
1291 
1292  struct MuttWindow *win_menu = nc->global_data;
1293  struct EventWindow *ev_w = nc->event_data;
1294  if (ev_w->win != win_menu)
1295  return 0;
1296 
1297  struct Menu *menu = win_menu->wdata;
1298 
1301 
1302  mutt_debug(LL_DEBUG5, "window delete done\n");
1303  return 0;
1304 }
Definition: lib.h:67
struct MuttWindow * win
Window that changed.
Definition: mutt_window.h:217
An Event that happened to a Window.
Definition: mutt_window.h:215
Window is about to be deleted.
Definition: mutt_window.h:206
Container for Accounts, Notifications.
Definition: neomutt.h:36
MuttWindow has changed, NotifyWindow, EventWindow.
Definition: notify_type.h:53
int event_subtype
Send: Event subtype, e.g. NT_ACCOUNT_ADD.
Definition: observer.h:43
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:42
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:138
void * global_data
Data from notify_observer_add()
Definition: observer.h:45
static int gpgme_key_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t.
Definition: dlggpgme.c:1257
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
void * event_data
Data from notify_send()
Definition: observer.h:44
static int gpgme_key_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t.
Definition: dlggpgme.c:1284
bool notify_observer_remove(struct Notify *notify, observer_t callback, void *global_data)
Remove an observer from an object.
Definition: notify.c:228
Log at debug level 5.
Definition: logging.h:44
void * wdata
Private data.
Definition: mutt_window.h:145
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dlg_select_gpgme_key()

struct CryptKeyInfo* dlg_select_gpgme_key ( struct CryptKeyInfo keys,
struct Address p,
const char *  s,
unsigned int  app,
int *  forced_valid 
)

Get the user to select a key.

Parameters
[in]keysList of keys to select from
[in]pAddress to match
[in]sReal name to display
[in]appFlags, e.g. APPLICATION_PGP
[out]forced_validSet to true if user overrode key's validity
Return values
ptrKey selected by user

Display a menu to select a key from the array of keys.

Definition at line 1317 of file dlggpgme.c.

1320 {
1321  int keymax;
1322  int i;
1323  bool done = false;
1324  struct CryptKeyInfo *k = NULL;
1325  int (*f)(const void *, const void *);
1326  enum MenuType menu_to_use = MENU_GENERIC;
1327  bool unusable = false;
1328 
1329  *forced_valid = 0;
1330 
1331  /* build the key table */
1332  keymax = 0;
1333  i = 0;
1334  struct CryptKeyInfo **key_table = NULL;
1335  for (k = keys; k; k = k->next)
1336  {
1337  const bool c_pgp_show_unusable =
1338  cs_subset_bool(NeoMutt->sub, "pgp_show_unusable");
1339  if (!c_pgp_show_unusable && (k->flags & KEYFLAG_CANTUSE))
1340  {
1341  unusable = true;
1342  continue;
1343  }
1344 
1345  if (i == keymax)
1346  {
1347  keymax += 20;
1348  mutt_mem_realloc(&key_table, sizeof(struct CryptKeyInfo *) * keymax);
1349  }
1350 
1351  key_table[i++] = k;
1352  }
1353 
1354  if (!i && unusable)
1355  {
1356  mutt_error(_("All matching keys are marked expired/revoked"));
1357  return NULL;
1358  }
1359 
1360  const short c_pgp_sort_keys = cs_subset_sort(NeoMutt->sub, "pgp_sort_keys");
1361  switch (c_pgp_sort_keys & SORT_MASK)
1362  {
1363  case SORT_ADDRESS:
1365  break;
1366  case SORT_DATE:
1368  break;
1369  case SORT_KEYID:
1371  break;
1372  case SORT_TRUST:
1373  default:
1375  break;
1376  }
1377  qsort(key_table, i, sizeof(struct CryptKeyInfo *), f);
1378 
1379  if (app & APPLICATION_PGP)
1380  menu_to_use = MENU_KEY_SELECT_PGP;
1381  else if (app & APPLICATION_SMIME)
1382  menu_to_use = MENU_KEY_SELECT_SMIME;
1383 
1384  struct MuttWindow *dlg = simple_dialog_new(menu_to_use, WT_DLG_CRYPT_GPGME, GpgmeHelp);
1385 
1386  struct Menu *menu = dlg->wdata;
1387  menu->max = i;
1388  menu->make_entry = crypt_make_entry;
1389  menu->mdata = key_table;
1391 
1392  struct MuttWindow *win_menu = menu->win;
1393 
1394  // NT_COLOR is handled by the SimpleDialog
1397 
1398  {
1399  const char *ts = NULL;
1400 
1401  if ((app & APPLICATION_PGP) && (app & APPLICATION_SMIME))
1402  ts = _("PGP and S/MIME keys matching");
1403  else if ((app & APPLICATION_PGP))
1404  ts = _("PGP keys matching");
1405  else if ((app & APPLICATION_SMIME))
1406  ts = _("S/MIME keys matching");
1407  else
1408  ts = _("keys matching");
1409 
1410  char buf[1024] = { 0 };
1411  if (p)
1412  {
1413  /* L10N: 1$s is one of the previous four entries.
1414  %2$s is an address.
1415  e.g. "S/MIME keys matching <me@mutt.org>" */
1416  snprintf(buf, sizeof(buf), _("%s <%s>"), ts, p->mailbox);
1417  }
1418  else
1419  {
1420  /* L10N: e.g. 'S/MIME keys matching "Michael Elkins".' */
1421  snprintf(buf, sizeof(buf), _("%s \"%s\""), ts, s);
1422  }
1423 
1424  struct MuttWindow *sbar = window_find_child(dlg, WT_STATUS_BAR);
1425  sbar_set_title(sbar, buf);
1426  }
1427 
1428  mutt_clear_error();
1429  k = NULL;
1430  while (!done)
1431  {
1432  *forced_valid = 0;
1433  switch (menu_loop(menu))
1434  {
1435  case OP_VERIFY_KEY:
1436  {
1437  const int index = menu_get_index(menu);
1438  struct CryptKeyInfo *cur_key = key_table[index];
1439  verify_key(cur_key);
1441  break;
1442  }
1443 
1444  case OP_VIEW_ID:
1445  {
1446  const int index = menu_get_index(menu);
1447  struct CryptKeyInfo *cur_key = key_table[index];
1448  mutt_message("%s", cur_key->uid);
1449  break;
1450  }
1451 
1452  case OP_GENERIC_SELECT_ENTRY:
1453  {
1454  const int index = menu_get_index(menu);
1455  struct CryptKeyInfo *cur_key = key_table[index];
1456  /* FIXME make error reporting more verbose - this should be
1457  * easy because GPGME provides more information */
1458  if (OptPgpCheckTrust)
1459  {
1460  if (!crypt_key_is_valid(cur_key))
1461  {
1462  mutt_error(_("This key can't be used: "
1463  "expired/disabled/revoked"));
1464  break;
1465  }
1466  }
1467 
1468  if (OptPgpCheckTrust && (!crypt_id_is_valid(cur_key) || !crypt_id_is_strong(cur_key)))
1469  {
1470  const char *warn_s = NULL;
1471  char buf2[1024];
1472 
1473  if (cur_key->flags & KEYFLAG_CANTUSE)
1474  {
1475  warn_s = _("ID is expired/disabled/revoked. Do you really want to "
1476  "use the key?");
1477  }
1478  else
1479  {
1480  warn_s = "??";
1481  switch (cur_key->validity)
1482  {
1483  case GPGME_VALIDITY_NEVER:
1484  warn_s =
1485  _("ID is not valid. Do you really want to use the key?");
1486  break;
1487  case GPGME_VALIDITY_MARGINAL:
1488  warn_s = _("ID is only marginally valid. Do you really want to "
1489  "use the key?");
1490  break;
1491  case GPGME_VALIDITY_FULL:
1492  case GPGME_VALIDITY_ULTIMATE:
1493  break;
1494  case GPGME_VALIDITY_UNKNOWN:
1495  case GPGME_VALIDITY_UNDEFINED:
1496  warn_s = _("ID has undefined validity. Do you really want to "
1497  "use the key?");
1498  break;
1499  }
1500  }
1501 
1502  snprintf(buf2, sizeof(buf2), "%s", warn_s);
1503 
1504  if (mutt_yesorno(buf2, MUTT_NO) != MUTT_YES)
1505  {
1506  mutt_clear_error();
1507  break;
1508  }
1509 
1510  /* A '!' is appended to a key in find_keys() when forced_valid is
1511  * set. Prior to GPGME 1.11.0, encrypt_gpgme_object() called
1512  * create_recipient_set() which interpreted the '!' to mean set
1513  * GPGME_VALIDITY_FULL for the key.
1514  *
1515  * Starting in GPGME 1.11.0, we now use a '\n' delimited recipient
1516  * string, which is passed directly to the gpgme_op_encrypt_ext()
1517  * function. This allows to use the original meaning of '!' to
1518  * force a subkey use. */
1519 #if (GPGME_VERSION_NUMBER < 0x010b00) /* GPGME < 1.11.0 */
1520  *forced_valid = 1;
1521 #endif
1522  }
1523 
1524  k = crypt_copy_key(cur_key);
1525  done = true;
1526  break;
1527  }
1528 
1529  case OP_EXIT:
1530  k = NULL;
1531  done = true;
1532  break;
1533  }
1534  }
1535 
1536  simple_dialog_free(&dlg);
1537  return k;
1538 }
struct MuttWindow * window_find_child(struct MuttWindow *win, enum WindowType type)
Recursively find a child Window of a given type.
Definition: mutt_window.c:550
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
MenuType
Types of GUI selections.
Definition: type.h:35
void simple_dialog_free(struct MuttWindow **ptr)
Destroy a simple index Dialog.
Definition: simple.c:165
Definition: lib.h:67
#define mutt_error(...)
Definition: logging.h:88
static void crypt_make_entry(struct Menu *menu, char *buf, size_t buflen, int line)
Format a menu item for the key selection list - Implements Menu::make_entry() -.
Definition: dlggpgme.c:1230
Generic selection list.
Definition: type.h:45
Crypt-GPGME Dialog, dlg_select_gpgme_key()
Definition: mutt_window.h:83
#define _(a)
Definition: message.h:28
Sort by email address.
Definition: sort2.h:54
char * mailbox
Mailbox and host address.
Definition: address.h:38
static const struct Mapping GpgmeHelp[]
Help Bar for the GPGME key selection dialog.
Definition: dlggpgme.c:103
static int crypt_crypt_compare_keyid_qsort(const void *a, const void *b)
Compare the IDs of two keys.
Definition: dlggpgme.c:237
struct CryptKeyInfo * next
Definition: crypt_gpgme.h:46
Container for Accounts, Notifications.
Definition: neomutt.h:36
MuttWindow has changed, NotifyWindow, EventWindow.
Definition: notify_type.h:53
static void gpgme_key_table_free(struct Menu *menu, void **ptr)
Free the key table - Implements Menu::mdata_free() -.
Definition: dlggpgme.c:1249
Status Bar containing extra info about the Index/Pager/etc.
Definition: mutt_window.h:102
void(* make_entry)(struct Menu *menu, char *buf, size_t buflen, int line)
Definition: lib.h:105
int crypt_id_is_valid(struct CryptKeyInfo *key)
Is key ID valid.
Definition: crypt_gpgme.c:519
A stored PGP key.
Definition: crypt_gpgme.h:44
static int crypt_compare_address_qsort(const void *a, const void *b)
Compare the addresses of two keys.
Definition: dlggpgme.c:203
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:138
struct MuttWindow * win
Window holding the Menu.
Definition: lib.h:76
Select a PGP key.
Definition: type.h:47
bool crypt_id_is_strong(struct CryptKeyInfo *key)
Is the key strong.
Definition: crypt_gpgme.c:484
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:112
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:189
struct CryptKeyInfo * crypt_copy_key(struct CryptKeyInfo *key)
Return a copy of KEY.
Definition: crypt_gpgme.c:443
#define KEYFLAG_CANTUSE
Definition: lib.h:136
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
static int crypt_compare_trust_qsort(const void *a, const void *b)
Compare the trust levels of two keys.
Definition: dlggpgme.c:343
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
static int gpgme_key_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t.
Definition: dlggpgme.c:1257
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:88
Sort by encryption key&#39;s trust level.
Definition: sort2.h:56
const char * uid
and for convenience point to this user ID
Definition: crypt_gpgme.h:49
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
void * mdata
Private data.
Definition: lib.h:155
static int crypt_compare_date_qsort(const void *a, const void *b)
Compare the dates of two keys.
Definition: dlggpgme.c:279
WHERE bool OptPgpCheckTrust
(pseudo) used by dlg_select_pgp_key()
Definition: options.h:48
void sbar_set_title(struct MuttWindow *win, const char *title)
Set the title for the Simple Bar.
Definition: sbar.c:221
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:180
int max
Number of entries in the menu.
Definition: lib.h:71
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:42
static int gpgme_key_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t.
Definition: dlggpgme.c:1284
void(* mdata_free)(struct Menu *menu, void **ptr)
Definition: lib.h:170
Select a SMIME key.
Definition: type.h:48
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.h:50
#define mutt_message(...)
Definition: logging.h:87
static void verify_key(struct CryptKeyInfo *key)
Show detailed information about the selected key.
Definition: dlggpgme.c:875
gpgme_validity_t validity
uid validity (cached for convenience)
Definition: crypt_gpgme.h:51
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
Sort by the encryption key&#39;s ID.
Definition: sort2.h:55
struct MuttWindow * simple_dialog_new(enum MenuType mtype, enum WindowType wtype, const struct Mapping *help_data)
Create a simple index Dialog.
Definition: simple.c:128
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Sort by the date the email was sent.
Definition: sort2.h:43
void * wdata
Private data.
Definition: mutt_window.h:145
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:78
static bool crypt_key_is_valid(struct CryptKeyInfo *k)
Is the key valid.
Definition: dlggpgme.c:169
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ GpgmeHelp

const struct Mapping GpgmeHelp[]
static
Initial value:
= {
{ N_("Exit"), OP_EXIT },
{ N_("Select"), OP_GENERIC_SELECT_ENTRY },
{ N_("Check key"), OP_VERIFY_KEY },
{ N_("Help"), OP_HELP },
{ NULL, 0 },
}
#define N_(a)
Definition: message.h:32

Help Bar for the GPGME key selection dialog.

Definition at line 103 of file dlggpgme.c.

◆ KeyInfoPrompts

const char* const KeyInfoPrompts[]
static
Initial value:
= {
N_("Name: "), N_("aka: "), N_("Valid From: "), N_("Valid To: "),
N_("Key Type: "), N_("Key Usage: "), N_("Fingerprint: "), N_("Serial-No: "),
N_("Issued By: "), N_("Subkey: ")
}
#define N_(a)
Definition: message.h:32

Definition at line 131 of file dlggpgme.c.

◆ KeyInfoPadding

int KeyInfoPadding[KIP_MAX] = { 0 }

Definition at line 140 of file dlggpgme.c.