diff options
author | Werner Koch <wk@gnupg.org> | 2022-10-07 17:35:44 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2022-10-07 17:35:44 +0200 |
commit | b0b4e24c4fa80c10d310a229f5a0c65a57ad9393 (patch) | |
tree | fae1c53e3e9735334b6543f5c8f6858f49d378b7 /tools | |
parent | wkd: Restrict gpg-wks-client --mirror to the given domains. (diff) | |
download | gnupg2-b0b4e24c4fa80c10d310a229f5a0c65a57ad9393.tar.xz gnupg2-b0b4e24c4fa80c10d310a229f5a0c65a57ad9393.zip |
wkd: Implement --blacklist option for gpg-wks-client
* tools/gpg-wks-client.c (blacklist_array, blacklist_array_len): New.
(parse_arguments): Install blacklist.
(read_file): New.
(cmp_blacklist, add_blacklist, is_in_blacklist): New.
(mirror_one_key): Check list.
* tools/gpg-wks.h (opt): Remove field blacklist.
--
GnuPG-bug-id: 6224
Diffstat (limited to 'tools')
-rw-r--r-- | tools/gpg-wks-client.c | 157 | ||||
-rw-r--r-- | tools/gpg-wks.h | 1 |
2 files changed, 156 insertions, 2 deletions
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. */ |