diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/Makefile.am | 5 | ||||
-rw-r--r-- | tools/gpg-check-pattern.c | 2 | ||||
-rw-r--r-- | tools/gpg-connect-agent.c | 6 | ||||
-rw-r--r-- | tools/gpg-wks-client.c | 262 | ||||
-rw-r--r-- | tools/gpg-wks-server.c | 33 | ||||
-rw-r--r-- | tools/gpg-wks.h | 1 | ||||
-rw-r--r-- | tools/gpg-zip.in | 148 | ||||
-rw-r--r-- | tools/gpgconf.c | 2 | ||||
-rw-r--r-- | tools/gpgtar.h | 2 | ||||
-rw-r--r-- | tools/mime-maker.c | 47 | ||||
-rw-r--r-- | tools/mime-parser.c | 2 | ||||
-rw-r--r-- | tools/no-libgcrypt.c | 2 | ||||
-rw-r--r-- | tools/rfc822parse.c | 113 | ||||
-rw-r--r-- | tools/rfc822parse.h | 2 | ||||
-rw-r--r-- | tools/wks-util.c | 6 |
15 files changed, 320 insertions, 313 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am index a15427622..196bf5210 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -34,11 +34,6 @@ AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) $(LIBASSUAN_CFLAGS) sbin_SCRIPTS = addgnupghome applygnupgdefaults -if HAVE_USTAR -# bin_SCRIPTS += gpg-zip -noinst_SCRIPTS = gpg-zip -endif - if BUILD_SYMCRYPTRUN symcryptrun = symcryptrun else diff --git a/tools/gpg-check-pattern.c b/tools/gpg-check-pattern.c index 4db8f3706..dee5d5d47 100644 --- a/tools/gpg-check-pattern.c +++ b/tools/gpg-check-pattern.c @@ -91,7 +91,7 @@ static struct enum { PAT_NULL, /* Indicates end of the array. */ PAT_STRING, /* The pattern is a simple string. */ - PAT_REGEX /* The pattern is an extended regualr expression. */ + PAT_REGEX /* The pattern is an extended regular expression. */ }; diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c index 00482a32e..7eb7ffa3a 100644 --- a/tools/gpg-connect-agent.c +++ b/tools/gpg-connect-agent.c @@ -983,7 +983,7 @@ do_open (char *line) name, mode, strerror (errno)); return; } - fd = fileno (fp); + fd = dup (fileno (fp)); if (fd >= 0 && fd < DIM (open_fd_table)) { open_fd_table[fd].inuse = 1; @@ -1030,8 +1030,10 @@ do_open (char *line) else { log_error ("can't put fd %d into table\n", fd); - close (fd); + if (fd != -1) + close (fd); /* Table was full. */ } + fclose (fp); } diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c index 73945ff30..0be5ea89b 100644 --- a/tools/gpg-wks-client.c +++ b/tools/gpg-wks-client.c @@ -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,15 +622,16 @@ command_supported (char *userid) gpg_error_t err; char *addrspec = NULL; char *submission_to = NULL; + policy_flags_t policy = NULL; if (!strchr (userid, '@')) { char *tmp = xstrconcat ("foo@", userid, NULL); - addrspec = mailbox_from_userid (tmp); + addrspec = mailbox_from_userid (tmp, 0); xfree (tmp); } else - addrspec = mailbox_from_userid (userid); + addrspec = mailbox_from_userid (userid, 0); if (!addrspec) { log_error (_("\"%s\" is not a proper mail address\n"), 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; @@ -534,7 +694,7 @@ command_check (char *userid) uidinfo_list_t sl; int found = 0; - addrspec = mailbox_from_userid (userid); + addrspec = mailbox_from_userid (userid, 0); if (!addrspec) { log_error (_("\"%s\" is not a proper mail address\n"), userid); @@ -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)) @@ -647,7 +805,7 @@ command_send (const char *fingerprint, const char *userid) goto leave; } - addrspec = mailbox_from_userid (userid); + addrspec = mailbox_from_userid (userid, 0); if (!addrspec) { log_error (_("\"%s\" is not a proper mail address\n"), userid); @@ -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; } diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c index a5881557f..1b533124a 100644 --- a/tools/gpg-wks-server.c +++ b/tools/gpg-wks-server.c @@ -58,6 +58,7 @@ enum cmd_and_opt_values oQuiet = 'q', oVerbose = 'v', oOutput = 'o', + oDirectory = 'C', oDebug = 500, @@ -108,6 +109,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_s (oGpgProgram, "gpg", "@"), ARGPARSE_s_n (oSend, "send", "send the mail using sendmail"), ARGPARSE_s_s (oOutput, "output", "|FILE|write the mail to FILE"), + ARGPARSE_s_s (oDirectory, "directory", "|DIR|use DIR as top directory"), ARGPARSE_s_s (oFrom, "from", "|ADDR|use ADDR as the default sender"), ARGPARSE_s_s (oHeader, "header" , "|NAME=VALUE|add \"NAME: VALUE\" as header to all mails"), @@ -225,6 +227,9 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts) case oGpgProgram: opt.gpg_program = pargs->r.ret_str; break; + case oDirectory: + opt.directory = pargs->r.ret_str; + break; case oFrom: opt.default_from = pargs->r.ret_str; break; @@ -350,6 +355,7 @@ main (int argc, char **argv) { log_error ("directory '%s' has too relaxed permissions\n", opt.directory); + log_info ("Fix by running: chmod o-rw '%s'\n", opt.directory); exit (2); } } @@ -1667,7 +1673,7 @@ command_receive_cb (void *opaque, const char *mediatype, -/* Return a list of all configured domains. ECh list element is the +/* Return a list of all configured domains. Each list element is the * top directory for the domain. To figure out the actual domain * name strrchr(name, '/') can be used. */ static gpg_error_t @@ -1946,7 +1952,17 @@ command_list_domains (void) if (!fp) { err = gpg_error_from_syserror (); - if (gpg_err_code (err) != GPG_ERR_ENOENT) + if (gpg_err_code (err) == GPG_ERR_ENOENT) + { + fp = es_fopen (fname, "w"); + if (!fp) + log_error ("domain %s: can't create policy file: %s\n", + domain, gpg_strerror (err)); + else + es_fclose (fp); + fp = NULL; + } + else log_error ("domain %s: error in policy file: %s\n", domain, gpg_strerror (err)); } @@ -1955,17 +1971,8 @@ command_list_domains (void) 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); - } wks_free_policy (&policy); } - - } err = 0; @@ -2013,7 +2020,7 @@ command_install_key (const char *fname, const char *userid) char *huname = NULL; int any; - addrspec = mailbox_from_userid (userid); + addrspec = mailbox_from_userid (userid, 0); if (!addrspec) { log_error ("\"%s\" is not a proper mail address\n", userid); @@ -2146,7 +2153,7 @@ fname_from_userid (const char *userid, char **r_fname, char **r_addrspec) if (r_addrspec) *r_addrspec = NULL; - addrspec = mailbox_from_userid (userid); + addrspec = mailbox_from_userid (userid, 0); if (!addrspec) { if (opt.verbose) diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h index 1b91b6504..fba73f085 100644 --- a/tools/gpg-wks.h +++ b/tools/gpg-wks.h @@ -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; diff --git a/tools/gpg-zip.in b/tools/gpg-zip.in deleted file mode 100644 index 48c4766b1..000000000 --- a/tools/gpg-zip.in +++ /dev/null @@ -1,148 +0,0 @@ -#!/bin/sh - -# gpg-archive - gpg-ized tar using the same format as PGP's PGP Zip. -# Copyright (C) 2005 Free Software Foundation, Inc. -# -# This file is part of GnuPG. -# -# GnuPG is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# GnuPG is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see <http://www.gnu.org/licenses/>. -# Despite the name, PGP Zip format is actually an OpenPGP-wrapped tar -# file. To be compatible with PGP itself, this must be a USTAR format -# tar file. Unclear on whether there is a distinction here between -# the GNU or POSIX variant of USTAR. - -VERSION=@VERSION@ -TAR=@TAR@ -GPG=gpg - -usage="\ -Usage: gpg-zip [--help] [--version] [--encrypt] [--decrypt] [--symmetric] - [--list-archive] [--output FILE] [--gpg GPG] [--gpg-args ARGS] - [--tar TAR] [--tar-args ARGS] filename1 [filename2, ...] - directory1 [directory2, ...] - -Encrypt or sign files into an archive." - -tar_verbose_opt="v" - -while test $# -gt 0 ; do - case $1 in - -h | --help | --h*) - echo "$usage" - exit 0 - ;; - --list-archive) - list=yes - create=no - unpack=no - shift - ;; - --encrypt | -e) - gpg_args="$gpg_args --encrypt" - list=no - create=yes - unpack=no - shift - ;; - --decrypt | -d) - gpg_args="$gpg_args --decrypt" - list=no - create=no - unpack=yes - shift - ;; - --symmetric | -c) - gpg_args="$gpg_args --symmetric" - list=no - create=yes - unpack=no - shift - ;; - --sign | -s) - gpg_args="$gpg_args --sign" - list=no - create=yes - unpack=no - shift - ;; - --recipient | -r) - gpg_args="$gpg_args --recipient $2" - shift - shift - ;; - --local-user | -u) - gpg_args="$gpg_args --local-user $2" - shift - shift - ;; - --output | -o) - gpg_args="$gpg_args --output $2" - shift - shift - ;; - --version) - echo "gpg-zip (GnuPG) $VERSION" - exit 0 - ;; - --gpg) - GPG=$2 - shift - shift - ;; - --gpg-args) - gpg_args="$gpg_args $2" - shift - shift - ;; - --tar) - TAR=$2 - shift - shift - ;; - --tar-args) - tar_args="$tar_args $2" - shift - shift - ;; - --quiet) - tar_verbose_opt="" - shift - ;; - --) - shift - break - ;; - -*) - echo "$usage" 1>&2 - exit 1 - ;; - *) - break - ;; - esac -done - -if test x$create = xyes ; then -# echo "$TAR $tar_args -cf - "$@" | $GPG --set-filename x.tar $gpg_args" 1>&2 - $TAR $tar_args -cf - "$@" | $GPG --set-filename x.tar $gpg_args -elif test x$list = xyes ; then -# echo "cat \"$1\" | $GPG $gpg_args | $TAR $tar_args -tf -" 1>&2 - cat "$1" | $GPG $gpg_args | $TAR $tar_args -tf - -elif test x$unpack = xyes ; then -# echo "cat \"$1\" | $GPG $gpg_args | $TAR $tar_args -xvf -" 1>&2 - cat "$1" | $GPG $gpg_args | $TAR $tar_args -x${tar_verbose_opt}f - -else - echo "$usage" 1>&2 - exit 1 -fi diff --git a/tools/gpgconf.c b/tools/gpgconf.c index 59085d8b5..df3ae8cab 100644 --- a/tools/gpgconf.c +++ b/tools/gpgconf.c @@ -823,7 +823,7 @@ main (int argc, char **argv) ; else if (rmdir (socketdir)) { - /* If the director is not empty we first try to delet + /* If the director is not empty we first try to delete * socket files. */ err = gpg_error_from_syserror (); if (gpg_err_code (err) == GPG_ERR_ENOTEMPTY diff --git a/tools/gpgtar.h b/tools/gpgtar.h index 8cbe80bbb..28d3d88b1 100644 --- a/tools/gpgtar.h +++ b/tools/gpgtar.h @@ -88,7 +88,7 @@ typedef enum } typeflag_t; -/* The internal represenation of a TAR header. */ +/* The internal representation of a TAR header. */ struct tar_header_s; typedef struct tar_header_s *tar_header_t; struct tar_header_s diff --git a/tools/mime-maker.c b/tools/mime-maker.c index 0edc14d78..91eab8258 100644 --- a/tools/mime-maker.c +++ b/tools/mime-maker.c @@ -25,14 +25,10 @@ #include "../common/util.h" #include "../common/zb32.h" +#include "rfc822parse.h" #include "mime-maker.h" -/* All valid characters in a header name. */ -#define HEADER_NAME_CHARS ("abcdefghijklmnopqrstuvwxyz" \ - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ - "-01234567890") - /* An object to store an header. Also used for a list of headers. */ struct header_s { @@ -269,38 +265,6 @@ ensure_part (mime_maker_t ctx, part_t *r_parent) } -/* Transform a header name into a standard capitalized format. - * "Content-Type". Conversion stops at the colon. */ -static void -capitalize_header_name (char *name) -{ - unsigned char *p = name; - int first = 1; - - /* Special cases first. */ - if (!ascii_strcasecmp (name, "MIME-Version")) - { - strcpy (name, "MIME-Version"); - return; - } - - /* Regular cases. */ - for (; *p && *p != ':'; p++) - { - if (*p == '-') - first = 1; - else if (first) - { - if (*p >= 'a' && *p <= 'z') - *p = *p - 'a' + 'A'; - first = 0; - } - else if (*p >= 'A' && *p <= 'Z') - *p = *p - 'A' + 'a'; - } -} - - /* Check whether a header with NAME has already been set into PART. * NAME must be in canonical capitalized format. Return true or * false. */ @@ -344,17 +308,14 @@ add_header (part_t part, const char *name, const char *value) memcpy (hdr->name, name, namelen); hdr->name[namelen] = 0; - /* Check that the header name is valid. We allow all lower and - * uppercase letters and, except for the first character, digits and - * the dash. */ - if (strspn (hdr->name, HEADER_NAME_CHARS) != namelen - || strchr ("-0123456789", *hdr->name)) + /* Check that the header name is valid. */ + if (!rfc822_valid_header_name_p (hdr->name)) { xfree (hdr); return gpg_error (GPG_ERR_INV_NAME); } - capitalize_header_name (hdr->name); + rfc822_capitalize_header_name (hdr->name); hdr->value = xtrystrdup (value); if (!hdr->value) { diff --git a/tools/mime-parser.c b/tools/mime-parser.c index a151dc65e..98f27105c 100644 --- a/tools/mime-parser.c +++ b/tools/mime-parser.c @@ -50,7 +50,7 @@ struct mime_parser_context_s { void *cookie; /* Cookie passed to all callbacks. */ - /* The callback to announce the transation from header to body. */ + /* The callback to announce the transition from header to body. */ gpg_error_t (*t2body) (void *cookie, int level); /* The callback to announce a new part. */ diff --git a/tools/no-libgcrypt.c b/tools/no-libgcrypt.c index 873996889..3b577567a 100644 --- a/tools/no-libgcrypt.c +++ b/tools/no-libgcrypt.c @@ -114,7 +114,7 @@ gcry_free (void *a) /* We need this dummy because exechelp.c uses gcry_control to - terminate the secure memeory. */ + terminate the secure memory. */ gcry_error_t gcry_control (enum gcry_ctl_cmds cmd, ...) { diff --git a/tools/rfc822parse.c b/tools/rfc822parse.c index e8cdb0215..f1e95bd34 100644 --- a/tools/rfc822parse.c +++ b/tools/rfc822parse.c @@ -41,6 +41,12 @@ #include "rfc822parse.h" +/* All valid characters in a header name. */ +#define HEADER_NAME_CHARS ("abcdefghijklmnopqrstuvwxyz" \ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + "-01234567890") + + enum token_type { tSPACE, @@ -90,7 +96,7 @@ struct rfc822parse_context void *callback_value; int callback_error; int in_body; - int in_preamble; /* Wether we are before the first boundary. */ + int in_preamble; /* Whether we are before the first boundary. */ part_t parts; /* The tree of parts. */ part_t current_part; /* Whom we are processing (points into parts). */ const char *boundary; /* Current boundary. */ @@ -131,28 +137,31 @@ lowercase_string (unsigned char *string) *string = *string - 'A' + 'a'; } -/* Transform a header name into a standard capitalized format; i.e - "Content-Type". Conversion stops at the colon. As usual we don't - use the localized versions of ctype.h. - */ -static void -capitalize_header_name (unsigned char *name) + +static int +my_toupper (int c) { - int first = 1; + if (c >= 'a' && c <= 'z') + c &= ~0x20; + return c; +} + +/* This is the same as ascii_strcasecmp. */ +static int +my_strcasecmp (const char *a, const char *b) +{ + if (a == b) + return 0; - for (; *name && *name != ':'; name++) - if (*name == '-') - first = 1; - else if (first) - { - if (*name >= 'a' && *name <= 'z') - *name = *name - 'a' + 'A'; - first = 0; - } - else if (*name >= 'A' && *name <= 'Z') - *name = *name - 'A' + 'a'; + for (; *a && *b; a++, b++) + { + if (*a != *b && my_toupper(*a) != my_toupper(*b)) + break; + } + return *a == *b? 0 : (my_toupper (*a) - my_toupper (*b)); } + #ifndef HAVE_STPCPY static char * my_stpcpy (char *a,const char *b) @@ -167,7 +176,7 @@ my_stpcpy (char *a,const char *b) #endif -/* If a callback has been registerd, call it for the event of type +/* If a callback has been registered, call it for the event of type EVENT. */ static int do_callback (rfc822parse_t msg, rfc822parse_event_t event) @@ -228,6 +237,62 @@ release_handle_data (rfc822parse_t msg) } +/* Check that the header name is valid. We allow all lower and + * uppercase letters and, except for the first character, digits and + * the dash. The check stops at the first colon or at string end. + * Returns true if the name is valid. */ +int +rfc822_valid_header_name_p (const char *name) +{ + const char *s; + size_t namelen; + + if ((s=strchr (name, ':'))) + namelen = s - name; + else + namelen = strlen (name); + + if (!namelen + || strspn (name, HEADER_NAME_CHARS) != namelen + || strchr ("-0123456789", *name)) + return 0; + return 1; +} + + +/* Transform a header NAME into a standard capitalized format. + * Conversion stops at the colon. */ +void +rfc822_capitalize_header_name (char *name) +{ + unsigned char *p = name; + int first = 1; + + /* Special cases first. */ + if (!my_strcasecmp (name, "MIME-Version")) + { + strcpy (name, "MIME-Version"); + return; + } + + /* Regular cases. */ + for (; *p && *p != ':'; p++) + { + if (*p == '-') + first = 1; + else if (first) + { + if (*p >= 'a' && *p <= 'z') + *p = *p - 'a' + 'A'; + first = 0; + } + else if (*p >= 'A' && *p <= 'Z') + *p = *p - 'A' + 'a'; + } +} + + + /* Create a new parsing context for an entire rfc822 message and return it. CB and CB_VALUE may be given to callback for certain events. NULL is returned on error with errno set appropriately. */ @@ -432,7 +497,7 @@ insert_header (rfc822parse_t msg, const unsigned char *line, size_t length) /* Transform a field name into canonical format. */ if (!hdr->cont && strchr (line, ':')) - capitalize_header_name (hdr->line); + rfc822_capitalize_header_name (hdr->line); *msg->current_part->hdr_lines_tail = hdr; msg->current_part->hdr_lines_tail = &hdr->next; @@ -578,7 +643,7 @@ rfc822parse_get_field (rfc822parse_t msg, const char *name, int which, /**************** * Enumerate all header. Caller has to provide the address of a pointer - * which has to be initialzed to NULL, the caller should then never change this + * which has to be initialized to NULL, the caller should then never change this * pointer until he has closed the enumeration by passing again the address * of the pointer but with msg set to NULL. * The function returns pointers to all the header lines or NULL when @@ -616,7 +681,7 @@ rfc822parse_enum_header_lines (rfc822parse_t msg, void **context) * >0 : Retrieve the n-th field * RPREV may be used to return the predecessor of the returned field; - * which may be NULL for the very first one. It has to be initialzed + * which may be NULL for the very first one. It has to be initialized * to either NULL in which case the search start at the first header line, * or it may point to a headerline, where the search should start */ @@ -1013,7 +1078,7 @@ is_parameter (TOKEN t) parse context is valid; NULL is returned in case that attr is not defined in the header, a missing value is reppresented by an empty string. - With LOWER_VALUE set to true, a matching field valuebe be + With LOWER_VALUE set to true, a matching field value will be lowercased. Note, that ATTR should be lowercase. diff --git a/tools/rfc822parse.h b/tools/rfc822parse.h index 177d8271a..e2f2bedac 100644 --- a/tools/rfc822parse.h +++ b/tools/rfc822parse.h @@ -48,6 +48,8 @@ typedef int (*rfc822parse_cb_t) (void *opaque, rfc822parse_event_t event, rfc822parse_t msg); +int rfc822_valid_header_name_p (const char *name); +void rfc822_capitalize_header_name (char *name); rfc822parse_t rfc822parse_open (rfc822parse_cb_t cb, void *opaque_value); diff --git a/tools/wks-util.c b/tools/wks-util.c index 3fd824c1a..cf80a25bc 100644 --- a/tools/wks-util.c +++ b/tools/wks-util.c @@ -65,7 +65,7 @@ wks_set_status_fd (int fd) } -/* Write a status line with code NO followed by the outout of the +/* Write a status line with code NO followed by the output of the * printf style FORMAT. The caller needs to make sure that LFs and * CRs are not printed. */ void @@ -104,7 +104,7 @@ append_to_uidinfo_list (uidinfo_list_t *list, const char *uid, time_t created) strcpy (sl->uid, uid); sl->created = created; - sl->mbox = mailbox_from_userid (uid); + sl->mbox = mailbox_from_userid (uid, 0); sl->next = NULL; if (!*list) *list = sl; @@ -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) |