aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/card-call-scd.c13
-rw-r--r--tools/card-yubikey.c10
-rw-r--r--tools/ccidmon.c47
-rw-r--r--tools/gpg-card.c299
-rw-r--r--tools/gpg-card.h3
-rw-r--r--tools/gpg-pair-tool.c2
-rw-r--r--tools/gpg-wks-client.c100
-rw-r--r--tools/gpg-wks-server.c2
-rw-r--r--tools/gpg-wks.h4
-rw-r--r--tools/gpgconf-comp.c51
-rw-r--r--tools/gpgconf.c1
-rw-r--r--tools/rfc822parse.c28
-rw-r--r--tools/wks-receive.c2
-rw-r--r--tools/wks-util.c72
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;
+}