diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2021-02-09 16:00:45 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2021-02-09 16:00:45 +0900 |
commit | e299a90138c4ee04892f06ea99394c0f55d311db (patch) | |
tree | c54132a01468497d3973c2e3053ca1ee258c855e | |
parent | c8351206466f4f5ac3feb7ad2e5457337b9593ad (diff) | |
download | gpg2-upstream/2.2.15.tar.gz gpg2-upstream/2.2.15.tar.bz2 gpg2-upstream/2.2.15.zip |
Imported Upstream version 2.2.15upstream/2.2.15
-rw-r--r-- | NEWS | 21 | ||||
-rw-r--r-- | agent/command.c | 24 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | dirmngr/dns.c | 80 | ||||
-rw-r--r-- | doc/gpg.texi | 6 | ||||
-rw-r--r-- | doc/wks.texi | 8 | ||||
-rw-r--r-- | sm/gpgsm.c | 19 | ||||
-rw-r--r-- | tools/gpg-wks-client.c | 100 | ||||
-rw-r--r-- | tools/gpg-wks-server.c | 2 | ||||
-rw-r--r-- | tools/gpg-wks.h | 4 | ||||
-rw-r--r-- | tools/wks-util.c | 72 |
11 files changed, 277 insertions, 61 deletions
@@ -1,3 +1,24 @@ +Noteworthy changes in version 2.2.15 (2019-03-26) +------------------------------------------------- + + * sm: Fix --logger-fd and --status-fd on Windows for non-standard + file descriptors. + + * sm: Allow decryption even if expired keys are configured. [#4431] + + * agent: Change command KEYINFO to print ssh fingerprints with other + hash algos. + + * dirmngr: Fix build problems on Solaris due to the use of reserved + symbol names. [#4420] + + * wkd: New commands --print-wkd-hash and --print-wkd-url for + gpg-wks-client. + + Release-info: https://dev.gnupg.org/T4434 + See-also: gnupg-announce/2019q1/000436.html + + Noteworthy changes in version 2.2.14 (2019-03-19) ------------------------------------------------- diff --git a/agent/command.c b/agent/command.c index f804178..4839ffe 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1048,7 +1048,7 @@ cmd_readkey (assuan_context_t ctx, char *line) static const char hlp_keyinfo[] = - "KEYINFO [--[ssh-]list] [--data] [--ssh-fpr] [--with-ssh] <keygrip>\n" + "KEYINFO [--[ssh-]list] [--data] [--ssh-fpr[=algo]] [--with-ssh] <keygrip>\n" "\n" "Return information about the key specified by the KEYGRIP. If the\n" "key is not available GPG_ERR_NOT_FOUND is returned. If the option\n" @@ -1084,7 +1084,9 @@ static const char hlp_keyinfo[] = " '-' - Unknown protection.\n" "\n" "FPR returns the formatted ssh-style fingerprint of the key. It is only\n" - " printed if the option --ssh-fpr has been used. It defaults to '-'.\n" + " printed if the option --ssh-fpr has been used. If ALGO is not given\n" + " to that option the default ssh fingerprint algo is used. Without the\n" + " option a '-' is printed.\n" "\n" "TTL is the TTL in seconds for that key or '-' if n/a.\n" "\n" @@ -1171,7 +1173,7 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx, if (!agent_raw_key_from_file (ctrl, grip, &key)) { - ssh_get_fingerprint_string (key, GCRY_MD_MD5, &fpr); + ssh_get_fingerprint_string (key, with_ssh_fpr, &fpr); gcry_sexp_release (key); } } @@ -1252,7 +1254,21 @@ cmd_keyinfo (assuan_context_t ctx, char *line) else list_mode = has_option (line, "--list"); opt_data = has_option (line, "--data"); - opt_ssh_fpr = has_option (line, "--ssh-fpr"); + + if (has_option_name (line, "--ssh-fpr")) + { + if (has_option (line, "--ssh-fpr=md5")) + opt_ssh_fpr = GCRY_MD_MD5; + else if (has_option (line, "--ssh-fpr=sha1")) + opt_ssh_fpr = GCRY_MD_SHA1; + else if (has_option (line, "--ssh-fpr=sha256")) + opt_ssh_fpr = GCRY_MD_SHA256; + else + opt_ssh_fpr = opt.ssh_fingerprint_digest; + } + else + opt_ssh_fpr = 0; + opt_with_ssh = has_option (line, "--with-ssh"); line = skip_options (line); diff --git a/configure.ac b/configure.ac index 9260684..7951bd2 100644 --- a/configure.ac +++ b/configure.ac @@ -28,7 +28,7 @@ min_automake_version="1.14" m4_define([mym4_package],[gnupg]) m4_define([mym4_major], [2]) m4_define([mym4_minor], [2]) -m4_define([mym4_micro], [14]) +m4_define([mym4_micro], [15]) # To start a new development series, i.e a new major or minor number # you need to mark an arbitrary commit before the first beta release diff --git a/dirmngr/dns.c b/dirmngr/dns.c index 14aab24..4c3b559 100644 --- a/dirmngr/dns.c +++ b/dirmngr/dns.c @@ -2217,8 +2217,8 @@ static void dns_p_dump3(struct dns_packet *P, struct dns_rr_i *I, FILE *fp) { void dns_p_dump(struct dns_packet *P, FILE *fp) { - struct dns_rr_i _I = { 0 }; - dns_p_dump3(P, &_I, fp); + struct dns_rr_i I_instance = { 0 }; + dns_p_dump3(P, &I_instance, fp); } /* dns_p_dump() */ @@ -5275,8 +5275,8 @@ error: struct dns_packet *dns_hosts_query(struct dns_hosts *hosts, struct dns_packet *Q, int *error_) { - union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _P = { 0 }; - struct dns_packet *P = dns_p_init(&_P.p, 512); + union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } P_instance = { 0 }; + struct dns_packet *P = dns_p_init(&P_instance.p, 512); struct dns_packet *A = 0; struct dns_rr rr; struct dns_hosts_entry *ent; @@ -6837,7 +6837,7 @@ unsigned dns_hints_grep(struct sockaddr **sa, socklen_t *sa_len, unsigned lim, s struct dns_packet *dns_hints_query(struct dns_hints *hints, struct dns_packet *Q, int *error_) { - union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _P = { 0 }; + union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } P_instance = { 0 }; struct dns_packet *A, *P; struct dns_rr rr; char zone[DNS_D_MAXNAME + 1]; @@ -6846,11 +6846,11 @@ struct dns_packet *dns_hints_query(struct dns_hints *hints, struct dns_packet *Q struct sockaddr *sa; socklen_t slen; int error; - struct dns_rr_i _I = { 0 }; + struct dns_rr_i I_instance = { 0 }; - _I.section = DNS_S_QUESTION; + I_instance.section = DNS_S_QUESTION; - if (!dns_rr_grep(&rr, 1, &_I, Q, &error)) + if (!dns_rr_grep(&rr, 1, &I_instance, Q, &error)) goto error; if (!(zlen = dns_d_expand(zone, sizeof zone, rr.dn.p, Q, &error))) @@ -6858,7 +6858,7 @@ struct dns_packet *dns_hints_query(struct dns_hints *hints, struct dns_packet *Q else if (zlen >= sizeof zone) goto toolong; - P = dns_p_init(&_P.p, 512); + P = dns_p_init(&P_instance.p, 512); dns_header(P)->qr = 1; if ((error = dns_rr_copy(P, &rr, Q))) @@ -8463,8 +8463,8 @@ error: static struct dns_packet *dns_res_glue(struct dns_resolver *R, struct dns_packet *Q) { - union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _P = { 0 }; - struct dns_packet *P = dns_p_init(&_P.p, 512); + union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } P_instance = { 0 }; + struct dns_packet *P = dns_p_init(&P_instance.p, 512); char qname[DNS_D_MAXNAME + 1]; size_t qlen; enum dns_type qtype; @@ -8537,20 +8537,20 @@ static int dns_res_nameserv_cmp(struct dns_rr *a, struct dns_rr *b, struct dns_r int cmp, error; if (!(error = dns_ns_parse(&ns, a, P))) { - struct dns_rr_i _I = { 0 }; + struct dns_rr_i I_instance = { 0 }; - _I.section = (DNS_S_ALL & ~DNS_S_QD); - _I.name = ns.host; - _I.type = DNS_T_A; - glued[0] = !!dns_rr_grep(&x, 1, &_I, P, &error); + I_instance.section = (DNS_S_ALL & ~DNS_S_QD); + I_instance.name = ns.host; + I_instance.type = DNS_T_A; + glued[0] = !!dns_rr_grep(&x, 1, &I_instance, P, &error); } if (!(error = dns_ns_parse(&ns, b, P))) { - struct dns_rr_i _I = { 0 }; + struct dns_rr_i I_instance = { 0 }; - _I.section = (DNS_S_ALL & ~DNS_S_QD); - _I.name = ns.host; - _I.type = DNS_T_A; - glued[1] = !!dns_rr_grep(&y, 1, &_I, P, &error); + I_instance.section = (DNS_S_ALL & ~DNS_S_QD); + I_instance.name = ns.host; + I_instance.type = DNS_T_A; + glued[1] = !!dns_rr_grep(&y, 1, &I_instance, P, &error); } if ((cmp = glued[1] - glued[0])) { return cmp; @@ -9916,13 +9916,13 @@ exec: return dns_ai_setent(ent, &any, rr.type, ai); case DNS_AI_S_SUBMIT_G: { - struct dns_rr_i _I = { 0 }; + struct dns_rr_i I_instance = { 0 }; - _I.section = DNS_S_QD; - _I.name = ai->g.name; - _I.type = ai->g.type; + I_instance.section = DNS_S_QD; + I_instance.name = ai->g.name; + I_instance.type = ai->g.type; /* skip if already queried */ - if (dns_rr_grep(&rr, 1, &_I, ai->glue, &error)) + if (dns_rr_grep(&rr, 1, &I_instance, ai->glue, &error)) dns_ai_goto(DNS_AI_S_FOREACH_I); /* skip if we recursed (CNAME chains should have been handled in the resolver) */ if (++ai->g_depth > 1) @@ -10598,7 +10598,7 @@ static struct dns_trace *trace(const char *mode) { static void print_packet(struct dns_packet *P, FILE *fp) { - struct dns_rr_i _I = { 0 }; + struct dns_rr_i I_instance = { 0 }; I.sort = MAIN.sort; dns_p_dump3(P, &I, fp); @@ -10608,10 +10608,10 @@ static void print_packet(struct dns_packet *P, FILE *fp) { static int parse_packet(int argc DNS_NOTUSED, char *argv[] DNS_NOTUSED) { - union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _P = { 0 }; - union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _Q = { 0 }; - struct dns_packet *P = dns_p_init(&_P.p, 512); - struct dns_packet *Q = dns_p_init(&_Q.p, 512); + union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } P_instance = { 0 }; + union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } Q_instance = { 0 }; + struct dns_packet *P = dns_p_init(&P_instance.p, 512); + struct dns_packet *Q = dns_p_init(&Q_instance.p, 512); enum dns_section section; struct dns_rr rr; int error; @@ -10655,7 +10655,7 @@ static int parse_packet(int argc DNS_NOTUSED, char *argv[] DNS_NOTUSED) { const char *dn = "ns8.yahoo.com"; char *_name = dns_d_init(_p, sizeof _p, dn, strlen (dn), DNS_D_ANCHOR); struct dns_rr rrset[32]; - struct dns_rr_i _I = { 0 }; + struct dns_rr_i I_instance = { 0 }; struct dns_rr_i *rri = &I; unsigned rrcount = dns_rr_grep(rrset, lengthof(rrset), rri, Q, &error); @@ -10818,8 +10818,8 @@ static int show_hosts(int argc DNS_NOTUSED, char *argv[] DNS_NOTUSED) { static int query_hosts(int argc, char *argv[]) { - union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _Q = { 0 }; - struct dns_packet *Q = dns_p_init(&_Q.p, 512); + union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } Q_instance = { 0 }; + struct dns_packet *Q = dns_p_init(&Q_instance.p, 512); struct dns_packet *A; char qname[DNS_D_MAXNAME + 1]; size_t qlen; @@ -10937,8 +10937,8 @@ static int dump_random(int argc, char *argv[]) { static int send_query(int argc, char *argv[]) { - union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _Q = { 0 }; - struct dns_packet *A, *Q = dns_p_init(&_Q.p, 512); + union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } Q_instance = { 0 }; + struct dns_packet *A, *Q = dns_p_init(&Q_instance.p, 512); char host[INET6_ADDRSTRLEN + 1]; struct sockaddr_storage ss; struct dns_socket *so; @@ -11033,10 +11033,10 @@ static int show_hints(int argc, char *argv[]) { if (0 == strcmp(how, "plain")) { dns_hints_dump(hints, stdout); } else { - union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _P = { 0 }; + union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } P_instance = { 0 }; struct dns_packet *query, *answer; - query = dns_p_init(&_P.p, 512); + query = dns_p_init(&P_instance.p, 512); if ((error = dns_p_push(query, DNS_S_QUESTION, who, strlen(who), DNS_T_A, DNS_C_IN, 0, 0))) panic("%s: %s", who, dns_strerror(error)); @@ -11199,8 +11199,8 @@ static int echo_port(int argc DNS_NOTUSED, char *argv[] DNS_NOTUSED) { panic("127.0.0.1:5353: %s", dns_strerror(errno)); for (;;) { - union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _P = { 0 }; - struct dns_packet *pkt = dns_p_init(&_P.p, 512); + union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } P_instance = { 0 }; + struct dns_packet *pkt = dns_p_init(&P_instance.p, 512); struct sockaddr_storage ss; socklen_t slen = sizeof ss; ssize_t count; diff --git a/doc/gpg.texi b/doc/gpg.texi index 1597f9e..22813c7 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -2320,7 +2320,8 @@ opposite meaning. The options are: on the keyring. This option is the same as running the @option{--edit-key} command "clean" after import. Defaults to no. - @item repair-keys. After import, fix various problems with the + @item repair-keys + After import, fix various problems with the keys. For example, this reorders signatures, and strips duplicate signatures. Defaults to yes. @@ -3229,7 +3230,8 @@ secret keyrings. @item --no-keyring @opindex no-keyring -Do not add use any keyrings even if specified as options. +Do not use any keyring at all. This overrides the default and all +options which specify keyrings. @item --skip-verify @opindex skip-verify diff --git a/doc/wks.texi b/doc/wks.texi index 7a19e75..2fa3c24 100644 --- a/doc/wks.texi +++ b/doc/wks.texi @@ -101,6 +101,14 @@ 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 the WKD user-id identifiers +and the corresponding mailboxes from the user-ids given on the command +line or via stdin (one user-id per line). + +The command @option{--print-wkd-url} prints the URLs used to fetch the +key for the given user-ids from WKD. The meanwhile preferred format +with sub-domains is used here. + @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 @@ -1281,8 +1281,12 @@ main ( int argc, char **argv) case oDebugNoChainValidation: opt.no_chain_validation = 1; break; case oDebugIgnoreExpiration: opt.ignore_expiration = 1; break; - case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break; - case oLoggerFD: log_set_fd (pargs.r.ret_int ); break; + case oStatusFD: + ctrl.status_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 1); + break; + case oLoggerFD: + log_set_fd (translate_sys2libc_fd_int (pargs.r.ret_int, 1)); + break; case oWithMD5Fingerprint: opt.with_md5_fingerprint=1; /*fall through*/ case oWithFingerprint: @@ -1732,6 +1736,8 @@ main ( int argc, char **argv) if (!do_not_setup_keys) { + int errcount = log_get_errorcount (0); + for (sl = locusr; sl ; sl = sl->next) { int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist, 0); @@ -1760,6 +1766,15 @@ main ( int argc, char **argv) if ((sl->flags & 1)) do_add_recipient (&ctrl, sl->d, &recplist, 1, recp_required); } + + /* We do not require a recipient for decryption but because + * recipients and signers are always checked and log_error is + * sometimes used (for failed signing keys or due to a failed + * CRL checking) that would have bumbed up the error counter. + * We clear the counter in the decryption case because there is + * no reason to force decryption to fail. */ + if (cmd == aDecrypt && !errcount) + log_get_errorcount (1); /* clear counter */ } if (log_get_errorcount(0)) diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c index 78e4fe4..050c8aa 100644 --- a/tools/gpg-wks-client.c +++ b/tools/gpg-wks-client.c @@ -61,6 +61,8 @@ enum cmd_and_opt_values aRead, aInstallKey, aRemoveKey, + aPrintWKDHash, + aPrintWKDURL, oGpgProgram, oSend, @@ -90,6 +92,10 @@ 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_c (aPrintWKDURL, "print-wkd-url", + "Print the WKD URL for the given user id"), ARGPARSE_group (301, ("@\nOptions:\n ")), @@ -129,6 +135,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 +238,8 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts) case aCheck: case aInstallKey: case aRemoveKey: + case aPrintWKDHash: + case aPrintWKDURL: cmd = pargs->r_opt; break; @@ -246,7 +256,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 +387,39 @@ main (int argc, char **argv) err = wks_cmd_remove_key (*argv); break; + case aPrintWKDHash: + case aPrintWKDURL: + if (!argc) + { + if (cmd == aPrintWKDHash) + err = proc_userid_from_stdin (wks_cmd_print_wkd_hash, + "printing WKD hash"); + else + err = proc_userid_from_stdin (wks_cmd_print_wkd_url, + "printing WKD URL"); + } + else + { + for (err = delayed_err = 0; !err && argc; argc--, argv++) + { + if (cmd == aPrintWKDHash) + err = wks_cmd_print_wkd_hash (*argv); + else + err = wks_cmd_print_wkd_url (*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 +433,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 f83ef65..2082fb8 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 e369430..9acd7c3 100644 --- a/tools/gpg-wks.h +++ b/tools/gpg-wks.h @@ -98,11 +98,13 @@ 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); +gpg_error_t wks_cmd_print_wkd_url (const char *userid); /*-- wks-receive.c --*/ diff --git a/tools/wks-util.c b/tools/wks-util.c index 3e48709..29e9248 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,47 @@ wks_cmd_remove_key (const char *userid) xfree (addrspec); return err; } + + +/* Print the WKD hash for the user id 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; +} + + +/* Print the WKD URL for the user id to stdout. */ +gpg_error_t +wks_cmd_print_wkd_url (const char *userid) +{ + gpg_error_t err; + char *addrspec, *fname; + char *domain; + + err = wks_fname_from_userid (userid, 1, &fname, &addrspec); + if (err) + return err; + + domain = strchr (addrspec, '@'); + if (domain) + *domain++ = 0; + + es_printf ("https://openpgpkey.%s/.well-known/openpgpkey/%s/hu/%s?l=%s\n", + domain, domain, fname, addrspec); + + xfree (fname); + xfree (addrspec); + return err; +} |