NeoMutt  2023-11-03-85-g512e01
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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 "globals.h"
48#include "mutt_logging.h"
49#ifdef ENABLE_NLS
50#include <libintl.h>
51#endif
52
55
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. */
92 fputs(tstr, fp);
93 FREE(&tstr);
94}
95
106static bool print_dn_part(FILE *fp, struct DnArray *dn, const char *key)
107{
108 bool any = false;
109
110 for (; dn->key; dn++)
111 {
112 if (mutt_str_equal(dn->key, key))
113 {
114 if (any)
115 fputs(" + ", fp);
116 print_utf8(fp, dn->value, strlen(dn->value));
117 any = true;
118 }
119 }
120 return any;
121}
122
128static void print_dn_parts(FILE *fp, struct DnArray *dn)
129{
130 static const char *const stdpart[] = {
131 "CN", "OU", "O", "STREET", "L", "ST", "C", NULL,
132 };
133 bool any = false;
134 bool any2 = false;
135
136 for (int i = 0; stdpart[i]; i++)
137 {
138 if (any)
139 fputs(", ", fp);
140 any = print_dn_part(fp, dn, stdpart[i]);
141 }
142 /* now print the rest without any specific ordering */
143 for (; dn->key; dn++)
144 {
145 int i;
146 for (i = 0; stdpart[i]; i++)
147 {
148 if (mutt_str_equal(dn->key, stdpart[i]))
149 break;
150 }
151 if (!stdpart[i])
152 {
153 if (any)
154 fputs(", ", fp);
155 if (!any2)
156 fputs("(", fp);
157 any = print_dn_part(fp, dn, dn->key);
158 any2 = true;
159 }
160 }
161 if (any2)
162 fputs(")", fp);
163}
164
173static const char *parse_dn_part(struct DnArray *array, const char *str)
174{
175 const char *s = NULL, *s1 = NULL;
176 size_t n;
177 char *p = NULL;
178
179 /* parse attribute type */
180 for (s = str + 1; (s[0] != '\0') && (s[0] != '='); s++)
181 ; // do nothing
182
183 if (s[0] == '\0')
184 return NULL; /* error */
185 n = s - str;
186 if (n == 0)
187 return NULL; /* empty key */
188 array->key = mutt_mem_malloc(n + 1);
189 p = array->key;
190 memcpy(p, str, n); /* fixme: trim trailing spaces */
191 p[n] = 0;
192 str = s + 1;
193
194 if (*str == '#')
195 { /* hexstring */
196 str++;
197 for (s = str; isxdigit(*s); s++)
198 s++;
199 n = s - str;
200 if ((n == 0) || (n & 1))
201 return NULL; /* empty or odd number of digits */
202 n /= 2;
203 p = mutt_mem_malloc(n + 1);
204 array->value = (char *) p;
205 for (s1 = str; n; s1 += 2, n--)
206 sscanf(s1, "%2hhx", (unsigned char *) p++);
207 *p = '\0';
208 }
209 else
210 { /* regular v3 quoted string */
211 for (n = 0, s = str; *s; s++)
212 {
213 if (*s == '\\')
214 { /* pair */
215 s++;
216 if ((*s == ',') || (*s == '=') || (*s == '+') || (*s == '<') || (*s == '>') ||
217 (*s == '#') || (*s == ';') || (*s == '\\') || (*s == '\"') || (*s == ' '))
218 {
219 n++;
220 }
221 else if (isxdigit(s[0]) && isxdigit(s[1]))
222 {
223 s++;
224 n++;
225 }
226 else
227 {
228 return NULL; /* invalid escape sequence */
229 }
230 }
231 else if (*s == '\"')
232 {
233 return NULL; /* invalid encoding */
234 }
235 else if ((*s == ',') || (*s == '=') || (*s == '+') || (*s == '<') ||
236 (*s == '>') || (*s == '#') || (*s == ';'))
237 {
238 break;
239 }
240 else
241 {
242 n++;
243 }
244 }
245
246 p = mutt_mem_malloc(n + 1);
247 array->value = (char *) p;
248 for (s = str; n; s++, n--)
249 {
250 if (*s == '\\')
251 {
252 s++;
253 if (isxdigit(*s))
254 {
255 sscanf(s, "%2hhx", (unsigned char *) p++);
256 s++;
257 }
258 else
259 {
260 *p++ = *s;
261 }
262 }
263 else
264 {
265 *p++ = *s;
266 }
267 }
268 *p = '\0';
269 }
270 return s;
271}
272
281static struct DnArray *parse_dn(const char *str)
282{
283 struct DnArray *array = NULL;
284 size_t arrayidx, arraysize;
285
286 arraysize = 7; /* C,ST,L,O,OU,CN,email */
287 array = mutt_mem_malloc((arraysize + 1) * sizeof(*array));
288 arrayidx = 0;
289 while (*str)
290 {
291 while (str[0] == ' ')
292 str++;
293 if (str[0] == '\0')
294 break; /* ready */
295 if (arrayidx >= arraysize)
296 {
297 /* neomutt lacks a real mutt_mem_realloc - so we need to copy */
298 arraysize += 5;
299 struct DnArray *a2 = mutt_mem_malloc((arraysize + 1) * sizeof(*array));
300 for (int i = 0; i < arrayidx; i++)
301 {
302 a2[i].key = array[i].key;
303 a2[i].value = array[i].value;
304 }
305 FREE(&array);
306 array = a2;
307 }
308 array[arrayidx].key = NULL;
309 array[arrayidx].value = NULL;
310 str = parse_dn_part(array + arrayidx, str);
311 arrayidx++;
312 if (!str)
313 goto failure;
314 while (str[0] == ' ')
315 str++;
316 if ((str[0] != '\0') && (str[0] != ',') && (str[0] != ';') && (str[0] != '+'))
317 goto failure; /* invalid delimiter */
318 if (str[0] != '\0')
319 str++;
320 }
321 array[arrayidx].key = NULL;
322 array[arrayidx].value = NULL;
323 return array;
324
325failure:
326 for (int i = 0; i < arrayidx; i++)
327 {
328 FREE(&array[i].key);
329 FREE(&array[i].value);
330 }
331 FREE(&array);
332 return NULL;
333}
334
343static void parse_and_print_user_id(FILE *fp, const char *userid)
344{
345 const char *s = NULL;
346
347 if (*userid == '<')
348 {
349 s = strchr(userid + 1, '>');
350 if (s)
351 print_utf8(fp, userid + 1, s - userid - 1);
352 }
353 else if (*userid == '(')
354 {
355 fputs(_("[Can't display this user ID (unknown encoding)]"), fp);
356 }
357 else if (!isalnum(userid[0]))
358 {
359 fputs(_("[Can't display this user ID (invalid encoding)]"), fp);
360 }
361 else
362 {
363 struct DnArray *dn = parse_dn(userid);
364 if (dn)
365 {
366 print_dn_parts(fp, dn);
367 for (int i = 0; dn[i].key; i++)
368 {
369 FREE(&dn[i].key);
370 FREE(&dn[i].value);
371 }
372 FREE(&dn);
373 }
374 else
375 {
376 fputs(_("[Can't display this user ID (invalid DN)]"), fp);
377 }
378 }
379}
380
386static void print_key_info(gpgme_key_t key, FILE *fp)
387{
388 int idx;
389 const char *s = NULL, *s2 = NULL;
390 time_t tt = 0;
391 char shortbuf[128] = { 0 };
392 unsigned long aval = 0;
393 const char *delim = NULL;
394 gpgme_user_id_t uid = NULL;
395 static int max_header_width = 0;
396
397 if (max_header_width == 0)
398 {
399 for (int i = 0; i < KIP_MAX; i++)
400 {
402 const int width = mutt_strwidth(_(KeyInfoPrompts[i]));
403 if (max_header_width < width)
404 max_header_width = width;
405 KeyInfoPadding[i] -= width;
406 }
407 for (int i = 0; i < KIP_MAX; i++)
408 KeyInfoPadding[i] += max_header_width;
409 }
410
411 bool is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
412
413 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
414 {
415 if (uid->revoked)
416 continue;
417
418 s = uid->uid;
419 /* L10N: DOTFILL */
420
421 if (idx == 0)
422 fprintf(fp, "%*s", KeyInfoPadding[KIP_NAME], _(KeyInfoPrompts[KIP_NAME]));
423 else
424 fprintf(fp, "%*s", KeyInfoPadding[KIP_AKA], _(KeyInfoPrompts[KIP_AKA]));
425 if (uid->invalid)
426 {
427 /* L10N: comes after the Name or aka if the key is invalid */
428 fputs(_("[Invalid]"), fp);
429 putc(' ', fp);
430 }
431 if (is_pgp)
432 print_utf8(fp, s, strlen(s));
433 else
435 putc('\n', fp);
436 }
437
438 if (key->subkeys && (key->subkeys->timestamp > 0))
439 {
440 tt = key->subkeys->timestamp;
441
442 mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
443 fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_FROM],
444 _(KeyInfoPrompts[KIP_VALID_FROM]), shortbuf);
445 }
446
447 if (key->subkeys && (key->subkeys->expires > 0))
448 {
449 tt = key->subkeys->expires;
450
451 mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
452 fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_TO],
453 _(KeyInfoPrompts[KIP_VALID_TO]), shortbuf);
454 }
455
456 if (key->subkeys)
457 s = gpgme_pubkey_algo_name(key->subkeys->pubkey_algo);
458 else
459 s = "?";
460
461 s2 = is_pgp ? "PGP" : "X.509";
462
463 if (key->subkeys)
464 aval = key->subkeys->length;
465
467 /* L10N: This is printed after "Key Type: " and looks like this: PGP, 2048 bit RSA */
468 fprintf(fp, ngettext("%s, %lu bit %s\n", "%s, %lu bit %s\n", aval), s2, aval, s);
469
471 delim = "";
472
474 {
475 /* L10N: value in Key Usage: field */
476 fprintf(fp, "%s%s", delim, _("encryption"));
477 delim = _(", ");
478 }
480 {
481 /* L10N: value in Key Usage: field */
482 fprintf(fp, "%s%s", delim, _("signing"));
483 delim = _(", ");
484 }
486 {
487 /* L10N: value in Key Usage: field */
488 fprintf(fp, "%s%s", delim, _("certification"));
489 }
490 putc('\n', fp);
491
492 if (key->subkeys)
493 {
494 s = key->subkeys->fpr;
496 if (is_pgp && (strlen(s) == 40))
497 {
498 for (int i = 0; (s[0] != '\0') && (s[1] != '\0') && (s[2] != '\0') &&
499 (s[3] != '\0') && (s[4] != '\0');
500 s += 4, i++)
501 {
502 putc(*s, fp);
503 putc(s[1], fp);
504 putc(s[2], fp);
505 putc(s[3], fp);
506 putc(' ', fp);
507 if (i == 4)
508 putc(' ', fp);
509 }
510 }
511 else
512 {
513 for (int i = 0; (s[0] != '\0') && (s[1] != '\0') && (s[2] != '\0'); s += 2, i++)
514 {
515 putc(*s, fp);
516 putc(s[1], fp);
517 putc(is_pgp ? ' ' : ':', fp);
518 if (is_pgp && (i == 7))
519 putc(' ', fp);
520 }
521 }
522 fprintf(fp, "%s\n", s);
523 }
524
525 if (key->issuer_serial)
526 {
527 s = key->issuer_serial;
528 fprintf(fp, "%*s0x%s\n", KeyInfoPadding[KIP_SERIAL_NO],
530 }
531
532 if (key->issuer_name)
533 {
534 s = key->issuer_name;
537 putc('\n', fp);
538 }
539
540 /* For PGP we list all subkeys. */
541 if (is_pgp)
542 {
543 gpgme_subkey_t subkey = NULL;
544
545 for (idx = 1, subkey = key->subkeys; subkey; idx++, subkey = subkey->next)
546 {
547 s = subkey->keyid;
548
549 putc('\n', fp);
550 if (strlen(s) == 16)
551 s += 8; /* display only the short keyID */
552 fprintf(fp, "%*s0x%s", KeyInfoPadding[KIP_SUBKEY], _(KeyInfoPrompts[KIP_SUBKEY]), s);
553 if (subkey->revoked)
554 {
555 putc(' ', fp);
556 /* L10N: describes a subkey */
557 fputs(_("[Revoked]"), fp);
558 }
559 if (subkey->invalid)
560 {
561 putc(' ', fp);
562 /* L10N: describes a subkey */
563 fputs(_("[Invalid]"), fp);
564 }
565 if (subkey->expired)
566 {
567 putc(' ', fp);
568 /* L10N: describes a subkey */
569 fputs(_("[Expired]"), fp);
570 }
571 if (subkey->disabled)
572 {
573 putc(' ', fp);
574 /* L10N: describes a subkey */
575 fputs(_("[Disabled]"), fp);
576 }
577 putc('\n', fp);
578
579 if (subkey->timestamp > 0)
580 {
581 tt = subkey->timestamp;
582
583 mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
584 fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_FROM],
585 _(KeyInfoPrompts[KIP_VALID_FROM]), shortbuf);
586 }
587
588 if (subkey->expires > 0)
589 {
590 tt = subkey->expires;
591
592 mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
593 fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_TO],
594 _(KeyInfoPrompts[KIP_VALID_TO]), shortbuf);
595 }
596
597 s = gpgme_pubkey_algo_name(subkey->pubkey_algo);
598
599 aval = subkey->length;
600
602 /* L10N: This is printed after "Key Type: " and looks like this: PGP, 2048 bit RSA */
603 fprintf(fp, ngettext("%s, %lu bit %s\n", "%s, %lu bit %s\n", aval), "PGP", aval, s);
604
606 delim = "";
607
608 if (subkey->can_encrypt)
609 {
610 fprintf(fp, "%s%s", delim, _("encryption"));
611 delim = _(", ");
612 }
613 if (subkey->can_sign)
614 {
615 fprintf(fp, "%s%s", delim, _("signing"));
616 delim = _(", ");
617 }
618 if (subkey->can_certify)
619 {
620 fprintf(fp, "%s%s", delim, _("certification"));
621 }
622 putc('\n', fp);
623 }
624 }
625}
626
631static void verify_key(struct CryptKeyInfo *key)
632{
633 const char *s = NULL;
634 gpgme_ctx_t listctx = NULL;
635 gpgme_error_t err;
636 gpgme_key_t k = NULL;
637 int maxdepth = 100;
638
639 struct Buffer tempfile = buf_make(PATH_MAX);
640 buf_mktemp(&tempfile);
641 FILE *fp = mutt_file_fopen(buf_string(&tempfile), "w");
642 if (!fp)
643 {
644 mutt_perror(_("Can't create temporary file"));
645 goto cleanup;
646 }
647 mutt_message(_("Collecting data..."));
648
649 print_key_info(key->kobj, fp);
650
651 listctx = create_gpgme_context(key->flags & KEYFLAG_ISX509);
652
653 k = key->kobj;
654 gpgme_key_ref(k);
655 while ((s = k->chain_id) && k->subkeys && !mutt_str_equal(s, k->subkeys->fpr))
656 {
657 putc('\n', fp);
658 err = gpgme_op_keylist_start(listctx, s, 0);
659 gpgme_key_unref(k);
660 k = NULL;
661 if (err == 0)
662 err = gpgme_op_keylist_next(listctx, &k);
663 if (err != 0)
664 {
665 fprintf(fp, _("Error finding issuer key: %s\n"), gpgme_strerror(err));
666 goto leave;
667 }
668 gpgme_op_keylist_end(listctx);
669
670 print_key_info(k, fp);
671 if (!--maxdepth)
672 {
673 putc('\n', fp);
674 fputs(_("Error: certification chain too long - stopping here\n"), fp);
675 break;
676 }
677 }
678
679leave:
680 gpgme_key_unref(k);
681 gpgme_release(listctx);
682 mutt_file_fclose(&fp);
684 char title[1024] = { 0 };
685 snprintf(title, sizeof(title), _("Key ID: 0x%s"), crypt_keyid(key));
686
687 struct PagerData pdata = { 0 };
688 struct PagerView pview = { &pdata };
689
690 pdata.fname = buf_string(&tempfile);
691
692 pview.banner = title;
694 pview.mode = PAGER_MODE_OTHER;
695
696 mutt_do_pager(&pview, NULL);
697
698cleanup:
699 buf_dealloc(&tempfile);
700}
701
707static bool crypt_key_is_valid(struct CryptKeyInfo *k)
708{
709 if (k->flags & KEYFLAG_CANTUSE)
710 return false;
711 return true;
712}
713
714// -----------------------------------------------------------------------------
715
719static int op_exit(struct GpgmeData *gd, int op)
720{
721 gd->done = true;
722 return FR_SUCCESS;
723}
724
728static int op_generic_select_entry(struct GpgmeData *gd, int op)
729{
730 const int index = menu_get_index(gd->menu);
731 struct CryptKeyInfo *cur_key = gd->key_table[index];
732 /* FIXME make error reporting more verbose - this should be
733 * easy because GPGME provides more information */
735 {
736 if (!crypt_key_is_valid(cur_key))
737 {
738 mutt_error(_("This key can't be used: expired/disabled/revoked"));
739 return FR_ERROR;
740 }
741 }
742
743 if (OptPgpCheckTrust && (!crypt_id_is_valid(cur_key) || !crypt_id_is_strong(cur_key)))
744 {
745 const char *warn_s = NULL;
746 char buf2[1024];
747
748 if (cur_key->flags & KEYFLAG_CANTUSE)
749 {
750 warn_s = _("ID is expired/disabled/revoked. Do you really want to use the key?");
751 }
752 else
753 {
754 warn_s = "??";
755 switch (cur_key->validity)
756 {
757 case GPGME_VALIDITY_NEVER:
758 warn_s = _("ID is not valid. Do you really want to use the key?");
759 break;
760 case GPGME_VALIDITY_MARGINAL:
761 warn_s = _("ID is only marginally valid. Do you really want to use the key?");
762 break;
763 case GPGME_VALIDITY_FULL:
764 case GPGME_VALIDITY_ULTIMATE:
765 break;
766 case GPGME_VALIDITY_UNKNOWN:
767 case GPGME_VALIDITY_UNDEFINED:
768 warn_s = _("ID has undefined validity. Do you really want to use the key?");
769 break;
770 }
771 }
772
773 snprintf(buf2, sizeof(buf2), "%s", warn_s);
774
775 if (query_yesorno(buf2, MUTT_NO) != MUTT_YES)
776 {
778 return FR_NO_ACTION;
779 }
780 }
781
782 gd->key = crypt_copy_key(cur_key);
783 gd->done = true;
784 return FR_SUCCESS;
785}
786
790static int op_verify_key(struct GpgmeData *gd, int op)
791{
792 const int index = menu_get_index(gd->menu);
793 struct CryptKeyInfo *cur_key = gd->key_table[index];
794 verify_key(cur_key);
796 return FR_SUCCESS;
797}
798
802static int op_view_id(struct GpgmeData *gd, int op)
803{
804 const int index = menu_get_index(gd->menu);
805 struct CryptKeyInfo *cur_key = gd->key_table[index];
806 mutt_message("%s", cur_key->uid);
807 return FR_SUCCESS;
808}
809
810// -----------------------------------------------------------------------------
811
815static const struct GpgmeFunction GpgmeFunctions[] = {
816 // clang-format off
817 { OP_EXIT, op_exit },
818 { OP_GENERIC_SELECT_ENTRY, op_generic_select_entry },
819 { OP_VERIFY_KEY, op_verify_key },
820 { OP_VIEW_ID, op_view_id },
821 { 0, NULL },
822 // clang-format on
823};
824
829{
830 if (!win || !win->wdata)
831 return FR_UNKNOWN;
832
833 struct MuttWindow *dlg = dialog_find(win);
834 if (!dlg)
835 return FR_ERROR;
836
837 struct GpgmeData *gd = dlg->wdata;
838
839 int rc = FR_UNKNOWN;
840 for (size_t i = 0; GpgmeFunctions[i].op != OP_NULL; i++)
841 {
842 const struct GpgmeFunction *fn = &GpgmeFunctions[i];
843 if (fn->op == op)
844 {
845 rc = fn->function(gd, op);
846 break;
847 }
848 }
849
850 if (rc == FR_UNKNOWN) // Not our function
851 return rc;
852
853 const char *result = dispatcher_get_retval_name(rc);
854 mutt_debug(LL_DEBUG1, "Handled %s (%d) -> %s\n", opcodes_get_name(op), op, NONULL(result));
855
856 return rc;
857}
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:389
struct Buffer buf_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:70
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
Convenience wrapper for the config headers.
const char * cc_charset(void)
Get the cached value of $charset.
Definition: config_cache.c:115
Convenience wrapper for the core headers.
struct CryptKeyInfo * crypt_copy_key(struct CryptKeyInfo *key)
Return a copy of KEY.
Definition: crypt_gpgme.c:233
int crypt_id_is_valid(struct CryptKeyInfo *key)
Is key ID valid.
Definition: crypt_gpgme.c:309
bool crypt_id_is_strong(struct CryptKeyInfo *key)
Is the key strong.
Definition: crypt_gpgme.c:274
unsigned int key_check_cap(gpgme_key_t key, enum KeyCap cap)
Check the capabilities of a key.
Definition: crypt_gpgme.c:2843
const char * crypt_keyid(struct CryptKeyInfo *k)
Find the ID for the key.
Definition: crypt_gpgme.c:137
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:454
struct MuttWindow * dialog_find(struct MuttWindow *win)
Find the parent Dialog of a Window.
Definition: dialog.c:89
const char * dispatcher_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:636
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
bool OptPgpCheckTrust
(pseudo) used by dlg_pgp()
Definition: globals.c:78
static int create_gpgme_context(gpgme_ctx_t *ctx)
Create a GPGME context.
Definition: gpgme.c:48
static const struct GpgmeFunction GpgmeFunctions[]
All the NeoMutt functions that the Gpgme supports.
static const char *const KeyInfoPrompts[]
Names of header fields used in the pgp key display, e.g. Name:, Fingerprint:
int KeyInfoPadding[KIP_MAX]
Number of padding spaces needed after each of the strings in KeyInfoPrompts after translation.
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.
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: logging2.h:92
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
#define mutt_perror(...)
Definition: logging2.h:93
Convenience wrapper for the gui headers.
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:45
GUI present the user with a selectable list.
#define MENU_REDRAW_FULL
Redraw everything.
Definition: lib.h:60
void menu_queue_redraw(struct Menu *menu, MenuRedrawFlags redraw)
Queue a request for a redraw.
Definition: menu.c:180
int menu_get_index(struct Menu *menu)
Get the current selection in the Menu.
Definition: menu.c:156
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:826
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:924
Convenience wrapper for the library headers.
#define N_(a)
Definition: message.h:32
#define _(a)
Definition: message.h:28
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:568
#define PATH_MAX
Definition: mutt.h:41
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
NeoMutt Logging.
#define KEYFLAG_ISX509
Key is an X.509 key.
Definition: lib.h:130
#define KEYFLAG_CANTUSE
Definition: lib.h:140
const char * opcodes_get_name(int op)
Get the name of an opcode.
Definition: opcodes.c:48
GUI display a file/email/help in a viewport with paging.
#define MUTT_PAGER_NO_FLAGS
No flags are set.
Definition: lib.h:59
@ PAGER_MODE_OTHER
Pager is invoked via 3rd path. Non-email content is likely to be shown.
Definition: lib.h:141
@ 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 query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:330
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
Data to be displayed by PagerView.
Definition: lib.h:160
const char * fname
Name of the file to read.
Definition: lib.h:164
Paged view into some data.
Definition: lib.h:171
struct PagerData * pdata
Data that pager displays. NOTNULL.
Definition: lib.h:172
enum PagerMode mode
Pager mode.
Definition: lib.h:173
PagerFlags flags
Additional settings to tweak pager's function.
Definition: lib.h:174
const char * banner
Title to display in status bar.
Definition: lib.h:175
#define buf_mktemp(buf)
Definition: tmp.h:33