NeoMutt  2025-12-11-769-g906513
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 (void)
 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 37 of file pgpkey.h.

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

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 196 of file pgpkey.c.

198{
200 struct PgpKeyInfo *key = NULL;
201 struct PgpCache *l = NULL;
202 struct Buffer *resp = buf_pool_get();
203
205
206 if (whatfor)
207 {
208 for (l = (struct PgpCache *) mod_data->pgp_id_defaults; l; l = l->next)
209 {
210 if (mutt_istr_equal(whatfor, l->what))
211 {
212 buf_strcpy(resp, l->dflt);
213 break;
214 }
215 }
216 }
217
218 while (true)
219 {
220 buf_reset(resp);
221 if (mw_get_field(tag, resp, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0)
222 {
223 goto done;
224 }
225
226 if (whatfor)
227 {
228 if (l)
229 {
230 mutt_str_replace(&l->dflt, buf_string(resp));
231 }
232 else
233 {
234 l = MUTT_MEM_MALLOC(1, struct PgpCache);
235 l->next = (struct PgpCache *) mod_data->pgp_id_defaults;
236 mod_data->pgp_id_defaults = l;
237 l->what = mutt_str_dup(whatfor);
238 l->dflt = buf_strdup(resp);
239 }
240 }
241
242 key = pgp_getkeybystr(buf_string(resp), abilities, keyring);
243 if (key)
244 goto done;
245
246 mutt_error(_("No matching keys found for \"%s\""), buf_string(resp));
247 }
248
249done:
250 buf_pool_release(&resp);
251 return key;
252}
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
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition wdata.h:42
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:60
#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:665
struct PgpKeyInfo * pgp_getkeybystr(const char *cp, KeyFlags abilities, enum PgpRing keyring)
Find a PGP key by string.
Definition pgpkey.c:512
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 373 of file pgpkey.c.

375{
376 if (!a)
377 return NULL;
378
379 struct ListHead hints = STAILQ_HEAD_INITIALIZER(hints);
380
381 bool multi = false;
382
383 struct PgpKeyInfo *keys = NULL, *k = NULL, *kn = NULL;
384 struct PgpKeyInfo *the_strong_valid_key = NULL;
385 struct PgpKeyInfo *a_valid_addrmatch_key = NULL;
386 struct PgpKeyInfo *matches = NULL;
387 struct PgpKeyInfo **last = &matches;
388 struct PgpUid *q = NULL;
389
390 if (a->mailbox)
392 if (a->personal)
394
395 if (!oppenc_mode)
396 mutt_message(_("Looking for keys matching \"%s\"..."), buf_string(a->mailbox));
397 keys = pgp_get_candidates(keyring, &hints);
398
399 mutt_list_free(&hints);
400
401 if (!keys)
402 return NULL;
403
404 mutt_debug(LL_DEBUG5, "looking for %s <%s>\n", buf_string(a->personal),
405 buf_string(a->mailbox));
406
407 for (k = keys; k; k = kn)
408 {
409 kn = k->next;
410
411 mutt_debug(LL_DEBUG5, " looking at key: %s\n", pgp_keyid(k));
412
413 if (abilities && !(k->flags & abilities))
414 {
415 mutt_debug(LL_DEBUG3, " insufficient abilities: Has %x, want %x\n", k->flags, abilities);
416 continue;
417 }
418
419 bool match = false; /* any match */
420
421 for (q = k->address; q; q = q->next)
422 {
423 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
425 struct Address *qa = NULL;
426 TAILQ_FOREACH(qa, &al, entries)
427 {
428 PgpKeyValidFlags validity = pgp_id_matches_addr(a, qa, q);
429
430 if (validity & PGP_KV_MATCH) /* something matches */
431 match = true;
432
433 if ((validity & PGP_KV_VALID) && (validity & PGP_KV_ADDR))
434 {
435 if (validity & PGP_KV_STRONGID)
436 {
437 if (the_strong_valid_key && (the_strong_valid_key != k))
438 multi = true;
439 the_strong_valid_key = k;
440 }
441 else
442 {
443 a_valid_addrmatch_key = k;
444 }
445 }
446 }
447
449 }
450
451 if (match)
452 {
453 *last = pgp_principal_key(k);
454 kn = pgp_remove_key(&keys, *last);
455 last = pgp_get_lastp(k);
456 }
457 }
458
459 pgp_key_free(&keys);
460
461 if (matches)
462 {
463 if (oppenc_mode || !isatty(STDIN_FILENO))
464 {
465 const bool c_crypt_opportunistic_encrypt_strong_keys =
466 cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt_strong_keys");
467 if (the_strong_valid_key)
468 {
469 pgp_remove_key(&matches, the_strong_valid_key);
470 k = the_strong_valid_key;
471 }
472 else if (a_valid_addrmatch_key && !c_crypt_opportunistic_encrypt_strong_keys)
473 {
474 pgp_remove_key(&matches, a_valid_addrmatch_key);
475 k = a_valid_addrmatch_key;
476 }
477 else
478 {
479 k = NULL;
480 }
481 }
482 else if (the_strong_valid_key && !multi)
483 {
484 /* There was precisely one strong match on a valid ID.
485 * Proceed without asking the user. */
486 pgp_remove_key(&matches, the_strong_valid_key);
487 k = the_strong_valid_key;
488 }
489 else
490 {
491 /* Else: Ask the user. */
492 k = dlg_pgp(matches, a, NULL);
493 if (k)
494 pgp_remove_key(&matches, k);
495 }
496
497 pgp_key_free(&matches);
498
499 return k;
500 }
501
502 return NULL;
503}
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
#define PGP_KV_STRONGID
PGP Key is strong.
Definition pgpkey.c:79
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:336
#define PGP_KV_MATCH
Definition pgpkey.c:82
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:163
#define PGP_KV_VALID
PGP Key ID is valid.
Definition pgpkey.c:76
#define PGP_KV_ADDR
PGP Key address is valid.
Definition pgpkey.c:77
static struct PgpKeyInfo ** pgp_get_lastp(struct PgpKeyInfo *p)
Get the last PGP key in a list.
Definition pgpkey.c:356
uint8_t PgpKeyValidFlags
Flags for valid Pgp Key fields, e.g. PGP_KV_VALID.
Definition pgpkey.c:74
struct PgpKeyInfo * pgp_principal_key(struct PgpKeyInfo *key)
Get the main (parent) PGP key.
Definition pgpkey.c:89
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 512 of file pgpkey.c.

513{
514 struct ListHead hints = STAILQ_HEAD_INITIALIZER(hints);
515 struct PgpKeyInfo *keys = NULL;
516 struct PgpKeyInfo *matches = NULL;
517 struct PgpKeyInfo **last = &matches;
518 struct PgpKeyInfo *k = NULL, *kn = NULL;
519 struct PgpUid *a = NULL;
520 size_t l;
521 const char *ps = NULL, *pl = NULL, *pfcopy = NULL, *phint = NULL;
522
523 char *p = strdup(cp); // mutt_str_dup converts "" into NULL, see #1809
524 l = mutt_str_len(p);
525 if ((l > 0) && (p[l - 1] == '!'))
526 p[l - 1] = 0;
527
528 mutt_message(_("Looking for keys matching \"%s\"..."), p);
529
530 pfcopy = crypt_get_fingerprint_or_id(p, &phint, &pl, &ps);
531 pgp_add_string_to_hints(phint, &hints);
532 keys = pgp_get_candidates(keyring, &hints);
533 mutt_list_free(&hints);
534
535 for (k = keys; k; k = kn)
536 {
537 kn = k->next;
538 if (abilities && !(k->flags & abilities))
539 continue;
540
541 /* This shouldn't happen, but keys without any addresses aren't selectable
542 * in dlg_pgp(). */
543 if (!k->address)
544 continue;
545
546 bool match = false;
547
548 mutt_debug(LL_DEBUG5, "matching \"%s\" against key %s:\n", p, pgp_long_keyid(k));
549
550 if ((*p == '\0') || (pfcopy && mutt_istr_equal(pfcopy, k->fingerprint)) ||
551 (pl && mutt_istr_equal(pl, pgp_long_keyid(k))) ||
552 (ps && mutt_istr_equal(ps, pgp_short_keyid(k))))
553 {
554 mutt_debug(LL_DEBUG5, " match #1\n");
555 match = true;
556 }
557 else
558 {
559 for (a = k->address; a; a = a->next)
560 {
561 mutt_debug(LL_DEBUG5, "matching \"%s\" against key %s, \"%s\":\n", p,
562 pgp_long_keyid(k), NONULL(a->addr));
563 if (mutt_istr_find(a->addr, p))
564 {
565 mutt_debug(LL_DEBUG5, " match #2\n");
566 match = true;
567 break;
568 }
569 }
570 }
571
572 if (match)
573 {
574 *last = pgp_principal_key(k);
575 kn = pgp_remove_key(&keys, *last);
576 last = pgp_get_lastp(k);
577 }
578 }
579
580 pgp_key_free(&keys);
581
582 k = NULL;
583 if (matches)
584 {
585 if (isatty(STDIN_FILENO))
586 {
587 k = dlg_pgp(matches, NULL, p);
588 if (k)
589 pgp_remove_key(&matches, k);
590 pgp_key_free(&matches);
591 }
592 else if (pgp_keys_are_valid(matches))
593 {
594 k = matches;
595 }
596 else
597 {
598 mutt_error(_("A key can't be used: expired/disabled/revoked"));
599 }
600 }
601
602 FREE(&pfcopy);
603 FREE(&p);
604 return k;
605}
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:117
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 133 of file pgpkey.c.

134{
135 if ((uid->trust & 3) < 3)
136 return false;
137 /* else */
138 return true;
139}
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 146 of file pgpkey.c.

147{
148 if (!pgp_key_is_valid(uid->parent))
149 return false;
150 if (uid->flags & KEYFLAG_CANTUSE)
151 return false;
152 /* else */
153 return true;
154}
#define KEYFLAG_CANTUSE
Definition lib.h:148
bool pgp_key_is_valid(struct PgpKeyInfo *k)
Is a PGP key valid?
Definition pgpkey.c:101
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 117 of file pgpkey.c.

118{
119 for (struct PgpKeyInfo *k = keys; k != NULL; k = k->next)
120 {
121 if (!pgp_key_is_valid(k))
122 return false;
123 }
124
125 return true;
126}
+ 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 101 of file pgpkey.c.

102{
103 struct PgpKeyInfo *pk = pgp_principal_key(k);
104 if (k->flags & KEYFLAG_CANTUSE)
105 return false;
106 if (pk->flags & KEYFLAG_CANTUSE)
107 return false;
108
109 return true;
110}
+ 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 89 of file pgpkey.c.

90{
91 if (key->flags & KEYFLAG_SUBKEY && key->parent)
92 return key->parent;
93 return key;
94}
#define KEYFLAG_SUBKEY
Key is a subkey.
Definition lib.h:143
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 ( void )

Free the PGP IdDefaults cache.

Definition at line 610 of file pgpkey.c.

611{
613 struct PgpCache *l = mod_data->pgp_id_defaults;
614 while (l)
615 {
616 struct PgpCache *next = l->next;
617 FREE(&l->what);
618 FREE(&l->dflt);
619 FREE(&l);
620 l = next;
621 }
622 mod_data->pgp_id_defaults = NULL;
623}
+ Here is the call graph for this function:
+ Here is the caller graph for this function: