diff options
Diffstat (limited to 'src/keylist.c')
-rw-r--r-- | src/keylist.c | 100 |
1 files changed, 95 insertions, 5 deletions
diff --git a/src/keylist.c b/src/keylist.c index 38ddd0c5..9f1e68db 100644 --- a/src/keylist.c +++ b/src/keylist.c @@ -33,6 +33,7 @@ #include <assert.h> #include <ctype.h> #include <errno.h> +#include <limits.h> /* Suppress warning for accessing deprecated member "class". */ #define _GPGME_IN_GPGME @@ -403,6 +404,84 @@ parse_sec_field15 (gpgme_key_t key, gpgme_subkey_t subkey, char *field) } +/* Parse a tfs record. */ +static gpg_error_t +parse_tfs_record (gpgme_user_id_t uid, char **field, int nfield) +{ + gpg_error_t err; + gpgme_tofu_info_t ti; + unsigned long uval; + + /* We add only the first TOFU record in case future versions emit + * several. */ + if (uid->tofu) + return 0; + + /* Check that we have enough fields and that the version is supported. */ + if (nfield < 8 || atoi(field[1]) != 1) + return trace_gpg_error (GPG_ERR_INV_ENGINE); + + ti = calloc (1, sizeof *ti); + if (!ti) + return gpg_error_from_syserror (); + + /* Note that we allow a value of up to 7 which is what we can store + * in the ti->validity. */ + err = _gpgme_strtoul_field (field[2], &uval); + if (err || uval > 7) + goto inv_engine; + ti->validity = uval; + + /* Parse the sign-count. */ + err = _gpgme_strtoul_field (field[3], &uval); + if (err) + goto inv_engine; + if (uval > USHRT_MAX) + uval = USHRT_MAX; + ti->signcount = uval; + + /* Parse the encr-count. */ + err = _gpgme_strtoul_field (field[4], &uval); + if (err) + goto inv_engine; + if (uval > USHRT_MAX) + uval = USHRT_MAX; + ti->encrcount = uval; + + /* Parse the policy. */ + if (!strcmp (field[5], "none")) + ti->policy = GPGME_TOFU_POLICY_NONE; + else if (!strcmp (field[5], "auto")) + ti->policy = GPGME_TOFU_POLICY_AUTO; + else if (!strcmp (field[5], "good")) + ti->policy = GPGME_TOFU_POLICY_GOOD; + else if (!strcmp (field[5], "bad")) + ti->policy = GPGME_TOFU_POLICY_BAD; + else if (!strcmp (field[5], "ask")) + ti->policy = GPGME_TOFU_POLICY_ASK; + else /* "unknown" and invalid policy strings. */ + ti->policy = GPGME_TOFU_POLICY_UNKNOWN; + + /* Parse first and last seen timestamps. */ + err = _gpgme_strtoul_field (field[6], &uval); + if (err) + goto inv_engine; + ti->firstseen = uval; + err = _gpgme_strtoul_field (field[7], &uval); + if (err) + goto inv_engine; + ti->lastseen = uval; + + /* Ready. */ + uid->tofu = ti; + return 0; + + inv_engine: + free (ti); + return trace_gpg_error (GPG_ERR_INV_ENGINE); +} + + /* We have read an entire key into tmp_key and should now finish it. It is assumed that this releases tmp_key. */ static void @@ -426,7 +505,7 @@ keylist_colon_handler (void *priv, char *line) gpgme_ctx_t ctx = (gpgme_ctx_t) priv; enum { - RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR, RT_GRP, + RT_NONE, RT_SIG, RT_UID, RT_TFS, RT_SUB, RT_PUB, RT_FPR, RT_GRP, RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK } rectype = RT_NONE; @@ -483,6 +562,8 @@ keylist_colon_handler (void *priv, char *line) rectype = RT_GRP; else if (!strcmp (field[0], "uid") && key) rectype = RT_UID; + else if (!strcmp (field[0], "tfs") && key) + rectype = RT_TFS; else if (!strcmp (field[0], "sub") && key) rectype = RT_SUB; else if (!strcmp (field[0], "ssb") && key) @@ -492,10 +573,10 @@ keylist_colon_handler (void *priv, char *line) else rectype = RT_NONE; - /* Only look at signatures immediately following a user ID. For - this, clear the user ID pointer when encountering anything but a - signature. */ - if (rectype != RT_SIG && rectype != RT_REV) + /* Only look at signature and trust info records immediately + following a user ID. For this, clear the user ID pointer when + encountering anything but a signature or trust record. */ + if (rectype != RT_SIG && rectype != RT_REV && rectype != RT_TFS) opd->tmp_uid = NULL; /* Only look at subpackets immediately following a signature. For @@ -695,6 +776,15 @@ keylist_colon_handler (void *priv, char *line) } break; + case RT_TFS: + if (opd->tmp_uid) + { + err = parse_tfs_record (opd->tmp_uid, field, fields); + if (err) + return err; + } + break; + case RT_FPR: /* Field 10 has the fingerprint (take only the first one). */ if (fields >= 10 && field[9] && *field[9]) |