[Pkg-gnupg-commit] [gpgme] 306/412: core: Add GPGME_KEYLIST_MODE_WITH_TOFU.
Daniel Kahn Gillmor
dkg at fifthhorseman.net
Thu Sep 22 21:27:08 UTC 2016
This is an automated email from the git hooks/post-receive script.
dkg pushed a commit to branch master
in repository gpgme.
commit 9ee103957e4136337b92d238283f8ef30fd4a7c5
Author: Werner Koch <wk at gnupg.org>
Date: Thu Aug 25 11:38:03 2016 +0200
core: Add GPGME_KEYLIST_MODE_WITH_TOFU.
* src/gpgme.h.in (GPGME_KEYLIST_MODE_WITH_TOFU): New.
* src/engine-gpg.c (gpg_keylist_build_options): Use that.
* src/keylist.c: Include limits.h.
(parse_tfs_record): New.
(keylist_colon_handler): Support TFS record.
* tests/run-keylist.c: Include time.h.
(isotimestr): New.
(main): Add option --tofu. Print TOFU info.
* tests/run-verify.c: Include time.h.
(isotimestr): New.
(print_result): Use isotimestr for TOFU dates.
Signed-off-by: Werner Koch <wk at gnupg.org>
---
NEWS | 1 +
doc/gpgme.texi | 5 +++
src/engine-gpg.c | 7 ++++
src/gpgme.h.in | 3 +-
src/keylist.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++---
tests/run-keylist.c | 60 +++++++++++++++++++++++++++----
tests/run-verify.c | 25 +++++++++++--
7 files changed, 186 insertions(+), 15 deletions(-)
diff --git a/NEWS b/NEWS
index 1294e0b..da331b4 100644
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,7 @@ Noteworthy changes in version 1.7.0 (unreleased) [C25/A14/R_]
GPGME_STATUS_TOFU_STATS NEW.
GPGME_STATUS_TOFU_STATS_LONG NEW.
GPGME_STATUS_NOTATION_FLAGS NEW.
+ GPGME_KEYLIST_MODE_WITH_TOFU NEW.
GPGME_DATA_TYPE_PGP_ENCRYPTED NEW.
GPGME_DATA_TYPE_PGP_SIGNATURE NEW.
GPGME_DATA_ENCODING_MIME NEW.
diff --git a/doc/gpgme.texi b/doc/gpgme.texi
index 02551d9..dfc9548 100644
--- a/doc/gpgme.texi
+++ b/doc/gpgme.texi
@@ -2683,6 +2683,11 @@ signature notations on key signatures should be included in the listed
keys. This only works if @code{GPGME_KEYLIST_MODE_SIGS} is also
enabled.
+ at item GPGME_KEYLIST_MODE_WITH_TOFU
+The @code{GPGME_KEYLIST_MODE_WITH_TOFU} symbol specifies that
+information pertaining to the TOFU trust model should be included in
+the listed keys.
+
@item GPGME_KEYLIST_MODE_WITH_SECRET
The @code{GPGME_KEYLIST_MODE_WITH_SECRET} returns information about
the presence of a corresponding secret key in a public key listing. A
diff --git a/src/engine-gpg.c b/src/engine-gpg.c
index 3edac6c..7036ee0 100644
--- a/src/engine-gpg.c
+++ b/src/engine-gpg.c
@@ -2338,8 +2338,13 @@ gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
err = add_arg (gpg, "--with-fingerprint");
}
+ if (!err && (mode & GPGME_KEYLIST_MODE_WITH_TOFU)
+ && have_gpg_version (gpg, "2.1.16"))
+ err = add_arg (gpg, "--with-tofu-info");
+
if (!err && (mode & GPGME_KEYLIST_MODE_WITH_SECRET))
err = add_arg (gpg, "--with-secret");
+
if (!err
&& (mode & GPGME_KEYLIST_MODE_SIGS)
&& (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
@@ -2348,6 +2353,7 @@ gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
if (!err)
err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
}
+
if (!err)
{
if ( (mode & GPGME_KEYLIST_MODE_EXTERN) )
@@ -2379,6 +2385,7 @@ gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
? "--check-sigs" : "--list-keys"));
}
}
+
if (!err)
err = add_arg (gpg, "--");
diff --git a/src/gpgme.h.in b/src/gpgme.h.in
index 79a7b9f..57f3446 100644
--- a/src/gpgme.h.in
+++ b/src/gpgme.h.in
@@ -411,6 +411,7 @@ gpgme_protocol_t;
#define GPGME_KEYLIST_MODE_SIGS 4
#define GPGME_KEYLIST_MODE_SIG_NOTATIONS 8
#define GPGME_KEYLIST_MODE_WITH_SECRET 16
+#define GPGME_KEYLIST_MODE_WITH_TOFU 32
#define GPGME_KEYLIST_MODE_EPHEMERAL 128
#define GPGME_KEYLIST_MODE_VALIDATE 256
@@ -843,7 +844,7 @@ struct _gpgme_user_id
* NULL is stored. */
char *address;
- /* The malloced tofo information or NULL. */
+ /* The malloced TOFU information or NULL. */
gpgme_tofu_info_t tofu;
};
typedef struct _gpgme_user_id *gpgme_user_id_t;
diff --git a/src/keylist.c b/src/keylist.c
index 38ddd0c..9f1e68d 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])
diff --git a/tests/run-keylist.c b/tests/run-keylist.c
index bae2dbb..00f874d 100644
--- a/tests/run-keylist.c
+++ b/tests/run-keylist.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <time.h>
#include <gpgme.h>
@@ -49,6 +50,7 @@ show_usage (int ex)
" --local use GPGME_KEYLIST_MODE_LOCAL\n"
" --extern use GPGME_KEYLIST_MODE_EXTERN\n"
" --sigs use GPGME_KEYLIST_MODE_SIGS\n"
+ " --tofu use GPGME_KEYLIST_MODE_TOFU\n"
" --sig-notations use GPGME_KEYLIST_MODE_SIG_NOTATIONS\n"
" --ephemeral use GPGME_KEYLIST_MODE_EPHEMERAL\n"
" --validate use GPGME_KEYLIST_MODE_VALIDATE\n"
@@ -60,6 +62,26 @@ show_usage (int ex)
}
+static const char *
+isotimestr (unsigned long value)
+{
+ time_t t;
+ static char buffer[25+5];
+ struct tm *tp;
+
+ if (!value)
+ return "none";
+ t = value;
+
+ tp = gmtime (&t);
+ snprintf (buffer, sizeof buffer, "%04d-%02d-%02d %02d:%02d:%02d",
+ 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
+ tp->tm_hour, tp->tm_min, tp->tm_sec);
+ return buffer;
+}
+
+
+
int
main (int argc, char **argv)
{
@@ -120,6 +142,11 @@ main (int argc, char **argv)
mode |= GPGME_KEYLIST_MODE_EXTERN;
argc--; argv++;
}
+ else if (!strcmp (*argv, "--tofu"))
+ {
+ mode |= GPGME_KEYLIST_MODE_WITH_TOFU;
+ argc--; argv++;
+ }
else if (!strcmp (*argv, "--sigs"))
{
mode |= GPGME_KEYLIST_MODE_SIGS;
@@ -181,6 +208,7 @@ main (int argc, char **argv)
while (!(err = gpgme_op_keylist_next (ctx, &key)))
{
gpgme_user_id_t uid;
+ gpgme_tofu_info_t ti;
int nuids;
int nsub;
@@ -233,24 +261,42 @@ main (int argc, char **argv)
for (nuids=0, uid=key->uids; uid; uid = uid->next, nuids++)
{
printf ("userid %d: %s\n", nuids, nonnull(uid->uid));
- printf (" mbox %d: %s\n", nuids, nonnull(uid->address));
+ printf (" mbox: %s\n", nonnull(uid->address));
if (uid->email && uid->email != uid->address)
- printf (" email %d: %s\n", nuids, uid->email);
+ printf (" email: %s\n", uid->email);
if (uid->name)
- printf (" name %d: %s\n", nuids, uid->name);
+ printf (" name: %s\n", uid->name);
if (uid->comment)
- printf (" cmmnt %d: %s\n", nuids, uid->comment);
- printf (" valid %d: %s\n", nuids,
+ printf (" cmmnt: %s\n", uid->comment);
+ printf (" valid: %s\n",
uid->validity == GPGME_VALIDITY_UNKNOWN? "unknown":
uid->validity == GPGME_VALIDITY_UNDEFINED? "undefined":
uid->validity == GPGME_VALIDITY_NEVER? "never":
uid->validity == GPGME_VALIDITY_MARGINAL? "marginal":
uid->validity == GPGME_VALIDITY_FULL? "full":
uid->validity == GPGME_VALIDITY_ULTIMATE? "ultimate": "[?]");
+ if ((ti = uid->tofu))
+ {
+ printf (" tofu: %u (%s)\n", ti->validity,
+ ti->validity == 0? "conflict" :
+ ti->validity == 1? "no history" :
+ ti->validity == 2? "little history" :
+ ti->validity == 3? "enough history" :
+ ti->validity == 4? "lot of history" : "?");
+ printf (" policy: %u (%s)\n", ti->policy,
+ ti->policy == GPGME_TOFU_POLICY_NONE? "none" :
+ ti->policy == GPGME_TOFU_POLICY_AUTO? "auto" :
+ ti->policy == GPGME_TOFU_POLICY_GOOD? "good" :
+ ti->policy == GPGME_TOFU_POLICY_UNKNOWN? "unknown" :
+ ti->policy == GPGME_TOFU_POLICY_BAD? "bad" :
+ ti->policy == GPGME_TOFU_POLICY_ASK? "ask" : "?");
+ printf (" nsigs: %hu\n", ti->signcount);
+ printf (" nencr: %hu\n", ti->encrcount);
+ printf (" first: %s\n", isotimestr (ti->firstseen));
+ printf (" last: %s\n", isotimestr (ti->lastseen));
+ }
}
-
-
putchar ('\n');
if (import)
diff --git a/tests/run-verify.c b/tests/run-verify.c
index ef4dd32..3c18d3b 100644
--- a/tests/run-verify.c
+++ b/tests/run-verify.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <time.h>
#include <gpgme.h>
@@ -36,6 +37,26 @@
static int verbose;
+
+static const char *
+isotimestr (unsigned long value)
+{
+ time_t t;
+ static char buffer[25+5];
+ struct tm *tp;
+
+ if (!value)
+ return "none";
+ t = value;
+
+ tp = gmtime (&t);
+ snprintf (buffer, sizeof buffer, "%04d-%02d-%02d %02d:%02d:%02d",
+ 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
+ tp->tm_hour, tp->tm_min, tp->tm_sec);
+ return buffer;
+}
+
+
static gpg_error_t
status_cb (void *opaque, const char *keyword, const char *value)
{
@@ -177,8 +198,8 @@ print_result (gpgme_verify_result_t result)
ti->policy == GPGME_TOFU_POLICY_BAD? "bad" :
ti->policy == GPGME_TOFU_POLICY_ASK? "ask" : "?");
printf (" sigcount : %hu\n", ti->signcount);
- printf (" firstseen: %u\n", ti->firstseen);
- printf (" lastseen : %u\n", ti->lastseen);
+ printf (" firstseen: %s\n", isotimestr (ti->firstseen));
+ printf (" lastseen : %s\n", isotimestr (ti->lastseen));
printf (" desc ....: ");
print_description (nonnull (ti->description), 15);
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gnupg/gpgme.git
More information about the Pkg-gnupg-commit
mailing list