aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/wks.texi4
-rw-r--r--tools/gpg-wks-client.c85
-rw-r--r--tools/gpg-wks-server.c2
-rw-r--r--tools/gpg-wks.h3
-rw-r--r--tools/wks-util.c47
5 files changed, 129 insertions, 12 deletions
diff --git a/doc/wks.texi b/doc/wks.texi
index 7a19e75ff..ee847aad7 100644
--- a/doc/wks.texi
+++ b/doc/wks.texi
@@ -101,6 +101,10 @@ fingerprint and the mailbox separated by a space. The command
@option{--remove-key} removes a key from that directory, its only
argument is a user-id.
+The command @option{--print-wkd-hash} prints a WKD user id identifier
+and the corresponding mailbox from the user-ids given on the command
+line or via stdin (one user-id per line).
+
@command{gpg-wks-client} is not commonly invoked directly and thus it
is not installed in the bin directory. Here is an example how it can
be invoked manually to check for a Web Key Directory entry for
diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c
index 78e4fe420..f1750bf4c 100644
--- a/tools/gpg-wks-client.c
+++ b/tools/gpg-wks-client.c
@@ -61,6 +61,7 @@ enum cmd_and_opt_values
aRead,
aInstallKey,
aRemoveKey,
+ aPrintWKDHash,
oGpgProgram,
oSend,
@@ -90,6 +91,8 @@ static ARGPARSE_OPTS opts[] = {
"install a key into a directory"),
ARGPARSE_c (aRemoveKey, "remove-key",
"remove a key from a directory"),
+ ARGPARSE_c (aPrintWKDHash, "print-wkd-hash",
+ "Print the WKD identifier for the given user ids"),
ARGPARSE_group (301, ("@\nOptions:\n ")),
@@ -129,6 +132,8 @@ const char *fake_submission_addr;
static void wrong_args (const char *text) GPGRT_ATTR_NORETURN;
+static gpg_error_t proc_userid_from_stdin (gpg_error_t (*func)(const char *),
+ const char *text);
static gpg_error_t command_supported (char *userid);
static gpg_error_t command_check (char *userid);
static gpg_error_t command_send (const char *fingerprint, const char *userid);
@@ -230,6 +235,7 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
case aCheck:
case aInstallKey:
case aRemoveKey:
+ case aPrintWKDHash:
cmd = pargs->r_opt;
break;
@@ -246,7 +252,7 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
int
main (int argc, char **argv)
{
- gpg_error_t err;
+ gpg_error_t err, delayed_err;
ARGPARSE_ARGS pargs;
enum cmd_and_opt_values cmd;
@@ -377,6 +383,28 @@ main (int argc, char **argv)
err = wks_cmd_remove_key (*argv);
break;
+ case aPrintWKDHash:
+ if (!argc)
+ err = proc_userid_from_stdin (wks_cmd_print_wkd_hash, "printing hash");
+ else
+ {
+ for (err = delayed_err = 0; !err && argc; argc--, argv++)
+ {
+ err = wks_cmd_print_wkd_hash (*argv);
+ if (gpg_err_code (err) == GPG_ERR_INV_USER_ID)
+ {
+ /* Diagnostic already printed. */
+ delayed_err = err;
+ err = 0;
+ }
+ else if (err)
+ log_error ("printing hash failed: %s\n", gpg_strerror (err));
+ }
+ if (!err)
+ err = delayed_err;
+ }
+ break;
+
default:
usage (1);
err = 0;
@@ -390,10 +418,63 @@ main (int argc, char **argv)
wks_write_status (STATUS_FAILURE, "- %u", GPG_ERR_GENERAL);
else
wks_write_status (STATUS_SUCCESS, NULL);
- return log_get_errorcount (0)? 1:0;
+ return (err || log_get_errorcount (0))? 1:0;
}
+/* Read user ids from stdin and call FUNC for each user id. TEXT is
+ * used for error messages. */
+static gpg_error_t
+proc_userid_from_stdin (gpg_error_t (*func)(const char *), const char *text)
+{
+ gpg_error_t err = 0;
+ gpg_error_t delayed_err = 0;
+ char line[2048];
+ size_t n = 0;
+
+ /* If we are on a terminal disable buffering to get direct response. */
+ if (gnupg_isatty (es_fileno (es_stdin))
+ && gnupg_isatty (es_fileno (es_stdout)))
+ {
+ es_setvbuf (es_stdin, NULL, _IONBF, 0);
+ es_setvbuf (es_stdout, NULL, _IOLBF, 0);
+ }
+
+ while (es_fgets (line, sizeof line - 1, es_stdin))
+ {
+ n = strlen (line);
+ if (!n || line[n-1] != '\n')
+ {
+ err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
+ : GPG_ERR_INCOMPLETE_LINE);
+ log_error ("error reading stdin: %s\n", gpg_strerror (err));
+ break;
+ }
+ trim_spaces (line);
+ err = func (line);
+ if (gpg_err_code (err) == GPG_ERR_INV_USER_ID)
+ {
+ delayed_err = err;
+ err = 0;
+ }
+ else if (err)
+ log_error ("%s failed: %s\n", text, gpg_strerror (err));
+ }
+ if (es_ferror (es_stdin))
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("error reading stdin: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+
+ leave:
+ if (!err)
+ err = delayed_err;
+ return err;
+}
+
+
+
/* Add the user id UID to the key identified by FINGERPRINT. */
static gpg_error_t
diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c
index f83ef6528..2082fb87d 100644
--- a/tools/gpg-wks-server.c
+++ b/tools/gpg-wks-server.c
@@ -1939,7 +1939,7 @@ command_check_key (const char *userid)
char *addrspec = NULL;
char *fname = NULL;
- err = wks_fname_from_userid (userid, &fname, &addrspec);
+ err = wks_fname_from_userid (userid, 0, &fname, &addrspec);
if (err)
goto leave;
diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h
index e36943090..99969c1ef 100644
--- a/tools/gpg-wks.h
+++ b/tools/gpg-wks.h
@@ -98,11 +98,12 @@ gpg_error_t wks_parse_policy (policy_flags_t flags, estream_t stream,
int ignore_unknown);
void wks_free_policy (policy_flags_t policy);
-gpg_error_t wks_fname_from_userid (const char *userid,
+gpg_error_t wks_fname_from_userid (const char *userid, int hash_only,
char **r_fname, char **r_addrspec);
gpg_error_t wks_compute_hu_fname (char **r_fname, const char *addrspec);
gpg_error_t wks_cmd_install_key (const char *fname, const char *userid);
gpg_error_t wks_cmd_remove_key (const char *userid);
+gpg_error_t wks_cmd_print_wkd_hash (const char *userid);
/*-- wks-receive.c --*/
diff --git a/tools/wks-util.c b/tools/wks-util.c
index 3e4870938..fee46d633 100644
--- a/tools/wks-util.c
+++ b/tools/wks-util.c
@@ -749,9 +749,12 @@ write_to_file (estream_t src, const char *fname)
/* Return the filename and optionally the addrspec for USERID at
- * R_FNAME and R_ADDRSPEC. R_ADDRSPEC might also be set on error. */
+ * R_FNAME and R_ADDRSPEC. R_ADDRSPEC might also be set on error. If
+ * HASH_ONLY is set only the has is returned at R_FNAME and no file is
+ * created. */
gpg_error_t
-wks_fname_from_userid (const char *userid, char **r_fname, char **r_addrspec)
+wks_fname_from_userid (const char *userid, int hash_only,
+ char **r_fname, char **r_addrspec)
{
gpg_error_t err;
char *addrspec = NULL;
@@ -767,7 +770,7 @@ wks_fname_from_userid (const char *userid, char **r_fname, char **r_addrspec)
addrspec = mailbox_from_userid (userid);
if (!addrspec)
{
- if (opt.verbose)
+ if (opt.verbose || hash_only)
log_info ("\"%s\" is not a proper mail address\n", userid);
err = gpg_error (GPG_ERR_INV_USER_ID);
goto leave;
@@ -788,11 +791,20 @@ wks_fname_from_userid (const char *userid, char **r_fname, char **r_addrspec)
goto leave;
}
- *r_fname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
- if (!*r_fname)
- err = gpg_error_from_syserror ();
+ if (hash_only)
+ {
+ *r_fname = hash;
+ hash = NULL;
+ err = 0;
+ }
else
- err = 0;
+ {
+ *r_fname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
+ if (!*r_fname)
+ err = gpg_error_from_syserror ();
+ else
+ err = 0;
+ }
leave:
if (r_addrspec && addrspec)
@@ -1062,7 +1074,7 @@ wks_cmd_remove_key (const char *userid)
char *addrspec = NULL;
char *fname = NULL;
- err = wks_fname_from_userid (userid, &fname, &addrspec);
+ err = wks_fname_from_userid (userid, 0, &fname, &addrspec);
if (err)
goto leave;
@@ -1090,3 +1102,22 @@ wks_cmd_remove_key (const char *userid)
xfree (addrspec);
return err;
}
+
+
+/* Print the WKD hash for the user ids to stdout. */
+gpg_error_t
+wks_cmd_print_wkd_hash (const char *userid)
+{
+ gpg_error_t err;
+ char *addrspec, *fname;
+
+ err = wks_fname_from_userid (userid, 1, &fname, &addrspec);
+ if (err)
+ return err;
+
+ es_printf ("%s %s\n", fname, addrspec);
+
+ xfree (fname);
+ xfree (addrspec);
+ return err;
+}