NeoMutt  2022-04-29-247-gc6aae8
Teaching an old dog new tricks
DOXYGEN
gpgme_functions.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <ctype.h>
31#include <gpgme.h>
32#include <langinfo.h>
33#include <limits.h>
34#include <stdio.h>
35#include <string.h>
36#include <time.h>
37#include "mutt/lib.h"
38#include "config/lib.h"
39#include "core/lib.h"
40#include "gui/lib.h"
41#include "gpgme_functions.h"
42#include "lib.h"
43#include "menu/lib.h"
44#include "pager/lib.h"
45#include "question/lib.h"
46#include "crypt_gpgme.h"
47#include "mutt_logging.h"
48#include "muttlib.h"
49#include "opcodes.h"
50#include "options.h"
51#ifdef ENABLE_NLS
52#include <libintl.h>
53#endif
54
56
57static const char *const KeyInfoPrompts[] = {
58 /* L10N: The following are the headers for the "verify key" output from the
59 GPGME key selection menu (bound to "c" in the key selection menu).
60 They will be automatically aligned. */
61 N_("Name: "), N_("aka: "), N_("Valid From: "), N_("Valid To: "),
62 N_("Key Type: "), N_("Key Usage: "), N_("Fingerprint: "), N_("Serial-No: "),
63 N_("Issued By: "), N_("Subkey: ")
64};
65
69struct DnArray
70{
71 char *key;
72 char *value;
73};
74
83static void print_utf8(FILE *fp, const char *buf, size_t len)
84{
85 char *tstr = mutt_mem_malloc(len + 1);
86 memcpy(tstr, buf, len);
87 tstr[len] = 0;
88
89 /* fromcode "utf-8" is sure, so we don't want
90 * charset-hook corrections: flags must be 0. */
91 const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
92 mutt_ch_convert_string(&tstr, "utf-8", c_charset, MUTT_ICONV_NO_FLAGS);
93 fputs(tstr, fp);
94 FREE(&tstr);
95}
96
107static bool print_dn_part(FILE *fp, struct DnArray *dn, const char *key)
108{
109 bool any = false;
110
111 for (; dn->key; dn++)
112 {
113 if (strcmp(dn->key, key) == 0)
114 {
115 if (any)
116 fputs(" + ", fp);
117 print_utf8(fp, dn->value, strlen(dn->value));
118 any = true;
119 }
120 }
121 return any;
122}
123
129static void print_dn_parts(FILE *fp, struct DnArray *dn)
130{
131 static const char *const stdpart[] = {
132 "CN", "OU", "O", "STREET", "L", "ST", "C", NULL,
133 };
134 bool any = false;
135 bool any2 = false;
136
137 for (int i = 0; stdpart[i]; i++)
138 {
139 if (any)
140 fputs(", ", fp);
141 any = print_dn_part(fp, dn, stdpart[i]);
142 }
143 /* now print the rest without any specific ordering */
144 for (; dn->key; dn++)
145 {
146 int i;
147 for (i = 0; stdpart[i]; i++)
148 {
149 if (strcmp(dn->key, stdpart[i]) == 0)
150 break;
151 }
152 if (!stdpart[i])
153 {
154 if (any)
155 fputs(", ", fp);
156 if (!any2)
157 fputs("(", fp);
158 any = print_dn_part(fp, dn, dn->key);
159 any2 = true;
160 }
161 }
162 if (any2)
163 fputs(")", fp);
164}
165
174static const char *parse_dn_part(struct DnArray *array, const char *str)
175{
176 const char *s = NULL, *s1 = NULL;
177 size_t n;
178 char *p = NULL;
179
180 /* parse attribute type */
181 for (s = str + 1; (s[0] != '\0') && (s[0] != '='); s++)
182 ; // do nothing
183
184 if (s[0] == '\0')
185 return NULL; /* error */
186 n = s - str;
187 if (n == 0)
188 return NULL; /* empty key */
189 array->key = mutt_mem_malloc(n + 1);
190 p = array->key;
191 memcpy(p, str, n); /* fixme: trim trailing spaces */
192 p[n] = 0;
193 str = s + 1;
194
195 if (*str == '#')
196 { /* hexstring */
197 str++;
198 for (s = str; isxdigit(*s); s++)
199 s++;
200 n = s - str;
201 if ((n == 0) || (n & 1))
202 return NULL; /* empty or odd number of digits */
203 n /= 2;
204 p = mutt_mem_malloc(n + 1);
205 array->value = (char *) p;
206 for (s1 = str; n; s1 += 2, n--)
207 sscanf(s1, "%2hhx", (unsigned char *) p++);
208 *p = '\0';
209 }
210 else
211 { /* regular v3 quoted string */
212 for (n = 0, s = str; *s; s++)
213 {
214 if (*s == '\\')
215 { /* pair */
216 s++;
217 if ((*s == ',') || (*s == '=') || (*s == '+') || (*s == '<') || (*s == '>') ||
218 (*s == '#') || (*s == ';') || (*s == '\\') || (*s == '\"') || (*s == ' '))
219 {
220 n++;
221 }
222 else if (isxdigit(s[0]) && isxdigit(s[1]))
223 {
224 s++;
225 n++;
226 }
227 else
228 return NULL; /* invalid escape sequence */
229 }
230 else if (*s == '\"')
231 return NULL; /* invalid encoding */
232 else if ((*s == ',') || (*s == '=') || (*s == '+') || (*s == '<') ||
233 (*s == '>') || (*s == '#') || (*s == ';'))
234 {
235 break;
236 }
237 else
238 n++;
239 }
240
241 p = mutt_mem_malloc(n + 1);
242 array->value = (char *) p;
243 for (s = str; n; s++, n--)
244 {
245 if (*s == '\\')
246 {
247 s++;
248 if (isxdigit(*s))
249 {
250 sscanf(s, "%2hhx", (unsigned char *) p++);
251 s++;
252 }
253 else
254 *p++ = *s;
255 }
256 else
257 *p++ = *s;
258 }
259 *p = '\0';
260 }
261 return s;
262}
263
272static struct DnArray *parse_dn(const char *str)
273{
274 struct DnArray *array = NULL;
275 size_t arrayidx, arraysize;
276
277 arraysize = 7; /* C,ST,L,O,OU,CN,email */
278 array = mutt_mem_malloc((arraysize + 1) * sizeof(*array));
279 arrayidx = 0;
280 while (*str)
281 {
282 while (str[0] == ' ')
283 str++;
284 if (str[0] == '\0')
285 break; /* ready */
286 if (arrayidx >= arraysize)
287 {
288 /* neomutt lacks a real mutt_mem_realloc - so we need to copy */
289 arraysize += 5;
290 struct DnArray *a2 = mutt_mem_malloc((arraysize + 1) * sizeof(*array));
291 for (int i = 0; i < arrayidx; i++)
292 {
293 a2[i].key = array[i].key;
294 a2[i].value = array[i].value;
295 }
296 FREE(&array);
297 array = a2;
298 }
299 array[arrayidx].key = NULL;
300 array[arrayidx].value = NULL;
301 str = parse_dn_part(array + arrayidx, str);
302 arrayidx++;
303 if (!str)
304 goto failure;
305 while (str[0] == ' ')
306 str++;
307 if ((str[0] != '\0') && (str[0] != ',') && (str[0] != ';') && (str[0] != '+'))
308 goto failure; /* invalid delimiter */
309 if (str[0] != '\0')
310 str++;
311 }
312 array[arrayidx].key = NULL;
313 array[arrayidx].value = NULL;
314 return array;
315
316failure:
317 for (int i = 0; i < arrayidx; i++)
318 {
319 FREE(&array[i].key);
320 FREE(&array[i].value);
321 }
322 FREE(&array);
323 return NULL;
324}
325
334static void parse_and_print_user_id(FILE *fp, const char *userid)
335{
336 const char *s = NULL;
337
338 if (*userid == '<')
339 {
340 s = strchr(userid + 1, '>');
341 if (s)
342 print_utf8(fp, userid + 1, s - userid - 1);
343 }
344 else if (*userid == '(')
345 fputs(_("[Can't display this user ID (unknown encoding)]"), fp);
346 else if (!isalnum(userid[0]))
347 fputs(_("[Can't display this user ID (invalid encoding)]"), fp);
348 else
349 {
350 struct DnArray *dn = parse_dn(userid);
351 if (!dn)
352 fputs(_("[Can't display this user ID (invalid DN)]"), fp);
353 else
354 {
355 print_dn_parts(fp, dn);
356 for (int i = 0; dn[i].key; i++)
357 {
358 FREE(&dn[i].key);
359 FREE(&dn[i].value);
360 }
361 FREE(&dn);
362 }
363 }
364}
365
371static void print_key_info(gpgme_key_t key, FILE *fp)
372{
373 int idx;
374 const char *s = NULL, *s2 = NULL;
375 time_t tt = 0;
376 char shortbuf[128] = { 0 };
377 unsigned long aval = 0;
378 const char *delim = NULL;
379 gpgme_user_id_t uid = NULL;
380 static int max_header_width = 0;
381
382 if (max_header_width == 0)
383 {
384 for (int i = 0; i < KIP_MAX; i++)
385 {
387 const int width = mutt_strwidth(_(KeyInfoPrompts[i]));
388 if (max_header_width < width)
389 max_header_width = width;
390 KeyInfoPadding[i] -= width;
391 }
392 for (int i = 0; i < KIP_MAX; i++)
393 KeyInfoPadding[i] += max_header_width;
394 }
395
396 bool is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
397
398 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
399 {
400 if (uid->revoked)
401 continue;
402
403 s = uid->uid;
404 /* L10N: DOTFILL */
405
406 if (idx == 0)
407 fprintf(fp, "%*s", KeyInfoPadding[KIP_NAME], _(KeyInfoPrompts[KIP_NAME]));
408 else
409 fprintf(fp, "%*s", KeyInfoPadding[KIP_AKA], _(KeyInfoPrompts[KIP_AKA]));
410 if (uid->invalid)
411 {
412 /* L10N: comes after the Name or aka if the key is invalid */
413 fputs(_("[Invalid]"), fp);
414 putc(' ', fp);
415 }
416 if (is_pgp)
417 print_utf8(fp, s, strlen(s));
418 else
420 putc('\n', fp);
421 }
422
423 if (key->subkeys && (key->subkeys->timestamp > 0))
424 {
425 tt = key->subkeys->timestamp;
426
427 mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
428 fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_FROM],
429 _(KeyInfoPrompts[KIP_VALID_FROM]), shortbuf);
430 }
431
432 if (key->subkeys && (key->subkeys->expires > 0))
433 {
434 tt = key->subkeys->expires;
435
436 mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
437 fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_TO],
438 _(KeyInfoPrompts[KIP_VALID_TO]), shortbuf);
439 }
440
441 if (key->subkeys)
442 s = gpgme_pubkey_algo_name(key->subkeys->pubkey_algo);
443 else
444 s = "?";
445
446 s2 = is_pgp ? "PGP" : "X.509";
447
448 if (key->subkeys)
449 aval = key->subkeys->length;
450
452 /* L10N: This is printed after "Key Type: " and looks like this: PGP, 2048 bit RSA */
453 fprintf(fp, ngettext("%s, %lu bit %s\n", "%s, %lu bit %s\n", aval), s2, aval, s);
454
456 delim = "";
457
459 {
460 /* L10N: value in Key Usage: field */
461 fprintf(fp, "%s%s", delim, _("encryption"));
462 delim = _(", ");
463 }
465 {
466 /* L10N: value in Key Usage: field */
467 fprintf(fp, "%s%s", delim, _("signing"));
468 delim = _(", ");
469 }
471 {
472 /* L10N: value in Key Usage: field */
473 fprintf(fp, "%s%s", delim, _("certification"));
474 }
475 putc('\n', fp);
476
477 if (key->subkeys)
478 {
479 s = key->subkeys->fpr;
481 if (is_pgp && (strlen(s) == 40))
482 {
483 for (int i = 0; (s[0] != '\0') && (s[1] != '\0') && (s[2] != '\0') &&
484 (s[3] != '\0') && (s[4] != '\0');
485 s += 4, i++)
486 {
487 putc(*s, fp);
488 putc(s[1], fp);
489 putc(s[2], fp);
490 putc(s[3], fp);
491 putc(' ', fp);
492 if (i == 4)
493 putc(' ', fp);
494 }
495 }
496 else
497 {
498 for (int i = 0; (s[0] != '\0') && (s[1] != '\0') && (s[2] != '\0'); s += 2, i++)
499 {
500 putc(*s, fp);
501 putc(s[1], fp);
502 putc(is_pgp ? ' ' : ':', fp);
503 if (is_pgp && (i == 7))
504 putc(' ', fp);
505 }
506 }
507 fprintf(fp, "%s\n", s);
508 }
509
510 if (key->issuer_serial)
511 {
512 s = key->issuer_serial;
513 fprintf(fp, "%*s0x%s\n", KeyInfoPadding[KIP_SERIAL_NO],
515 }
516
517 if (key->issuer_name)
518 {
519 s = key->issuer_name;
522 putc('\n', fp);
523 }
524
525 /* For PGP we list all subkeys. */
526 if (is_pgp)
527 {
528 gpgme_subkey_t subkey = NULL;
529
530 for (idx = 1, subkey = key->subkeys; subkey; idx++, subkey = subkey->next)
531 {
532 s = subkey->keyid;
533
534 putc('\n', fp);
535 if (strlen(s) == 16)
536 s += 8; /* display only the short keyID */
537 fprintf(fp, "%*s0x%s", KeyInfoPadding[KIP_SUBKEY], _(KeyInfoPrompts[KIP_SUBKEY]), s);
538 if (subkey->revoked)
539 {
540 putc(' ', fp);
541 /* L10N: describes a subkey */
542 fputs(_("[Revoked]"), fp);
543 }
544 if (subkey->invalid)
545 {
546 putc(' ', fp);
547 /* L10N: describes a subkey */
548 fputs(_("[Invalid]"), fp);
549 }
550 if (subkey->expired)
551 {
552 putc(' ', fp);
553 /* L10N: describes a subkey */
554 fputs(_("[Expired]"), fp);
555 }
556 if (subkey->disabled)
557 {
558 putc(' ', fp);
559 /* L10N: describes a subkey */
560 fputs(_("[Disabled]"), fp);
561 }
562 putc('\n', fp);
563
564 if (subkey->timestamp > 0)
565 {
566 tt = subkey->timestamp;
567
568 mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
569 fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_FROM],
570 _(KeyInfoPrompts[KIP_VALID_FROM]), shortbuf);
571 }
572
573 if (subkey->expires > 0)
574 {
575 tt = subkey->expires;
576
577 mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
578 fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_TO],
579 _(KeyInfoPrompts[KIP_VALID_TO]), shortbuf);
580 }
581
582 s = gpgme_pubkey_algo_name(subkey->pubkey_algo);
583
584 aval = subkey->length;
585
587 /* L10N: This is printed after "Key Type: " and looks like this: PGP, 2048 bit RSA */
588 fprintf(fp, ngettext("%s, %lu bit %s\n", "%s, %lu bit %s\n", aval), "PGP", aval, s);
589
591 delim = "";
592
593 if (subkey->can_encrypt)
594 {
595 fprintf(fp, "%s%s", delim, _("encryption"));
596 delim = _(", ");
597 }
598 if (subkey->can_sign)
599 {
600 fprintf(fp, "%s%s", delim, _("signing"));
601 delim = _(", ");
602 }
603 if (subkey->can_certify)
604 {
605 fprintf(fp, "%s%s", delim, _("certification"));
606 }
607 putc('\n', fp);
608 }
609 }
610}
611
616static void verify_key(struct CryptKeyInfo *key)
617{
618 const char *s = NULL;
619 gpgme_ctx_t listctx = NULL;
620 gpgme_error_t err;
621 gpgme_key_t k = NULL;
622 int maxdepth = 100;
623
624 struct Buffer tempfile = mutt_buffer_make(PATH_MAX);
625 mutt_buffer_mktemp(&tempfile);
626 FILE *fp = mutt_file_fopen(mutt_buffer_string(&tempfile), "w");
627 if (!fp)
628 {
629 mutt_perror(_("Can't create temporary file"));
630 goto cleanup;
631 }
632 mutt_message(_("Collecting data..."));
633
634 print_key_info(key->kobj, fp);
635
636 listctx = create_gpgme_context(key->flags & KEYFLAG_ISX509);
637
638 k = key->kobj;
639 gpgme_key_ref(k);
640 while ((s = k->chain_id) && k->subkeys && (strcmp(s, k->subkeys->fpr) != 0))
641 {
642 putc('\n', fp);
643 err = gpgme_op_keylist_start(listctx, s, 0);
644 gpgme_key_unref(k);
645 k = NULL;
646 if (err == 0)
647 err = gpgme_op_keylist_next(listctx, &k);
648 if (err != 0)
649 {
650 fprintf(fp, _("Error finding issuer key: %s\n"), gpgme_strerror(err));
651 goto leave;
652 }
653 gpgme_op_keylist_end(listctx);
654
655 print_key_info(k, fp);
656 if (!--maxdepth)
657 {
658 putc('\n', fp);
659 fputs(_("Error: certification chain too long - stopping here\n"), fp);
660 break;
661 }
662 }
663
664leave:
665 gpgme_key_unref(k);
666 gpgme_release(listctx);
667 mutt_file_fclose(&fp);
669 char title[1024] = { 0 };
670 snprintf(title, sizeof(title), _("Key ID: 0x%s"), crypt_keyid(key));
671
672 struct PagerData pdata = { 0 };
673 struct PagerView pview = { &pdata };
674
675 pdata.fname = mutt_buffer_string(&tempfile);
676
677 pview.banner = title;
679 pview.mode = PAGER_MODE_OTHER;
680
681 mutt_do_pager(&pview, NULL);
682
683cleanup:
684 mutt_buffer_dealloc(&tempfile);
685}
686
692static bool crypt_key_is_valid(struct CryptKeyInfo *k)
693{
694 if (k->flags & KEYFLAG_CANTUSE)
695 return false;
696 return true;
697}
698
699// -----------------------------------------------------------------------------
700
704static int op_exit(struct GpgmeData *gd, int op)
705{
706 gd->done = true;
707 return FR_SUCCESS;
708}
709
713static int op_generic_select_entry(struct GpgmeData *gd, int op)
714{
715 const int index = menu_get_index(gd->menu);
716 struct CryptKeyInfo *cur_key = gd->key_table[index];
717 /* FIXME make error reporting more verbose - this should be
718 * easy because GPGME provides more information */
720 {
721 if (!crypt_key_is_valid(cur_key))
722 {
723 mutt_error(_("This key can't be used: expired/disabled/revoked"));
724 return FR_ERROR;
725 }
726 }
727
728 if (OptPgpCheckTrust && (!crypt_id_is_valid(cur_key) || !crypt_id_is_strong(cur_key)))
729 {
730 const char *warn_s = NULL;
731 char buf2[1024];
732
733 if (cur_key->flags & KEYFLAG_CANTUSE)
734 {
735 warn_s = _("ID is expired/disabled/revoked. Do you really want to use the key?");
736 }
737 else
738 {
739 warn_s = "??";
740 switch (cur_key->validity)
741 {
742 case GPGME_VALIDITY_NEVER:
743 warn_s = _("ID is not valid. Do you really want to use the key?");
744 break;
745 case GPGME_VALIDITY_MARGINAL:
746 warn_s = _("ID is only marginally valid. Do you really want to use the key?");
747 break;
748 case GPGME_VALIDITY_FULL:
749 case GPGME_VALIDITY_ULTIMATE:
750 break;
751 case GPGME_VALIDITY_UNKNOWN:
752 case GPGME_VALIDITY_UNDEFINED:
753 warn_s = _("ID has undefined validity. Do you really want to use the key?");
754 break;
755 }
756 }
757
758 snprintf(buf2, sizeof(buf2), "%s", warn_s);
759
760 if (mutt_yesorno(buf2, MUTT_NO) != MUTT_YES)
761 {
763 return FR_NO_ACTION;
764 }
765 }
766
767 gd->key = crypt_copy_key(cur_key);
768 gd->done = true;
769 return FR_SUCCESS;
770}
771
775static int op_verify_key(struct GpgmeData *gd, int op)
776{
777 const int index = menu_get_index(gd->menu);
778 struct CryptKeyInfo *cur_key = gd->key_table[index];
779 verify_key(cur_key);
781 return FR_SUCCESS;
782}
783
787static int op_view_id(struct GpgmeData *gd, int op)
788{
789 const int index = menu_get_index(gd->menu);
790 struct CryptKeyInfo *cur_key = gd->key_table[index];
791 mutt_message("%s", cur_key->uid);
792 return FR_SUCCESS;
793}
794
795// -----------------------------------------------------------------------------
796
801 // clang-format off
802 { OP_EXIT, op_exit },
803 { OP_GENERIC_SELECT_ENTRY, op_generic_select_entry },
804 { OP_VERIFY_KEY, op_verify_key },
805 { OP_VIEW_ID, op_view_id },
806 { 0, NULL },
807 // clang-format on
808};
809
814{
815 if (!win || !win->wdata)
816 return FR_UNKNOWN;
817
818 struct MuttWindow *dlg = dialog_find(win);
819 if (!dlg)
820 return FR_ERROR;
821
822 struct GpgmeData *gd = dlg->wdata;
823
824 int rc = FR_UNKNOWN;
825 for (size_t i = 0; GpgmeFunctions[i].op != OP_NULL; i++)
826 {
827 const struct GpgmeFunction *fn = &GpgmeFunctions[i];
828 if (fn->op == op)
829 {
830 rc = fn->function(gd, op);
831 break;
832 }
833 }
834
835 if (rc == FR_UNKNOWN) // Not our function
836 return rc;
837
838 const char *result = dispacher_get_retval_name(rc);
839 mutt_debug(LL_DEBUG1, "Handled %s (%d) -> %s\n", opcodes_get_name(op), op, NONULL(result));
840
841 return rc;
842}
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:67
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:309
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
struct CryptKeyInfo * crypt_copy_key(struct CryptKeyInfo *key)
Return a copy of KEY.
Definition: crypt_gpgme.c:234
int crypt_id_is_valid(struct CryptKeyInfo *key)
Is key ID valid.
Definition: crypt_gpgme.c:310
bool crypt_id_is_strong(struct CryptKeyInfo *key)
Is the key strong.
Definition: crypt_gpgme.c:275
unsigned int key_check_cap(gpgme_key_t key, enum KeyCap cap)
Check the capabilities of a key.
Definition: crypt_gpgme.c:2837
const char * crypt_keyid(struct CryptKeyInfo *k)
Find the ID for the key.
Definition: crypt_gpgme.c:138
Wrapper for PGP/SMIME calls to GPGME.
@ KIP_FINGERPRINT
PGP Key field: Fingerprint.
Definition: crypt_gpgme.h:64
@ KIP_SERIAL_NO
PGP Key field: Serial number.
Definition: crypt_gpgme.h:65
@ KIP_SUBKEY
PGP Key field: Subkey.
Definition: crypt_gpgme.h:67
@ KIP_AKA
PGP Key field: aka (Also Known As)
Definition: crypt_gpgme.h:59
@ KIP_VALID_FROM
PGP Key field: Valid From date.
Definition: crypt_gpgme.h:60
@ KIP_MAX
Definition: crypt_gpgme.h:68
@ KIP_KEY_TYPE
PGP Key field: Key Type.
Definition: crypt_gpgme.h:62
@ KIP_NAME
PGP Key field: Name.
Definition: crypt_gpgme.h:58
@ KIP_ISSUED_BY
PGP Key field: Issued By.
Definition: crypt_gpgme.h:66
@ KIP_KEY_USAGE
PGP Key field: Key Usage.
Definition: crypt_gpgme.h:63
@ KIP_VALID_TO
PGP Key field: Valid To date.
Definition: crypt_gpgme.h:61
@ KEY_CAP_CAN_CERTIFY
Key can be used to certify.
Definition: crypt_gpgme.h:78
@ KEY_CAP_CAN_ENCRYPT
Key can be used for encryption.
Definition: crypt_gpgme.h:76
@ KEY_CAP_CAN_SIGN
Key can be used for signing.
Definition: crypt_gpgme.h:77
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition: curs_lib.c:907
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:692
struct MuttWindow * dialog_find(struct MuttWindow *win)
Find the parent Dialog of a Window.
Definition: dialog.c:83
const char * dispacher_get_retval_name(int rv)
Get the name of a return value.
Definition: dispatcher.c:54
@ FR_SUCCESS
Valid function - successfully performed.
Definition: dispatcher.h:39
@ FR_UNKNOWN
Unknown function.
Definition: dispatcher.h:33
@ FR_ERROR
Valid function - error occurred.
Definition: dispatcher.h:38
@ FR_NO_ACTION
Valid function - no action performed.
Definition: dispatcher.h:37
int mutt_do_pager(struct PagerView *pview, struct Email *e)
Display some page-able text to the user (help or attachment)
Definition: do_pager.c:123
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
static int create_gpgme_context(gpgme_ctx_t *ctx)
Create a GPGME context.
Definition: gpgme.c:48
static const char *const KeyInfoPrompts[]
int KeyInfoPadding[KIP_MAX]
static void parse_and_print_user_id(FILE *fp, const char *userid)
Print a nice representation of the userid.
static struct DnArray * parse_dn(const char *str)
Parse a DN and return an array-ized one.
static void print_key_info(gpgme_key_t key, FILE *fp)
Verbose information about a key or certificate to a file.
static void print_utf8(FILE *fp, const char *buf, size_t len)
Write a UTF-8 string to a file.
static bool print_dn_part(FILE *fp, struct DnArray *dn, const char *key)
Print the X.500 Distinguished Name.
struct GpgmeFunction GpgmeFunctions[]
All the NeoMutt functions that the Gpgme supports.
static bool crypt_key_is_valid(struct CryptKeyInfo *k)
Is the key valid.
static void verify_key(struct CryptKeyInfo *key)
Show detailed information about the selected key.
static void print_dn_parts(FILE *fp, struct DnArray *dn)
Print all parts of a DN in a standard sequence.
static const char * parse_dn_part(struct DnArray *array, const char *str)
Parse an RDN.
Gpgme functions.
int gpgme_function_dispatcher(struct MuttWindow *win, int op)
Perform a Gpgme function - Implements function_dispatcher_t -.
static int op_exit(struct GpgmeData *gd, int op)
Exit this menu - Implements gpgme_function_t -.
static int op_generic_select_entry(struct GpgmeData *gd, int op)
Select the current entry - Implements gpgme_function_t -.
static int op_view_id(struct GpgmeData *gd, int op)
View the key's user id - Implements gpgme_function_t -.
static int op_verify_key(struct GpgmeData *gd, int op)
Verify a PGP public key - Implements gpgme_function_t -.
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
#define mutt_perror(...)
Definition: logging.h:88
Convenience wrapper for the gui headers.
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:43
GUI present the user with a selectable list.
#define MENU_REDRAW_FULL
Redraw everything.
Definition: lib.h:59
void menu_queue_redraw(struct Menu *menu, MenuRedrawFlags redraw)
Queue a request for a redraw.
Definition: menu.c:178
int menu_get_index(struct Menu *menu)
Get the current selection in the Menu.
Definition: menu.c:154
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:752
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
Convenience wrapper for the library headers.
#define N_(a)
Definition: message.h:32
#define _(a)
Definition: message.h:28
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
#define PATH_MAX
Definition: mutt.h:40
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
NeoMutt Logging.
Some miscellaneous functions.
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
#define KEYFLAG_ISX509
Key is an X.509 key.
Definition: lib.h:129
#define KEYFLAG_CANTUSE
Definition: lib.h:139
const char * opcodes_get_name(int op)
Get the name of an opcode.
Definition: opcodes.c:46
All user-callable functions.
Handling of global boolean variables.
bool OptPgpCheckTrust
(pseudo) used by dlg_select_pgp_key()
Definition: options.h:54
GUI display a file/email/help in a viewport with paging.
#define MUTT_PAGER_NO_FLAGS
No flags are set.
Definition: lib.h:58
@ PAGER_MODE_OTHER
Pager is invoked via 3rd path. Non-email content is likely to be shown.
Definition: lib.h:139
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition: quad.h:38
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
Ask the user a question.
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:194
Key value store.
#define NONULL(x)
Definition: string2.h:37
String manipulation buffer.
Definition: buffer.h:34
A stored PGP key.
Definition: crypt_gpgme.h:44
gpgme_validity_t validity
uid validity (cached for convenience)
Definition: crypt_gpgme.h:50
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.h:49
const char * uid
and for convenience point to this user ID
Definition: crypt_gpgme.h:48
gpgme_key_t kobj
Definition: crypt_gpgme.h:46
An X500 Distinguished Name.
char * key
Key.
char * value
Value.
Data to pass to the Gpgme Functions.
struct CryptKeyInfo * key
Selected Key.
struct CryptKeyInfo ** key_table
Array of Keys.
bool done
Should we close the Dialog?
struct Menu * menu
Gpgme Menu.
A NeoMutt function.
gpgme_function_t function
Function to call.
int op
Op code, e.g. OP_GENERIC_SELECT_ENTRY.
void * wdata
Private data.
Definition: mutt_window.h:145
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Data to be displayed by PagerView.
Definition: lib.h:158
const char * fname
Name of the file to read.
Definition: lib.h:162
Paged view into some data.
Definition: lib.h:169
struct PagerData * pdata
Data that pager displays. NOTNULL.
Definition: lib.h:170
enum PagerMode mode
Pager mode.
Definition: lib.h:171
PagerFlags flags
Additional settings to tweak pager's function.
Definition: lib.h:172
const char * banner
Title to display in status bar.
Definition: lib.h:173