diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/card-call-scd.c | 13 | ||||
-rw-r--r-- | tools/card-yubikey.c | 10 | ||||
-rw-r--r-- | tools/ccidmon.c | 47 | ||||
-rw-r--r-- | tools/gpg-card.c | 299 | ||||
-rw-r--r-- | tools/gpg-card.h | 3 | ||||
-rw-r--r-- | tools/gpg-pair-tool.c | 2 | ||||
-rw-r--r-- | tools/gpg-wks-client.c | 100 | ||||
-rw-r--r-- | tools/gpg-wks-server.c | 2 | ||||
-rw-r--r-- | tools/gpg-wks.h | 4 | ||||
-rw-r--r-- | tools/gpgconf-comp.c | 51 | ||||
-rw-r--r-- | tools/gpgconf.c | 1 | ||||
-rw-r--r-- | tools/rfc822parse.c | 28 | ||||
-rw-r--r-- | tools/wks-receive.c | 2 | ||||
-rw-r--r-- | tools/wks-util.c | 72 |
14 files changed, 456 insertions, 178 deletions
diff --git a/tools/card-call-scd.c b/tools/card-call-scd.c index 0a01bf5ca..c2580bf5c 100644 --- a/tools/card-call-scd.c +++ b/tools/card-call-scd.c @@ -310,11 +310,13 @@ static gpg_error_t start_agent (unsigned int flags) { gpg_error_t err; + int started = 0; if (agent_ctx) err = 0; else { + started = 1; err = start_new_gpg_agent (&agent_ctx, GPG_ERR_SOURCE_DEFAULT, opt.agent_program, @@ -347,7 +349,7 @@ start_agent (unsigned int flags) } } - if (!err && !(flags & START_AGENT_NO_STARTUP_CMDS)) + if (started && !err && !(flags & START_AGENT_NO_STARTUP_CMDS)) { /* Request the serial number of the card for an early test. */ struct card_info_s info; @@ -990,7 +992,7 @@ learn_status_cb (void *opaque, const char *line) /* Call the scdaemon to learn about a smartcard. This fills INFO - * wioth data from the card. */ + * with data from the card. */ gpg_error_t scd_learn (card_info_t info) { @@ -1268,7 +1270,7 @@ scd_genkey (const char *keyref, int force, const char *algo, u32 *createtime) /* Return the serial number of the card or an appropriate error. The * serial number is returned as a hexstring. If DEMAND is not NULL - * the reader with the a card of the serilanumber DEMAND is + * the reader with the a card of the serial number DEMAND is * requested. */ gpg_error_t scd_serialno (char **r_serialno, const char *demand) @@ -1295,7 +1297,10 @@ scd_serialno (char **r_serialno, const char *demand) return err; } - *r_serialno = serialno; + if (r_serialno) + *r_serialno = serialno; + else + xfree (serialno); return 0; } diff --git a/tools/card-yubikey.c b/tools/card-yubikey.c index f9d130988..fff669cc0 100644 --- a/tools/card-yubikey.c +++ b/tools/card-yubikey.c @@ -310,7 +310,7 @@ yk_enable_disable (struct ykapps_s *yk, struct iface_s *iface, * stream to output information. This function must only be called on * Yubikeys. */ gpg_error_t -yubikey_commands (estream_t fp, int argc, char *argv[]) +yubikey_commands (card_info_t info, estream_t fp, int argc, char *argv[]) { gpg_error_t err; enum {ykLIST, ykENABLE, ykDISABLE } cmd; @@ -336,6 +336,14 @@ yubikey_commands (estream_t fp, int argc, char *argv[]) goto leave; } + if (info->cardversion < 0x050000 && cmd != ykLIST) + { + log_info ("Sub-command '%s' is only support by Yubikey-5 and later\n", + argv[0]); + err = gpg_error (GPG_ERR_NOT_SUPPORTED); + goto leave; + } + /* Parse interface if needed. */ if (cmd == ykLIST) iface.usb = iface.nfc = 1; diff --git a/tools/ccidmon.c b/tools/ccidmon.c index d61bb3c64..4e99da54d 100644 --- a/tools/ccidmon.c +++ b/tools/ccidmon.c @@ -64,9 +64,10 @@ static int any_error; struct { int is_bi; + char timestamp[20]; char address[50]; int count; - char data[2000]; + char data[16000]; } databuffer; @@ -576,7 +577,10 @@ flush_data (void) return; if (verbose) - printf ("Address: %s\n", databuffer.address); + { + printf ("Timestamp: %s\n", databuffer.timestamp); + printf ("Address..: %s\n", databuffer.address); + } if (databuffer.is_bi) { print_r2p (databuffer.data, databuffer.count); @@ -590,7 +594,8 @@ flush_data (void) } static void -collect_data (char *hexdata, const char *address, unsigned int lineno) +collect_data (char *hexdata, const char *timestamp, + const char *address, unsigned int lineno) { size_t length; int is_bi; @@ -602,6 +607,9 @@ collect_data (char *hexdata, const char *address, unsigned int lineno) if (databuffer.is_bi != is_bi || strcmp (databuffer.address, address)) flush_data (); databuffer.is_bi = is_bi; + if (strlen (timestamp) >= sizeof databuffer.timestamp) + die ("timestamp field too long"); + strcpy (databuffer.timestamp, timestamp); if (strlen (address) >= sizeof databuffer.address) die ("address field too long"); strcpy (databuffer.address, address); @@ -627,7 +635,7 @@ collect_data (char *hexdata, const char *address, unsigned int lineno) if (length >= sizeof (databuffer.data)) { - err ("too much data at line %u - can handle only up to % bytes", + err ("too much data at line %u - can handle only up to %zu bytes", lineno, sizeof (databuffer.data)); break; } @@ -641,43 +649,50 @@ static void parse_line (char *line, unsigned int lineno) { char *p; - char *event_type, *address, *data, *status, *datatag; + char *timestamp, *event_type, *address, *data, *status, *datatag; + + if (*line == '#' || !*line) + return; if (debug) printf ("line[%u] ='%s'\n", lineno, line); p = strtok (line, " "); if (!p) - die ("invalid line %d (no URB)"); - p = strtok (NULL, " "); - if (!p) - die ("invalid line %d (no timestamp)"); + die ("invalid line %d (no URB)", lineno); + timestamp = strtok (NULL, " "); + if (!timestamp) + die ("invalid line %d (no timestamp)", lineno); event_type = strtok (NULL, " "); if (!event_type) - die ("invalid line %d (no event type)"); + die ("invalid line %d (no event type)", lineno); address = strtok (NULL, " "); if (!address) - die ("invalid line %d (no address"); + die ("invalid line %d (no address", lineno); if (usb_bus || usb_dev) { int bus, dev; p = strchr (address, ':'); if (!p) - die ("invalid line %d (invalid address"); + die ("invalid line %d (invalid address", lineno); p++; bus = atoi (p); p = strchr (p, ':'); if (!p) - die ("invalid line %d (invalid address"); + die ("invalid line %d (invalid address", lineno); p++; dev = atoi (p); if ((usb_bus && usb_bus != bus) || (usb_dev && usb_dev != dev)) return; /* We don't want that one. */ } - if (*address != 'B' || (address[1] != 'o' && address[1] != 'i')) - return; /* We only want block in and block out. */ + if (*address == 'B' && (address[1] == 'o' || address[1] == 'i')) + ; /* We want block ind and out. */ + else if (*address == 'C' && (address[1] == 'o' || address[1] == 'i')) + ; /* We want control ind and out. */ + else + return; /* But nothing else. */ status = strtok (NULL, " "); if (!status) return; @@ -692,7 +707,7 @@ parse_line (char *line, unsigned int lineno) if (datatag && *datatag == '=') { data = strtok (NULL, ""); - collect_data (data?data:"", address, lineno); + collect_data (data?data:"", timestamp, address, lineno); } } diff --git a/tools/gpg-card.c b/tools/gpg-card.c index e2d728dab..ddc4d12bf 100644 --- a/tools/gpg-card.c +++ b/tools/gpg-card.c @@ -429,6 +429,24 @@ put_data_to_file (const char *fname, const void *buffer, size_t length) } +/* Return a malloced string with the number opf the menu PROMPT. + * Control-D is mapped to "Q". */ +static char * +get_selection (const char *prompt) +{ + char *answer; + + tty_printf ("\n"); + tty_printf ("%s", prompt); + tty_printf ("\n"); + answer = tty_get (_("Your selection? ")); + tty_kill_prompt (); + if (*answer == CONTROL_D) + strcpy (answer, "q"); + return answer; +} + + /* Simply prints TEXT to the output. Returns 0 as a convenience. * This is a separate fucntion so that it can be extended to run @@ -655,7 +673,7 @@ list_one_kinfo (key_info_t firstkinfo, key_info_t kinfo, if (!scd_readkey (kinfo->keyref, &s_pkey)) { - char *tmp = pubkey_algo_string (s_pkey); + char *tmp = pubkey_algo_string (s_pkey, NULL); tty_fprintf (fp, " algorithm ..: %s\n", tmp); xfree (tmp); gcry_sexp_release (s_pkey); @@ -982,6 +1000,81 @@ list_card (card_info_t info) +/* The LIST command. This also updates INFO. */ +static gpg_error_t +cmd_list (card_info_t info, char *argstr) +{ + gpg_error_t err; + int opt_cards; + strlist_t cards = NULL; + strlist_t sl; + estream_t fp = opt.interactive? NULL : es_stdout; + int cardno, count; + + + if (!info) + return print_help + ("LIST [--cards] [N]\n\n" + "Show the content of the current card or with N given the N-th card.\n" + "Option --cards lists available cards.", + 0); + + opt_cards = has_leading_option (argstr, "--cards"); + argstr = skip_options (argstr); + + + if (digitp (argstr)) + { + cardno = atoi (argstr); + while (digitp (argstr)) + argstr++; + while (spacep (argstr)) + argstr++; + } + else + cardno = -1; + + + if (opt_cards) + { + err = scd_cardlist (&cards); + if (err) + goto leave; + for (count = 0, sl = cards; sl; sl = sl->next, count++) + tty_fprintf (fp, "%d %s\n", count, sl->d); + } + else + { + if (cardno != -1) + { + err = scd_cardlist (&cards); + if (err) + goto leave; + for (count = 0, sl = cards; sl; sl = sl->next, count++) + if (count == cardno) + break; + if (!sl) + { + err = gpg_error (GPG_ERR_INV_INDEX); + goto leave; + } + err = scd_serialno (NULL, sl->d); + if (err) + goto leave; + } + + err = scd_learn (info); + if (!err) + list_card (info); + } + + leave: + free_strlist (cards); + return err; +} + + + /* The VERIFY command. */ static gpg_error_t cmd_verify (card_info_t info, char *argstr) @@ -2097,21 +2190,23 @@ cmd_generate (card_info_t info, char *argstr) -/* Sub-menu to change a PIN. */ +/* Change a PIN. */ static gpg_error_t cmd_passwd (card_info_t info, char *argstr) { - gpg_error_t err; + gpg_error_t err = 0; char *answer = NULL; - const char *pinref; + const char *pinref = NULL; + int reset_mode = 0; + int menu_used = 0; if (!info) return print_help ("PASSWD [PINREF]\n\n" - "Menu to change or unblock the PINs. Note that the\n" - "presented menu options depend on the type of card\n" - "and whether the admin mode is enabled. For OpenPGP\n" - "and PIV cards defaults for PINREF are available.", + "Change or unblock the PINs. Note that in interactive mode\n" + "and without a PINREF a menu is presented for certain cards;\n" + "in non-interactive and without a PINREF a default value is\n" + "used for these cards.", 0); if (opt.interactive || opt.verbose) @@ -2119,92 +2214,93 @@ cmd_passwd (card_info_t info, char *argstr) app_type_string (info->apptype), info->dispserialno? info->dispserialno : info->serialno); - if (!*argstr && info->apptype == APP_TYPE_OPENPGP) + if (*argstr) + pinref = argstr; + else if (opt.interactive && info->apptype == APP_TYPE_OPENPGP) { - /* For an OpenPGP card we present the well known menu if no - * argument is given. */ - for (;;) + menu_used = 1; + while (!pinref) { - tty_printf ("\n"); - tty_printf ("1 - change PIN\n" - "2 - unblock and set new PIN\n" - "3 - change Admin PIN\n" - "4 - set the Reset Code\n" - "Q - quit\n"); - tty_printf ("\n"); - - err = 0; xfree (answer); - answer = tty_get (_("Your selection? ")); - tty_kill_prompt (); - if (*answer == CONTROL_D) - break; /* Quit. */ + answer = get_selection ("1 - change the PIN\n" + "2 - unblock and set new a PIN\n" + "3 - change the Admin PIN\n" + "4 - set the Reset Code\n" + "Q - quit\n"); if (strlen (answer) != 1) continue; - if (*answer == 'q' || *answer == 'Q') - break; /* Quit. */ - - if (*answer == '1') - { - /* Change PIN (same as the direct thing in non-admin mode). */ - err = scd_change_pin ("OPENPGP.1", 0); - if (err) - log_error ("Error changing the PIN: %s\n", gpg_strerror (err)); - else - log_info ("PIN changed.\n"); - } + else if (*answer == 'q' || *answer == 'Q') + goto leave; + else if (*answer == '1') + pinref = "OPENPGP.1"; else if (*answer == '2') - { - /* Unblock PIN by setting a new PIN. */ - err = scd_change_pin ("OPENPGP.1", 1); - if (err) - log_error ("Error unblocking the PIN: %s\n", gpg_strerror(err)); - else - log_info ("PIN unblocked and new PIN set.\n"); - } + { pinref = "OPENPGP.1"; reset_mode = 1; } else if (*answer == '3') - { - /* Change Admin PIN. */ - err = scd_change_pin ("OPENPGP.3", 0); - if (err) - log_error ("Error changing the PIN: %s\n", gpg_strerror (err)); - else - log_info ("PIN changed.\n"); - } + pinref = "OPENPGP.3"; else if (*answer == '4') - { - /* Set a new Reset Code. */ - err = scd_change_pin ("OPENPGP.2", 1); - if (err) - log_error ("Error setting the Reset Code: %s\n", - gpg_strerror (err)); - else - log_info ("Reset Code set.\n"); - } - - } /*end for loop*/ + { pinref = "OPENPGP.2"; reset_mode = 1; } + } } - else + else if (info->apptype == APP_TYPE_OPENPGP) + pinref = "OPENPGP.1"; + else if (opt.interactive && info->apptype == APP_TYPE_PIV) { - if (*argstr) - pinref = argstr; - else if (info->apptype == APP_TYPE_PIV) - pinref = "PIV.80"; - else + menu_used = 1; + while (!pinref) { - /* Note that we do not have a default value for OpenPGP - * because we want to be mostly compatible to "gpg - * --card-edit" and show a menu in that case (above). */ - err = gpg_error (GPG_ERR_MISSING_VALUE); - goto leave; + xfree (answer); + answer = get_selection ("1 - change the PIN\n" + "2 - change the PUK\n" + "3 - change the Global PIN\n" + "Q - quit\n"); + if (strlen (answer) != 1) + ; + else if (*answer == 'q' || *answer == 'Q') + goto leave; + else if (*answer == '1') + pinref = "PIV.80"; + else if (*answer == '2') + pinref = "PIV.81"; + else if (*answer == '3') + pinref = "PIV.00"; } - err = scd_change_pin (pinref, 0); - if (err) - goto leave; + } + else if (info->apptype == APP_TYPE_PIV) + pinref = "PIV.80"; + else + { + err = gpg_error (GPG_ERR_MISSING_VALUE); + goto leave; + } - if (info->apptype == APP_TYPE_PIV - && !ascii_strcasecmp (pinref, "PIV.81")) + err = scd_change_pin (pinref, reset_mode); + if (err) + { + if (!opt.interactive && !menu_used && !opt.verbose) + ; + else if (!ascii_strcasecmp (pinref, "PIV.81")) + log_error ("Error changing the PUK.\n"); + else if (!ascii_strcasecmp (pinref, "OPENPGP.1") && reset_mode) + log_error ("Error unblocking the PIN.\n"); + else if (!ascii_strcasecmp (pinref, "OPENPGP.2") && reset_mode) + log_error ("Error setting the Reset Code.\n"); + else if (!ascii_strcasecmp (pinref, "OPENPGP.3")) + log_error ("Error changing the Admin PIN.\n"); + else + log_error ("Error changing the PIN.\n"); + } + else + { + if (!opt.interactive && !opt.verbose) + ; + else if (!ascii_strcasecmp (pinref, "PIV.81")) log_info ("PUK changed.\n"); + else if (!ascii_strcasecmp (pinref, "OPENPGP.1") && reset_mode) + log_info ("PIN unblocked and new PIN set.\n"); + else if (!ascii_strcasecmp (pinref, "OPENPGP.2") && reset_mode) + log_info ("Reset Code set.\n"); + else if (!ascii_strcasecmp (pinref, "OPENPGP.3")) + log_info ("Admin PIN changed.\n"); else log_info ("PIN changed.\n"); } @@ -2261,7 +2357,7 @@ cmd_unblock (card_info_t info) } else { - log_info ("Unblocking not yet supported for '%s'\n", + log_info ("Unblocking not supported for '%s'.\n", app_type_string (info->apptype)); err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); } @@ -2457,9 +2553,8 @@ cmd_factoryreset (card_info_t info) if (err) goto leave; - /* Then, connect the card again (answer used as a dummy). */ - xfree (answer); answer = NULL; - err = scd_serialno (&answer, NULL); + /* Then, connect the card again. */ + err = scd_serialno (NULL, NULL); leave: if (err && any_apdu && !is_yubikey) @@ -2988,7 +3083,7 @@ cmd_yubikey (card_info_t info, char *argstr) /* Note that we always do a learn to get a chance to the card back * into a usable state. */ - err = yubikey_commands (fp, nwords, words); + err = yubikey_commands (info, fp, nwords, words); err2 = scd_learn (info); if (err2) log_error ("Error re-reading card: %s\n", gpg_strerror (err)); @@ -3137,20 +3232,6 @@ dispatch_command (card_info_t info, const char *orig_command) } break; - case cmdLIST: - if (!info) - print_help ("LIST\n\n" - "Show content of the card.", 0); - else - { - err = scd_learn (info); - if (err) - log_error ("Error reading card: %s\n", gpg_strerror (err)); - else - list_card (info); - } - break; - case cmdRESET: if (!info) print_help ("RESET\n\n" @@ -3162,6 +3243,7 @@ dispatch_command (card_info_t info, const char *orig_command) } break; + case cmdLIST: err = cmd_list (info, argstr); break; case cmdVERIFY: err = cmd_verify (info, argstr); break; case cmdAUTH: err = cmd_authenticate (info, argstr); break; case cmdNAME: err = cmd_name (info, argstr); break; @@ -3247,14 +3329,11 @@ interactive_loop (void) } else if (redisplay) { - err = scd_learn (info); + err = cmd_list (info, ""); if (err) - { - log_error ("Error reading card: %s\n", gpg_strerror (err)); - } + log_error ("Error reading card: %s\n", gpg_strerror (err)); else { - list_card (info); tty_printf("\n"); redisplay = 0; } @@ -3367,17 +3446,6 @@ interactive_loop (void) } break; - case cmdLIST: - if (!info) - print_help ("LIST\n\n" - "Show content of the card.", 0); - else - { - /* Actual work is done by the redisplay code block. */ - redisplay = 1; - } - break; - case cmdRESET: if (!info) print_help ("RESET\n\n" @@ -3389,6 +3457,7 @@ interactive_loop (void) } break; + case cmdLIST: err = cmd_list (info, argstr); break; case cmdVERIFY: err = cmd_verify (info, argstr); if (!err) diff --git a/tools/gpg-card.h b/tools/gpg-card.h index 099ea5448..35db14d25 100644 --- a/tools/gpg-card.h +++ b/tools/gpg-card.h @@ -224,7 +224,8 @@ gpg_error_t scd_checkpin (const char *serialno); unsigned long agent_get_s2k_count (void); /*-- card-yubikey.c --*/ -gpg_error_t yubikey_commands (estream_t fp, int argc, char *argv[]); +gpg_error_t yubikey_commands (card_info_t info, + estream_t fp, int argc, char *argv[]); #endif /*GNUPG_GPG_CARD_H*/ diff --git a/tools/gpg-pair-tool.c b/tools/gpg-pair-tool.c index 347b29d24..9a781def1 100644 --- a/tools/gpg-pair-tool.c +++ b/tools/gpg-pair-tool.c @@ -976,7 +976,7 @@ read_message (unsigned char **r_msg, size_t *r_msglen, int *r_msgtype, static gpg_error_t display_sas (const unsigned char *hash, size_t hashlen, int wait) { - gpg_error_t err; + gpg_error_t err = 0; unsigned long sas = 0; char sasbuf[12]; diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c index 0f08737c4..861a1fc61 100644 --- a/tools/gpg-wks-client.c +++ b/tools/gpg-wks-client.c @@ -61,6 +61,8 @@ enum cmd_and_opt_values aRead, aInstallKey, aRemoveKey, + aPrintWKDHash, + aPrintWKDURL, oGpgProgram, oSend, @@ -90,6 +92,10 @@ static ARGPARSE_OPTS opts[] = { "install a key into a directory"), ARGPARSE_c (aRemoveKey, "remove-key", "remove a key from a directory"), + ARGPARSE_c (aPrintWKDHash, "print-wkd-hash", + "Print the WKD identifier for the given user ids"), + ARGPARSE_c (aPrintWKDURL, "print-wkd-url", + "Print the WKD URL for the given user id"), ARGPARSE_group (301, ("@\nOptions:\n ")), @@ -129,6 +135,8 @@ const char *fake_submission_addr; static void wrong_args (const char *text) GPGRT_ATTR_NORETURN; +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); static gpg_error_t command_check (char *userid); static gpg_error_t command_send (const char *fingerprint, const char *userid); @@ -230,6 +238,8 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts) case aCheck: case aInstallKey: case aRemoveKey: + case aPrintWKDHash: + case aPrintWKDURL: cmd = pargs->r_opt; break; @@ -246,7 +256,7 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts) int main (int argc, char **argv) { - gpg_error_t err; + gpg_error_t err, delayed_err; ARGPARSE_ARGS pargs; enum cmd_and_opt_values cmd; @@ -377,6 +387,39 @@ main (int argc, char **argv) err = wks_cmd_remove_key (*argv); break; + case aPrintWKDHash: + case aPrintWKDURL: + if (!argc) + { + if (cmd == aPrintWKDHash) + err = proc_userid_from_stdin (wks_cmd_print_wkd_hash, + "printing WKD hash"); + else + err = proc_userid_from_stdin (wks_cmd_print_wkd_url, + "printing WKD URL"); + } + else + { + for (err = delayed_err = 0; !err && argc; argc--, argv++) + { + if (cmd == aPrintWKDHash) + err = wks_cmd_print_wkd_hash (*argv); + else + err = wks_cmd_print_wkd_url (*argv); + if (gpg_err_code (err) == GPG_ERR_INV_USER_ID) + { + /* Diagnostic already printed. */ + delayed_err = err; + err = 0; + } + else if (err) + log_error ("printing hash failed: %s\n", gpg_strerror (err)); + } + if (!err) + err = delayed_err; + } + break; + default: usage (1); err = 0; @@ -390,10 +433,63 @@ main (int argc, char **argv) wks_write_status (STATUS_FAILURE, "- %u", GPG_ERR_GENERAL); else wks_write_status (STATUS_SUCCESS, NULL); - return log_get_errorcount (0)? 1:0; + return (err || log_get_errorcount (0))? 1:0; +} + + +/* Read user ids from stdin and call FUNC for each user id. TEXT is + * used for error messages. */ +static gpg_error_t +proc_userid_from_stdin (gpg_error_t (*func)(const char *), const char *text) +{ + gpg_error_t err = 0; + gpg_error_t delayed_err = 0; + char line[2048]; + size_t n = 0; + + /* If we are on a terminal disable buffering to get direct response. */ + if (gnupg_isatty (es_fileno (es_stdin)) + && gnupg_isatty (es_fileno (es_stdout))) + { + es_setvbuf (es_stdin, NULL, _IONBF, 0); + es_setvbuf (es_stdout, NULL, _IOLBF, 0); + } + + while (es_fgets (line, sizeof line - 1, es_stdin)) + { + n = strlen (line); + if (!n || line[n-1] != '\n') + { + err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG + : GPG_ERR_INCOMPLETE_LINE); + log_error ("error reading stdin: %s\n", gpg_strerror (err)); + break; + } + trim_spaces (line); + err = func (line); + if (gpg_err_code (err) == GPG_ERR_INV_USER_ID) + { + delayed_err = err; + err = 0; + } + else if (err) + log_error ("%s failed: %s\n", text, gpg_strerror (err)); + } + if (es_ferror (es_stdin)) + { + err = gpg_error_from_syserror (); + log_error ("error reading stdin: %s\n", gpg_strerror (err)); + goto leave; + } + + leave: + if (!err) + err = delayed_err; + return err; } + /* Add the user id UID to the key identified by FINGERPRINT. */ static gpg_error_t diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c index f83ef6528..2082fb87d 100644 --- a/tools/gpg-wks-server.c +++ b/tools/gpg-wks-server.c @@ -1939,7 +1939,7 @@ command_check_key (const char *userid) char *addrspec = NULL; char *fname = NULL; - err = wks_fname_from_userid (userid, &fname, &addrspec); + err = wks_fname_from_userid (userid, 0, &fname, &addrspec); if (err) goto leave; diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h index e36943090..9acd7c37f 100644 --- a/tools/gpg-wks.h +++ b/tools/gpg-wks.h @@ -98,11 +98,13 @@ gpg_error_t wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown); void wks_free_policy (policy_flags_t policy); -gpg_error_t wks_fname_from_userid (const char *userid, +gpg_error_t wks_fname_from_userid (const char *userid, int hash_only, char **r_fname, char **r_addrspec); gpg_error_t wks_compute_hu_fname (char **r_fname, const char *addrspec); gpg_error_t wks_cmd_install_key (const char *fname, const char *userid); gpg_error_t wks_cmd_remove_key (const char *userid); +gpg_error_t wks_cmd_print_wkd_hash (const char *userid); +gpg_error_t wks_cmd_print_wkd_url (const char *userid); /*-- wks-receive.c --*/ diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 2ae79d91d..628ca358f 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -653,6 +653,10 @@ static gc_option_t gc_options_scdaemon[] = { "card-timeout", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "|N|disconnect the card after N seconds of inactivity", GC_ARG_TYPE_UINT32, GC_BACKEND_SCDAEMON }, + { "application-priority", + GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, + "gnupg", "|LIST|Change the application priority to LIST", + GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, @@ -967,7 +971,7 @@ static gc_option_t gc_options_dirmngr[] = GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Options controlling the use of Tor") }, { "use-tor", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, - "dirmngr", "route all network traffic via TOR", + "dirmngr", "route all network traffic via Tor", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "Keyserver", @@ -1152,12 +1156,8 @@ gpg_agent_runtime_change (int killflag) pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT); if (!gnupg_default_homedir_p ()) { - abs_homedir = make_absfilename_try (gnupg_homedir (), NULL); - if (!abs_homedir) - err = gpg_error_from_syserror (); - argv[i++] = "--homedir"; - argv[i++] = abs_homedir; + argv[i++] = gnupg_homedir (); } argv[i++] = "--no-autostart"; argv[i++] = killflag? "KILLAGENT" : "RELOADAGENT"; @@ -1195,12 +1195,8 @@ scdaemon_runtime_change (int killflag) pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT); if (!gnupg_default_homedir_p ()) { - abs_homedir = make_absfilename_try (gnupg_homedir (), NULL); - if (!abs_homedir) - err = gpg_error_from_syserror (); - argv[i++] = "--homedir"; - argv[i++] = abs_homedir; + argv[i++] = gnupg_homedir (); } argv[i++] = "-s"; argv[i++] = "--no-autostart"; @@ -1239,12 +1235,8 @@ dirmngr_runtime_change (int killflag) argv[3] = NULL; else { - abs_homedir = make_absfilename_try (gnupg_homedir (), NULL); - if (!abs_homedir) - err = gpg_error_from_syserror (); - argv[3] = "--homedir"; - argv[4] = abs_homedir; + argv[4] = gnupg_homedir (); argv[5] = NULL; } @@ -1266,7 +1258,7 @@ gc_component_launch (int component) { gpg_error_t err; const char *pgmname; - const char *argv[3]; + const char *argv[5]; int i; pid_t pid; @@ -1281,13 +1273,27 @@ gc_component_launch (int component) if (!(component == GC_COMPONENT_GPG_AGENT || component == GC_COMPONENT_DIRMNGR)) { - es_fputs (_("Component not suitable for launching"), es_stderr); - es_putc ('\n', es_stderr); + log_error ("%s\n", _("Component not suitable for launching")); + gpgconf_failure (0); + } + + if (gc_component_check_options (component, NULL, NULL)) + { + log_error (_("Configuration file of component %s is broken\n"), + gc_component[component].name); + if (!opt.quiet) + log_info (_("Note: Use the command \"%s%s\" to get details.\n"), + "gpgconf --check-options ", gc_component[component].name); gpgconf_failure (0); } pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT); i = 0; + if (!gnupg_default_homedir_p ()) + { + argv[i++] = "--homedir"; + argv[i++] = gnupg_homedir (); + } if (component == GC_COMPONENT_DIRMNGR) argv[i++] = "--dirmngr"; argv[i++] = "NOP"; @@ -1337,7 +1343,7 @@ gc_component_kill (int component) } /* Do the restart for the selected backends. */ - for (backend = 0; backend < GC_BACKEND_NR; backend++) + for (backend = GC_BACKEND_NR-1; backend; backend--) { if (runtime[backend] && gc_backend[backend].runtime_change) (*gc_backend[backend].runtime_change) (1); @@ -1688,8 +1694,9 @@ collect_error_output (estream_t fp, const char *tag) } -/* Check the options of a single component. Returns 0 if everything - is OK. */ +/* Check the options of a single component. If CONF_FILE is NULL the + * standard config file is used. If OUT is not NULL the output is + * written to that stream. Returns 0 if everything is OK. */ int gc_component_check_options (int component, estream_t out, const char *conf_file) { diff --git a/tools/gpgconf.c b/tools/gpgconf.c index b67125b89..a0cd97f60 100644 --- a/tools/gpgconf.c +++ b/tools/gpgconf.c @@ -900,6 +900,7 @@ main (int argc, char **argv) void gpgconf_failure (gpg_error_t err) { + log_flush (); if (!err) err = gpg_error (GPG_ERR_GENERAL); gpgconf_write_status diff --git a/tools/rfc822parse.c b/tools/rfc822parse.c index f1e95bd34..ac6ecb17c 100644 --- a/tools/rfc822parse.c +++ b/tools/rfc822parse.c @@ -420,7 +420,12 @@ transition_to_body (rfc822parse_t msg) s = rfc822parse_query_parameter (ctx, "boundary", 0); if (s) { - assert (!msg->current_part->boundary); + if (msg->current_part->boundary) + { + errno = ENOENT; + return -1; + } + msg->current_part->boundary = malloc (strlen (s) + 1); if (msg->current_part->boundary) { @@ -437,7 +442,11 @@ transition_to_body (rfc822parse_t msg) return -1; } rc = do_callback (msg, RFC822PARSE_LEVEL_DOWN); - assert (!msg->current_part->down); + if (msg->current_part->down) + { + errno = ENOENT; + return -1; + } msg->current_part->down = part; msg->current_part = part; msg->in_preamble = 1; @@ -458,8 +467,12 @@ transition_to_header (rfc822parse_t msg) { part_t part; - assert (msg->current_part); - assert (!msg->current_part->right); + if (!(msg->current_part + && !msg->current_part->right)) + { + errno = ENOENT; + return -1; + } part = new_part (); if (!part) @@ -476,7 +489,12 @@ insert_header (rfc822parse_t msg, const unsigned char *line, size_t length) { HDR_LINE hdr; - assert (msg->current_part); + if (!msg->current_part) + { + errno = ENOENT; + return -1; + } + if (!length) { msg->in_body = 1; diff --git a/tools/wks-receive.c b/tools/wks-receive.c index e67da628d..e5d2ed4b2 100644 --- a/tools/wks-receive.c +++ b/tools/wks-receive.c @@ -96,7 +96,7 @@ decrypt_data (receive_ctx_t ctx) /* We limit the output to 64 KiB to avoid DoS using compression * tricks. A regular client will anyway only send a minimal key; * that is one w/o key signatures and attribute packets. */ - ccparray_put (&ccp, "--max-output=0xf0000"); /*FIXME: Change s/F/1/ */ + ccparray_put (&ccp, "--max-output=0x10000"); ccparray_put (&ccp, "--batch"); if (opt.verbose) ccparray_put (&ccp, "--verbose"); diff --git a/tools/wks-util.c b/tools/wks-util.c index 1459045ef..1c1ac8c0b 100644 --- a/tools/wks-util.c +++ b/tools/wks-util.c @@ -749,9 +749,12 @@ write_to_file (estream_t src, const char *fname) /* Return the filename and optionally the addrspec for USERID at - * R_FNAME and R_ADDRSPEC. R_ADDRSPEC might also be set on error. */ + * R_FNAME and R_ADDRSPEC. R_ADDRSPEC might also be set on error. If + * HASH_ONLY is set only the has is returned at R_FNAME and no file is + * created. */ gpg_error_t -wks_fname_from_userid (const char *userid, char **r_fname, char **r_addrspec) +wks_fname_from_userid (const char *userid, int hash_only, + char **r_fname, char **r_addrspec) { gpg_error_t err; char *addrspec = NULL; @@ -767,7 +770,7 @@ wks_fname_from_userid (const char *userid, char **r_fname, char **r_addrspec) addrspec = mailbox_from_userid (userid, 0); if (!addrspec) { - if (opt.verbose) + if (opt.verbose || hash_only) log_info ("\"%s\" is not a proper mail address\n", userid); err = gpg_error (GPG_ERR_INV_USER_ID); goto leave; @@ -788,11 +791,20 @@ wks_fname_from_userid (const char *userid, char **r_fname, char **r_addrspec) goto leave; } - *r_fname = make_filename_try (opt.directory, domain, "hu", hash, NULL); - if (!*r_fname) - err = gpg_error_from_syserror (); + if (hash_only) + { + *r_fname = hash; + hash = NULL; + err = 0; + } else - err = 0; + { + *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) @@ -1061,7 +1073,7 @@ wks_cmd_remove_key (const char *userid) char *addrspec = NULL; char *fname = NULL; - err = wks_fname_from_userid (userid, &fname, &addrspec); + err = wks_fname_from_userid (userid, 0, &fname, &addrspec); if (err) goto leave; @@ -1089,3 +1101,47 @@ wks_cmd_remove_key (const char *userid) xfree (addrspec); return err; } + + +/* Print the WKD hash for the user id to stdout. */ +gpg_error_t +wks_cmd_print_wkd_hash (const char *userid) +{ + gpg_error_t err; + char *addrspec, *fname; + + err = wks_fname_from_userid (userid, 1, &fname, &addrspec); + if (err) + return err; + + es_printf ("%s %s\n", fname, addrspec); + + xfree (fname); + xfree (addrspec); + return err; +} + + +/* Print the WKD URL for the user id to stdout. */ +gpg_error_t +wks_cmd_print_wkd_url (const char *userid) +{ + gpg_error_t err; + char *addrspec, *fname; + char *domain; + + err = wks_fname_from_userid (userid, 1, &fname, &addrspec); + if (err) + return err; + + domain = strchr (addrspec, '@'); + if (domain) + *domain++ = 0; + + es_printf ("https://openpgpkey.%s/.well-known/openpgpkey/%s/hu/%s?l=%s\n", + domain, domain, fname, addrspec); + + xfree (fname); + xfree (addrspec); + return err; +} |