mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
wks: New option --with-colons for gpg-wks-client.
* tools/gpg-wks.h (opt): Add field with_colons. * tools/gpg-wks-client.c (oWithColons): New const. (opts, parse_arguments): Add option --with-colons. (main): Change aSupported to take several domains in --with-colons mode. (command_send): Factor policy getting code out to ... (get_policy_and_sa): New function. (command_supported): Make use of new function. -- In addition to this the --create command now also supports a submission address only in the policy file. That means the submission-address file is not anymore required and can be replaced by the policy file. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
d7323bb2d9
commit
e3a1e80d13
41
doc/wks.texi
41
doc/wks.texi
@ -65,7 +65,8 @@ site supports the Web Key Service. The argument is an arbitrary
|
||||
address in the to be tested domain. For example
|
||||
@file{foo@@example.net}. The command returns success if the Web Key
|
||||
Service is supported. The operation is silent; to get diagnostic
|
||||
output use the option @option{--verbose}.
|
||||
output use the option @option{--verbose}. See option
|
||||
@option{--with-colons} for a variant of this command.
|
||||
|
||||
With the @option{--check} command the caller can test whether a key
|
||||
exists for a supplied mail address. The command returns success if a
|
||||
@ -109,6 +110,44 @@ $(gpgconf --list-dirs libexecdir)/gpg-wks-client --check foo@@example.net
|
||||
Directly send created mails using the @command{sendmail} command.
|
||||
Requires installation of that command.
|
||||
|
||||
@item --with-colons
|
||||
@opindex with-colons
|
||||
This option has currently only an effect on the @option{--supported}
|
||||
command. If it is used all arguimenst on the command line are taken
|
||||
as domain names and tested for WKD support. The output format is one
|
||||
line per domain with colon delimited fields. The currently specified
|
||||
fields are (future versions may specify additional fields):
|
||||
|
||||
@table @asis
|
||||
|
||||
@item 1 - domain
|
||||
This is the domain name. Although quoting is not required for valid
|
||||
domain names this field is specified to be quoted in standard C
|
||||
manner.
|
||||
|
||||
@item 2 - WKD
|
||||
If the value is true the domain supports the Web Key Directory.
|
||||
|
||||
@item 3 - WKS
|
||||
If the value is true the domain supports the Web Key Service
|
||||
protocol to upload keys to the directory.
|
||||
|
||||
@item 4 - error-code
|
||||
This may contain an gpg-error code to describe certain
|
||||
failures. Use @samp{gpg-error CODE} to explain the code.
|
||||
|
||||
@item 5 - protocol-version
|
||||
The minimum protocol version supported by the server.
|
||||
|
||||
@item 6 - auth-submit
|
||||
The auth-submit flag from the policy file of the server.
|
||||
|
||||
@item 7 - mailbox-only
|
||||
The mailbox-only flag from the policy file of the server.
|
||||
@end table
|
||||
|
||||
|
||||
|
||||
@item --output @var{file}
|
||||
@itemx -o
|
||||
@opindex output
|
||||
|
@ -61,6 +61,7 @@ enum cmd_and_opt_values
|
||||
oSend,
|
||||
oFakeSubmissionAddr,
|
||||
oStatusFD,
|
||||
oWithColons,
|
||||
|
||||
oDummy
|
||||
};
|
||||
@ -90,6 +91,7 @@ static ARGPARSE_OPTS opts[] = {
|
||||
ARGPARSE_s_n (oSend, "send", "send the mail using sendmail"),
|
||||
ARGPARSE_s_s (oOutput, "output", "|FILE|write the mail to FILE"),
|
||||
ARGPARSE_s_i (oStatusFD, "status-fd", N_("|FD|write status info to this FD")),
|
||||
ARGPARSE_s_n (oWithColons, "with-colons", "@"),
|
||||
|
||||
ARGPARSE_s_s (oFakeSubmissionAddr, "fake-submission-addr", "@"),
|
||||
|
||||
@ -204,6 +206,9 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
|
||||
case oStatusFD:
|
||||
wks_set_status_fd (translate_sys2libc_fd_int (pargs->r.ret_int, 1));
|
||||
break;
|
||||
case oWithColons:
|
||||
opt.with_colons = 1;
|
||||
break;
|
||||
|
||||
case aSupported:
|
||||
case aCreate:
|
||||
@ -271,11 +276,20 @@ main (int argc, char **argv)
|
||||
switch (cmd)
|
||||
{
|
||||
case aSupported:
|
||||
if (argc != 1)
|
||||
wrong_args ("--supported USER-ID");
|
||||
err = command_supported (argv[0]);
|
||||
if (err && gpg_err_code (err) != GPG_ERR_FALSE)
|
||||
log_error ("checking support failed: %s\n", gpg_strerror (err));
|
||||
if (opt.with_colons)
|
||||
{
|
||||
for (; argc; argc--, argv++)
|
||||
command_supported (*argv);
|
||||
err = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (argc != 1)
|
||||
wrong_args ("--supported DOMAIN");
|
||||
err = command_supported (argv[0]);
|
||||
if (err && gpg_err_code (err) != GPG_ERR_FALSE)
|
||||
log_error ("checking support failed: %s\n", gpg_strerror (err));
|
||||
}
|
||||
break;
|
||||
|
||||
case aCreate:
|
||||
@ -471,6 +485,134 @@ decrypt_stream (estream_t *r_output, struct decrypt_stream_parm_s *decinfo,
|
||||
}
|
||||
|
||||
|
||||
/* Return the submission address for the address or just the domain in
|
||||
* ADDRSPEC. The submission address is stored as a malloced string at
|
||||
* R_SUBMISSION_ADDRESS. At R_POLICY the policy flags of the domain
|
||||
* are stored. The caller needs to free them with wks_free_policy.
|
||||
* The function returns an error code on failure to find a submission
|
||||
* address or policy file. Note: The function may store NULL at
|
||||
* R_SUBMISSION_ADDRESS but return success to indicate that the web
|
||||
* key directory is supported but not the web key service. As per WKD
|
||||
* specs a policy file is always required and will thus be return on
|
||||
* success. */
|
||||
static gpg_error_t
|
||||
get_policy_and_sa (const char *addrspec, int silent,
|
||||
policy_flags_t *r_policy, char **r_submission_address)
|
||||
{
|
||||
gpg_error_t err;
|
||||
estream_t mbuf = NULL;
|
||||
const char *domain;
|
||||
const char *s;
|
||||
policy_flags_t policy = NULL;
|
||||
char *submission_to = NULL;
|
||||
|
||||
*r_submission_address = NULL;
|
||||
*r_policy = NULL;
|
||||
|
||||
domain = strchr (addrspec, '@');
|
||||
if (domain)
|
||||
domain++;
|
||||
|
||||
if (opt.with_colons)
|
||||
{
|
||||
s = domain? domain : addrspec;
|
||||
es_write_sanitized (es_stdout, s, strlen (s), ":", NULL);
|
||||
es_putc (':', es_stdout);
|
||||
}
|
||||
|
||||
/* We first try to get the submission address from the policy file
|
||||
* (this is the new method). If both are available we check that
|
||||
* they match and print a warning if not. In the latter case we
|
||||
* keep on using the one from the submission-address file. */
|
||||
err = wkd_get_policy_flags (addrspec, &mbuf);
|
||||
if (err && gpg_err_code (err) != GPG_ERR_NO_DATA
|
||||
&& gpg_err_code (err) != GPG_ERR_NO_NAME)
|
||||
{
|
||||
if (!opt.with_colons)
|
||||
log_error ("error reading policy flags for '%s': %s\n",
|
||||
domain, gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
if (!mbuf)
|
||||
{
|
||||
if (!opt.with_colons)
|
||||
log_error ("provider for '%s' does NOT support the Web Key Directory\n",
|
||||
addrspec);
|
||||
err = gpg_error (GPG_ERR_FALSE);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
policy = xtrycalloc (1, sizeof *policy);
|
||||
if (!policy)
|
||||
err = gpg_error_from_syserror ();
|
||||
else
|
||||
err = wks_parse_policy (policy, mbuf, 1);
|
||||
es_fclose (mbuf);
|
||||
mbuf = NULL;
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
err = wkd_get_submission_address (addrspec, &submission_to);
|
||||
if (err && !policy->submission_address)
|
||||
{
|
||||
if (!silent && !opt.with_colons)
|
||||
log_error (_("error looking up submission address for domain '%s'"
|
||||
": %s\n"), domain, gpg_strerror (err));
|
||||
if (!silent && gpg_err_code (err) == GPG_ERR_NO_DATA && !opt.with_colons)
|
||||
log_error (_("this domain probably doesn't support WKS.\n"));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (submission_to && policy->submission_address
|
||||
&& ascii_strcasecmp (submission_to, policy->submission_address))
|
||||
log_info ("Warning: different submission addresses (sa=%s, po=%s)\n",
|
||||
submission_to, policy->submission_address);
|
||||
|
||||
if (!submission_to && policy->submission_address)
|
||||
{
|
||||
submission_to = xtrystrdup (policy->submission_address);
|
||||
if (!submission_to)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
leave:
|
||||
*r_submission_address = submission_to;
|
||||
submission_to = NULL;
|
||||
*r_policy = policy;
|
||||
policy = NULL;
|
||||
|
||||
if (opt.with_colons)
|
||||
{
|
||||
if (*r_policy && !*r_submission_address)
|
||||
es_fprintf (es_stdout, "1:0::");
|
||||
else if (*r_policy && *r_submission_address)
|
||||
es_fprintf (es_stdout, "1:1::");
|
||||
else if (err && !(gpg_err_code (err) == GPG_ERR_FALSE
|
||||
|| gpg_err_code (err) == GPG_ERR_NO_DATA
|
||||
|| gpg_err_code (err) == GPG_ERR_UNKNOWN_HOST))
|
||||
es_fprintf (es_stdout, "0:0:%d:", err);
|
||||
else
|
||||
es_fprintf (es_stdout, "0:0::");
|
||||
if (*r_policy)
|
||||
{
|
||||
es_fprintf (es_stdout, "%u:%u:%u:",
|
||||
(*r_policy)->protocol_version,
|
||||
(*r_policy)->auth_submit,
|
||||
(*r_policy)->mailbox_only);
|
||||
}
|
||||
es_putc ('\n', es_stdout);
|
||||
}
|
||||
|
||||
xfree (submission_to);
|
||||
wks_free_policy (policy);
|
||||
xfree (policy);
|
||||
es_fclose (mbuf);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Check whether the provider supports the WKS protocol. */
|
||||
@ -480,6 +622,7 @@ command_supported (char *userid)
|
||||
gpg_error_t err;
|
||||
char *addrspec = NULL;
|
||||
char *submission_to = NULL;
|
||||
policy_flags_t policy = NULL;
|
||||
|
||||
if (!strchr (userid, '@'))
|
||||
{
|
||||
@ -497,24 +640,41 @@ command_supported (char *userid)
|
||||
}
|
||||
|
||||
/* Get the submission address. */
|
||||
err = wkd_get_submission_address (addrspec, &submission_to);
|
||||
if (err)
|
||||
err = get_policy_and_sa (addrspec, 1, &policy, &submission_to);
|
||||
if (err || !submission_to)
|
||||
{
|
||||
if (gpg_err_code (err) == GPG_ERR_NO_DATA
|
||||
|| gpg_err_code (err) == GPG_ERR_UNKNOWN_HOST)
|
||||
if (!submission_to
|
||||
|| gpg_err_code (err) == GPG_ERR_FALSE
|
||||
|| gpg_err_code (err) == GPG_ERR_NO_DATA
|
||||
|| gpg_err_code (err) == GPG_ERR_UNKNOWN_HOST
|
||||
)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("provider for '%s' does NOT support WKS (%s)\n",
|
||||
addrspec, gpg_strerror (err));
|
||||
/* FALSE is returned if we already figured out that even the
|
||||
* Web Key Directory is not supported and thus printed an
|
||||
* error message. */
|
||||
if (opt.verbose && gpg_err_code (err) != GPG_ERR_FALSE
|
||||
&& !opt.with_colons)
|
||||
{
|
||||
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
|
||||
log_info ("provider for '%s' does NOT support WKS\n",
|
||||
addrspec);
|
||||
else
|
||||
log_info ("provider for '%s' does NOT support WKS (%s)\n",
|
||||
addrspec, gpg_strerror (err));
|
||||
}
|
||||
err = gpg_error (GPG_ERR_FALSE);
|
||||
log_inc_errorcount ();
|
||||
if (!opt.with_colons)
|
||||
log_inc_errorcount ();
|
||||
}
|
||||
goto leave;
|
||||
}
|
||||
if (opt.verbose)
|
||||
|
||||
if (opt.verbose && !opt.with_colons)
|
||||
log_info ("provider for '%s' supports WKS\n", addrspec);
|
||||
|
||||
leave:
|
||||
wks_free_policy (policy);
|
||||
xfree (policy);
|
||||
xfree (submission_to);
|
||||
xfree (addrspec);
|
||||
return err;
|
||||
@ -628,7 +788,7 @@ command_send (const char *fingerprint, const char *userid)
|
||||
estream_t keyenc = NULL;
|
||||
char *submission_to = NULL;
|
||||
mime_maker_t mime = NULL;
|
||||
struct policy_flags_s policy;
|
||||
policy_flags_t policy = NULL;
|
||||
int no_encrypt = 0;
|
||||
int posteo_hack = 0;
|
||||
const char *domain;
|
||||
@ -636,8 +796,6 @@ command_send (const char *fingerprint, const char *userid)
|
||||
uidinfo_list_t uid, thisuid;
|
||||
time_t thistime;
|
||||
|
||||
memset (&policy, 0, sizeof policy);
|
||||
|
||||
if (classify_user_id (fingerprint, &desc, 1)
|
||||
|| !(desc.mode == KEYDB_SEARCH_MODE_FPR
|
||||
|| desc.mode == KEYDB_SEARCH_MODE_FPR20))
|
||||
@ -665,62 +823,26 @@ command_send (const char *fingerprint, const char *userid)
|
||||
/* Get the submission address. */
|
||||
if (fake_submission_addr)
|
||||
{
|
||||
policy = xcalloc (1, sizeof *policy);
|
||||
submission_to = xstrdup (fake_submission_addr);
|
||||
err = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We first try to get the submission address from the policy
|
||||
* file (this is the new method). If both are available we
|
||||
* check that they match and print a warning if not. In the
|
||||
* latter case we keep on using the one from the
|
||||
* submission-address file. */
|
||||
estream_t mbuf;
|
||||
|
||||
err = wkd_get_policy_flags (addrspec, &mbuf);
|
||||
if (err && gpg_err_code (err) != GPG_ERR_NO_DATA)
|
||||
{
|
||||
log_error ("error reading policy flags for '%s': %s\n",
|
||||
domain, gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
if (mbuf)
|
||||
{
|
||||
err = wks_parse_policy (&policy, mbuf, 1);
|
||||
es_fclose (mbuf);
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = wkd_get_submission_address (addrspec, &submission_to);
|
||||
if (err && !policy.submission_address)
|
||||
{
|
||||
log_error (_("error looking up submission address for domain '%s'"
|
||||
": %s\n"), domain, gpg_strerror (err));
|
||||
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
|
||||
log_error (_("this domain probably doesn't support WKS.\n"));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (submission_to && policy.submission_address
|
||||
&& ascii_strcasecmp (submission_to, policy.submission_address))
|
||||
log_info ("Warning: different submission addresses (sa=%s, po=%s)\n",
|
||||
submission_to, policy.submission_address);
|
||||
|
||||
err = get_policy_and_sa (addrspec, 0, &policy, &submission_to);
|
||||
if (err)
|
||||
goto leave;
|
||||
if (!submission_to)
|
||||
{
|
||||
submission_to = xtrystrdup (policy.submission_address);
|
||||
if (!submission_to)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
log_error (_("this domain probably doesn't support WKS.\n"));
|
||||
err = gpg_error (GPG_ERR_NO_DATA);
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
log_info ("submitting request to '%s'\n", submission_to);
|
||||
|
||||
if (policy.auth_submit)
|
||||
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
|
||||
@ -738,8 +860,7 @@ 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))
|
||||
if (policy->mailbox_only && ascii_strcasecmp (uid->uid, uid->mbox))
|
||||
continue; /* UID has more than just the mailbox. */
|
||||
if (uid->created > thistime)
|
||||
{
|
||||
@ -770,7 +891,7 @@ command_send (const char *fingerprint, const char *userid)
|
||||
key = newkey;
|
||||
}
|
||||
|
||||
if (policy.mailbox_only
|
||||
if (policy->mailbox_only
|
||||
&& (!thisuid->mbox || ascii_strcasecmp (thisuid->uid, thisuid->mbox)))
|
||||
{
|
||||
log_info ("Warning: policy requires 'mailbox-only'"
|
||||
@ -791,7 +912,7 @@ command_send (const char *fingerprint, const char *userid)
|
||||
|
||||
/* Hack to support posteo but let them disable this by setting the
|
||||
* new policy-version flag. */
|
||||
if (policy.protocol_version < 3
|
||||
if (policy->protocol_version < 3
|
||||
&& !ascii_strcasecmp (domain, "posteo.de"))
|
||||
{
|
||||
log_info ("Warning: Using draft-1 method for domain '%s'\n", domain);
|
||||
@ -908,7 +1029,8 @@ command_send (const char *fingerprint, const char *userid)
|
||||
free_uidinfo_list (uidlist);
|
||||
es_fclose (keyenc);
|
||||
es_fclose (key);
|
||||
wks_free_policy (&policy);
|
||||
wks_free_policy (policy);
|
||||
xfree (policy);
|
||||
xfree (addrspec);
|
||||
return err;
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ struct
|
||||
unsigned int debug;
|
||||
int quiet;
|
||||
int use_sendmail;
|
||||
int with_colons;
|
||||
const char *output;
|
||||
const char *gpg_program;
|
||||
const char *directory;
|
||||
|
@ -556,7 +556,7 @@ wks_send_mime (mime_maker_t mime)
|
||||
|
||||
|
||||
/* Parse the policy flags by reading them from STREAM and storing them
|
||||
* into FLAGS. If IGNORE_UNKNOWN is iset unknown keywords are
|
||||
* into FLAGS. If IGNORE_UNKNOWN is set unknown keywords are
|
||||
* ignored. */
|
||||
gpg_error_t
|
||||
wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown)
|
||||
|
Loading…
x
Reference in New Issue
Block a user