NeoMutt  2025-12-11-872-g385a04
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
pgpkey.h File Reference

PGP key management routines. More...

#include <stdbool.h>
#include "lib.h"
+ Include dependency graph for pgpkey.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  PgpRing { PGP_PUBRING , PGP_SECRING }
 PGP ring type. More...
 

Functions

struct Bodypgp_class_make_key_attachment (void)
 Generate a public key attachment - Implements CryptModuleSpecs::pgp_make_key_attachment() -.
 
struct PgpKeyInfopgp_ask_for_key (char *tag, const char *whatfor, KeyFlags abilities, enum PgpRing keyring)
 Ask the user for a PGP key.
 
struct PgpKeyInfopgp_getkeybyaddr (struct Address *a, KeyFlags abilities, enum PgpRing keyring, bool oppenc_mode)
 Find a PGP key by address.
 
struct PgpKeyInfopgp_getkeybystr (const char *p, KeyFlags abilities, enum PgpRing keyring)
 Find a PGP key by string.
 
bool pgp_id_is_strong (struct PgpUid *uid)
 Is a PGP key strong?
 
bool pgp_id_is_valid (struct PgpUid *uid)
 Is a PGP key valid.
 
bool pgp_keys_are_valid (struct PgpKeyInfo *keys)
 Are all these PGP keys valid?
 
bool pgp_key_is_valid (struct PgpKeyInfo *k)
 Is a PGP key valid?
 
struct PgpKeyInfopgp_principal_key (struct PgpKeyInfo *key)
 Get the main (parent) PGP key.
 
void pgp_id_defaults_cleanup (struct PgpCache **pgp_id_defaults)
 Free the PGP IdDefaults cache.
 

Detailed Description

PGP key management routines.

Authors
  • Richard Russon
  • Pietro Cerutti

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

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

Definition in file pgpkey.h.

Enumeration Type Documentation

◆ PgpRing

enum PgpRing

PGP ring type.

Enumerator
PGP_PUBRING 

Public keys.

PGP_SECRING 

Secret keys.

Definition at line 38 of file pgpkey.h.

39{
42};
@ PGP_SECRING
Secret keys.
Definition pgpkey.h:41
@ PGP_PUBRING
Public keys.
Definition pgpkey.h:40

Function Documentation

◆ pgp_ask_for_key()

struct PgpKeyInfo * pgp_ask_for_key ( char * tag,
const char * whatfor,
KeyFlags abilities,
enum PgpRing keyring )

Ask the user for a PGP key.

Parameters
tagPrompt for the user
whatforUse for key, e.g. "signing"
abilitiesAbilities to match, see KeyFlags
keyringPGP keyring to use
Return values
ptrSelected PGP key

Definition at line 202 of file pgpkey.c.

204{
206 struct PgpKeyInfo *key = NULL;
207 struct PgpCache *l = NULL;
208 struct Buffer *resp = buf_pool_get();
209
211
212 if (whatfor)
213 {
214 for (l = (struct PgpCache *) mod_data->pgp_id_defaults; l; l = l->next)
215 {
216 if (mutt_istr_equal(whatfor, l->what))
217 {
218 buf_strcpy(resp, l->dflt);
219 break;
220 }
221 }
222 }
223
224 while (true)
225 {
226 buf_reset(resp);
227 if (mw_get_field(tag, resp, MUTT_COMP_NONE, HC_OTHER, NULL, NULL) != 0)
228 {
229 goto done;
230 }
231
232 if (whatfor)
233 {
234 if (l)
235 {
236 mutt_str_replace(&l->dflt, buf_string(resp));
237 }
238 else
239 {
240 l = MUTT_MEM_MALLOC(1, struct PgpCache);
241 l->next = (struct PgpCache *) mod_data->pgp_id_defaults;
242 mod_data->pgp_id_defaults = l;
243 l->what = mutt_str_dup(whatfor);
244 l->dflt = buf_strdup(resp);
245 }
246 }
247
248 key = pgp_getkeybystr(buf_string(resp), abilities, keyring);
249 if (key)
250 goto done;
251
252 mutt_error(_("No matching keys found for \"%s\""), buf_string(resp));
253 }
254
255done:
256 buf_pool_release(&resp);
257 return key;
258}
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
@ MUTT_COMP_NONE
No flags are set.
Definition wdata.h:46
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:467
#define mutt_error(...)
Definition logging2.h:94
@ HC_OTHER
Miscellaneous strings.
Definition lib.h:61
#define MUTT_MEM_MALLOC(n, type)
Definition memory.h:53
@ MODULE_ID_NCRYPT
ModuleNcrypt, Ncrypt
Definition module_api.h:80
#define _(a)
Definition message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:677
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
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)
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:663
struct PgpKeyInfo * pgp_getkeybystr(const char *cp, KeyFlags abilities, enum PgpRing keyring)
Find a PGP key by string.
Definition pgpkey.c:518
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
String manipulation buffer.
Definition buffer.h:36
Ncrypt private Module data.
Definition module_data.h:38
struct PgpCache * pgp_id_defaults
PGP IdDefaults cache.
Definition module_data.h:52
Container for Accounts, Notifications.
Definition neomutt.h:41
List of cached PGP keys.
Definition pgpkey.c:67
char * dflt
Default key ID.
Definition pgpkey.c:69
struct PgpCache * next
Linked list.
Definition pgpkey.c:70
char * what
Cached key identifier.
Definition pgpkey.c:68
Information about a PGP key.
Definition pgplib.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_getkeybyaddr()

struct PgpKeyInfo * pgp_getkeybyaddr ( struct Address * a,
KeyFlags abilities,
enum PgpRing keyring,
bool oppenc_mode )

Find a PGP key by address.

Parameters
aEmail address to match
abilitiesAbilities to match, see KeyFlags
keyringPGP keyring to use
oppenc_modeIf true, use opportunistic encryption
Return values
ptrMatching PGP key

Definition at line 379 of file pgpkey.c.

381{
382 if (!a)
383 return NULL;
384
385 struct ListHead hints = STAILQ_HEAD_INITIALIZER(hints);
386
387 bool multi = false;
388
389 struct PgpKeyInfo *keys = NULL, *k = NULL, *kn = NULL;
390 struct PgpKeyInfo *the_strong_valid_key = NULL;
391 struct PgpKeyInfo *a_valid_addrmatch_key = NULL;
392 struct PgpKeyInfo *matches = NULL;
393 struct PgpKeyInfo **last = &matches;
394 struct PgpUid *q = NULL;
395
396 if (a->mailbox)
398 if (a->personal)
400
401 if (!oppenc_mode)
402 mutt_message(_("Looking for keys matching \"%s\"..."), buf_string(a->mailbox));
403 keys = pgp_get_candidates(keyring, &hints);
404
405 mutt_list_free(&hints);
406
407 if (!keys)
408 return NULL;
409
410 mutt_debug(LL_DEBUG5, "looking for %s <%s>\n", buf_string(a->personal),
411 buf_string(a->mailbox));
412
413 for (k = keys; k; k = kn)
414 {
415 kn = k->next;
416
417 mutt_debug(LL_DEBUG5, " looking at key: %s\n", pgp_keyid(k));
418
419 if (abilities && !(k->flags & abilities))
420 {
421 mutt_debug(LL_DEBUG3, " insufficient abilities: Has %x, want %x\n", k->flags, abilities);
422 continue;
423 }
424
425 bool match = false; /* any match */
426
427 for (q = k->address; q; q = q->next)
428 {
429 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
431 struct Address *qa = NULL;
432 TAILQ_FOREACH(qa, &al, entries)
433 {
434 PgpKeyValidFlags validity = pgp_id_matches_addr(a, qa, q);
435
436 if (validity & PGP_KV_MATCH) /* something matches */
437 match = true;
438
439 if ((validity & PGP_KV_VALID) && (validity & PGP_KV_ADDR))
440 {
441 if (validity & PGP_KV_STRONGID)
442 {
443 if (the_strong_valid_key && (the_strong_valid_key != k))
444 multi = true;
445 the_strong_valid_key = k;
446 }
447 else
448 {
449 a_valid_addrmatch_key = k;
450 }
451 }
452 }
453
455 }
456
457 if (match)
458 {
459 *last = pgp_principal_key(k);
460 kn = pgp_remove_key(&keys, *last);
461 last = pgp_get_lastp(k);
462 }
463 }
464
465 pgp_key_free(&keys);
466
467 if (matches)
468 {
469 if (oppenc_mode || !isatty(STDIN_FILENO))
470 {
471 const bool c_crypt_opportunistic_encrypt_strong_keys =
472 cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt_strong_keys");
473 if (the_strong_valid_key)
474 {
475 pgp_remove_key(&matches, the_strong_valid_key);
476 k = the_strong_valid_key;
477 }
478 else if (a_valid_addrmatch_key && !c_crypt_opportunistic_encrypt_strong_keys)
479 {
480 pgp_remove_key(&matches, a_valid_addrmatch_key);
481 k = a_valid_addrmatch_key;
482 }
483 else
484 {
485 k = NULL;
486 }
487 }
488 else if (the_strong_valid_key && !multi)
489 {
490 /* There was precisely one strong match on a valid ID.
491 * Proceed without asking the user. */
492 pgp_remove_key(&matches, the_strong_valid_key);
493 k = the_strong_valid_key;
494 }
495 else
496 {
497 /* Else: Ask the user. */
498 k = dlg_pgp(matches, a, NULL);
499 if (k)
500 pgp_remove_key(&matches, k);
501 }
502
503 pgp_key_free(&matches);
504
505 return k;
506 }
507
508 return NULL;
509}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition address.c:1469
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition address.c:480
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
struct PgpKeyInfo * pgp_get_candidates(enum PgpRing keyring, struct ListHead *hints)
Find PGP keys matching a list of hints.
Definition gnupgparse.c:417
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:192
#define mutt_message(...)
Definition logging2.h:93
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
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
char * pgp_keyid(struct PgpKeyInfo *k)
Get the ID of the main (parent) key.
Definition pgp.c:201
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:342
#define PGP_KV_MATCH
Definition pgpkey.c:88
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:169
static struct PgpKeyInfo ** pgp_get_lastp(struct PgpKeyInfo *p)
Get the last PGP key in a list.
Definition pgpkey.c:362
@ PGP_KV_ADDR
PGP Key address is valid.
Definition pgpkey.c:81
@ PGP_KV_VALID
PGP Key ID is valid.
Definition pgpkey.c:80
@ PGP_KV_STRONGID
PGP Key is strong.
Definition pgpkey.c:83
uint8_t PgpKeyValidFlags
Definition pgpkey.c:86
struct PgpKeyInfo * pgp_principal_key(struct PgpKeyInfo *key)
Get the main (parent) PGP key.
Definition pgpkey.c:95
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
#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
#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
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
PGP User ID.
Definition pgplib.h:36
char * addr
Email address.
Definition pgplib.h:37
struct PgpUid * next
Linked list.
Definition pgplib.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_getkeybystr()

struct PgpKeyInfo * pgp_getkeybystr ( const char * cp,
KeyFlags abilities,
enum PgpRing keyring )

Find a PGP key by string.

Parameters
cpString to match, can be empty but cannot be NULL
abilitiesAbilities to match, see KeyFlags
keyringPGP keyring to use
Return values
ptrMatching PGP key

Definition at line 518 of file pgpkey.c.

519{
520 struct ListHead hints = STAILQ_HEAD_INITIALIZER(hints);
521 struct PgpKeyInfo *keys = NULL;
522 struct PgpKeyInfo *matches = NULL;
523 struct PgpKeyInfo **last = &matches;
524 struct PgpKeyInfo *k = NULL, *kn = NULL;
525 struct PgpUid *a = NULL;
526 size_t l;
527 const char *ps = NULL, *pl = NULL, *pfcopy = NULL, *phint = NULL;
528
529 char *p = strdup(cp); // mutt_str_dup converts "" into NULL, see #1809
530 l = mutt_str_len(p);
531 if ((l > 0) && (p[l - 1] == '!'))
532 p[l - 1] = 0;
533
534 mutt_message(_("Looking for keys matching \"%s\"..."), p);
535
536 pfcopy = crypt_get_fingerprint_or_id(p, &phint, &pl, &ps);
537 pgp_add_string_to_hints(phint, &hints);
538 keys = pgp_get_candidates(keyring, &hints);
539 mutt_list_free(&hints);
540
541 for (k = keys; k; k = kn)
542 {
543 kn = k->next;
544 if (abilities && !(k->flags & abilities))
545 continue;
546
547 /* This shouldn't happen, but keys without any addresses aren't selectable
548 * in dlg_pgp(). */
549 if (!k->address)
550 continue;
551
552 bool match = false;
553
554 mutt_debug(LL_DEBUG5, "matching \"%s\" against key %s:\n", p, pgp_long_keyid(k));
555
556 if ((*p == '\0') || (pfcopy && mutt_istr_equal(pfcopy, k->fingerprint)) ||
557 (pl && mutt_istr_equal(pl, pgp_long_keyid(k))) ||
558 (ps && mutt_istr_equal(ps, pgp_short_keyid(k))))
559 {
560 mutt_debug(LL_DEBUG5, " match #1\n");
561 match = true;
562 }
563 else
564 {
565 for (a = k->address; a; a = a->next)
566 {
567 mutt_debug(LL_DEBUG5, "matching \"%s\" against key %s, \"%s\":\n", p,
568 pgp_long_keyid(k), NONULL(a->addr));
569 if (mutt_istr_find(a->addr, p))
570 {
571 mutt_debug(LL_DEBUG5, " match #2\n");
572 match = true;
573 break;
574 }
575 }
576 }
577
578 if (match)
579 {
580 *last = pgp_principal_key(k);
581 kn = pgp_remove_key(&keys, *last);
582 last = pgp_get_lastp(k);
583 }
584 }
585
586 pgp_key_free(&keys);
587
588 k = NULL;
589 if (matches)
590 {
591 if (isatty(STDIN_FILENO))
592 {
593 k = dlg_pgp(matches, NULL, p);
594 if (k)
595 pgp_remove_key(&matches, k);
596 pgp_key_free(&matches);
597 }
598 else if (pgp_keys_are_valid(matches))
599 {
600 k = matches;
601 }
602 else
603 {
604 mutt_error(_("A key can't be used: expired/disabled/revoked"));
605 }
606 }
607
608 FREE(&pfcopy);
609 FREE(&p);
610 return k;
611}
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:1395
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition string.c:528
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:503
char * pgp_long_keyid(struct PgpKeyInfo *k)
Get a key's long id.
Definition pgp.c:162
char * pgp_short_keyid(struct PgpKeyInfo *k)
Get a key's short id.
Definition pgp.c:174
bool pgp_keys_are_valid(struct PgpKeyInfo *keys)
Are all these PGP keys valid?
Definition pgpkey.c:123
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_id_is_strong()

bool pgp_id_is_strong ( struct PgpUid * uid)

Is a PGP key strong?

Parameters
uidUID of a PGP key
Return values
trueKey is strong

Definition at line 139 of file pgpkey.c.

140{
141 if ((uid->trust & 3) < 3)
142 return false;
143 /* else */
144 return true;
145}
short trust
Trust level.
Definition pgplib.h:38
+ Here is the caller graph for this function:

◆ pgp_id_is_valid()

bool pgp_id_is_valid ( struct PgpUid * uid)

Is a PGP key valid.

Parameters
uidUID of a PGP key
Return values
trueKey is valid

Definition at line 152 of file pgpkey.c.

153{
154 if (!pgp_key_is_valid(uid->parent))
155 return false;
156 if (uid->flags & KEYFLAG_CANTUSE)
157 return false;
158 /* else */
159 return true;
160}
#define KEYFLAG_CANTUSE
Definition lib.h:161
bool pgp_key_is_valid(struct PgpKeyInfo *k)
Is a PGP key valid?
Definition pgpkey.c:107
struct PgpKeyInfo * parent
Parent key.
Definition pgplib.h:40
int flags
Flags for this UID.
Definition pgplib.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_keys_are_valid()

bool pgp_keys_are_valid ( struct PgpKeyInfo * keys)

Are all these PGP keys valid?

Parameters
keysSet of keys to examine
Return values
trueAll keys are valid

Definition at line 123 of file pgpkey.c.

124{
125 for (struct PgpKeyInfo *k = keys; k != NULL; k = k->next)
126 {
127 if (!pgp_key_is_valid(k))
128 return false;
129 }
130
131 return true;
132}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_key_is_valid()

bool pgp_key_is_valid ( struct PgpKeyInfo * k)

Is a PGP key valid?

Parameters
kKey to examine
Return values
trueKey is valid

Definition at line 107 of file pgpkey.c.

108{
109 struct PgpKeyInfo *pk = pgp_principal_key(k);
110 if (k->flags & KEYFLAG_CANTUSE)
111 return false;
112 if (pk->flags & KEYFLAG_CANTUSE)
113 return false;
114
115 return true;
116}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_principal_key()

struct PgpKeyInfo * pgp_principal_key ( struct PgpKeyInfo * key)

Get the main (parent) PGP key.

Parameters
keyKey to start with
Return values
ptrPGP Key

Definition at line 95 of file pgpkey.c.

96{
97 if (key->flags & KEYFLAG_SUBKEY && key->parent)
98 return key->parent;
99 return key;
100}
@ KEYFLAG_SUBKEY
Key is a subkey.
Definition lib.h:154
struct PgpKeyInfo * parent
Parent key.
Definition pgplib.h:58
+ Here is the caller graph for this function:

◆ pgp_id_defaults_cleanup()

void pgp_id_defaults_cleanup ( struct PgpCache ** pgp_id_defaults)

Free the PGP IdDefaults cache.

Parameters
pgp_id_defaultsPointer to the PGP cache head

Definition at line 617 of file pgpkey.c.

618{
619 struct PgpCache *l = *pgp_id_defaults;
620 while (l)
621 {
622 struct PgpCache *next = l->next;
623 FREE(&l->what);
624 FREE(&l->dflt);
625 FREE(&l);
626 l = next;
627 }
628 *pgp_id_defaults = NULL;
629}
+ Here is the caller graph for this function: