NeoMutt  2025-12-11-435-g4ac674
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
pgpkey.c
Go to the documentation of this file.
1
26
32
33#include "config.h"
34#include <stdbool.h>
35#include <stdint.h>
36#include <stdio.h>
37#include <string.h>
38#include <sys/stat.h>
39#include <sys/types.h>
40#include <unistd.h>
41#include "private.h"
42#include "mutt/lib.h"
43#include "address/lib.h"
44#include "config/lib.h"
45#include "email/lib.h"
46#include "core/lib.h"
47#include "pgpkey.h"
48#include "lib.h"
49#include "editor/lib.h"
50#include "history/lib.h"
51#include "send/lib.h"
52#include "crypt.h"
53#include "globals.h"
54#include "gnupgparse.h"
55#include "mutt_logging.h"
56#include "pgpinvoke.h"
57#ifdef CRYPT_BACKEND_CLASSIC_PGP
58#include "pgp.h"
59#include "pgplib.h"
60#endif
61
66{
67 char *what;
68 char *dflt;
69 struct PgpCache *next;
70};
71
73static struct PgpCache *IdDefaults = NULL;
74
75// clang-format off
76typedef uint8_t PgpKeyValidFlags;
77#define PGP_KV_NO_FLAGS 0
78#define PGP_KV_VALID (1 << 0)
79#define PGP_KV_ADDR (1 << 1)
80#define PGP_KV_STRING (1 << 2)
81#define PGP_KV_STRONGID (1 << 3)
82// clang-format on
83
84#define PGP_KV_MATCH (PGP_KV_ADDR | PGP_KV_STRING)
85
92{
93 if (key->flags & KEYFLAG_SUBKEY && key->parent)
94 return key->parent;
95 return key;
96}
97
104{
105 struct PgpKeyInfo *pk = pgp_principal_key(k);
106 if (k->flags & KEYFLAG_CANTUSE)
107 return false;
108 if (pk->flags & KEYFLAG_CANTUSE)
109 return false;
110
111 return true;
112}
113
120{
121 for (struct PgpKeyInfo *k = keys; k != NULL; k = k->next)
122 {
123 if (!pgp_key_is_valid(k))
124 return false;
125 }
126
127 return true;
128}
129
135bool pgp_id_is_strong(struct PgpUid *uid)
136{
137 if ((uid->trust & 3) < 3)
138 return false;
139 /* else */
140 return true;
141}
142
148bool pgp_id_is_valid(struct PgpUid *uid)
149{
150 if (!pgp_key_is_valid(uid->parent))
151 return false;
152 if (uid->flags & KEYFLAG_CANTUSE)
153 return false;
154 /* else */
155 return true;
156}
157
166 struct Address *u_addr, struct PgpUid *uid)
167{
169
170 if (pgp_id_is_valid(uid))
172
173 if (pgp_id_is_strong(uid))
175
176 if (addr->mailbox && u_addr->mailbox && buf_istr_equal(addr->mailbox, u_addr->mailbox))
177 {
179 }
180
181 if (addr->personal && u_addr->personal &&
182 buf_istr_equal(addr->personal, u_addr->personal))
183 {
185 }
186
187 return flags;
188}
189
198struct PgpKeyInfo *pgp_ask_for_key(char *tag, const char *whatfor,
199 KeyFlags abilities, enum PgpRing keyring)
200{
201 struct PgpKeyInfo *key = NULL;
202 struct PgpCache *l = NULL;
203 struct Buffer *resp = buf_pool_get();
204
206
207 if (whatfor)
208 {
209 for (l = IdDefaults; l; l = l->next)
210 {
211 if (mutt_istr_equal(whatfor, l->what))
212 {
213 buf_strcpy(resp, l->dflt);
214 break;
215 }
216 }
217 }
218
219 while (true)
220 {
221 buf_reset(resp);
222 if (mw_get_field(tag, resp, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0)
223 {
224 goto done;
225 }
226
227 if (whatfor)
228 {
229 if (l)
230 {
231 mutt_str_replace(&l->dflt, buf_string(resp));
232 }
233 else
234 {
235 l = MUTT_MEM_MALLOC(1, struct PgpCache);
236 l->next = IdDefaults;
237 IdDefaults = l;
238 l->what = mutt_str_dup(whatfor);
239 l->dflt = buf_strdup(resp);
240 }
241 }
242
243 key = pgp_getkeybystr(buf_string(resp), abilities, keyring);
244 if (key)
245 goto done;
246
247 mutt_error(_("No matching keys found for \"%s\""), buf_string(resp));
248 }
249
250done:
251 buf_pool_release(&resp);
252 return key;
253}
254
259{
260 struct Body *att = NULL;
261 char buf[1024] = { 0 };
262 char tmp[256] = { 0 };
263 struct stat st = { 0 };
264 pid_t pid;
265 OptPgpCheckTrust = false;
266
267 struct PgpKeyInfo *key = pgp_ask_for_key(_("Please enter the key ID: "), NULL,
269
270 if (!key)
271 return NULL;
272
273 snprintf(tmp, sizeof(tmp), "0x%s", pgp_fpr_or_lkeyid(pgp_principal_key(key)));
274 pgp_key_free(&key);
275
276 struct Buffer *tempfile = buf_pool_get();
277 buf_mktemp(tempfile);
278 FILE *fp_tmp = mutt_file_fopen(buf_string(tempfile), "w");
279 if (!fp_tmp)
280 {
281 mutt_perror(_("Can't create temporary file"));
282 goto cleanup;
283 }
284
285 FILE *fp_null = mutt_file_fopen("/dev/null", "w");
286 if (!fp_null)
287 {
288 mutt_perror(_("Can't open /dev/null"));
289 mutt_file_fclose(&fp_tmp);
290 unlink(buf_string(tempfile));
291 goto cleanup;
292 }
293
294 mutt_message(_("Invoking PGP..."));
295
296 pid = pgp_invoke_export(NULL, NULL, NULL, -1, fileno(fp_tmp), fileno(fp_null), tmp);
297 if (pid == -1)
298 {
299 mutt_perror(_("Can't create filter"));
300 unlink(buf_string(tempfile));
301 mutt_file_fclose(&fp_tmp);
302 mutt_file_fclose(&fp_null);
303 goto cleanup;
304 }
305
306 filter_wait(pid);
307
308 mutt_file_fclose(&fp_tmp);
309 mutt_file_fclose(&fp_null);
310
311 att = mutt_body_new();
312 att->filename = buf_strdup(tempfile);
313 att->unlink = true;
314 att->use_disp = false;
315 att->type = TYPE_APPLICATION;
316 att->subtype = mutt_str_dup("pgp-keys");
317 snprintf(buf, sizeof(buf), _("PGP Key %s"), tmp);
318 att->description = mutt_str_dup(buf);
320
321 stat(buf_string(tempfile), &st);
322 att->length = st.st_size;
323
324cleanup:
325 buf_pool_release(&tempfile);
326 return att;
327}
328
337static void pgp_add_string_to_hints(const char *str, struct ListHead *hints)
338{
339 char *scratch = mutt_str_dup(str);
340 if (!scratch)
341 return;
342
343 for (char *t = strtok(scratch, " ,.:\"()<>\n"); t; t = strtok(NULL, " ,.:\"()<>\n"))
344 {
345 if (strlen(t) > 3)
347 }
348
349 FREE(&scratch);
350}
351
357static struct PgpKeyInfo **pgp_get_lastp(struct PgpKeyInfo *p)
358{
359 for (; p; p = p->next)
360 if (!p->next)
361 return &p->next;
362
363 return NULL;
364}
365
374struct PgpKeyInfo *pgp_getkeybyaddr(struct Address *a, KeyFlags abilities,
375 enum PgpRing keyring, bool oppenc_mode)
376{
377 if (!a)
378 return NULL;
379
380 struct ListHead hints = STAILQ_HEAD_INITIALIZER(hints);
381
382 bool multi = false;
383
384 struct PgpKeyInfo *keys = NULL, *k = NULL, *kn = NULL;
385 struct PgpKeyInfo *the_strong_valid_key = NULL;
386 struct PgpKeyInfo *a_valid_addrmatch_key = NULL;
387 struct PgpKeyInfo *matches = NULL;
388 struct PgpKeyInfo **last = &matches;
389 struct PgpUid *q = NULL;
390
391 if (a->mailbox)
393 if (a->personal)
395
396 if (!oppenc_mode)
397 mutt_message(_("Looking for keys matching \"%s\"..."), buf_string(a->mailbox));
398 keys = pgp_get_candidates(keyring, &hints);
399
400 mutt_list_free(&hints);
401
402 if (!keys)
403 return NULL;
404
405 mutt_debug(LL_DEBUG5, "looking for %s <%s>\n", buf_string(a->personal),
406 buf_string(a->mailbox));
407
408 for (k = keys; k; k = kn)
409 {
410 kn = k->next;
411
412 mutt_debug(LL_DEBUG5, " looking at key: %s\n", pgp_keyid(k));
413
414 if (abilities && !(k->flags & abilities))
415 {
416 mutt_debug(LL_DEBUG3, " insufficient abilities: Has %x, want %x\n", k->flags, abilities);
417 continue;
418 }
419
420 bool match = false; /* any match */
421
422 for (q = k->address; q; q = q->next)
423 {
424 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
426 struct Address *qa = NULL;
427 TAILQ_FOREACH(qa, &al, entries)
428 {
429 PgpKeyValidFlags validity = pgp_id_matches_addr(a, qa, q);
430
431 if (validity & PGP_KV_MATCH) /* something matches */
432 match = true;
433
434 if ((validity & PGP_KV_VALID) && (validity & PGP_KV_ADDR))
435 {
436 if (validity & PGP_KV_STRONGID)
437 {
438 if (the_strong_valid_key && (the_strong_valid_key != k))
439 multi = true;
440 the_strong_valid_key = k;
441 }
442 else
443 {
444 a_valid_addrmatch_key = k;
445 }
446 }
447 }
448
450 }
451
452 if (match)
453 {
454 *last = pgp_principal_key(k);
455 kn = pgp_remove_key(&keys, *last);
456 last = pgp_get_lastp(k);
457 }
458 }
459
460 pgp_key_free(&keys);
461
462 if (matches)
463 {
464 if (oppenc_mode || !isatty(STDIN_FILENO))
465 {
466 const bool c_crypt_opportunistic_encrypt_strong_keys =
467 cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt_strong_keys");
468 if (the_strong_valid_key)
469 {
470 pgp_remove_key(&matches, the_strong_valid_key);
471 k = the_strong_valid_key;
472 }
473 else if (a_valid_addrmatch_key && !c_crypt_opportunistic_encrypt_strong_keys)
474 {
475 pgp_remove_key(&matches, a_valid_addrmatch_key);
476 k = a_valid_addrmatch_key;
477 }
478 else
479 {
480 k = NULL;
481 }
482 }
483 else if (the_strong_valid_key && !multi)
484 {
485 /* There was precisely one strong match on a valid ID.
486 * Proceed without asking the user. */
487 pgp_remove_key(&matches, the_strong_valid_key);
488 k = the_strong_valid_key;
489 }
490 else
491 {
492 /* Else: Ask the user. */
493 k = dlg_pgp(matches, a, NULL);
494 if (k)
495 pgp_remove_key(&matches, k);
496 }
497
498 pgp_key_free(&matches);
499
500 return k;
501 }
502
503 return NULL;
504}
505
513struct PgpKeyInfo *pgp_getkeybystr(const char *cp, KeyFlags abilities, enum PgpRing keyring)
514{
515 struct ListHead hints = STAILQ_HEAD_INITIALIZER(hints);
516 struct PgpKeyInfo *keys = NULL;
517 struct PgpKeyInfo *matches = NULL;
518 struct PgpKeyInfo **last = &matches;
519 struct PgpKeyInfo *k = NULL, *kn = NULL;
520 struct PgpUid *a = NULL;
521 size_t l;
522 const char *ps = NULL, *pl = NULL, *pfcopy = NULL, *phint = NULL;
523
524 char *p = strdup(cp); // mutt_str_dup converts "" into NULL, see #1809
525 l = mutt_str_len(p);
526 if ((l > 0) && (p[l - 1] == '!'))
527 p[l - 1] = 0;
528
529 mutt_message(_("Looking for keys matching \"%s\"..."), p);
530
531 pfcopy = crypt_get_fingerprint_or_id(p, &phint, &pl, &ps);
532 pgp_add_string_to_hints(phint, &hints);
533 keys = pgp_get_candidates(keyring, &hints);
534 mutt_list_free(&hints);
535
536 for (k = keys; k; k = kn)
537 {
538 kn = k->next;
539 if (abilities && !(k->flags & abilities))
540 continue;
541
542 /* This shouldn't happen, but keys without any addresses aren't selectable
543 * in dlg_pgp(). */
544 if (!k->address)
545 continue;
546
547 bool match = false;
548
549 mutt_debug(LL_DEBUG5, "matching \"%s\" against key %s:\n", p, pgp_long_keyid(k));
550
551 if ((*p == '\0') || (pfcopy && mutt_istr_equal(pfcopy, k->fingerprint)) ||
552 (pl && mutt_istr_equal(pl, pgp_long_keyid(k))) ||
553 (ps && mutt_istr_equal(ps, pgp_short_keyid(k))))
554 {
555 mutt_debug(LL_DEBUG5, " match #1\n");
556 match = true;
557 }
558 else
559 {
560 for (a = k->address; a; a = a->next)
561 {
562 mutt_debug(LL_DEBUG5, "matching \"%s\" against key %s, \"%s\":\n", p,
563 pgp_long_keyid(k), NONULL(a->addr));
564 if (mutt_istr_find(a->addr, p))
565 {
566 mutt_debug(LL_DEBUG5, " match #2\n");
567 match = true;
568 break;
569 }
570 }
571 }
572
573 if (match)
574 {
575 *last = pgp_principal_key(k);
576 kn = pgp_remove_key(&keys, *last);
577 last = pgp_get_lastp(k);
578 }
579 }
580
581 pgp_key_free(&keys);
582
583 k = NULL;
584 if (matches)
585 {
586 if (isatty(STDIN_FILENO))
587 {
588 k = dlg_pgp(matches, NULL, p);
589 if (k)
590 pgp_remove_key(&matches, k);
591 pgp_key_free(&matches);
592 }
593 else if (pgp_keys_are_valid(matches))
594 {
595 k = matches;
596 }
597 else
598 {
599 mutt_error(_("A key can't be used: expired/disabled/revoked"));
600 }
601 }
602
603 FREE(&pfcopy);
604 FREE(&p);
605 return k;
606}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition address.c:1464
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition address.c:480
Email Address Handling.
bool buf_istr_equal(const struct Buffer *a, const struct Buffer *b)
Return if two buffers are equal, case insensitive.
Definition buffer.c:695
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:571
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
const char * crypt_get_fingerprint_or_id(const char *p, const char **pphint, const char **ppl, const char **pps)
Get the fingerprint or long key ID.
Definition crypt.c:1383
Signing/encryption multiplexor.
static struct CryptCache * IdDefaults
Cache of GPGME keys.
Definition crypt_gpgme.c:92
Edit a string.
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition wdata.h:42
struct Body * mutt_body_new(void)
Create a new Body.
Definition body.c:44
Structs that make up an email.
#define mutt_file_fclose(FP)
Definition file.h:139
#define mutt_file_fopen(PATH, MODE)
Definition file.h:138
bool OptPgpCheckTrust
(pseudo) used by dlg_pgp()
Definition globals.c:55
Global variables.
struct PgpKeyInfo * pgp_get_candidates(enum PgpRing keyring, struct ListHead *hints)
Find PGP keys matching a list of hints.
Definition gnupgparse.c:417
Parse the output of CLI PGP programinclude "pgpkey.h".
struct Body * pgp_class_make_key_attachment(void)
Generate a public key attachment - Implements CryptModuleSpecs::pgp_make_key_attachment() -.
Definition pgpkey.c:258
struct PgpKeyInfo * dlg_pgp(struct PgpKeyInfo *keys, struct Address *p, const char *s)
Let the user select a key to use -.
Definition dlg_pgp.c:191
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition window.c:270
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
#define mutt_perror(...)
Definition logging2.h:95
Read/write command history from/to a file.
@ HC_OTHER
Miscellaneous strings.
Definition lib.h:60
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition list.c:65
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition list.c:123
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:47
@ LL_DEBUG5
Log at debug level 5.
Definition logging2.h:49
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define MUTT_MEM_MALLOC(n, type)
Definition memory.h:53
@ TYPE_APPLICATION
Type: 'application/*'.
Definition mime.h:33
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition filter.c:220
Convenience wrapper for the library headers.
#define _(a)
Definition message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:674
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition string.c:525
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:500
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
NeoMutt Logging.
API for encryption/signing of emails.
uint16_t KeyFlags
Flags describing PGP/SMIME keys, e.g. KEYFLAG_CANSIGN.
Definition lib.h:133
#define KEYFLAG_SUBKEY
Key is a subkey.
Definition lib.h:142
#define KEYFLAG_CANTUSE
Definition lib.h:147
#define KEYFLAG_NO_FLAGS
No flags are set.
Definition lib.h:134
Shared constants/structs that are private to libconn.
char * pgp_long_keyid(struct PgpKeyInfo *k)
Get a key's long id.
Definition pgp.c:164
char * pgp_keyid(struct PgpKeyInfo *k)
Get the ID of the main (parent) key.
Definition pgp.c:203
char * pgp_fpr_or_lkeyid(struct PgpKeyInfo *k)
Get the fingerprint or long keyid.
Definition pgp.c:233
char * pgp_short_keyid(struct PgpKeyInfo *k)
Get a key's short id.
Definition pgp.c:176
PGP sign, encrypt, check routines.
pid_t pgp_invoke_export(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err, int fd_pgp_in, int fd_pgp_out, int fd_pgp_err, const char *uids)
Use PGP to export a key from the user's keyring.
Definition pgpinvoke.c:374
Wrapper around calls to external PGP program.
bool pgp_id_is_valid(struct PgpUid *uid)
Is a PGP key valid.
Definition pgpkey.c:148
#define PGP_KV_NO_FLAGS
No flags are set.
Definition pgpkey.c:77
#define PGP_KV_STRONGID
PGP Key is strong.
Definition pgpkey.c:81
static void pgp_add_string_to_hints(const char *str, struct ListHead *hints)
Split a string and add the parts to a List.
Definition pgpkey.c:337
#define PGP_KV_MATCH
Definition pgpkey.c:84
static PgpKeyValidFlags pgp_id_matches_addr(struct Address *addr, struct Address *u_addr, struct PgpUid *uid)
Does the key ID match the address.
Definition pgpkey.c:165
struct PgpKeyInfo * pgp_ask_for_key(char *tag, const char *whatfor, KeyFlags abilities, enum PgpRing keyring)
Ask the user for a PGP key.
Definition pgpkey.c:198
#define PGP_KV_VALID
PGP Key ID is valid.
Definition pgpkey.c:78
#define PGP_KV_STRING
PGP Key name string is valid.
Definition pgpkey.c:80
#define PGP_KV_ADDR
PGP Key address is valid.
Definition pgpkey.c:79
bool pgp_keys_are_valid(struct PgpKeyInfo *keys)
Are all these PGP keys valid?
Definition pgpkey.c:119
static struct PgpKeyInfo ** pgp_get_lastp(struct PgpKeyInfo *p)
Get the last PGP key in a list.
Definition pgpkey.c:357
bool pgp_id_is_strong(struct PgpUid *uid)
Is a PGP key strong?
Definition pgpkey.c:135
struct PgpKeyInfo * pgp_getkeybyaddr(struct Address *a, KeyFlags abilities, enum PgpRing keyring, bool oppenc_mode)
Find a PGP key by address.
Definition pgpkey.c:374
bool pgp_key_is_valid(struct PgpKeyInfo *k)
Is a PGP key valid?
Definition pgpkey.c:103
struct PgpKeyInfo * pgp_getkeybystr(const char *cp, KeyFlags abilities, enum PgpRing keyring)
Find a PGP key by string.
Definition pgpkey.c:513
uint8_t PgpKeyValidFlags
Flags for valid Pgp Key fields, e.g. PGP_KV_VALID.
Definition pgpkey.c:76
struct PgpKeyInfo * pgp_principal_key(struct PgpKeyInfo *key)
Get the main (parent) PGP key.
Definition pgpkey.c:91
PGP key management routines.
PgpRing
PGP ring type.
Definition pgpkey.h:38
@ PGP_PUBRING
Public keys.
Definition pgpkey.h:39
void pgp_key_free(struct PgpKeyInfo **kpp)
Free a PGP key info.
Definition pgplib.c:201
struct PgpKeyInfo * pgp_remove_key(struct PgpKeyInfo **klist, struct PgpKeyInfo *key)
Remove a PGP key from a list.
Definition pgplib.c:169
Misc PGP helper routines.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:782
#define STAILQ_HEAD_INITIALIZER(head)
Definition queue.h:324
#define TAILQ_HEAD_INITIALIZER(head)
Definition queue.h:694
Convenience wrapper for the send headers.
void mutt_update_encoding(struct Body *b, struct ConfigSubset *sub)
Update the encoding type.
Definition sendlib.c:421
#define NONULL(x)
Definition string2.h:44
An email address.
Definition address.h:35
struct Buffer * personal
Real name of address.
Definition address.h:36
struct Buffer * mailbox
Mailbox and host address.
Definition address.h:37
The body of an email.
Definition body.h:36
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition body.h:68
LOFF_T length
length (in bytes) of attachment
Definition body.h:53
bool use_disp
Content-Disposition uses filename= ?
Definition body.h:47
char * description
content-description
Definition body.h:55
char * subtype
content-type subtype
Definition body.h:61
unsigned int type
content-type primary type, ContentType
Definition body.h:40
char * filename
When sending a message, this is the file to which this structure refers.
Definition body.h:59
String manipulation buffer.
Definition buffer.h:36
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
List of cached PGP keys.
Definition pgpkey.c:66
char * dflt
Default key ID.
Definition pgpkey.c:68
struct PgpCache * next
Linked list.
Definition pgpkey.c:69
char * what
Cached key identifier.
Definition pgpkey.c:67
Information about a PGP key.
Definition pgplib.h:49
KeyFlags flags
Key flags.
Definition pgplib.h:53
struct PgpKeyInfo * next
Linked list.
Definition pgplib.h:59
struct PgpUid * address
User IDs.
Definition pgplib.h:52
char * fingerprint
Key fingerprint.
Definition pgplib.h:51
struct PgpKeyInfo * parent
Parent key.
Definition pgplib.h:58
PGP User ID.
Definition pgplib.h:36
short trust
Trust level.
Definition pgplib.h:38
struct PgpKeyInfo * parent
Parent key.
Definition pgplib.h:40
int flags
Flags for this UID.
Definition pgplib.h:39
char * addr
Email address.
Definition pgplib.h:37
struct PgpUid * next
Linked list.
Definition pgplib.h:41
#define buf_mktemp(buf)
Definition tmp.h:33