mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
wks: Add framework for policy flags.
* tools/call-dirmngr.c (wkd_get_policy_flags): New. * tools/gpg-wks.h (struct policy_flags_s, policy_flags_t): New. * tools/wks-util.c (wks_parse_policy): New. * tools/gpg-wks-client.c (command_send): Get the policy flags to show a new info line. * tools/gpg-wks-server.c (get_policy_flags): New. (process_new_key): get policy flag and add a stub for "auth-submit". (command_list_domains): Check policy flags. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
505ee45106
commit
46362cbc0e
@ -203,3 +203,58 @@ wkd_get_submission_address (const char *addrspec, char **r_addrspec)
|
||||
assuan_release (ctx);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Ask the dirmngr for the policy flags and return them as an estream
|
||||
* memory stream. If no policy flags are set, NULL is stored at
|
||||
* R_BUFFER. */
|
||||
gpg_error_t
|
||||
wkd_get_policy_flags (const char *addrspec, estream_t *r_buffer)
|
||||
{
|
||||
gpg_error_t err;
|
||||
assuan_context_t ctx;
|
||||
struct wkd_get_parm_s parm;
|
||||
char *line = NULL;
|
||||
char *buffer = NULL;
|
||||
|
||||
memset (&parm, 0, sizeof parm);
|
||||
*r_buffer = NULL;
|
||||
|
||||
err = connect_dirmngr (&ctx);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
line = es_bsprintf ("WKD_GET --policy-flags -- %s", addrspec);
|
||||
if (!line)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_TOO_LARGE);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
parm.memfp = es_fopenmem (0, "rwb");
|
||||
if (!parm.memfp)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
err = assuan_transact (ctx, line, wkd_get_data_cb, &parm,
|
||||
NULL, NULL, wkd_get_status_cb, &parm);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
es_rewind (parm.memfp);
|
||||
*r_buffer = parm.memfp;
|
||||
parm.memfp = 0;
|
||||
|
||||
leave:
|
||||
es_free (buffer);
|
||||
es_fclose (parm.memfp);
|
||||
xfree (line);
|
||||
assuan_release (ctx);
|
||||
return err;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ void set_dirmngr_options (int verbose, int debug_ipc, int autostart);
|
||||
|
||||
gpg_error_t wkd_get_submission_address (const char *addrspec,
|
||||
char **r_addrspec);
|
||||
gpg_error_t wkd_get_policy_flags (const char *addrspec, estream_t *r_buffer);
|
||||
|
||||
|
||||
#endif /*GNUPG_TOOLS_CALL_DIRMNGR_H*/
|
||||
|
@ -447,6 +447,9 @@ command_send (const char *fingerprint, char *userid)
|
||||
estream_t key = NULL;
|
||||
char *submission_to = NULL;
|
||||
mime_maker_t mime = NULL;
|
||||
struct policy_flags_s policy;
|
||||
|
||||
memset (&policy, 0, sizeof policy);
|
||||
|
||||
if (classify_user_id (fingerprint, &desc, 1)
|
||||
|| !(desc.mode == KEYDB_SEARCH_MODE_FPR
|
||||
@ -473,6 +476,29 @@ command_send (const char *fingerprint, char *userid)
|
||||
goto leave;
|
||||
log_info ("submitting request to '%s'\n", submission_to);
|
||||
|
||||
/* Get the policy flags. */
|
||||
{
|
||||
estream_t mbuf;
|
||||
|
||||
err = wkd_get_policy_flags (addrspec, &mbuf);
|
||||
if (err)
|
||||
{
|
||||
log_error ("error reading policy flags for '%s': %s\n",
|
||||
submission_to, gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
if (mbuf)
|
||||
{
|
||||
err = wks_parse_policy (&policy, mbuf, 1);
|
||||
es_fclose (mbuf);
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
if (policy.auth_submit)
|
||||
log_info ("no confirmation required for '%s'\n", addrspec);
|
||||
|
||||
/* Send the key. */
|
||||
err = mime_maker_new (&mime, NULL);
|
||||
if (err)
|
||||
|
@ -766,6 +766,50 @@ get_submission_address (const char *mbox)
|
||||
}
|
||||
|
||||
|
||||
/* Get the policy flags for address MBOX and store them in POLICY. */
|
||||
static gpg_error_t
|
||||
get_policy_flags (policy_flags_t policy, const char *mbox)
|
||||
{
|
||||
gpg_error_t err;
|
||||
const char *domain;
|
||||
char *fname;
|
||||
estream_t fp;
|
||||
|
||||
memset (policy, 0, sizeof *policy);
|
||||
|
||||
domain = strchr (mbox, '@');
|
||||
if (!domain)
|
||||
return gpg_error (GPG_ERR_INV_USER_ID);
|
||||
domain++;
|
||||
|
||||
fname = make_filename_try (opt.directory, domain, "policy", NULL);
|
||||
if (!fname)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("make_filename failed in %s: %s\n",
|
||||
__func__, gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
|
||||
fp = es_fopen (fname, "r");
|
||||
if (!fp)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
||||
err = 0;
|
||||
else
|
||||
log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
|
||||
xfree (fname);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = wks_parse_policy (policy, fp, 0);
|
||||
es_fclose (fp);
|
||||
xfree (fname);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* We store the key under the name of the nonce we will then send to
|
||||
* the user. On success the nonce is stored at R_NONCE and the file
|
||||
* name at R_FNAME. */
|
||||
@ -1005,6 +1049,7 @@ process_new_key (server_ctx_t ctx, estream_t key)
|
||||
char *dname = NULL;
|
||||
char *nonce = NULL;
|
||||
char *fname = NULL;
|
||||
struct policy_flags_s policybuf;
|
||||
|
||||
/* First figure out the user id from the key. */
|
||||
err = list_key (ctx, key);
|
||||
@ -1035,23 +1080,40 @@ process_new_key (server_ctx_t ctx, estream_t key)
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
/* Fixme: check for proper directory permissions. */
|
||||
|
||||
if (access (dname, W_OK))
|
||||
{
|
||||
log_info ("skipping address '%s': Domain not configured\n", sl->d);
|
||||
continue;
|
||||
}
|
||||
log_info ("storing address '%s'\n", sl->d);
|
||||
if (get_policy_flags (&policybuf, sl->d))
|
||||
{
|
||||
log_info ("skipping address '%s': Bad policy flags\n", sl->d);
|
||||
continue;
|
||||
}
|
||||
|
||||
xfree (nonce);
|
||||
xfree (fname);
|
||||
err = store_key_as_pending (dname, key, &nonce, &fname);
|
||||
if (err)
|
||||
goto leave;
|
||||
if (policybuf.auth_submit)
|
||||
{
|
||||
/* Bypass the confirmation stuff and publish the the key as is. */
|
||||
log_info ("publishing address '%s'\n", sl->d);
|
||||
/* FIXME: We need to make sure that we do this only for the
|
||||
* address in the mail. */
|
||||
log_debug ("auth-submit not yet working!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
log_info ("storing address '%s'\n", sl->d);
|
||||
|
||||
err = send_confirmation_request (ctx, sl->d, nonce, fname);
|
||||
if (err)
|
||||
goto leave;
|
||||
xfree (nonce);
|
||||
xfree (fname);
|
||||
err = store_key_as_pending (dname, key, &nonce, &fname);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
err = send_confirmation_request (ctx, sl->d, nonce, fname);
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
leave:
|
||||
@ -1639,6 +1701,7 @@ command_list_domains (void)
|
||||
const char *domain;
|
||||
char *fname = NULL;
|
||||
int i;
|
||||
estream_t fp;
|
||||
|
||||
err = get_domain_list (&domaindirs);
|
||||
if (err)
|
||||
@ -1686,7 +1749,7 @@ command_list_domains (void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Print a warning if the sumbission address is not configured. */
|
||||
/* Print a warning if the submission address is not configured. */
|
||||
xfree (fname);
|
||||
fname = make_filename_try (sl->d, "submission-address", NULL);
|
||||
if (!fname)
|
||||
@ -1704,6 +1767,38 @@ command_list_domains (void)
|
||||
log_error ("domain %s: problem with '%s': %s\n",
|
||||
domain, fname, gpg_strerror (err));
|
||||
}
|
||||
|
||||
/* Check the syntax of the optional policy file. */
|
||||
xfree (fname);
|
||||
fname = make_filename_try (sl->d, "policy", NULL);
|
||||
if (!fname)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
fp = es_fopen (fname, "r");
|
||||
if (!fp)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
if (gpg_err_code (err) != GPG_ERR_ENOENT)
|
||||
log_error ("domain %s: error in policy file: %s\n",
|
||||
domain, gpg_strerror (err));
|
||||
}
|
||||
else
|
||||
{
|
||||
struct policy_flags_s policy;
|
||||
err = wks_parse_policy (&policy, fp, 0);
|
||||
es_fclose (fp);
|
||||
if (!err)
|
||||
{
|
||||
struct policy_flags_s empty_policy;
|
||||
memset (&empty_policy, 0, sizeof empty_policy);
|
||||
if (!memcmp (&empty_policy, &policy, sizeof policy))
|
||||
log_error ("domain %s: empty policy file\n", domain);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
err = 0;
|
||||
|
||||
|
@ -46,8 +46,22 @@ struct
|
||||
#define DBG_EXTPROG_VALUE 16384 /* debug external program calls */
|
||||
|
||||
|
||||
/* The parsed policy flags. */
|
||||
struct policy_flags_s
|
||||
{
|
||||
unsigned int mailbox_only : 1;
|
||||
unsigned int dane_only : 1;
|
||||
unsigned int auth_submit : 1;
|
||||
unsigned int max_pending; /* Seconds to wait for a confirmation. */
|
||||
};
|
||||
typedef struct policy_flags_s *policy_flags_t;
|
||||
|
||||
|
||||
|
||||
/*-- wks-util.c --*/
|
||||
gpg_error_t wks_send_mime (mime_maker_t mime);
|
||||
gpg_error_t wks_parse_policy (policy_flags_t flags, estream_t stream,
|
||||
int ignore_unknown);
|
||||
|
||||
/*-- wks-receive.c --*/
|
||||
gpg_error_t wks_receive (estream_t fp,
|
||||
|
108
tools/wks-util.c
108
tools/wks-util.c
@ -63,3 +63,111 @@ wks_send_mime (mime_maker_t mime)
|
||||
es_fclose (mail);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Parse the policy flags by reading them from STREAM and storing them
|
||||
* into FLAGS. If IGNORE_UNKNOWN is iset unknown keywords are
|
||||
* ignored. */
|
||||
gpg_error_t
|
||||
wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown)
|
||||
{
|
||||
enum tokens {
|
||||
TOK_MAILBOX_ONLY,
|
||||
TOK_DANE_ONLY,
|
||||
TOK_AUTH_SUBMIT,
|
||||
TOK_MAX_PENDING
|
||||
};
|
||||
static struct {
|
||||
const char *name;
|
||||
enum tokens token;
|
||||
} keywords[] = {
|
||||
{ "mailbox-only", TOK_MAILBOX_ONLY },
|
||||
{ "dane-only", TOK_DANE_ONLY },
|
||||
{ "auth-submit", TOK_AUTH_SUBMIT },
|
||||
{ "max-pending", TOK_MAX_PENDING }
|
||||
};
|
||||
gpg_error_t err = 0;
|
||||
int lnr = 0;
|
||||
char line[1024];
|
||||
char *p, *keyword, *value;
|
||||
int i, n;
|
||||
|
||||
memset (flags, 0, sizeof *flags);
|
||||
|
||||
while (es_fgets (line, DIM(line)-1, stream) )
|
||||
{
|
||||
lnr++;
|
||||
n = strlen (line);
|
||||
if (!n || line[n-1] != '\n')
|
||||
{
|
||||
err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
|
||||
: GPG_ERR_INCOMPLETE_LINE);
|
||||
break;
|
||||
}
|
||||
trim_trailing_spaces (line);
|
||||
/* Skip empty and comment lines. */
|
||||
for (p=line; spacep (p); p++)
|
||||
;
|
||||
if (!*p || *p == '#')
|
||||
continue;
|
||||
|
||||
if (*p == ':')
|
||||
{
|
||||
err = gpg_error (GPG_ERR_SYNTAX);
|
||||
break;
|
||||
}
|
||||
|
||||
keyword = p;
|
||||
value = NULL;
|
||||
if ((p = strchr (p, ':')))
|
||||
{
|
||||
/* Colon found: Keyword with value. */
|
||||
*p++ = 0;
|
||||
for (; spacep (p); p++)
|
||||
;
|
||||
if (!*p)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_MISSING_VALUE);
|
||||
break;
|
||||
}
|
||||
value = p;
|
||||
}
|
||||
|
||||
for (i=0; i < DIM (keywords); i++)
|
||||
if (!ascii_strcasecmp (keywords[i].name, keyword))
|
||||
break;
|
||||
if (!(i < DIM (keywords)))
|
||||
{
|
||||
if (ignore_unknown)
|
||||
continue;
|
||||
err = gpg_error (GPG_ERR_INV_NAME);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (keywords[i].token)
|
||||
{
|
||||
case TOK_MAILBOX_ONLY: flags->mailbox_only = 1; break;
|
||||
case TOK_DANE_ONLY: flags->dane_only = 1; break;
|
||||
case TOK_AUTH_SUBMIT: flags->auth_submit = 1; break;
|
||||
case TOK_MAX_PENDING:
|
||||
if (!value)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_SYNTAX);
|
||||
goto leave;
|
||||
}
|
||||
/* FIXME: Define whether these are seconds, hours, or days
|
||||
* and decide whether to allow other units. */
|
||||
flags->max_pending = atoi (value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!err && !es_feof (stream))
|
||||
err = gpg_error_from_syserror ();
|
||||
leave:
|
||||
if (err)
|
||||
log_error ("error reading '%s', line %d: %s\n",
|
||||
es_fname_get (stream), lnr, gpg_strerror (err));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user