NeoMutt  2024-11-14-34-g5aaf0d
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.
 

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

201{
202 struct PgpKeyInfo *key = NULL;
203 struct PgpCache *l = NULL;
204 struct Buffer *resp = buf_pool_get();
205
207
208 if (whatfor)
209 {
210 for (l = IdDefaults; l; l = l->next)
211 {
212 if (mutt_istr_equal(whatfor, l->what))
213 {
214 buf_strcpy(resp, l->dflt);
215 break;
216 }
217 }
218 }
219
220 while (true)
221 {
222 buf_reset(resp);
223 if (mw_get_field(tag, resp, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0)
224 {
225 goto done;
226 }
227
228 if (whatfor)
229 {
230 if (l)
231 {
232 mutt_str_replace(&l->dflt, buf_string(resp));
233 }
234 else
235 {
236 l = MUTT_MEM_MALLOC(1, struct PgpCache);
237 l->next = IdDefaults;
238 IdDefaults = l;
239 l->what = mutt_str_dup(whatfor);
240 l->dflt = buf_strdup(resp);
241 }
242 }
243
244 key = pgp_getkeybystr(buf_string(resp), abilities, keyring);
245 if (key)
246 goto done;
247
248 mutt_error(_("No matching keys found for \"%s\""), buf_string(resp));
249 }
250
251done:
252 buf_pool_release(&resp);
253 return key;
254}
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
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:274
#define mutt_error(...)
Definition: logging2.h:92
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:59
#define MUTT_MEM_MALLOC(n, type)
Definition: memory.h:41
#define _(a)
Definition: message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:672
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:280
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
static struct PgpCache * IdDefaults
Cache of GPGME keys.
Definition: pgpkey.c:74
struct PgpKeyInfo * pgp_getkeybystr(const char *cp, KeyFlags abilities, enum PgpRing keyring)
Find a PGP key by string.
Definition: pgpkey.c:515
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
String manipulation buffer.
Definition: buffer.h:36
List of cached PGP keys.
Definition: pgpkey.c:67
char * dflt
Definition: pgpkey.c:69
struct PgpCache * next
Linked list.
Definition: pgpkey.c:70
char * what
Definition: pgpkey.c:68
Information about a PGP key.
Definition: pgplib.h:48
+ 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 376 of file pgpkey.c.

378{
379 if (!a)
380 return NULL;
381
382 struct ListHead hints = STAILQ_HEAD_INITIALIZER(hints);
383
384 bool multi = false;
385
386 struct PgpKeyInfo *keys = NULL, *k = NULL, *kn = NULL;
387 struct PgpKeyInfo *the_strong_valid_key = NULL;
388 struct PgpKeyInfo *a_valid_addrmatch_key = NULL;
389 struct PgpKeyInfo *matches = NULL;
390 struct PgpKeyInfo **last = &matches;
391 struct PgpUid *q = NULL;
392
393 if (a->mailbox)
395 if (a->personal)
397
398 if (!oppenc_mode)
399 mutt_message(_("Looking for keys matching \"%s\"..."), buf_string(a->mailbox));
400 keys = pgp_get_candidates(keyring, &hints);
401
402 mutt_list_free(&hints);
403
404 if (!keys)
405 return NULL;
406
407 mutt_debug(LL_DEBUG5, "looking for %s <%s>\n", buf_string(a->personal),
408 buf_string(a->mailbox));
409
410 for (k = keys; k; k = kn)
411 {
412 kn = k->next;
413
414 mutt_debug(LL_DEBUG5, " looking at key: %s\n", pgp_keyid(k));
415
416 if (abilities && !(k->flags & abilities))
417 {
418 mutt_debug(LL_DEBUG3, " insufficient abilities: Has %x, want %x\n", k->flags, abilities);
419 continue;
420 }
421
422 bool match = false; /* any match */
423
424 for (q = k->address; q; q = q->next)
425 {
426 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
428 struct Address *qa = NULL;
429 TAILQ_FOREACH(qa, &al, entries)
430 {
431 PgpKeyValidFlags validity = pgp_id_matches_addr(a, qa, q);
432
433 if (validity & PGP_KV_MATCH) /* something matches */
434 match = true;
435
436 if ((validity & PGP_KV_VALID) && (validity & PGP_KV_ADDR))
437 {
438 if (validity & PGP_KV_STRONGID)
439 {
440 if (the_strong_valid_key && (the_strong_valid_key != k))
441 multi = true;
442 the_strong_valid_key = k;
443 }
444 else
445 {
446 a_valid_addrmatch_key = k;
447 }
448 }
449 }
450
452 }
453
454 if (match)
455 {
456 *last = pgp_principal_key(k);
457 kn = pgp_remove_key(&keys, *last);
458 last = pgp_get_lastp(k);
459 }
460 }
461
462 pgp_key_free(&keys);
463
464 if (matches)
465 {
466 if (oppenc_mode || !isatty(STDIN_FILENO))
467 {
468 const bool c_crypt_opportunistic_encrypt_strong_keys =
469 cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt_strong_keys");
470 if (the_strong_valid_key)
471 {
472 pgp_remove_key(&matches, the_strong_valid_key);
473 k = the_strong_valid_key;
474 }
475 else if (a_valid_addrmatch_key && !c_crypt_opportunistic_encrypt_strong_keys)
476 {
477 pgp_remove_key(&matches, a_valid_addrmatch_key);
478 k = a_valid_addrmatch_key;
479 }
480 else
481 {
482 k = NULL;
483 }
484 }
485 else if (the_strong_valid_key && !multi)
486 {
487 /* There was precisely one strong match on a valid ID.
488 * Proceed without asking the user. */
489 pgp_remove_key(&matches, the_strong_valid_key);
490 k = the_strong_valid_key;
491 }
492 else
493 {
494 /* Else: Ask the user. */
495 k = dlg_pgp(matches, a, NULL);
496 if (k)
497 pgp_remove_key(&matches, k);
498 }
499
500 pgp_key_free(&matches);
501
502 return k;
503 }
504
505 return NULL;
506}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1460
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:419
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:613
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
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:45
@ LL_DEBUG5
Log at debug level 5.
Definition: logging2.h:47
char * pgp_keyid(struct PgpKeyInfo *k)
Get the ID of the main (parent) key.
Definition: pgp.c:204
#define PGP_KV_STRONGID
PGP Key is strong.
Definition: pgpkey.c:82
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:339
#define PGP_KV_MATCH
Definition: pgpkey.c:85
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:166
#define PGP_KV_VALID
PGP Key ID is valid.
Definition: pgpkey.c:79
#define PGP_KV_ADDR
PGP Key address is valid.
Definition: pgpkey.c:80
static struct PgpKeyInfo ** pgp_get_lastp(struct PgpKeyInfo *p)
Get the last PGP key in a list.
Definition: pgpkey.c:359
uint8_t PgpKeyValidFlags
Flags for valid Pgp Key fields, e.g. PGP_KV_VALID.
Definition: pgpkey.c:77
struct PgpKeyInfo * pgp_principal_key(struct PgpKeyInfo *key)
Get the main (parent) PGP key.
Definition: pgpkey.c:92
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:725
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
#define NONULL(x)
Definition: string2.h:37
An email address.
Definition: address.h:36
struct Buffer * personal
Real name of address.
Definition: address.h:37
struct Buffer * mailbox
Mailbox and host address.
Definition: address.h:38
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
PGP User ID.
Definition: pgplib.h:35
char * addr
Definition: pgplib.h:36
struct PgpUid * next
Linked list.
Definition: pgplib.h:40
+ 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 515 of file pgpkey.c.

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

137{
138 if ((uid->trust & 3) < 3)
139 return false;
140 /* else */
141 return true;
142}
short trust
Definition: pgplib.h:37
+ 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 149 of file pgpkey.c.

150{
151 if (!pgp_key_is_valid(uid->parent))
152 return false;
153 if (uid->flags & KEYFLAG_CANTUSE)
154 return false;
155 /* else */
156 return true;
157}
#define KEYFLAG_CANTUSE
Definition: lib.h:139
bool pgp_key_is_valid(struct PgpKeyInfo *k)
Is a PGP key valid?
Definition: pgpkey.c:104
struct PgpKeyInfo * parent
Parent key.
Definition: pgplib.h:39
int flags
Definition: pgplib.h:38
+ 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 120 of file pgpkey.c.

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

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

93{
94 if (key->flags & KEYFLAG_SUBKEY && key->parent)
95 return key->parent;
96 return key;
97}
#define KEYFLAG_SUBKEY
Key is a subkey.
Definition: lib.h:134
struct PgpKeyInfo * parent
Definition: pgplib.h:57
+ Here is the caller graph for this function: