NeoMutt  2024-12-12-19-ge4b57e
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:58
#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:514
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:96
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: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 375 of file pgpkey.c.

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

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