[Pkg-gnupg-commit] [gnupg2] 56/118: wks: Add framework for policy flags.
Daniel Kahn Gillmor
dkg at fifthhorseman.net
Thu Sep 15 18:25:08 UTC 2016
This is an automated email from the git hooks/post-receive script.
dkg pushed a commit to branch encoding-and-speling
in repository gnupg2.
commit 46362cbc0e2260e989820795a6e4245c72335172
Author: Werner Koch <wk at gnupg.org>
Date: Fri Sep 2 16:54:42 2016 +0200
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 at gnupg.org>
---
tools/call-dirmngr.c | 55 +++++++++++++++++++++++
tools/call-dirmngr.h | 1 +
tools/gpg-wks-client.c | 26 +++++++++++
tools/gpg-wks-server.c | 117 ++++++++++++++++++++++++++++++++++++++++++++-----
tools/gpg-wks.h | 14 ++++++
tools/wks-util.c | 108 +++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 310 insertions(+), 11 deletions(-)
diff --git a/tools/call-dirmngr.c b/tools/call-dirmngr.c
index 0e591dd..9142350 100644
--- a/tools/call-dirmngr.c
+++ b/tools/call-dirmngr.c
@@ -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;
+}
diff --git a/tools/call-dirmngr.h b/tools/call-dirmngr.h
index f1bc368..6c866e7 100644
--- a/tools/call-dirmngr.h
+++ b/tools/call-dirmngr.h
@@ -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*/
diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c
index 34b26ea..c0e34c4 100644
--- a/tools/gpg-wks-client.c
+++ b/tools/gpg-wks-client.c
@@ -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)
diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c
index 221db05..678000c 100644
--- a/tools/gpg-wks-server.c
+++ b/tools/gpg-wks-server.c
@@ -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;
diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h
index be85eec..85000cc 100644
--- a/tools/gpg-wks.h
+++ b/tools/gpg-wks.h
@@ -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,
diff --git a/tools/wks-util.c b/tools/wks-util.c
index 8d9f92b..7a87a27 100644
--- a/tools/wks-util.c
+++ b/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;
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gnupg/gnupg2.git
More information about the Pkg-gnupg-commit
mailing list