NeoMutt  2023-03-22
Teaching an old dog new tricks
DOXYGEN
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)
 Implements CryptModuleSpecs::pgp_make_key_attachment() -. More...
 
struct PgpKeyInfopgp_ask_for_key (char *tag, char *whatfor, KeyFlags abilities, enum PgpRing keyring)
 Ask the user for a PGP key. More...
 
struct PgpKeyInfopgp_getkeybyaddr (struct Address *a, KeyFlags abilities, enum PgpRing keyring, bool oppenc_mode)
 Find a PGP key by address. More...
 
struct PgpKeyInfopgp_getkeybystr (const char *p, KeyFlags abilities, enum PgpRing keyring)
 Find a PGP key by string. More...
 
struct PgpKeyInfopgp_principal_key (struct PgpKeyInfo *key)
 Get the main (parent) PGP key. More...
 
bool pgp_key_is_valid (struct PgpKeyInfo *k)
 Is a PGP key valid? More...
 
bool pgp_id_is_valid (struct PgpUid *uid)
 Is a PGP key valid. More...
 
bool pgp_id_is_strong (struct PgpUid *uid)
 Is a PGP key strong? More...
 

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

181{
182 struct PgpKeyInfo *key = NULL;
183 struct PgpCache *l = NULL;
184 struct Buffer *resp = mutt_buffer_pool_get();
185
187
188 if (whatfor)
189 {
190 for (l = id_defaults; l; l = l->next)
191 {
192 if (mutt_istr_equal(whatfor, l->what))
193 {
194 mutt_buffer_strcpy(resp, l->dflt);
195 break;
196 }
197 }
198 }
199
200 while (true)
201 {
202 mutt_buffer_reset(resp);
203 if (mutt_buffer_get_field(tag, resp, MUTT_COMP_NO_FLAGS, false, NULL, NULL, NULL) != 0)
204 {
205 goto done;
206 }
207
208 if (whatfor)
209 {
210 if (l)
212 else
213 {
214 l = mutt_mem_malloc(sizeof(struct PgpCache));
215 l->next = id_defaults;
216 id_defaults = l;
217 l->what = mutt_str_dup(whatfor);
218 l->dflt = mutt_buffer_strdup(resp);
219 }
220 }
221
222 key = pgp_getkeybystr(mutt_buffer_string(resp), abilities, keyring);
223 if (key)
224 goto done;
225
226 mutt_error(_("No matching keys found for \"%s\""), mutt_buffer_string(resp));
227 }
228
229done:
231 return key;
232}
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:365
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:485
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:78
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: window.c:178
#define mutt_error(...)
Definition: logging.h:87
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define _(a)
Definition: message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:819
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:55
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
static struct PgpCache * id_defaults
Definition: pgpkey.c:70
struct PgpKeyInfo * pgp_getkeybystr(const char *cp, KeyFlags abilities, enum PgpRing keyring)
Find a PGP key by string.
Definition: pgpkey.c:490
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
String manipulation buffer.
Definition: buffer.h:34
List of cached PGP keys.
Definition: pgpkey.c:64
char * dflt
Definition: pgpkey.c:66
struct PgpCache * next
Linked list.
Definition: pgpkey.c:67
char * what
Definition: pgpkey.c:65
Information about a PGP key.
Definition: pgplib.h:47
+ 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 354 of file pgpkey.c.

356{
357 if (!a)
358 return NULL;
359
360 struct ListHead hints = STAILQ_HEAD_INITIALIZER(hints);
361
362 bool multi = false;
363
364 struct PgpKeyInfo *keys = NULL, *k = NULL, *kn = NULL;
365 struct PgpKeyInfo *the_strong_valid_key = NULL;
366 struct PgpKeyInfo *a_valid_addrmatch_key = NULL;
367 struct PgpKeyInfo *matches = NULL;
368 struct PgpKeyInfo **last = &matches;
369 struct PgpUid *q = NULL;
370
371 if (a->mailbox)
373 if (a->personal)
375
376 if (!oppenc_mode)
377 mutt_message(_("Looking for keys matching \"%s\"..."), a->mailbox);
378 keys = pgp_get_candidates(keyring, &hints);
379
380 mutt_list_free(&hints);
381
382 if (!keys)
383 return NULL;
384
385 mutt_debug(LL_DEBUG5, "looking for %s <%s>\n", NONULL(a->personal), NONULL(a->mailbox));
386
387 for (k = keys; k; k = kn)
388 {
389 kn = k->next;
390
391 mutt_debug(LL_DEBUG5, " looking at key: %s\n", pgp_keyid(k));
392
393 if (abilities && !(k->flags & abilities))
394 {
395 mutt_debug(LL_DEBUG3, " insufficient abilities: Has %x, want %x\n", k->flags, abilities);
396 continue;
397 }
398
399 bool match = false; /* any match */
400
401 for (q = k->address; q; q = q->next)
402 {
403 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
405 struct Address *qa = NULL;
406 TAILQ_FOREACH(qa, &al, entries)
407 {
408 PgpKeyValidFlags validity = pgp_id_matches_addr(a, qa, q);
409
410 if (validity & PGP_KV_MATCH) /* something matches */
411 match = true;
412
413 if ((validity & PGP_KV_VALID) && (validity & PGP_KV_ADDR))
414 {
415 if (validity & PGP_KV_STRONGID)
416 {
417 if (the_strong_valid_key && (the_strong_valid_key != k))
418 multi = true;
419 the_strong_valid_key = k;
420 }
421 else
422 {
423 a_valid_addrmatch_key = k;
424 }
425 }
426 }
427
429 }
430
431 if (match)
432 {
433 *last = pgp_principal_key(k);
434 kn = pgp_remove_key(&keys, *last);
435 last = pgp_get_lastp(k);
436 }
437 }
438
439 pgp_key_free(&keys);
440
441 if (matches)
442 {
443 if (oppenc_mode)
444 {
445 const bool c_crypt_opportunistic_encrypt_strong_keys =
446 cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt_strong_keys");
447 if (the_strong_valid_key)
448 {
449 pgp_remove_key(&matches, the_strong_valid_key);
450 k = the_strong_valid_key;
451 }
452 else if (a_valid_addrmatch_key && !c_crypt_opportunistic_encrypt_strong_keys)
453 {
454 pgp_remove_key(&matches, a_valid_addrmatch_key);
455 k = a_valid_addrmatch_key;
456 }
457 else
458 k = NULL;
459 }
460 else if (the_strong_valid_key && !multi)
461 {
462 /* There was precisely one strong match on a valid ID.
463 * Proceed without asking the user. */
464 pgp_remove_key(&matches, the_strong_valid_key);
465 k = the_strong_valid_key;
466 }
467 else
468 {
469 /* Else: Ask the user. */
470 k = dlg_select_pgp_key(matches, a, NULL);
471 if (k)
472 pgp_remove_key(&matches, k);
473 }
474
475 pgp_key_free(&matches);
476
477 return k;
478 }
479
480 return NULL;
481}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1435
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
struct PgpKeyInfo * dlg_select_pgp_key(struct PgpKeyInfo *keys, struct Address *p, const char *s)
Let the user select a key to use.
Definition: dlg_pgp.c:586
struct PgpKeyInfo * pgp_get_candidates(enum PgpRing keyring, struct ListHead *hints)
Find PGP keys matching a list of hints.
Definition: gnupgparse.c:415
#define mutt_message(...)
Definition: logging.h:86
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
@ LL_DEBUG5
Log at debug level 5.
Definition: logging.h:44
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:78
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:317
#define PGP_KV_MATCH
Definition: pgpkey.c:81
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:146
#define PGP_KV_VALID
PGP Key ID is valid.
Definition: pgpkey.c:75
#define PGP_KV_ADDR
PGP Key address is valid.
Definition: pgpkey.c:76
static struct PgpKeyInfo ** pgp_get_lastp(struct PgpKeyInfo *p)
Get the last PGP key in a list.
Definition: pgpkey.c:337
uint8_t PgpKeyValidFlags
Flags for valid Pgp Key fields, e.g. PGP_KV_VALID.
Definition: pgpkey.c:73
struct PgpKeyInfo * pgp_principal_key(struct PgpKeyInfo *key)
Get the main (parent) PGP key.
Definition: pgpkey.c:88
void pgp_key_free(struct PgpKeyInfo **kpp)
Free a PGP key info.
Definition: pgplib.c:199
struct PgpKeyInfo * pgp_remove_key(struct PgpKeyInfo **klist, struct PgpKeyInfo *key)
Remove a PGP key from a list.
Definition: pgplib.c:167
#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
char * mailbox
Mailbox and host address.
Definition: address.h:38
char * personal
Real name of address.
Definition: address.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
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 490 of file pgpkey.c.

491{
492 struct ListHead hints = STAILQ_HEAD_INITIALIZER(hints);
493 struct PgpKeyInfo *keys = NULL;
494 struct PgpKeyInfo *matches = NULL;
495 struct PgpKeyInfo **last = &matches;
496 struct PgpKeyInfo *k = NULL, *kn = NULL;
497 struct PgpUid *a = NULL;
498 size_t l;
499 const char *ps = NULL, *pl = NULL, *pfcopy = NULL, *phint = NULL;
500
501 char *p = strdup(cp); // mutt_str_dup converts "" into NULL, see #1809
502 l = mutt_str_len(p);
503 if ((l > 0) && (p[l - 1] == '!'))
504 p[l - 1] = 0;
505
506 mutt_message(_("Looking for keys matching \"%s\"..."), p);
507
508 pfcopy = crypt_get_fingerprint_or_id(p, &phint, &pl, &ps);
509 pgp_add_string_to_hints(phint, &hints);
510 keys = pgp_get_candidates(keyring, &hints);
511 mutt_list_free(&hints);
512
513 for (k = keys; k; k = kn)
514 {
515 kn = k->next;
516 if (abilities && !(k->flags & abilities))
517 continue;
518
519 /* This shouldn't happen, but keys without any addresses aren't selectable
520 * in dlg_select_pgp_key(). */
521 if (!k->address)
522 continue;
523
524 bool match = false;
525
526 mutt_debug(LL_DEBUG5, "matching \"%s\" against key %s:\n", p, pgp_long_keyid(k));
527
528 if ((*p == '\0') || (pfcopy && mutt_istr_equal(pfcopy, k->fingerprint)) ||
529 (pl && mutt_istr_equal(pl, pgp_long_keyid(k))) ||
530 (ps && mutt_istr_equal(ps, pgp_short_keyid(k))))
531 {
532 mutt_debug(LL_DEBUG5, " match #1\n");
533 match = true;
534 }
535 else
536 {
537 for (a = k->address; a; a = a->next)
538 {
539 mutt_debug(LL_DEBUG5, "matching \"%s\" against key %s, \"%s\":\n", p,
540 pgp_long_keyid(k), NONULL(a->addr));
541 if (mutt_istr_find(a->addr, p))
542 {
543 mutt_debug(LL_DEBUG5, " match #2\n");
544 match = true;
545 break;
546 }
547 }
548 }
549
550 if (match)
551 {
552 *last = pgp_principal_key(k);
553 kn = pgp_remove_key(&keys, *last);
554 last = pgp_get_lastp(k);
555 }
556 }
557
558 pgp_key_free(&keys);
559
560 if (matches)
561 {
562 k = dlg_select_pgp_key(matches, NULL, p);
563 if (k)
564 pgp_remove_key(&matches, k);
565 pgp_key_free(&matches);
566 }
567 else
568 {
569 k = NULL;
570 }
571
572 FREE(&pfcopy);
573 FREE(&p);
574 return k;
575}
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:1262
#define FREE(x)
Definition: memory.h:43
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:592
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
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
KeyFlags flags
Definition: pgplib.h:51
struct PgpKeyInfo * next
Definition: pgplib.h:57
struct PgpUid * address
Definition: pgplib.h:50
char * fingerprint
Definition: pgplib.h:49
+ 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 88 of file pgpkey.c.

89{
90 if (key->flags & KEYFLAG_SUBKEY && key->parent)
91 return key->parent;
92 return key;
93}
#define KEYFLAG_SUBKEY
Key is a subkey.
Definition: lib.h:134
struct PgpKeyInfo * parent
Definition: pgplib.h:56
+ 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 100 of file pgpkey.c.

101{
102 struct PgpKeyInfo *pk = pgp_principal_key(k);
103 if (k->flags & KEYFLAG_CANTUSE)
104 return false;
105 if (pk->flags & KEYFLAG_CANTUSE)
106 return false;
107
108 return true;
109}
#define KEYFLAG_CANTUSE
Definition: lib.h:139
+ Here is the call graph for this function:
+ 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 129 of file pgpkey.c.

130{
131 if (!pgp_key_is_valid(uid->parent))
132 return false;
133 if (uid->flags & KEYFLAG_CANTUSE)
134 return false;
135 /* else */
136 return true;
137}
bool pgp_key_is_valid(struct PgpKeyInfo *k)
Is a PGP key valid?
Definition: pgpkey.c:100
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_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 116 of file pgpkey.c.

117{
118 if ((uid->trust & 3) < 3)
119 return false;
120 /* else */
121 return true;
122}
short trust
Definition: pgplib.h:37
+ Here is the caller graph for this function: