From 50c8b6c88f5d9f4b6c4e9c03aee31fe29afa94b8 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 18 Sep 2017 15:37:21 +0200 Subject: [PATCH] wks: Create a new user id if provider wants mailbox-only. * tools/gpg-wks-client.c (get_key): Add arg 'exact'. (add_user_id): New. (command_send): Create new user id. Signed-off-by: Werner Koch --- doc/wks.texi | 4 ++- tools/gpg-wks-client.c | 77 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/doc/wks.texi b/doc/wks.texi index f9b1a0c14..029dbf0c0 100644 --- a/doc/wks.texi +++ b/doc/wks.texi @@ -78,7 +78,9 @@ the command is a properly formatted mail with all standard headers. This mail can be fed to @command{sendmail(8)} or any other tool to actually send that mail. If @command{sendmail(8)} is installed the option @option{--send} can be used to directly send the created -request. +request. If the provider request a 'mailbox-only' user id and no such +user id is found, @command{gpg-wks-client} will try an additional user +id. The @option{--receive} and @option{--read} commands are used to process confirmation mails as send from the service provider. The diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c index 37b75606b..73a8a1f43 100644 --- a/tools/gpg-wks-client.c +++ b/tools/gpg-wks-client.c @@ -348,10 +348,13 @@ get_key_status_cb (void *opaque, const char *keyword, char *args) /* Get a key by fingerprint from gpg's keyring and make sure that the - * mail address ADDRSPEC is included in the key. The key is returned - * as a new memory stream at R_KEY. */ + * mail address ADDRSPEC is included in the key. If EXACT is set the + * returned user id must match Addrspec exactly and not just in the + * addr-spec (mailbox) part. The key is returned as a new memory + * stream at R_KEY. */ static gpg_error_t -get_key (estream_t *r_key, const char *fingerprint, const char *addrspec) +get_key (estream_t *r_key, const char *fingerprint, const char *addrspec, + int exact) { gpg_error_t err; ccparray_t ccp; @@ -376,7 +379,7 @@ get_key (estream_t *r_key, const char *fingerprint, const char *addrspec) es_fputs ("Content-Type: application/pgp-keys\n" "\n", key); - filterexp = es_bsprintf ("keep-uid=mbox = %s", addrspec); + filterexp = es_bsprintf ("keep-uid=%s=%s", exact? "uid":"mbox", addrspec); if (!filterexp) { err = gpg_error_from_syserror (); @@ -435,6 +438,49 @@ get_key (estream_t *r_key, const char *fingerprint, const char *addrspec) } +/* Add the user id UID to the key identified by FINGERPRINT. */ +static gpg_error_t +add_user_id (const char *fingerprint, const char *uid) +{ + gpg_error_t err; + ccparray_t ccp; + const char **argv = NULL; + + 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, "--always-trust"); + ccparray_put (&ccp, "--quick-add-uid"); + ccparray_put (&ccp, fingerprint); + ccparray_put (&ccp, uid); + + 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, NULL, + NULL, NULL, + NULL, NULL); + if (err) + { + log_error ("adding user id failed: %s\n", gpg_strerror (err)); + goto leave; + } + + leave: + xfree (argv); + return err; +} + + struct decrypt_stream_parm_s { @@ -721,7 +767,7 @@ command_send (const char *fingerprint, const char *userid) err = gpg_error (GPG_ERR_INV_USER_ID); goto leave; } - err = get_key (&key, fingerprint, addrspec); + err = get_key (&key, fingerprint, addrspec, 0); if (err) goto leave; @@ -786,6 +832,9 @@ command_send (const char *fingerprint, const char *userid) { if (!uid->mbox) continue; /* Should not happen anyway. */ + if (policy.mailbox_only + && ascii_strcasecmp (uid->uid, uid->mbox)) + continue; /* UID has more than just the mailbox. */ if (uid->created > thistime) { thistime = uid->created; @@ -793,7 +842,7 @@ command_send (const char *fingerprint, const char *userid) } } if (!thisuid) - thisuid = uid; /* This is the case for a missing timestamp. */ + thisuid = uidlist; /* This is the case for a missing timestamp. */ if (opt.verbose) log_info ("submitting key with user id '%s'\n", thisuid->uid); @@ -816,10 +865,22 @@ command_send (const char *fingerprint, const char *userid) } if (policy.mailbox_only - && ascii_strcasecmp (userid, addrspec)) + && (!thisuid->mbox || ascii_strcasecmp (thisuid->uid, thisuid->mbox))) { log_info ("Warning: policy requires 'mailbox-only'" - " - creating new user id'\n"); + " - adding user id '%s'\n", addrspec); + err = add_user_id (fingerprint, addrspec); + if (err) + goto leave; + + /* Need to get the key again. This time we request filtering + * for the full user id, so that we do not need check and filter + * the key again. */ + es_fclose (key); + key = NULL; + err = get_key (&key, fingerprint, addrspec, 1); + if (err) + goto leave; } /* Hack to support posteo but let them disable this by setting the