wkd: New command --print-wkd-hash for gpg-wks-client.

* tools/gpg-wks-client.c (aPrintWKDHash): New.
(opts) : Add "--print-wkd-hash".
(main): Implement that command.
(proc_userid_from_stdin): New.
* tools/wks-util.c (wks_fname_from_userid): Add option HASH_ONLY.
(wks_cmd_print_wkd_hash): New.
--

GnuPG-bug-id: 4418
Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2019-03-22 11:40:01 +01:00
parent 393269948c
commit e847cf1df7
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
5 changed files with 129 additions and 12 deletions

View File

@ -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 @option{--remove-key} removes a key from that directory, its only
argument is a user-id. 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 @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 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 be invoked manually to check for a Web Key Directory entry for

View File

@ -61,6 +61,7 @@ enum cmd_and_opt_values
aRead, aRead,
aInstallKey, aInstallKey,
aRemoveKey, aRemoveKey,
aPrintWKDHash,
oGpgProgram, oGpgProgram,
oSend, oSend,
@ -90,6 +91,8 @@ static ARGPARSE_OPTS opts[] = {
"install a key into a directory"), "install a key into a directory"),
ARGPARSE_c (aRemoveKey, "remove-key", ARGPARSE_c (aRemoveKey, "remove-key",
"remove a key from a directory"), "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 ")), 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 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_supported (char *userid);
static gpg_error_t command_check (char *userid); static gpg_error_t command_check (char *userid);
static gpg_error_t command_send (const char *fingerprint, const 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 aCheck:
case aInstallKey: case aInstallKey:
case aRemoveKey: case aRemoveKey:
case aPrintWKDHash:
cmd = pargs->r_opt; cmd = pargs->r_opt;
break; break;
@ -246,7 +252,7 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
gpg_error_t err; gpg_error_t err, delayed_err;
ARGPARSE_ARGS pargs; ARGPARSE_ARGS pargs;
enum cmd_and_opt_values cmd; enum cmd_and_opt_values cmd;
@ -377,6 +383,28 @@ main (int argc, char **argv)
err = wks_cmd_remove_key (*argv); err = wks_cmd_remove_key (*argv);
break; 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: default:
usage (1); usage (1);
err = 0; err = 0;
@ -390,10 +418,63 @@ main (int argc, char **argv)
wks_write_status (STATUS_FAILURE, "- %u", GPG_ERR_GENERAL); wks_write_status (STATUS_FAILURE, "- %u", GPG_ERR_GENERAL);
else else
wks_write_status (STATUS_SUCCESS, NULL); 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. */ /* Add the user id UID to the key identified by FINGERPRINT. */
static gpg_error_t static gpg_error_t

View File

@ -1939,7 +1939,7 @@ command_check_key (const char *userid)
char *addrspec = NULL; char *addrspec = NULL;
char *fname = NULL; char *fname = NULL;
err = wks_fname_from_userid (userid, &fname, &addrspec); err = wks_fname_from_userid (userid, 0, &fname, &addrspec);
if (err) if (err)
goto leave; goto leave;

View File

@ -98,11 +98,12 @@ gpg_error_t wks_parse_policy (policy_flags_t flags, estream_t stream,
int ignore_unknown); int ignore_unknown);
void wks_free_policy (policy_flags_t policy); 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); char **r_fname, char **r_addrspec);
gpg_error_t wks_compute_hu_fname (char **r_fname, const char *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_install_key (const char *fname, const char *userid);
gpg_error_t wks_cmd_remove_key (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 --*/ /*-- wks-receive.c --*/

View File

@ -749,9 +749,12 @@ write_to_file (estream_t src, const char *fname)
/* Return the filename and optionally the addrspec for USERID at /* 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 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; gpg_error_t err;
char *addrspec = NULL; 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, 0); addrspec = mailbox_from_userid (userid, 0);
if (!addrspec) if (!addrspec)
{ {
if (opt.verbose) if (opt.verbose || hash_only)
log_info ("\"%s\" is not a proper mail address\n", userid); log_info ("\"%s\" is not a proper mail address\n", userid);
err = gpg_error (GPG_ERR_INV_USER_ID); err = gpg_error (GPG_ERR_INV_USER_ID);
goto leave; goto leave;
@ -788,11 +791,20 @@ wks_fname_from_userid (const char *userid, char **r_fname, char **r_addrspec)
goto leave; goto leave;
} }
*r_fname = make_filename_try (opt.directory, domain, "hu", hash, NULL); if (hash_only)
if (!*r_fname) {
err = gpg_error_from_syserror (); *r_fname = hash;
hash = NULL;
err = 0;
}
else 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: leave:
if (r_addrspec && addrspec) if (r_addrspec && addrspec)
@ -1061,7 +1073,7 @@ wks_cmd_remove_key (const char *userid)
char *addrspec = NULL; char *addrspec = NULL;
char *fname = NULL; char *fname = NULL;
err = wks_fname_from_userid (userid, &fname, &addrspec); err = wks_fname_from_userid (userid, 0, &fname, &addrspec);
if (err) if (err)
goto leave; goto leave;
@ -1089,3 +1101,22 @@ wks_cmd_remove_key (const char *userid)
xfree (addrspec); xfree (addrspec);
return err; 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;
}