aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/wks.texi39
-rw-r--r--tools/gpg-wks-client.c157
-rw-r--r--tools/gpg-wks.h1
3 files changed, 193 insertions, 4 deletions
diff --git a/doc/wks.texi b/doc/wks.texi
index 48e534b7d..73934fb54 100644
--- a/doc/wks.texi
+++ b/doc/wks.texi
@@ -53,6 +53,26 @@ Directory.
.B gpg-wks-client
.RI [ options ]
.B \-\-read
+.br
+.B gpg-wks-client
+.RI [ options ]
+.B \-\-mirror
+.br
+.B gpg-wks-client
+.RI [ options ]
+.B \-\-install-key
+.br
+.B gpg-wks-client
+.RI [ options ]
+.B \-\-remove-key
+.br
+.B gpg-wks-client
+.RI [ options ]
+.B \-\-print-wkd-hash
+.br
+.B gpg-wks-client
+.RI [ options ]
+.B \-\-print-wkd-url
@end ifset
@mansect description
@@ -101,6 +121,13 @@ 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{--mirror} is similar to @option{--install-key} but
+takes the keys from the the LDAP server configured for Dirmngr. If no
+arguments are given all keys and user ids are installed. If arguments
+are given they are taken as domain names to limit the to be installed
+keys. The option @option{--blacklist} may be used to further limit
+the to be installed keys.
+
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).
@@ -175,8 +202,16 @@ easily get the return code of the process.
@itemx --directory @var{dir}
@opindex directory
Use @var{dir} as top level directory for the commands
-@option{--install-key} and @option{--remove-key}. The default is
-@file{openpgpkey}.
+@option{--mirror}, @option{--install-key} and @option{--remove-key}.
+The default is @file{openpgpkey}.
+
+
+@item --blacklist @var{file}
+@opindex blacklist
+This option is used to exclude certain mail addresses from a mirror
+operation. The format of @var{file} is one mail address (just the
+addrspec, e.g. "postel@@isi.edu") per line. Empty lines and lines
+starting with a '#' are ignored.
@item --verbose
@opindex verbose
diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c
index c9e6e5a50..a30457e75 100644
--- a/tools/gpg-wks-client.c
+++ b/tools/gpg-wks-client.c
@@ -144,8 +144,14 @@ static struct debug_flags_s debug_flags [] =
/* Value of the option --fake-submission-addr. */
const char *fake_submission_addr;
+/* An array with blacklisted addresses and its length. Use
+ * is_in_blacklist to check. */
+static char **blacklist_array;
+static size_t blacklist_array_len;
+
static void wrong_args (const char *text) GPGRT_ATTR_NORETURN;
+static void add_blacklist (const char *fname);
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);
@@ -249,7 +255,7 @@ parse_arguments (gpgrt_argparse_t *pargs, gpgrt_opt_t *popts)
opt.no_autostart = 1;
break;
case oBlacklist:
- opt.blacklist = pargs->r.ret_str;
+ add_blacklist (pargs->r.ret_str);
break;
case aSupported:
@@ -477,6 +483,153 @@ main (int argc, char **argv)
}
+
+/* Read a file FNAME into a buffer and return that malloced buffer.
+ * Caller must free the buffer. On error NULL is returned, on success
+ * the valid length of the buffer is stored at R_LENGTH. The returned
+ * buffer is guaranteed to be Nul terminated. */
+static char *
+read_file (const char *fname, size_t *r_length)
+{
+ estream_t fp;
+ char *buf;
+ size_t buflen;
+
+ if (!strcmp (fname, "-"))
+ {
+ size_t nread, bufsize = 0;
+
+ fp = es_stdin;
+ es_set_binary (fp);
+ buf = NULL;
+ buflen = 0;
+#define NCHUNK 32767
+ do
+ {
+ bufsize += NCHUNK;
+ if (!buf)
+ buf = xmalloc (bufsize+1);
+ else
+ buf = xrealloc (buf, bufsize+1);
+
+ nread = es_fread (buf+buflen, 1, NCHUNK, fp);
+ if (nread < NCHUNK && es_ferror (fp))
+ {
+ log_error ("error reading '[stdin]': %s\n", strerror (errno));
+ xfree (buf);
+ return NULL;
+ }
+ buflen += nread;
+ }
+ while (nread == NCHUNK);
+#undef NCHUNK
+ }
+ else
+ {
+ struct stat st;
+
+ fp = es_fopen (fname, "rb");
+ if (!fp)
+ {
+ log_error ("can't open '%s': %s\n", fname, strerror (errno));
+ return NULL;
+ }
+
+ if (fstat (es_fileno (fp), &st))
+ {
+ log_error ("can't stat '%s': %s\n", fname, strerror (errno));
+ es_fclose (fp);
+ return NULL;
+ }
+
+ buflen = st.st_size;
+ buf = xmalloc (buflen+1);
+ if (es_fread (buf, buflen, 1, fp) != 1)
+ {
+ log_error ("error reading '%s': %s\n", fname, strerror (errno));
+ es_fclose (fp);
+ xfree (buf);
+ return NULL;
+ }
+ es_fclose (fp);
+ }
+ buf[buflen] = 0;
+ if (r_length)
+ *r_length = buflen;
+ return buf;
+}
+
+
+static int
+cmp_blacklist (const void *arg_a, const void *arg_b)
+{
+ const char *a = *(const char **)arg_a;
+ const char *b = *(const char **)arg_b;
+ return strcmp (a, b);
+}
+
+
+/* Add a blacklist to our global table. This is called during option
+ * parsing and thus any use of log_error will eventually stop further
+ * processing. */
+static void
+add_blacklist (const char *fname)
+{
+ char *buffer;
+ char *p, *pend;
+ char **array;
+ size_t arraysize, arrayidx;
+
+ buffer = read_file (fname, NULL);
+ if (!buffer)
+ return;
+
+ /* Estimate the number of entries by counting the non-comment lines. */
+ arraysize = 2; /* For the first and an extra NULL item. */
+ for (p=buffer; *p; p++)
+ if (*p == '\n' && p[1] && p[1] != '#')
+ arraysize++;
+
+ array = xcalloc (arraysize, sizeof *array);
+ arrayidx = 0;
+
+ /* Loop over all lines. */
+ for (p = buffer; p && *p; p = pend)
+ {
+ pend = strchr (p, '\n');
+ if (pend)
+ *pend++ = 0;
+ trim_spaces (p);
+ if (!*p || *p == '#' )
+ continue;
+ ascii_strlwr (p);
+ log_assert (arrayidx < arraysize);
+ array[arrayidx] = p;
+ arrayidx++;
+ }
+ log_assert (arrayidx < arraysize);
+
+ qsort (array, arrayidx, sizeof *array, cmp_blacklist);
+
+ blacklist_array = array;
+ blacklist_array_len = arrayidx;
+ gpgrt_annotate_leaked_object (buffer);
+ gpgrt_annotate_leaked_object (blacklist_array);
+}
+
+
+/* Return true if NAME is in a blacklist. */
+static int
+is_in_blacklist (const char *name)
+{
+ if (!name || !blacklist_array)
+ return 0;
+ return !!bsearch (&name, blacklist_array, blacklist_array_len,
+ sizeof *blacklist_array, cmp_blacklist);
+}
+
+
+
/* Read user ids from stdin and call FUNC for each user id. TEXT is
* used for error messages. */
static gpg_error_t
@@ -1765,6 +1918,8 @@ mirror_one_key (estream_t key)
continue; /* No mail box or already processed. */
if (!domain_matches_mbox (domain, uid->mbox))
continue; /* We don't want this one. */
+ if (is_in_blacklist (uid->mbox))
+ continue;
err = mirror_one_keys_userid (key, uid->mbox, uidlist, fpr);
if (err)
diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h
index 50350eddb..32aa8c328 100644
--- a/tools/gpg-wks.h
+++ b/tools/gpg-wks.h
@@ -44,7 +44,6 @@ struct
const char *directory;
const char *default_from;
strlist_t extra_headers;
- const char *blacklist;
} opt;
/* Debug values and macros. */