NeoMutt  2025-12-11-435-g4ac674
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
gpgme_functions.c File Reference

Gpgme functions. More...

#include "config.h"
#include <gpg-error.h>
#include <gpgme.h>
#include <langinfo.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "gpgme_functions.h"
#include "lib.h"
#include "key/lib.h"
#include "menu/lib.h"
#include "pager/lib.h"
#include "question/lib.h"
#include "crypt_gpgme.h"
#include "globals.h"
#include "mutt_logging.h"
#include <libintl.h>
+ Include dependency graph for gpgme_functions.c:

Go to the source code of this file.

Data Structures

struct  DnArray
 An X500 Distinguished Name. More...
 

Functions

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 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.
 
static struct DnArrayparse_dn (const char *str)
 Parse a DN and return an array-ized one.
 
static void parse_and_print_user_id (FILE *fp, const char *userid)
 Print a nice representation of the userid.
 
static void print_key_info (gpgme_key_t key, FILE *fp)
 Verbose information about a key or certificate to a file.
 
static void verify_key (struct CryptKeyInfo *key)
 Show detailed information about the selected key.
 
static bool crypt_key_is_valid (struct CryptKeyInfo *k)
 Is the key valid.
 
bool crypt_keys_are_valid (struct CryptKeyInfo *keys)
 Are all these keys valid?
 
static int op_exit (struct GpgmeData *gd, const struct KeyEvent *event)
 Exit this menu - Implements gpgme_function_t -.
 
static int op_generic_select_entry (struct GpgmeData *gd, const struct KeyEvent *event)
 Select the current entry - Implements gpgme_function_t -.
 
static int op_verify_key (struct GpgmeData *gd, const struct KeyEvent *event)
 Verify a PGP public key - Implements gpgme_function_t -.
 
static int op_view_id (struct GpgmeData *gd, const struct KeyEvent *event)
 View the key's user id - Implements gpgme_function_t -.
 
int gpgme_function_dispatcher (struct MuttWindow *win, const struct KeyEvent *event)
 Perform a Gpgme function - Implements function_dispatcher_t -.
 

Variables

int KeyInfoPadding [KIP_MAX] = { 0 }
 Number of padding spaces needed after each of the strings in KeyInfoPrompts after translation.
 
static const char *const KeyInfoPrompts []
 Names of header fields used in the pgp key display, e.g. Name:, Fingerprint:
 
static const struct GpgmeFunction GpgmeFunctions []
 All the NeoMutt functions that the Gpgme supports.
 

Detailed Description

Gpgme functions.

Authors
  • Richard Russon
  • Alejandro Colomar
  • Thomas Klausner

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 gpgme_functions.c.

Function Documentation

◆ print_utf8()

static void print_utf8 ( FILE * fp,
const char * buf,
size_t len )
static

Write a UTF-8 string to a file.

Parameters
fpFile to write to
bufBuffer to read from
lenLength to read

Convert the character set.

Definition at line 85 of file gpgme_functions.c.

86{
87 char *tstr = MUTT_MEM_MALLOC(len + 1, char);
88 memcpy(tstr, buf, len);
89 tstr[len] = 0;
90
91 /* fromcode "utf-8" is sure, so we don't want
92 * charset-hook corrections: flags must be 0. */
94 fputs(tstr, fp);
95 FREE(&tstr);
96}
const char * cc_charset(void)
Get the cached value of $charset.
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define MUTT_MEM_MALLOC(n, type)
Definition memory.h:53
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition charset.c:817
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition charset.h:66
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_dn_part()

static bool print_dn_part ( FILE * fp,
struct DnArray * dn,
const char * key )
static

Print the X.500 Distinguished Name.

Parameters
fpFile to write to
dnDistinguished Name
keyKey string
Return values
trueAny DN keys match the given key string
falseOtherwise

Print the X.500 Distinguished Name part KEY from the array of parts DN to FP.

Definition at line 108 of file gpgme_functions.c.

109{
110 bool any = false;
111
112 for (; dn->key; dn++)
113 {
114 if (mutt_str_equal(dn->key, key))
115 {
116 if (any)
117 fputs(" + ", fp);
118 print_utf8(fp, dn->value, strlen(dn->value));
119 any = true;
120 }
121 }
122 return any;
123}
static void print_utf8(FILE *fp, const char *buf, size_t len)
Write a UTF-8 string to a file.
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:662
char * key
Key.
char * value
Value.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_dn_parts()

static void print_dn_parts ( FILE * fp,
struct DnArray * dn )
static

Print all parts of a DN in a standard sequence.

Parameters
fpFile to write to
dnArray of Distinguished Names

Definition at line 130 of file gpgme_functions.c.

131{
132 static const char *const stdpart[] = {
133 "CN", "OU", "O", "STREET", "L", "ST", "C", NULL,
134 };
135 bool any = false;
136 bool any2 = false;
137
138 for (int i = 0; stdpart[i]; i++)
139 {
140 if (any)
141 fputs(", ", fp);
142 any = print_dn_part(fp, dn, stdpart[i]);
143 }
144 /* now print the rest without any specific ordering */
145 for (; dn->key; dn++)
146 {
147 int i;
148 for (i = 0; stdpart[i]; i++)
149 {
150 if (mutt_str_equal(dn->key, stdpart[i]))
151 break;
152 }
153 if (!stdpart[i])
154 {
155 if (any)
156 fputs(", ", fp);
157 if (!any2)
158 fputs("(", fp);
159 any = print_dn_part(fp, dn, dn->key);
160 any2 = true;
161 }
162 }
163 if (any2)
164 fputs(")", fp);
165}
static bool print_dn_part(FILE *fp, struct DnArray *dn, const char *key)
Print the X.500 Distinguished Name.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_dn_part()

static const char * parse_dn_part ( struct DnArray * array,
const char * str )
static

Parse an RDN.

Parameters
arrayArray for results
strString to parse
Return values
ptrFirst character after Distinguished Name

This is a helper to parse_dn()

Definition at line 175 of file gpgme_functions.c.

176{
177 const char *s = NULL, *s1 = NULL;
178 int n;
179 char *p = NULL;
180
181 /* parse attribute type */
182 for (s = str + 1; (s[0] != '\0') && (s[0] != '='); s++)
183 ; // do nothing
184
185 if (s[0] == '\0')
186 return NULL; /* error */
187 n = s - str;
188 if (n == 0)
189 return NULL; /* empty key */
190 array->key = MUTT_MEM_MALLOC(n + 1, char);
191 p = array->key;
192 memcpy(p, str, n); /* fixme: trim trailing spaces */
193 p[n] = 0;
194 str = s + 1;
195
196 if (*str == '#')
197 { /* hexstring */
198 str++;
199 for (s = str; mutt_isxdigit(*s); s++)
200 s++;
201 n = s - str;
202 if ((n == 0) || (n & 1))
203 return NULL; /* empty or odd number of digits */
204 n /= 2;
205 p = MUTT_MEM_MALLOC(n + 1, char);
206 array->value = (char *) p;
207 for (s1 = str; n > 0; s1 += 2, n--)
208 sscanf(s1, "%2hhx", (unsigned char *) p++);
209 *p = '\0';
210 }
211 else
212 { /* regular v3 quoted string */
213 for (n = 0, s = str; *s; s++)
214 {
215 if (*s == '\\')
216 { /* pair */
217 s++;
218 if ((*s == ',') || (*s == '=') || (*s == '+') || (*s == '<') || (*s == '>') ||
219 (*s == '#') || (*s == ';') || (*s == '\\') || (*s == '\"') || (*s == ' '))
220 {
221 n++;
222 }
223 else if (mutt_isxdigit(s[0]) && mutt_isxdigit(s[1]))
224 {
225 s++;
226 n++;
227 }
228 else
229 {
230 return NULL; /* invalid escape sequence */
231 }
232 }
233 else if (*s == '\"')
234 {
235 return NULL; /* invalid encoding */
236 }
237 else if ((*s == ',') || (*s == '=') || (*s == '+') || (*s == '<') ||
238 (*s == '>') || (*s == '#') || (*s == ';'))
239 {
240 break;
241 }
242 else
243 {
244 n++;
245 }
246 }
247
248 p = MUTT_MEM_MALLOC(n + 1, char);
249 array->value = (char *) p;
250 for (s = str; n > 0; s++, n--)
251 {
252 if (*s == '\\')
253 {
254 s++;
255 if (mutt_isxdigit(*s))
256 {
257 sscanf(s, "%2hhx", (unsigned char *) p++);
258 s++;
259 }
260 else
261 {
262 *p++ = *s;
263 }
264 }
265 else
266 {
267 *p++ = *s;
268 }
269 }
270 *p = '\0';
271 }
272 return s;
273}
bool mutt_isxdigit(int arg)
Wrapper for isxdigit(3)
Definition ctype.c:111
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_dn()

static struct DnArray * parse_dn ( const char * str)
static

Parse a DN and return an array-ized one.

Parameters
strString to parse
Return values
ptrArray of Distinguished Names

This is not a validating parser and it does not support any old-stylish syntax; GPGME is expected to return only rfc2253 compatible strings.

Definition at line 283 of file gpgme_functions.c.

284{
285 struct DnArray *array = NULL;
286 size_t arrayidx, arraysize;
287
288 arraysize = 7; /* C,ST,L,O,OU,CN,email */
289 array = MUTT_MEM_MALLOC(arraysize + 1, struct DnArray);
290 arrayidx = 0;
291 while (*str)
292 {
293 while (str[0] == ' ')
294 str++;
295 if (str[0] == '\0')
296 break; /* ready */
297 if (arrayidx >= arraysize)
298 {
299 /* neomutt lacks a real mutt_mem_realloc - so we need to copy */
300 arraysize += 5;
301 struct DnArray *a2 = MUTT_MEM_MALLOC(arraysize + 1, struct DnArray);
302 for (int i = 0; i < arrayidx; i++)
303 {
304 a2[i].key = array[i].key;
305 a2[i].value = array[i].value;
306 }
307 FREE(&array);
308 array = a2;
309 }
310 array[arrayidx].key = NULL;
311 array[arrayidx].value = NULL;
312 str = parse_dn_part(array + arrayidx, str);
313 arrayidx++;
314 if (!str)
315 goto failure;
316 while (str[0] == ' ')
317 str++;
318 if ((str[0] != '\0') && (str[0] != ',') && (str[0] != ';') && (str[0] != '+'))
319 goto failure; /* invalid delimiter */
320 if (str[0] != '\0')
321 str++;
322 }
323 array[arrayidx].key = NULL;
324 array[arrayidx].value = NULL;
325 return array;
326
327failure:
328 for (int i = 0; i < arrayidx; i++)
329 {
330 FREE(&array[i].key);
331 FREE(&array[i].value);
332 }
333 FREE(&array);
334 return NULL;
335}
static const char * parse_dn_part(struct DnArray *array, const char *str)
Parse an RDN.
An X500 Distinguished Name.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_and_print_user_id()

static void parse_and_print_user_id ( FILE * fp,
const char * userid )
static

Print a nice representation of the userid.

Parameters
fpFile to write to
useridString returned by GPGME key functions (utf-8 encoded)

Make sure it is displayed in a proper way, which does mean to reorder some parts for S/MIME's DNs.

Definition at line 345 of file gpgme_functions.c.

346{
347 const char *s = NULL;
348
349 if (*userid == '<')
350 {
351 s = strchr(userid + 1, '>');
352 if (s)
353 print_utf8(fp, userid + 1, s - userid - 1);
354 }
355 else if (*userid == '(')
356 {
357 fputs(_("[Can't display this user ID (unknown encoding)]"), fp);
358 }
359 else if (!mutt_isalnum(userid[0]))
360 {
361 fputs(_("[Can't display this user ID (invalid encoding)]"), fp);
362 }
363 else
364 {
365 struct DnArray *dn = parse_dn(userid);
366 if (dn)
367 {
368 print_dn_parts(fp, dn);
369 for (int i = 0; dn[i].key; i++)
370 {
371 FREE(&dn[i].key);
372 FREE(&dn[i].value);
373 }
374 FREE(&dn);
375 }
376 else
377 {
378 fputs(_("[Can't display this user ID (invalid DN)]"), fp);
379 }
380 }
381}
bool mutt_isalnum(int arg)
Wrapper for isalnum(3)
Definition ctype.c:40
static struct DnArray * parse_dn(const char *str)
Parse a DN and return an array-ized one.
static void print_dn_parts(FILE *fp, struct DnArray *dn)
Print all parts of a DN in a standard sequence.
#define _(a)
Definition message.h:28
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_key_info()

static void print_key_info ( gpgme_key_t key,
FILE * fp )
static

Verbose information about a key or certificate to a file.

Parameters
keyKey to use
fpFile to write to

Definition at line 388 of file gpgme_functions.c.

389{
390 int idx;
391 const char *s = NULL, *s2 = NULL;
392 time_t tt = 0;
393 char shortbuf[128] = { 0 };
394 unsigned long aval = 0;
395 const char *delim = NULL;
396 gpgme_user_id_t uid = NULL;
397 static int max_header_width = 0;
398
399 if (max_header_width == 0)
400 {
401 for (int i = 0; i < KIP_MAX; i++)
402 {
404 const int width = mutt_strwidth(_(KeyInfoPrompts[i]));
405 if (max_header_width < width)
406 max_header_width = width;
407 KeyInfoPadding[i] -= width;
408 }
409 for (int i = 0; i < KIP_MAX; i++)
410 KeyInfoPadding[i] += max_header_width;
411 }
412
413 bool is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
414
415 for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
416 {
417 if (uid->revoked)
418 continue;
419
420 s = uid->uid;
421 /* L10N: DOTFILL */
422
423 if (idx == 0)
424 fprintf(fp, "%*s", KeyInfoPadding[KIP_NAME], _(KeyInfoPrompts[KIP_NAME]));
425 else
426 fprintf(fp, "%*s", KeyInfoPadding[KIP_AKA], _(KeyInfoPrompts[KIP_AKA]));
427 if (uid->invalid)
428 {
429 /* L10N: comes after the Name or aka if the key is invalid */
430 fputs(_("[Invalid]"), fp);
431 putc(' ', fp);
432 }
433 if (is_pgp)
434 print_utf8(fp, s, strlen(s));
435 else
437 putc('\n', fp);
438 }
439
440 if (key->subkeys && (key->subkeys->timestamp > 0))
441 {
442 tt = key->subkeys->timestamp;
443
444 mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
445 fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_FROM],
446 _(KeyInfoPrompts[KIP_VALID_FROM]), shortbuf);
447 }
448
449 if (key->subkeys && (key->subkeys->expires > 0))
450 {
451 tt = key->subkeys->expires;
452
453 mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
454 fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_TO],
455 _(KeyInfoPrompts[KIP_VALID_TO]), shortbuf);
456 }
457
458 if (key->subkeys)
459 s = gpgme_pubkey_algo_name(key->subkeys->pubkey_algo);
460 else
461 s = "?";
462
463 s2 = is_pgp ? "PGP" : "X.509";
464
465 if (key->subkeys)
466 aval = key->subkeys->length;
467
469 /* L10N: This is printed after "Key Type: " and looks like this: PGP, 2048 bit RSA */
470 fprintf(fp, ngettext("%s, %lu bit %s\n", "%s, %lu bit %s\n", aval), s2, aval, s);
471
473 delim = "";
474
476 {
477 /* L10N: value in Key Usage: field */
478 fprintf(fp, "%s%s", delim, _("encryption"));
479 delim = _(", ");
480 }
482 {
483 /* L10N: value in Key Usage: field */
484 fprintf(fp, "%s%s", delim, _("signing"));
485 delim = _(", ");
486 }
488 {
489 /* L10N: value in Key Usage: field */
490 fprintf(fp, "%s%s", delim, _("certification"));
491 }
492 putc('\n', fp);
493
494 if (key->subkeys)
495 {
496 s = key->subkeys->fpr;
498 if (is_pgp && (strlen(s) == 40))
499 {
500 for (int i = 0; (s[0] != '\0') && (s[1] != '\0') && (s[2] != '\0') &&
501 (s[3] != '\0') && (s[4] != '\0');
502 s += 4, i++)
503 {
504 putc(*s, fp);
505 putc(s[1], fp);
506 putc(s[2], fp);
507 putc(s[3], fp);
508 putc(' ', fp);
509 if (i == 4)
510 putc(' ', fp);
511 }
512 }
513 else
514 {
515 for (int i = 0; (s[0] != '\0') && (s[1] != '\0') && (s[2] != '\0'); s += 2, i++)
516 {
517 putc(*s, fp);
518 putc(s[1], fp);
519 putc(is_pgp ? ' ' : ':', fp);
520 if (is_pgp && (i == 7))
521 putc(' ', fp);
522 }
523 }
524 fprintf(fp, "%s\n", s);
525 }
526
527 if (key->issuer_serial)
528 {
529 s = key->issuer_serial;
530 fprintf(fp, "%*s0x%s\n", KeyInfoPadding[KIP_SERIAL_NO],
532 }
533
534 if (key->issuer_name)
535 {
536 s = key->issuer_name;
539 putc('\n', fp);
540 }
541
542 /* For PGP we list all subkeys. */
543 if (is_pgp)
544 {
545 gpgme_subkey_t subkey = NULL;
546
547 for (idx = 1, subkey = key->subkeys; subkey; idx++, subkey = subkey->next)
548 {
549 s = subkey->keyid;
550
551 putc('\n', fp);
552 if (strlen(s) == 16)
553 s += 8; /* display only the short keyID */
554 fprintf(fp, "%*s0x%s", KeyInfoPadding[KIP_SUBKEY], _(KeyInfoPrompts[KIP_SUBKEY]), s);
555 if (subkey->revoked)
556 {
557 putc(' ', fp);
558 /* L10N: describes a subkey */
559 fputs(_("[Revoked]"), fp);
560 }
561 if (subkey->invalid)
562 {
563 putc(' ', fp);
564 /* L10N: describes a subkey */
565 fputs(_("[Invalid]"), fp);
566 }
567 if (subkey->expired)
568 {
569 putc(' ', fp);
570 /* L10N: describes a subkey */
571 fputs(_("[Expired]"), fp);
572 }
573 if (subkey->disabled)
574 {
575 putc(' ', fp);
576 /* L10N: describes a subkey */
577 fputs(_("[Disabled]"), fp);
578 }
579 putc('\n', fp);
580
581 if (subkey->timestamp > 0)
582 {
583 tt = subkey->timestamp;
584
585 mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
586 fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_FROM],
587 _(KeyInfoPrompts[KIP_VALID_FROM]), shortbuf);
588 }
589
590 if (subkey->expires > 0)
591 {
592 tt = subkey->expires;
593
594 mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
595 fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_TO],
596 _(KeyInfoPrompts[KIP_VALID_TO]), shortbuf);
597 }
598
599 s = gpgme_pubkey_algo_name(subkey->pubkey_algo);
600
601 aval = subkey->length;
602
604 /* L10N: This is printed after "Key Type: " and looks like this: PGP, 2048 bit RSA */
605 fprintf(fp, ngettext("%s, %lu bit %s\n", "%s, %lu bit %s\n", aval), "PGP", aval, s);
606
608 delim = "";
609
610 if (subkey->can_encrypt)
611 {
612 fprintf(fp, "%s%s", delim, _("encryption"));
613 delim = _(", ");
614 }
615 if (subkey->can_sign)
616 {
617 fprintf(fp, "%s%s", delim, _("signing"));
618 delim = _(", ");
619 }
620 if (subkey->can_certify)
621 {
622 fprintf(fp, "%s%s", delim, _("certification"));
623 }
624 putc('\n', fp);
625 }
626 }
627}
unsigned int key_check_cap(gpgme_key_t key, enum KeyCap cap)
Check the capabilities of a key.
@ KIP_FINGERPRINT
PGP Key field: Fingerprint.
Definition crypt_gpgme.h:65
@ KIP_SERIAL_NO
PGP Key field: Serial number.
Definition crypt_gpgme.h:66
@ KIP_SUBKEY
PGP Key field: Subkey.
Definition crypt_gpgme.h:68
@ KIP_AKA
PGP Key field: aka (Also Known As)
Definition crypt_gpgme.h:60
@ KIP_VALID_FROM
PGP Key field: Valid From date.
Definition crypt_gpgme.h:61
@ KIP_MAX
Definition crypt_gpgme.h:69
@ KIP_KEY_TYPE
PGP Key field: Key Type.
Definition crypt_gpgme.h:63
@ KIP_NAME
PGP Key field: Name.
Definition crypt_gpgme.h:59
@ KIP_ISSUED_BY
PGP Key field: Issued By.
Definition crypt_gpgme.h:67
@ KIP_KEY_USAGE
PGP Key field: Key Usage.
Definition crypt_gpgme.h:64
@ KIP_VALID_TO
PGP Key field: Valid To date.
Definition crypt_gpgme.h:62
@ KEY_CAP_CAN_CERTIFY
Key can be used to certify.
Definition crypt_gpgme.h:79
@ KEY_CAP_CAN_ENCRYPT
Key can be used for encryption.
Definition crypt_gpgme.h:77
@ KEY_CAP_CAN_SIGN
Key can be used for signing.
Definition crypt_gpgme.h:78
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition curs_lib.c:444
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.
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition date.c:952
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:500
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ verify_key()

static void verify_key ( struct CryptKeyInfo * key)
static

Show detailed information about the selected key.

Parameters
keyKey to show

Definition at line 633 of file gpgme_functions.c.

634{
635 const char *s = NULL;
636 gpgme_ctx_t listctx = NULL;
637 gpgme_error_t err = GPG_ERR_NO_ERROR;
638 gpgme_key_t k = NULL;
639 int maxdepth = 100;
640
641 struct Buffer *tempfile = buf_pool_get();
642 buf_mktemp(tempfile);
643 FILE *fp = mutt_file_fopen(buf_string(tempfile), "w");
644 if (!fp)
645 {
646 mutt_perror(_("Can't create temporary file"));
647 goto cleanup;
648 }
649 mutt_message(_("Collecting data..."));
650
651 print_key_info(key->kobj, fp);
652
653 listctx = create_gpgme_context(key->flags & KEYFLAG_ISX509);
654
655 k = key->kobj;
656 gpgme_key_ref(k);
657 while ((s = k->chain_id) && k->subkeys && !mutt_str_equal(s, k->subkeys->fpr))
658 {
659 putc('\n', fp);
660 err = gpgme_op_keylist_start(listctx, s, 0);
661 gpgme_key_unref(k);
662 k = NULL;
663 if (err == GPG_ERR_NO_ERROR)
664 err = gpgme_op_keylist_next(listctx, &k);
665 if (err != GPG_ERR_NO_ERROR)
666 {
667 fprintf(fp, _("Error finding issuer key: %s\n"), gpgme_strerror(err));
668 goto leave;
669 }
670 gpgme_op_keylist_end(listctx);
671
672 print_key_info(k, fp);
673 if (!--maxdepth)
674 {
675 putc('\n', fp);
676 fputs(_("Error: certification chain too long - stopping here\n"), fp);
677 break;
678 }
679 }
680
681leave:
682 gpgme_key_unref(k);
683 gpgme_release(listctx);
684 mutt_file_fclose(&fp);
686 char title[1024] = { 0 };
687 snprintf(title, sizeof(title), _("Key ID: 0x%s"), crypt_keyid(key));
688
689 struct PagerData pdata = { 0 };
690 struct PagerView pview = { &pdata };
691
692 pdata.fname = buf_string(tempfile);
693
694 pview.banner = title;
696 pview.mode = PAGER_MODE_OTHER;
697
698 mutt_do_pager(&pview, NULL);
699
700cleanup:
701 buf_pool_release(&tempfile);
702}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
const char * crypt_keyid(struct CryptKeyInfo *k)
Find the ID for the key.
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:122
#define mutt_file_fclose(FP)
Definition file.h:139
#define mutt_file_fopen(PATH, MODE)
Definition file.h:138
static int create_gpgme_context(gpgme_ctx_t *ctx)
Create a GPGME context.
Definition gpgme.c:51
static void print_key_info(gpgme_key_t key, FILE *fp)
Verbose information about a key or certificate to a file.
#define mutt_message(...)
Definition logging2.h:93
#define mutt_perror(...)
Definition logging2.h:95
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
#define KEYFLAG_ISX509
Key is an X.509 key.
Definition lib.h:137
#define MUTT_PAGER_NO_FLAGS
No flags are set.
Definition lib.h:62
@ PAGER_MODE_OTHER
Pager is invoked via 3rd path. Non-email content is likely to be shown.
Definition lib.h:142
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
String manipulation buffer.
Definition buffer.h:36
KeyFlags flags
global and per uid flags (for convenience)
Definition crypt_gpgme.h:49
gpgme_key_t kobj
GPGME key object.
Definition crypt_gpgme.h:46
Data to be displayed by PagerView.
Definition lib.h:161
const char * fname
Name of the file to read.
Definition lib.h:165
Paged view into some data.
Definition lib.h:172
struct PagerData * pdata
Data that pager displays. NOTNULL.
Definition lib.h:173
enum PagerMode mode
Pager mode.
Definition lib.h:174
PagerFlags flags
Additional settings to tweak pager's function.
Definition lib.h:175
const char * banner
Title to display in status bar.
Definition lib.h:176
#define buf_mktemp(buf)
Definition tmp.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_key_is_valid()

static bool crypt_key_is_valid ( struct CryptKeyInfo * k)
static

Is the key valid.

Parameters
kKey to test
Return values
trueKey is valid

Definition at line 709 of file gpgme_functions.c.

710{
711 if (k->flags & KEYFLAG_CANTUSE)
712 return false;
713 return true;
714}
#define KEYFLAG_CANTUSE
Definition lib.h:147
+ Here is the caller graph for this function:

◆ crypt_keys_are_valid()

bool crypt_keys_are_valid ( struct CryptKeyInfo * keys)

Are all these keys valid?

Parameters
keysSet of keys to test
Return values
trueAll keys are valid

Definition at line 721 of file gpgme_functions.c.

722{
723 for (struct CryptKeyInfo *k = keys; k != NULL; k = k->next)
724 {
725 if (!crypt_key_is_valid(k))
726 return false;
727 }
728
729 return true;
730}
static bool crypt_key_is_valid(struct CryptKeyInfo *k)
Is the key valid.
A stored PGP key.
Definition crypt_gpgme.h:44
struct CryptKeyInfo * next
Linked list.
Definition crypt_gpgme.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ KeyInfoPadding

int KeyInfoPadding[KIP_MAX] = { 0 }

Number of padding spaces needed after each of the strings in KeyInfoPrompts after translation.

Definition at line 56 of file gpgme_functions.c.

56{ 0 };

◆ KeyInfoPrompts

const char* const KeyInfoPrompts[]
static
Initial value:
= {
N_("Name: "), N_("aka: "), N_("Valid From: "), N_("Valid To: "),
N_("Key Type: "), N_("Key Usage: "), N_("Fingerprint: "), N_("Serial-No: "),
N_("Issued By: "), N_("Subkey: ")
}
#define N_(a)
Definition message.h:32

Names of header fields used in the pgp key display, e.g. Name:, Fingerprint:

Definition at line 59 of file gpgme_functions.c.

59 {
60 /* L10N: The following are the headers for the "verify key" output from the
61 GPGME key selection menu (bound to "c" in the key selection menu).
62 They will be automatically aligned. */
63 N_("Name: "), N_("aka: "), N_("Valid From: "), N_("Valid To: "),
64 N_("Key Type: "), N_("Key Usage: "), N_("Fingerprint: "), N_("Serial-No: "),
65 N_("Issued By: "), N_("Subkey: ")
66};

◆ GpgmeFunctions

const struct GpgmeFunction GpgmeFunctions[]
static
Initial value:
= {
{ OP_EXIT, op_exit },
{ OP_GENERIC_SELECT_ENTRY, op_generic_select_entry },
{ OP_VERIFY_KEY, op_verify_key },
{ OP_VIEW_ID, op_view_id },
{ 0, NULL },
}
static int op_generic_select_entry(struct AliasMenuData *mdata, const struct KeyEvent *event)
select the current entry - Implements alias_function_t -
Definition functions.c:248
static int op_exit(struct AliasMenuData *mdata, const struct KeyEvent *event)
exit this menu - Implements alias_function_t -
Definition functions.c:234
static int op_verify_key(struct GpgmeData *gd, const struct KeyEvent *event)
Verify a PGP public key - Implements gpgme_function_t -.
static int op_view_id(struct GpgmeData *gd, const struct KeyEvent *event)
View the key's user id - Implements gpgme_function_t -.

All the NeoMutt functions that the Gpgme supports.

Definition at line 844 of file gpgme_functions.c.

844 {
845 // clang-format off
846 { OP_EXIT, op_exit },
847 { OP_GENERIC_SELECT_ENTRY, op_generic_select_entry },
848 { OP_VERIFY_KEY, op_verify_key },
849 { OP_VIEW_ID, op_view_id },
850 { 0, NULL },
851 // clang-format on
852};