aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2017-09-18 10:52:20 +0000
committerWerner Koch <[email protected]>2017-09-18 10:52:20 +0000
commit7f7f5d06fa5aa3a3c5ab8d2e59ee76207bfdeaa0 (patch)
tree24341aa29bd58424d584c46e8b9a8eda1bf135b4
parentwks: Print the UID creation time with gpg-wks-client --check. (diff)
downloadgnupg-7f7f5d06fa5aa3a3c5ab8d2e59ee76207bfdeaa0.tar.gz
gnupg-7f7f5d06fa5aa3a3c5ab8d2e59ee76207bfdeaa0.zip
wks: Send only the newest UID to the server.
* tools/wks-util.c (list_key_status_cb): Rename to key_status_cb. (wks_filter_uid): New. (wks_list_key): Allow FPR to be NULL. Return an error if no fingerprint was found. * tools/gpg-wks-server.c (process_new_key) (check_and_publish): Remove now useless extra check for FPR. * tools/gpg-wks-client.c (command_check): Ditto. (command_send): Filter out the newest uid. -- This fixes the case of having several userids with all the the same mailbox. Now we use the latest user id created. This patch is also a prerequisite to automatically create a new user id for providers with the mailbox-only policy. Signed-off-by: Werner Koch <[email protected]>
-rw-r--r--tools/gpg-wks-client.c60
-rw-r--r--tools/gpg-wks-server.c14
-rw-r--r--tools/gpg-wks.h2
-rw-r--r--tools/wks-util.c104
4 files changed, 158 insertions, 22 deletions
diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c
index 18a0edd72..37b75606b 100644
--- a/tools/gpg-wks-client.c
+++ b/tools/gpg-wks-client.c
@@ -644,10 +644,9 @@ command_check (char *userid)
/* Look closer at the key. */
err = wks_list_key (key, &fpr, &mboxes);
- if (err || !fpr)
+ if (err)
{
- log_error ("error parsing key: %s\n",
- err? gpg_strerror (err) : "no fingerprint found");
+ log_error ("error parsing key: %s\n", gpg_strerror (err));
err = gpg_error (GPG_ERR_NO_PUBKEY);
goto leave;
}
@@ -700,6 +699,9 @@ command_send (const char *fingerprint, const char *userid)
int no_encrypt = 0;
int posteo_hack = 0;
const char *domain;
+ uidinfo_list_t uidlist = NULL;
+ uidinfo_list_t uid, thisuid;
+ time_t thistime;
memset (&policy, 0, sizeof policy);
@@ -769,6 +771,57 @@ command_send (const char *fingerprint, const char *userid)
if (policy.auth_submit)
log_info ("no confirmation required for '%s'\n", addrspec);
+ /* In case the key has several uids with the same addr-spec we will
+ * use the newest one. */
+ err = wks_list_key (key, NULL, &uidlist);
+ if (err)
+ {
+ log_error ("error parsing key: %s\n",gpg_strerror (err));
+ err = gpg_error (GPG_ERR_NO_PUBKEY);
+ goto leave;
+ }
+ thistime = 0;
+ thisuid = NULL;
+ for (uid = uidlist; uid; uid = uid->next)
+ {
+ if (!uid->mbox)
+ continue; /* Should not happen anyway. */
+ if (uid->created > thistime)
+ {
+ thistime = uid->created;
+ thisuid = uid;
+ }
+ }
+ if (!thisuid)
+ thisuid = uid; /* This is the case for a missing timestamp. */
+ if (opt.verbose)
+ log_info ("submitting key with user id '%s'\n", thisuid->uid);
+
+ /* If we have more than one user id we need to filter the key to
+ * include only THISUID. */
+ if (uidlist->next)
+ {
+ estream_t newkey;
+
+ es_rewind (key);
+ err = wks_filter_uid (&newkey, key, thisuid->uid);
+ if (err)
+ {
+ log_error ("error filtering key: %s\n", gpg_strerror (err));
+ err = gpg_error (GPG_ERR_NO_PUBKEY);
+ goto leave;
+ }
+ es_fclose (key);
+ key = newkey;
+ }
+
+ if (policy.mailbox_only
+ && ascii_strcasecmp (userid, addrspec))
+ {
+ log_info ("Warning: policy requires 'mailbox-only'"
+ " - creating new user id'\n");
+ }
+
/* Hack to support posteo but let them disable this by setting the
* new policy-version flag. */
if (policy.protocol_version < 3
@@ -885,6 +938,7 @@ command_send (const char *fingerprint, const char *userid)
leave:
mime_maker_release (mime);
xfree (submission_to);
+ free_uidinfo_list (uidlist);
es_fclose (keyenc);
es_fclose (key);
xfree (addrspec);
diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c
index f7aadba3d..7e3f05017 100644
--- a/tools/gpg-wks-server.c
+++ b/tools/gpg-wks-server.c
@@ -1105,12 +1105,7 @@ process_new_key (server_ctx_t ctx, estream_t key)
err = wks_list_key (key, &ctx->fpr, &ctx->mboxes);
if (err)
goto leave;
- if (!ctx->fpr)
- {
- log_error ("error parsing key (no fingerprint)\n");
- err = gpg_error (GPG_ERR_NO_PUBKEY);
- goto leave;
- }
+ log_assert (ctx->fpr);
log_info ("fingerprint: %s\n", ctx->fpr);
for (sl = ctx->mboxes; sl; sl = sl->next)
{
@@ -1358,12 +1353,7 @@ check_and_publish (server_ctx_t ctx, const char *address, const char *nonce)
err = wks_list_key (key, &ctx->fpr, &ctx->mboxes);
if (err)
goto leave;
- if (!ctx->fpr)
- {
- log_error ("error parsing key (no fingerprint)\n");
- err = gpg_error (GPG_ERR_NO_PUBKEY);
- goto leave;
- }
+ log_assert (ctx->fpr);
log_info ("fingerprint: %s\n", ctx->fpr);
for (sl = ctx->mboxes; sl; sl = sl->next)
if (sl->mbox)
diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h
index cb89fd501..ece7add5f 100644
--- a/tools/gpg-wks.h
+++ b/tools/gpg-wks.h
@@ -87,6 +87,8 @@ void wks_write_status (int no, const char *format, ...) GPGRT_ATTR_PRINTF(2,3);
void free_uidinfo_list (uidinfo_list_t list);
gpg_error_t wks_list_key (estream_t key, char **r_fpr,
uidinfo_list_t *r_mboxes);
+gpg_error_t wks_filter_uid (estream_t *r_newkey, estream_t key,
+ const char *uid);
gpg_error_t wks_send_mime (mime_maker_t mime);
gpg_error_t wks_parse_policy (policy_flags_t flags, estream_t stream,
int ignore_unknown);
diff --git a/tools/wks-util.c b/tools/wks-util.c
index 8fc0a2e5c..889ca36dc 100644
--- a/tools/wks-util.c
+++ b/tools/wks-util.c
@@ -133,9 +133,9 @@ free_uidinfo_list (uidinfo_list_t list)
-/* Helper for wks_list_key. */
+/* Helper for wks_list_key and wks_filter_uid. */
static void
-list_key_status_cb (void *opaque, const char *keyword, char *args)
+key_status_cb (void *opaque, const char *keyword, char *args)
{
(void)opaque;
@@ -146,7 +146,8 @@ list_key_status_cb (void *opaque, const char *keyword, char *args)
/* Run gpg on KEY and store the primary fingerprint at R_FPR and the
* list of mailboxes at R_MBOXES. Returns 0 on success; on error NULL
- * is stored at R_FPR and R_MBOXES and an error code is returned. */
+ * is stored at R_FPR and R_MBOXES and an error code is returned.
+ * R_FPR may be NULL if the fingerprint is not needed. */
gpg_error_t
wks_list_key (estream_t key, char **r_fpr, uidinfo_list_t *r_mboxes)
{
@@ -164,7 +165,8 @@ wks_list_key (estream_t key, char **r_fpr, uidinfo_list_t *r_mboxes)
char *fpr = NULL;
uidinfo_list_t mboxes = NULL;
- *r_fpr = NULL;
+ if (r_fpr)
+ *r_fpr = NULL;
*r_mboxes = NULL;
/* Open a memory stream. */
@@ -200,7 +202,7 @@ wks_list_key (estream_t key, char **r_fpr, uidinfo_list_t *r_mboxes)
}
err = gnupg_exec_tool_stream (opt.gpg_program, argv, key,
NULL, listing,
- list_key_status_cb, NULL);
+ key_status_cb, NULL);
if (err)
{
log_error ("import failed: %s\n", gpg_strerror (err));
@@ -289,8 +291,17 @@ wks_list_key (estream_t key, char **r_fpr, uidinfo_list_t *r_mboxes)
goto leave;
}
- *r_fpr = fpr;
- fpr = NULL;
+ if (!fpr)
+ {
+ err = gpg_error (GPG_ERR_NO_PUBKEY);
+ goto leave;
+ }
+
+ if (r_fpr)
+ {
+ *r_fpr = fpr;
+ fpr = NULL;
+ }
*r_mboxes = mboxes;
mboxes = NULL;
@@ -305,6 +316,85 @@ wks_list_key (estream_t key, char **r_fpr, uidinfo_list_t *r_mboxes)
}
+/* Run gpg as a filter on KEY and write the output to a new stream
+ * stored at R_NEWKEY. The new key will containn only the user id
+ * UID. Returns 0 on success. Only one key is expected in KEY. */
+gpg_error_t
+wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid)
+{
+ gpg_error_t err;
+ ccparray_t ccp;
+ const char **argv = NULL;
+ estream_t newkey;
+ char *filterexp = NULL;
+
+ *r_newkey = NULL;
+
+ /* Open a memory stream. */
+ newkey = es_fopenmem (0, "w+b");
+ if (!newkey)
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
+ return err;
+ }
+
+ /* Prefix the key with the MIME content type. */
+ es_fputs ("Content-Type: application/pgp-keys\n"
+ "\n", newkey);
+
+ filterexp = es_bsprintf ("keep-uid=uid=%s", uid);
+ if (!filterexp)
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+
+ ccparray_init (&ccp, 0);
+
+ ccparray_put (&ccp, "--no-options");
+ if (!opt.verbose)
+ ccparray_put (&ccp, "--quiet");
+ else if (opt.verbose > 1)
+ ccparray_put (&ccp, "--verbose");
+ ccparray_put (&ccp, "--batch");
+ ccparray_put (&ccp, "--status-fd=2");
+ ccparray_put (&ccp, "--always-trust");
+ ccparray_put (&ccp, "--armor");
+ ccparray_put (&ccp, "--import-options=import-export");
+ ccparray_put (&ccp, "--import-filter");
+ ccparray_put (&ccp, filterexp);
+ ccparray_put (&ccp, "--import");
+
+ ccparray_put (&ccp, NULL);
+ argv = ccparray_get (&ccp, NULL);
+ if (!argv)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ err = gnupg_exec_tool_stream (opt.gpg_program, argv, key,
+ NULL, newkey,
+ key_status_cb, NULL);
+ if (err)
+ {
+ log_error ("import/export failed: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+
+ es_rewind (newkey);
+ *r_newkey = newkey;
+ newkey = NULL;
+
+ leave:
+ xfree (filterexp);
+ xfree (argv);
+ es_fclose (newkey);
+ return err;
+}
+
+
/* Helper to write mail to the output(s). */
gpg_error_t
wks_send_mime (mime_maker_t mime)