card: Allow card selection with LIST.

* tools/card-call-scd.c (start_agent): Request serialno only whean
started.
(scd_serialno): Allow NULL for r_serialno.
* tools/gpg-card.c (cmd_factoryreset): Use changed scd_serialno.
(cmd_list): New.
(dispatch_command): Use cmd_list for cmdLIST.
(interactive_loop): Ditto.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2019-04-03 10:27:08 +02:00
parent 2d3392c147
commit bcca3acb87
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 90 additions and 37 deletions

View File

@ -310,11 +310,13 @@ static gpg_error_t
start_agent (unsigned int flags) start_agent (unsigned int flags)
{ {
gpg_error_t err; gpg_error_t err;
int started = 0;
if (agent_ctx) if (agent_ctx)
err = 0; err = 0;
else else
{ {
started = 1;
err = start_new_gpg_agent (&agent_ctx, err = start_new_gpg_agent (&agent_ctx,
GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_DEFAULT,
opt.agent_program, 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. */ /* Request the serial number of the card for an early test. */
struct card_info_s info; 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 /* Call the scdaemon to learn about a smartcard. This fills INFO
* wioth data from the card. */ * with data from the card. */
gpg_error_t gpg_error_t
scd_learn (card_info_t info) 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 /* Return the serial number of the card or an appropriate error. The
* serial number is returned as a hexstring. If DEMAND is not NULL * 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. */ * requested. */
gpg_error_t gpg_error_t
scd_serialno (char **r_serialno, const char *demand) scd_serialno (char **r_serialno, const char *demand)
@ -1295,7 +1297,10 @@ scd_serialno (char **r_serialno, const char *demand)
return err; return err;
} }
*r_serialno = serialno; if (r_serialno)
*r_serialno = serialno;
else
xfree (serialno);
return 0; return 0;
} }

View File

@ -999,6 +999,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. */ /* The VERIFY command. */
static gpg_error_t static gpg_error_t
@ -2478,9 +2553,8 @@ cmd_factoryreset (card_info_t info)
if (err) if (err)
goto leave; goto leave;
/* Then, connect the card again (answer used as a dummy). */ /* Then, connect the card again. */
xfree (answer); answer = NULL; err = scd_serialno (NULL, NULL);
err = scd_serialno (&answer, NULL);
leave: leave:
if (err && any_apdu && !is_yubikey) if (err && any_apdu && !is_yubikey)
@ -3158,20 +3232,6 @@ dispatch_command (card_info_t info, const char *orig_command)
} }
break; 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: case cmdRESET:
if (!info) if (!info)
print_help ("RESET\n\n" print_help ("RESET\n\n"
@ -3183,6 +3243,7 @@ dispatch_command (card_info_t info, const char *orig_command)
} }
break; break;
case cmdLIST: err = cmd_list (info, argstr); break;
case cmdVERIFY: err = cmd_verify (info, argstr); break; case cmdVERIFY: err = cmd_verify (info, argstr); break;
case cmdAUTH: err = cmd_authenticate (info, argstr); break; case cmdAUTH: err = cmd_authenticate (info, argstr); break;
case cmdNAME: err = cmd_name (info, argstr); break; case cmdNAME: err = cmd_name (info, argstr); break;
@ -3268,14 +3329,11 @@ interactive_loop (void)
} }
else if (redisplay) else if (redisplay)
{ {
err = scd_learn (info); err = cmd_list (info, "");
if (err) if (err)
{ log_error ("Error reading card: %s\n", gpg_strerror (err));
log_error ("Error reading card: %s\n", gpg_strerror (err));
}
else else
{ {
list_card (info);
tty_printf("\n"); tty_printf("\n");
redisplay = 0; redisplay = 0;
} }
@ -3388,17 +3446,6 @@ interactive_loop (void)
} }
break; 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: case cmdRESET:
if (!info) if (!info)
print_help ("RESET\n\n" print_help ("RESET\n\n"
@ -3410,6 +3457,7 @@ interactive_loop (void)
} }
break; break;
case cmdLIST: err = cmd_list (info, argstr); break;
case cmdVERIFY: case cmdVERIFY:
err = cmd_verify (info, argstr); err = cmd_verify (info, argstr);
if (!err) if (!err)