diff options
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/applygnupgdefaults | 2 | ||||
-rw-r--r-- | tools/gpg-wks-server.c | 195 | ||||
-rw-r--r-- | tools/gpgconf-comp.c | 29 | ||||
-rw-r--r-- | tools/gpgconf.c | 112 | ||||
-rw-r--r-- | tools/gpgconf.h | 4 |
5 files changed, 311 insertions, 31 deletions
diff --git a/tools/applygnupgdefaults b/tools/applygnupgdefaults index 54365ce34..316509faf 100755 --- a/tools/applygnupgdefaults +++ b/tools/applygnupgdefaults @@ -1,5 +1,5 @@ #!/bin/sh -# Apply defaults from /etc/gnupg/gpg.conf to all users -*- sh -*- +# Apply defaults from /etc/gnupg/gpgconf.conf to all users -*- sh -*- # # Copyright 2007 Free Software Foundation, Inc. # diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c index 7e3f05017..0b1d64261 100644 --- a/tools/gpg-wks-server.c +++ b/tools/gpg-wks-server.c @@ -66,11 +66,14 @@ enum cmd_and_opt_values aInstallKey, aRevokeKey, aRemoveKey, + aCheck, oGpgProgram, oSend, oFrom, oHeader, + oWithDir, + oWithFile, oDummy }; @@ -86,12 +89,15 @@ static ARGPARSE_OPTS opts[] = { ("run regular jobs")), ARGPARSE_c (aListDomains, "list-domains", ("list configured domains")), + ARGPARSE_c (aCheck, "check", + ("check whether a key is installed")), + ARGPARSE_c (aCheck, "check-key", "@"), ARGPARSE_c (aInstallKey, "install-key", - "|FILE|install a key from FILE into the WKD"), + "install a key from FILE into the WKD"), ARGPARSE_c (aRemoveKey, "remove-key", - "|ADDR|remove the key ADDR from the WKD"), + "remove a key from the WKD"), ARGPARSE_c (aRevokeKey, "revoke-key", - "|ADDR|mark the key ADDR in the WKD as revoked"), + "mark a key as revoked"), ARGPARSE_group (301, ("@\nOptions:\n ")), @@ -104,6 +110,8 @@ static ARGPARSE_OPTS opts[] = { 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"), + ARGPARSE_s_n (oWithDir, "with-dir", "@"), + ARGPARSE_s_n (oWithFile, "with-file", "@"), ARGPARSE_end () }; @@ -132,6 +140,13 @@ struct server_ctx_s }; typedef struct server_ctx_s *server_ctx_t; + +/* Flag for --with-dir. */ +static int opt_with_dir; +/* Flag for --with-file. */ +static int opt_with_file; + + /* Prototypes. */ static gpg_error_t get_domain_list (strlist_t *r_list); @@ -142,6 +157,7 @@ static gpg_error_t command_list_domains (void); static gpg_error_t command_install_key (const char *fname); static gpg_error_t command_remove_key (const char *mailaddr); static gpg_error_t command_revoke_key (const char *mailaddr); +static gpg_error_t command_check_key (const char *mailaddr); static gpg_error_t command_cron (void); @@ -220,10 +236,17 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts) case oOutput: opt.output = pargs->r.ret_str; break; + case oWithDir: + opt_with_dir = 1; + break; + case oWithFile: + opt_with_file = 1; + break; case aReceive: case aCron: case aListDomains: + case aCheck: case aInstallKey: case aRemoveKey: case aRevokeKey: @@ -243,7 +266,7 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts) int main (int argc, char **argv) { - gpg_error_t err; + gpg_error_t err, firsterr; ARGPARSE_ARGS pargs; enum cmd_and_opt_values cmd; @@ -360,16 +383,29 @@ main (int argc, char **argv) case aRemoveKey: if (argc != 1) - wrong_args ("--remove-key MAILADDR"); + wrong_args ("--remove-key USER-ID"); err = command_remove_key (*argv); break; case aRevokeKey: if (argc != 1) - wrong_args ("--revoke-key MAILADDR"); + wrong_args ("--revoke-key USER-ID"); err = command_revoke_key (*argv); break; + case aCheck: + if (!argc) + wrong_args ("--check USER-IDs"); + firsterr = 0; + for (; argc; argc--, argv++) + { + err = command_check_key (*argv); + if (!firsterr) + firsterr = err; + } + err = firsterr; + break; + default: usage (1); err = gpg_error (GPG_ERR_BUG); @@ -1776,7 +1812,11 @@ command_list_domains (void) domain = strrchr (sl->d, '/'); log_assert (domain); domain++; - es_printf ("%s\n", domain); + if (opt_with_dir) + es_printf ("%s %s\n", domain, sl->d); + else + es_printf ("%s\n", domain); + /* Check that the required directories are there. */ for (i=0; i < DIM (requireddirs); i++) @@ -1900,12 +1940,140 @@ command_install_key (const char *fname) } -/* Remove the key with mail address MAILADDR. */ +/* Return the filename and optioanlly the addrspec for USERID at + * R_FNAME and R_ADDRSPEC. R_ADDRSPEC might also be set on error. */ static gpg_error_t -command_remove_key (const char *mailaddr) +fname_from_userid (const char *userid, char **r_fname, char **r_addrspec) { - (void)mailaddr; - return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + gpg_error_t err; + char *addrspec = NULL; + const char *domain; + char *hash = NULL; + const char *s; + char shaxbuf[32]; /* Used for SHA-1 and SHA-256 */ + + *r_fname = NULL; + if (r_addrspec) + *r_addrspec = NULL; + + addrspec = mailbox_from_userid (userid); + if (!addrspec) + { + if (opt.verbose) + log_info ("\"%s\" is not a proper mail address\n", userid); + err = gpg_error (GPG_ERR_INV_USER_ID); + goto leave; + } + + domain = strchr (addrspec, '@'); + log_assert (domain); + domain++; + + /* Hash user ID and create filename. */ + s = strchr (addrspec, '@'); + log_assert (s); + gcry_md_hash_buffer (GCRY_MD_SHA1, shaxbuf, addrspec, s - addrspec); + hash = zb32_encode (shaxbuf, 8*20); + if (!hash) + { + err = gpg_error_from_syserror (); + goto leave; + } + + *r_fname = make_filename_try (opt.directory, domain, "hu", hash, NULL); + if (!*r_fname) + err = gpg_error_from_syserror (); + else + err = 0; + + leave: + if (r_addrspec && addrspec) + *r_addrspec = addrspec; + else + xfree (addrspec); + xfree (hash); + return err; +} + + +/* Check whether the key with USER_ID is installed. */ +static gpg_error_t +command_check_key (const char *userid) +{ + gpg_error_t err; + char *addrspec = NULL; + char *fname = NULL; + + err = fname_from_userid (userid, &fname, &addrspec); + if (err) + goto leave; + + if (access (fname, R_OK)) + { + err = gpg_error_from_syserror (); + if (opt_with_file) + es_printf ("%s n %s\n", addrspec, fname); + if (gpg_err_code (err) == GPG_ERR_ENOENT) + { + if (!opt.quiet) + log_info ("key for '%s' is NOT installed\n", addrspec); + log_inc_errorcount (); + err = 0; + } + else + log_error ("error stating '%s': %s\n", fname, gpg_strerror (err)); + goto leave; + } + + if (opt_with_file) + es_printf ("%s i %s\n", addrspec, fname); + + if (opt.verbose) + log_info ("key for '%s' is installed\n", addrspec); + err = 0; + + leave: + xfree (fname); + xfree (addrspec); + return err; +} + + +/* Remove the key with mail address in USERID. */ +static gpg_error_t +command_remove_key (const char *userid) +{ + gpg_error_t err; + char *addrspec = NULL; + char *fname = NULL; + + err = fname_from_userid (userid, &fname, &addrspec); + if (err) + goto leave; + + if (gnupg_remove (fname)) + { + err = gpg_error_from_syserror (); + if (gpg_err_code (err) == GPG_ERR_ENOENT) + { + if (!opt.quiet) + log_info ("key for '%s' is not installed\n", addrspec); + log_inc_errorcount (); + err = 0; + } + else + log_error ("error removing '%s': %s\n", fname, gpg_strerror (err)); + goto leave; + } + + if (opt.verbose) + log_info ("key for '%s' removed\n", addrspec); + err = 0; + + leave: + xfree (fname); + xfree (addrspec); + return err; } @@ -1913,6 +2081,7 @@ command_remove_key (const char *mailaddr) static gpg_error_t command_revoke_key (const char *mailaddr) { - (void)mailaddr; - return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + /* Remove should be different from removing but we have not yet + * defined a suitable way to do this. */ + return command_remove_key (mailaddr); } diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index c799143cd..099f43952 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -48,6 +48,7 @@ #include "../common/i18n.h" #include "../common/exechelp.h" #include "../common/sysutils.h" +#include "../common/status.h" #include "../common/gc-opt-flags.h" #include "gpgconf.h" @@ -99,7 +100,7 @@ gc_error (int status, int errnum, const char *fmt, ...) { log_printf (NULL); log_printf ("fatal error (exit status %i)\n", status); - exit (status); + gpgconf_failure (gpg_error_from_errno (errnum)); } } @@ -1310,7 +1311,7 @@ gc_component_launch (int component) { es_fputs (_("Component not suitable for launching"), es_stderr); es_putc ('\n', es_stderr); - exit (1); + gpgconf_failure (0); } pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT); @@ -3757,6 +3758,10 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults, { gc_error (0, 0, "missing rule at '%s', line %d", fname, lineno); result = -1; + gpgconf_write_status (STATUS_WARNING, + "gpgconf.conf %d file '%s' line %d " + "missing rule", + GPG_ERR_SYNTAX, fname, lineno); continue; } *p++ = 0; @@ -3786,6 +3791,10 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults, { gc_error (0, 0, "missing component at '%s', line %d", fname, lineno); + gpgconf_write_status (STATUS_WARNING, + "gpgconf.conf %d file '%s' line %d " + " missing component", + GPG_ERR_NO_NAME, fname, lineno); result = -1; continue; } @@ -3797,6 +3806,10 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults, { gc_error (0, 0, "unknown component at '%s', line %d", fname, lineno); + gpgconf_write_status (STATUS_WARNING, + "gpgconf.conf %d file '%s' line %d " + "unknown component", + GPG_ERR_UNKNOWN_NAME, fname, lineno); result = -1; } @@ -3809,6 +3822,10 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults, { gc_error (0, 0, "missing option at '%s', line %d", fname, lineno); + gpgconf_write_status (STATUS_WARNING, + "gpgconf.conf %d file '%s' line %d " + "missing option", + GPG_ERR_INV_NAME, fname, lineno); result = -1; continue; } @@ -3821,6 +3838,10 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults, { gc_error (0, 0, "unknown option at '%s', line %d", fname, lineno); + gpgconf_write_status (STATUS_WARNING, + "gpgconf.conf %d file '%s' line %d " + "unknown option", + GPG_ERR_UNKNOWN_OPTION, fname, lineno); result = -1; } } @@ -3837,6 +3858,10 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults, { gc_error (0, 0, "syntax error in rule at '%s', line %d", fname, lineno); + gpgconf_write_status (STATUS_WARNING, + "gpgconf.conf %d file '%s' line %d " + "syntax error in rule", + GPG_ERR_SYNTAX, fname, lineno); result = -1; continue; } diff --git a/tools/gpgconf.c b/tools/gpgconf.c index 09b2a76e9..59085d8b5 100644 --- a/tools/gpgconf.c +++ b/tools/gpgconf.c @@ -29,6 +29,7 @@ #include "../common/i18n.h" #include "../common/sysutils.h" #include "../common/init.h" +#include "../common/status.h" /* Constants to identify the commands and options. */ @@ -45,6 +46,7 @@ enum cmd_and_opt_values oNoVerbose = 500, oHomedir, oBuilddir, + oStatusFD, aListComponents, aCheckPrograms, @@ -100,6 +102,7 @@ static ARGPARSE_OPTS opts[] = { oQuiet, "quiet", 0, N_("quiet") }, { oDryRun, "dry-run", 0, N_("do not make any changes") }, { oRuntime, "runtime", 0, N_("activate changes at runtime, if possible") }, + ARGPARSE_s_i (oStatusFD, "status-fd", N_("|FD|write status info to this FD")), /* hidden options */ { oHomedir, "homedir", 2, "@" }, { oBuilddir, "build-prefix", 2, "@" }, @@ -110,6 +113,11 @@ static ARGPARSE_OPTS opts[] = }; +/* The stream to output the status information. Status Output is disabled if + * this is NULL. */ +static estream_t statusfp; + + /* Print usage information and provide strings for help. */ static const char * my_strusage( int level ) @@ -159,6 +167,60 @@ get_outfp (estream_t *fp) } +/* Set the status FD. */ +static void +set_status_fd (int fd) +{ + static int last_fd = -1; + + if (fd != -1 && last_fd == fd) + return; + + if (statusfp && statusfp != es_stdout && statusfp != es_stderr) + es_fclose (statusfp); + statusfp = NULL; + if (fd == -1) + return; + + if (fd == 1) + statusfp = es_stdout; + else if (fd == 2) + statusfp = es_stderr; + else + statusfp = es_fdopen (fd, "w"); + if (!statusfp) + { + log_fatal ("can't open fd %d for status output: %s\n", + fd, gpg_strerror (gpg_error_from_syserror ())); + } + last_fd = fd; +} + + +/* 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 +gpgconf_write_status (int no, const char *format, ...) +{ + va_list arg_ptr; + + if (!statusfp) + return; /* Not enabled. */ + + es_fputs ("[GNUPG:] ", statusfp); + es_fputs (get_status_string (no), statusfp); + if (format) + { + es_putc (' ', statusfp); + va_start (arg_ptr, format); + es_vfprintf (statusfp, format, arg_ptr); + va_end (arg_ptr); + } + es_putc ('\n', statusfp); +} + + static void list_dirs (estream_t fp, char **names) { @@ -493,6 +555,9 @@ main (int argc, char **argv) case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break; case oBuilddir: gnupg_set_builddir (pargs.r.ret_str); break; case oNull: opt.null = 1; break; + case oStatusFD: + set_status_fd (translate_sys2libc_fd_int (pargs.r.ret_int, 1)); + break; case aListDirs: case aListComponents: @@ -518,7 +583,7 @@ main (int argc, char **argv) } if (log_get_errorcount (0)) - exit (2); + gpgconf_failure (GPG_ERR_USER_2); /* Print a warning if an argument looks like an option. */ if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN)) @@ -554,7 +619,7 @@ main (int argc, char **argv) es_putc ('\n', es_stderr); es_fputs (_("Need one component argument"), es_stderr); es_putc ('\n', es_stderr); - exit (2); + gpgconf_failure (GPG_ERR_USER_2); } else { @@ -563,7 +628,7 @@ main (int argc, char **argv) { es_fputs (_("Component not found"), es_stderr); es_putc ('\n', es_stderr); - exit (1); + gpgconf_failure (0); } if (cmd == aCheckOptions) gc_component_check_options (idx, get_outfp (&outfp), NULL); @@ -571,7 +636,7 @@ main (int argc, char **argv) { gc_component_retrieve_options (idx); if (gc_process_gpgconf_conf (NULL, 1, 0, NULL)) - exit (1); + gpgconf_failure (0); if (cmd == aListOptions) gc_component_list_options (idx, get_outfp (&outfp)); else if (cmd == aChangeOptions) @@ -589,14 +654,14 @@ main (int argc, char **argv) es_putc ('\n', es_stderr); es_fputs (_("Need one component argument"), es_stderr); es_putc ('\n', es_stderr); - exit (2); + gpgconf_failure (GPG_ERR_USER_2); } else if (!strcmp (fname, "all")) { if (cmd == aLaunch) { if (gc_component_launch (-1)) - exit (1); + gpgconf_failure (0); } else { @@ -613,12 +678,12 @@ main (int argc, char **argv) { es_fputs (_("Component not found"), es_stderr); es_putc ('\n', es_stderr); - exit (1); + gpgconf_failure (0); } else if (cmd == aLaunch) { if (gc_component_launch (idx)) - exit (1); + gpgconf_failure (0); } else { @@ -646,7 +711,7 @@ main (int argc, char **argv) { es_fputs (_("Component not found"), es_stderr); es_putc ('\n', es_stderr); - exit (1); + gpgconf_failure (0); } else { @@ -657,12 +722,12 @@ main (int argc, char **argv) case aListConfig: if (gc_process_gpgconf_conf (fname, 0, 0, get_outfp (&outfp))) - exit (1); + gpgconf_failure (0); break; case aCheckConfig: if (gc_process_gpgconf_conf (fname, 0, 0, NULL)) - exit (1); + gpgconf_failure (0); break; case aApplyDefaults: @@ -672,17 +737,17 @@ main (int argc, char **argv) es_putc ('\n', es_stderr); es_fputs (_("No argument allowed"), es_stderr); es_putc ('\n', es_stderr); - exit (2); + gpgconf_failure (GPG_ERR_USER_2); } gc_component_retrieve_options (-1); if (gc_process_gpgconf_conf (NULL, 1, 1, NULL)) - exit (1); + gpgconf_failure (0); break; case aApplyProfile: gc_component_retrieve_options (-1); if (gc_apply_profile (fname)) - exit (1); + gpgconf_failure (0); break; case aListDirs: @@ -697,7 +762,7 @@ main (int argc, char **argv) { es_fprintf (es_stderr, "usage: %s --query-swdb NAME [VERSION]\n", GPGCONF_NAME); - exit (2); + gpgconf_failure (GPG_ERR_USER_2); } get_outfp (&outfp); query_swdb (outfp, fname, argc > 1? argv[1] : NULL); @@ -804,5 +869,22 @@ main (int argc, char **argv) if (es_fclose (outfp)) gc_error (1, errno, "error closing '%s'", opt.outfile); + + if (log_get_errorcount (0)) + gpgconf_failure (0); + else + gpgconf_write_status (STATUS_SUCCESS, NULL); return 0; } + + +void +gpgconf_failure (gpg_error_t err) +{ + if (!err) + err = gpg_error (GPG_ERR_GENERAL); + gpgconf_write_status + (STATUS_FAILURE, "- %u", + gpg_err_code (err) == GPG_ERR_USER_2? GPG_ERR_EINVAL : err); + exit (gpg_err_code (err) == GPG_ERR_USER_2? 2 : 1); +} diff --git a/tools/gpgconf.h b/tools/gpgconf.h index d6d7627aa..8a061ef68 100644 --- a/tools/gpgconf.h +++ b/tools/gpgconf.h @@ -36,6 +36,10 @@ struct } opt; +/*-- gpgconf.c --*/ +void gpgconf_write_status (int no, const char *format, + ...) GPGRT_ATTR_PRINTF(2,3); +void gpgconf_failure (gpg_error_t err) GPGRT_ATTR_NORETURN; /*-- gpgconf-comp.c --*/ |