[git] GPGME - branch, master, updated. gpgme-1.6.0-124-g10df06e
by Werner Koch
cvs at cvs.gnupg.org
Sat May 21 10:34:14 CEST 2016
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GnuPG Made Easy".
The branch, master has been updated
via 10df06ee8f9192309bf124872438f7c32457e1c6 (commit)
via dac2c5441d418536632f014c8b0e1359580279d1 (commit)
via a92946a8cacc44f655249d84b316deae59e62671 (commit)
from eaf2d018e63c15cd9a81e5c1fd2fedbf8829f7b9 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 10df06ee8f9192309bf124872438f7c32457e1c6
Author: Werner Koch <wk at gnupg.org>
Date: Sat May 21 10:29:49 2016 +0200
api: Return Tofu info for signatures.
* src/gpgme.h.in (gpgme_tofu_policy_t): New.
(gpgme_status_code_t): Add status codes for TOFU.
(struct _gpgme_tofu_info, gpgme_tofu_info_t): New.
(struct _gpgme_signature): Add field 'tofu'.
* src/status-table.c (status_table): Add new codes.
* src/verify.c: Include limits.h.
(release_tofu_info): New.
(release_op_data): Call that.
(parse_tofu_user): New.
(parse_tofu_stats): New.
(parse_tofu_stats_long): New.
(_gpgme_verify_status_handler): Handle TOFU status lines.
* tests/run-verify.c (print_description): New.
(print_result): print tofu info.
Signed-off-by: Werner Koch <wk at gnupg.org>
diff --git a/NEWS b/NEWS
index 119866e..04cfe12 100644
--- a/NEWS
+++ b/NEWS
@@ -6,8 +6,15 @@ Noteworthy changes in version 1.7.0 (unreleased) [C25/A14/R_]
* Interface changes relative to the 1.6.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_pubkey_algo_string NEW.
- gpgme_set_ctx_flag NEW.
GPGME_PK_EDDSA NEW.
+ gpgme_set_ctx_flag NEW.
+ gpgme_signature_t EXTENDED: New field tofu.
+ gpgme_tofu_policy_t NEW.
+ gpgme_tofu_info_t NEW.
+ GPGME_STATUS_KEY_CONSIDERED NEW.
+ GPGME_STATUS_TOFU_USER NEW.
+ GPGME_STATUS_TOFU_STATS NEW.
+ GPGME_STATUS_TOFU_STATS_LONG NEW.
Noteworthy changes in version 1.6.0 (2015-08-26) [C25/A14/R0]
diff --git a/src/gpgme.h.in b/src/gpgme.h.in
index 5f7896d..335ed6b 100644
--- a/src/gpgme.h.in
+++ b/src/gpgme.h.in
@@ -371,6 +371,19 @@ typedef enum
gpgme_validity_t;
+/* The TOFU policies. */
+typedef enum
+ {
+ GPGME_TOFU_POLICY_NONE = 0,
+ GPGME_TOFU_POLICY_AUTO = 1,
+ GPGME_TOFU_POLICY_GOOD = 2,
+ GPGME_TOFU_POLICY_UNKNOWN = 3,
+ GPGME_TOFU_POLICY_BAD = 4,
+ GPGME_TOFU_POLICY_ASK = 5
+ }
+gpgme_tofu_policy_t;
+
+
/* The available protocols. */
typedef enum
{
@@ -533,7 +546,10 @@ typedef enum
GPGME_STATUS_KEY_NOT_CREATED = 91,
GPGME_STATUS_INQUIRE_MAXLEN = 92,
GPGME_STATUS_FAILURE = 93,
- GPGME_STATUS_KEY_CONSIDERED = 94
+ GPGME_STATUS_KEY_CONSIDERED = 94,
+ GPGME_STATUS_TOFU_USER = 95,
+ GPGME_STATUS_TOFU_STATS = 96,
+ GPGME_STATUS_TOFU_STATS_LONG = 97
}
gpgme_status_code_t;
@@ -1533,6 +1549,46 @@ typedef enum
}
gpgme_sigsum_t;
+
+struct _gpgme_tofu_info
+{
+ struct _gpgme_tofu_info *next;
+
+ /* The mail address (addr-spec from RFC5322) of the tofu binding. */
+ char *address;
+
+ /* The fingerprint of the primary key. */
+ char *fpr;
+
+ /* The TOFU validity:
+ * 0 := conflict
+ * 1 := key without history
+ * 2 := key with too little history
+ * 3 := key with enough history for basic trust
+ * 4 := key with a lot of history
+ */
+ unsigned int validity : 3;
+
+ /* The TOFU policy (gpgme_tofu_policy_t). */
+ unsigned int policy : 4;
+
+ unsigned int _rfu : 25;
+
+ /* Number of signatures seen for this binding. Capped at USHRT_MAX. */
+ unsigned short signcount;
+ unsigned short reserved;
+
+ /* Number of seconds since the first and the most recently seen
+ * message was verified. */
+ unsigned int firstseen;
+ unsigned int lastseen;
+
+ /* If non-NULL a human readable string summarizing the TOFU data. */
+ char *description;
+};
+typedef struct _gpgme_tofu_info *gpgme_tofu_info_t;
+
+
struct _gpgme_signature
{
struct _gpgme_signature *next;
@@ -1578,6 +1634,9 @@ struct _gpgme_signature
/* The mailbox from the PKA information or NULL. */
char *pka_address;
+
+ /* If non-NULL, TOFU info for this signature are available. */
+ gpgme_tofu_info_t tofu;
};
typedef struct _gpgme_signature *gpgme_signature_t;
diff --git a/src/status-table.c b/src/status-table.c
index e70cb8b..5850a36 100644
--- a/src/status-table.c
+++ b/src/status-table.c
@@ -124,6 +124,9 @@ static struct status_table_s status_table[] =
{ "SIG_SUBPACKET", GPGME_STATUS_SIG_SUBPACKET },
{ "SIGEXPIRED", GPGME_STATUS_SIGEXPIRED },
{ "SUCCESS", GPGME_STATUS_SUCCESS },
+ { "TOFU_STATS", GPGME_STATUS_TOFU_STATS },
+ { "TOFU_STATS_LONG", GPGME_STATUS_TOFU_STATS_LONG },
+ { "TOFU_USER", GPGME_STATUS_TOFU_USER },
{ "TRUNCATED", GPGME_STATUS_TRUNCATED },
{ "TRUST_FULLY", GPGME_STATUS_TRUST_FULLY },
{ "TRUST_MARGINAL", GPGME_STATUS_TRUST_MARGINAL },
diff --git a/src/verify.c b/src/verify.c
index 4781d99..e6c9665 100644
--- a/src/verify.c
+++ b/src/verify.c
@@ -26,6 +26,7 @@
#include <string.h>
#include <errno.h>
#include <assert.h>
+#include <limits.h>
#include "gpgme.h"
#include "debug.h"
@@ -49,6 +50,22 @@ typedef struct
static void
+release_tofu_info (gpgme_tofu_info_t t)
+{
+ while (t)
+ {
+ gpgme_tofu_info_t t2 = t->next;
+
+ free (t->address);
+ free (t->fpr);
+ free (t->description);
+ free (t);
+ t = t2;
+ }
+}
+
+
+static void
release_op_data (void *hook)
{
op_data_t opd = (op_data_t) hook;
@@ -71,6 +88,7 @@ release_op_data (void *hook)
free (sig->fpr);
if (sig->pka_address)
free (sig->pka_address);
+ release_tofu_info (sig->tofu);
free (sig);
sig = next;
}
@@ -635,6 +653,169 @@ parse_trust (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
}
+/* Parse a TOFU_USER line and put the info into SIG. */
+static gpgme_error_t
+parse_tofu_user (gpgme_signature_t sig, char *args)
+{
+ gpg_error_t err;
+ char *tail;
+ gpgme_tofu_info_t ti, ti2;
+
+ tail = strchr (args, ' ');
+ if (!tail || tail == args)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* No fingerprint. */
+ *tail++ = 0;
+
+ ti = calloc (1, sizeof *ti);
+ if (!ti)
+ return gpg_error_from_syserror ();
+
+ ti->fpr = strdup (args);
+ if (!ti->fpr)
+ {
+ free (ti);
+ return gpg_error_from_syserror ();
+ }
+
+ args = tail;
+ tail = strchr (args, ' ');
+ if (tail == args)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* No addr-spec. */
+ if (tail)
+ *tail = 0;
+
+ err = _gpgme_decode_percent_string (args, &ti->address, 0, 0);
+ if (err)
+ {
+ free (ti);
+ return err;
+ }
+
+ /* Append to the tofu info list. */
+ if (!sig->tofu)
+ sig->tofu = ti;
+ else
+ {
+ for (ti2 = sig->tofu; ti2->next; ti2 = ti2->next)
+ ;
+ ti2->next = ti;
+ }
+
+ return 0;
+}
+
+
+/* Parse a TOFU_STATS line and store it in the last tofu info of SIG.
+ *
+ * TOFU_STATS <validity> <sign-count> 0 [<policy> [<tm1> <tm2>]]
+ */
+static gpgme_error_t
+parse_tofu_stats (gpgme_signature_t sig, char *args)
+{
+ gpgme_error_t err;
+ gpgme_tofu_info_t ti;
+ char *field[6];
+ int nfields;
+ unsigned long uval;
+
+ if (!sig->tofu)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* No TOFU_USER seen. */
+ for (ti = sig->tofu; ti->next; ti = ti->next)
+ ;
+ if (ti->firstseen || ti->signcount || ti->validity || ti->policy)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Already seen. */
+
+ nfields = _gpgme_split_fields (args, field, DIM (field));
+ if (nfields < 3)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Required args missing. */
+
+ /* 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[0], &uval);
+ if (err || uval > 7)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+ ti->validity = uval;
+
+ /* Parse the sign-count. */
+ err = _gpgme_strtoul_field (field[1], &uval);
+ if (err)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+ if (uval > USHRT_MAX)
+ uval = USHRT_MAX;
+ ti->signcount = uval;
+
+ /* We skip the 0, which is RFU. */
+
+ if (nfields == 3)
+ return 0; /* All mandatory fields parsed. */
+
+ /* Parse the policy. */
+ if (!strcmp (field[3], "none"))
+ ti->policy = GPGME_TOFU_POLICY_NONE;
+ else if (!strcmp (field[3], "auto"))
+ ti->policy = GPGME_TOFU_POLICY_AUTO;
+ else if (!strcmp (field[3], "good"))
+ ti->policy = GPGME_TOFU_POLICY_GOOD;
+ else if (!strcmp (field[3], "bad"))
+ ti->policy = GPGME_TOFU_POLICY_BAD;
+ else if (!strcmp (field[3], "ask"))
+ ti->policy = GPGME_TOFU_POLICY_ASK;
+ else /* "unknown" and invalid policy strings. */
+ ti->policy = GPGME_TOFU_POLICY_UNKNOWN;
+
+ if (nfields == 4)
+ return 0; /* No more optional fields. */
+
+ /* Parse first and last seen (none or both are required). */
+ if (nfields < 6)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* "tm2" missing. */
+ err = _gpgme_strtoul_field (field[4], &uval);
+ if (err)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+ if (uval > UINT_MAX)
+ uval = UINT_MAX;
+ ti->firstseen = uval;
+ err = _gpgme_strtoul_field (field[5], &uval);
+ if (err)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+ if (uval > UINT_MAX)
+ uval = UINT_MAX;
+ ti->lastseen = uval;
+
+ return 0;
+}
+
+
+/* Parse a TOFU_STATS_LONG line and store it in the last tofu info of SIG. */
+static gpgme_error_t
+parse_tofu_stats_long (gpgme_signature_t sig, char *args, int raw)
+{
+ gpgme_error_t err;
+ gpgme_tofu_info_t ti;
+ char *p;
+
+ if (!sig->tofu)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* No TOFU_USER seen. */
+ for (ti = sig->tofu; ti->next; ti = ti->next)
+ ;
+ if (ti->description)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Already seen. */
+
+ err = _gpgme_decode_percent_string (args, &ti->description, 0, 0);
+ if (err)
+ return err;
+
+ /* Remove the non-breaking spaces. */
+ if (!raw)
+ {
+ for (p = ti->description; *p; p++)
+ if (*p == '~')
+ *p = ' ';
+ }
+ return 0;
+}
+
+
/* Parse an error status line and if SET_STATUS is true update the
result status as appropriate. With SET_STATUS being false, only
check for an error. */
@@ -766,6 +947,21 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
sig->pka_address = strdup (args);
break;
+ case GPGME_STATUS_TOFU_USER:
+ opd->only_newsig_seen = 0;
+ return sig ? parse_tofu_user (sig, args)
+ /* */ : trace_gpg_error (GPG_ERR_INV_ENGINE);
+
+ case GPGME_STATUS_TOFU_STATS:
+ opd->only_newsig_seen = 0;
+ return sig ? parse_tofu_stats (sig, args)
+ /* */ : trace_gpg_error (GPG_ERR_INV_ENGINE);
+
+ case GPGME_STATUS_TOFU_STATS_LONG:
+ opd->only_newsig_seen = 0;
+ return sig ? parse_tofu_stats_long (sig, args, ctx->raw_description)
+ /* */ : trace_gpg_error (GPG_ERR_INV_ENGINE);
+
case GPGME_STATUS_ERROR:
opd->only_newsig_seen = 0;
/* Some error stati are informational, so we don't return an
diff --git a/tests/run-verify.c b/tests/run-verify.c
index b7be320..df8cbf6 100644
--- a/tests/run-verify.c
+++ b/tests/run-verify.c
@@ -94,9 +94,23 @@ print_validity (gpgme_validity_t val)
static void
+print_description (const char *text, int indent)
+{
+ for (; *text; text++)
+ {
+ putchar (*text);
+ if (*text == '\n')
+ printf ("%*s", indent, "");
+ }
+ putchar ('\n');
+}
+
+
+static void
print_result (gpgme_verify_result_t result)
{
gpgme_signature_t sig;
+ gpgme_tofu_info_t ti;
int count = 0;
printf ("Original file name: %s\n", nonnull(result->file_name));
@@ -126,6 +140,30 @@ print_result (gpgme_verify_result_t result)
);
printf (" notations .: %s\n",
sig->notations? "yes":"no");
+ for (ti = sig->tofu; ti; ti = ti->next)
+ {
+ printf (" tofu addr .: %s\n", ti->address);
+ if (!sig->fpr || strcmp (sig->fpr, ti->fpr))
+ printf (" WARNING .: fpr mismatch (%s)\n", ti->fpr);
+ printf (" validity : %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 (" sigcount : %hu\n", ti->signcount);
+ printf (" firstseen: %u\n", ti->firstseen);
+ printf (" lastseen : %u\n", ti->lastseen);
+ printf (" desc ....: ");
+ print_description (nonnull (ti->description), 15);
+ }
}
}
@@ -230,6 +268,7 @@ main (int argc, char **argv)
gpgme_set_status_cb (ctx, status_cb, NULL);
gpgme_set_ctx_flag (ctx, "full-status", "1");
}
+ /* gpgme_set_ctx_flag (ctx, "raw-description", "1"); */
err = gpgme_data_new_from_stream (&sig, fp_sig);
if (err)
commit dac2c5441d418536632f014c8b0e1359580279d1
Author: Werner Koch <wk at gnupg.org>
Date: Sat May 21 10:22:57 2016 +0200
api: Add new context flag "raw-description".
* src/context.h (struct gpgme_context): Add field raw_description.
* src/gpgme.c (gpgme_set_ctx_flag): New flag.
Signed-off-by: Werner Koch <wk at gnupg.org>
diff --git a/doc/gpgme.texi b/doc/gpgme.texi
index 4d7a874..8d666c3 100644
--- a/doc/gpgme.texi
+++ b/doc/gpgme.texi
@@ -2752,6 +2752,12 @@ gpgme_set_status_cb returns all status lines with the exception of
PROGRESS lines. With the default of "0" the status callback is only
called in certain situations.
+ at item "raw-description"
+Setting the @var{value} to "1" returns human readable strings in a raw
+format. For example the non breaking space characters ("~") will not
+be removed from the @code{description} field of the
+ at code{gpgme_tofu_info_t} object.
+
@end table
This function returns @code{0} on success.
diff --git a/src/context.h b/src/context.h
index 078f0cb..de69a7a 100644
--- a/src/context.h
+++ b/src/context.h
@@ -105,6 +105,11 @@ struct gpgme_context
* lines. */
unsigned int full_status : 1;
+ /* The Tofu info has a human readable string which is presented to
+ * the user in a directly usable format. By enabling this flag the
+ * unmodified string, as received form gpg, will be returned. */
+ unsigned int raw_description : 1;
+
/* Flags for keylist mode. */
gpgme_keylist_mode_t keylist_mode;
diff --git a/src/gpgme.c b/src/gpgme.c
index 3289be9..e0cd9b0 100644
--- a/src/gpgme.c
+++ b/src/gpgme.c
@@ -93,11 +93,20 @@ gpgme_set_global_flag (const char *name, const char *value)
gpgme_error_t
gpgme_set_ctx_flag (gpgme_ctx_t ctx, const char *name, const char *value)
{
+ int abool;
+
if (!ctx || !name || !value)
return gpg_error (GPG_ERR_INV_VALUE);
- else if (!strcmp (name, "full-status"))
+
+ abool = *value? !!atoi (value) : 0;
+
+ if (!strcmp (name, "full-status"))
+ {
+ ctx->full_status = abool;
+ }
+ else if (!strcmp (name, "raw-description"))
{
- ctx->full_status = *value? !!atoi (value) : 0;
+ ctx->raw_description = abool;
}
else
return gpg_error (GPG_ERR_UNKNOWN_NAME);
commit a92946a8cacc44f655249d84b316deae59e62671
Author: Werner Koch <wk at gnupg.org>
Date: Sat May 21 10:21:06 2016 +0200
core: New functions to help parsing of status lines.
* src/conversion.c (_gpgme_split_fields): New.
(_gpgme_strtoul_field): New.
--
Signed-off-by: Werner Koch <wk at gnupg.org>
diff --git a/src/conversion.c b/src/conversion.c
index 0992225..c2b27a1 100644
--- a/src/conversion.c
+++ b/src/conversion.c
@@ -317,6 +317,53 @@ _gpgme_encode_percent_string (const char *src, char **destp, size_t len)
}
+/* Split a string into space delimited fields and remove leading and
+ * trailing spaces from each field. A pointer to the each field is
+ * stored in ARRAY. Stop splitting at ARRAYSIZE fields. The function
+ * modifies STRING. The number of parsed fields is returned.
+ */
+int
+_gpgme_split_fields (char *string, char **array, int arraysize)
+{
+ int n = 0;
+ char *p, *pend;
+
+ for (p = string; *p == ' '; p++)
+ ;
+ do
+ {
+ if (n == arraysize)
+ break;
+ array[n++] = p;
+ pend = strchr (p, ' ');
+ if (!pend)
+ break;
+ *pend++ = 0;
+ for (p = pend; *p == ' '; p++)
+ ;
+ }
+ while (*p);
+
+ return n;
+}
+
+/* Convert the field STRING into an unsigned long value. Check for
+ * trailing garbage. */
+gpgme_error_t
+_gpgme_strtoul_field (const char *string, unsigned long *result)
+{
+ char *endp;
+
+ gpg_err_set_errno (0);
+ *result = strtoul (string, &endp, 0);
+ if (errno)
+ return gpg_error_from_syserror ();
+ if (endp == string || *endp)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ return 0;
+}
+
+
#ifdef HAVE_W32_SYSTEM
static time_t
_gpgme_timegm (struct tm *tm)
diff --git a/src/util.h b/src/util.h
index 365f1d8..9c62f57 100644
--- a/src/util.h
+++ b/src/util.h
@@ -124,6 +124,15 @@ gpgme_error_t _gpgme_decode_percent_string (const char *src, char **destp,
gpgme_error_t _gpgme_encode_percent_string (const char *src, char **destp,
size_t len);
+/* Split a string into space delimited fields and remove leading and
+ * trailing spaces from each field. A pointer to the each field is
+ * stored in ARRAY. Stop splitting at ARRAYSIZE fields. The function
+ * modifies STRING. The number of parsed fields is returned. */
+int _gpgme_split_fields (char *string, char **array, int arraysize);
+
+/* Convert the field STRING into an unsigned long value. Check for
+ * trailing garbage. */
+gpgme_error_t _gpgme_strtoul_field (const char *string, unsigned long *result);
/* Parse the string TIMESTAMP into a time_t. The string may either be
seconds since Epoch or in the ISO 8601 format like
-----------------------------------------------------------------------
Summary of changes:
NEWS | 9 ++-
doc/gpgme.texi | 6 ++
src/context.h | 5 ++
src/conversion.c | 47 +++++++++++++
src/gpgme.c | 13 +++-
src/gpgme.h.in | 61 ++++++++++++++++-
src/status-table.c | 3 +
src/util.h | 9 +++
src/verify.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++++++++
tests/run-verify.c | 39 +++++++++++
10 files changed, 384 insertions(+), 4 deletions(-)
hooks/post-receive
--
GnuPG Made Easy
http://git.gnupg.org
More information about the Gnupg-commits
mailing list