mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
scd: Support PC/SC for "getinfo reader_list".
* scd/apdu.c: Include membuf.h. (pcsc): Add reader_list field. (open_pcsc_reader): Fill that field. (apdu_get_reader_list): New. * scd/command.c: Remove header ccid-driver.h. (pretty_assuan_send_data): New. (cmd_getinfo): Print all reader names. -- Note that depending on the card backend (ccid or PC/SC) it might be necessary to first send a reset followed by SERIALNO to get an updated list of reader. Or well send KILLSCD. The pretty printing of Assuan data lines does only work if you connect direct to scdaemon because the wrapper in gpg-agent does not know about this and combines the Assuan lines again. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
192113552f
commit
f32994b0bf
45
scd/apdu.c
45
scd/apdu.c
@ -60,6 +60,7 @@
|
||||
#include "../common/exechelp.h"
|
||||
#endif /* GNUPG_MAJOR_VERSION != 1 */
|
||||
#include "../common/host2net.h"
|
||||
#include "../common/membuf.h"
|
||||
|
||||
#include "iso7816.h"
|
||||
#include "apdu.h"
|
||||
@ -92,6 +93,7 @@ typedef unsigned long pcsc_dword_t;
|
||||
static struct pcsc {
|
||||
int count; /* Reference count - valid if .context != -1 */
|
||||
long context;
|
||||
char *reader_list; /* List of detected readers. */
|
||||
} pcsc;
|
||||
|
||||
/* A structure to collect information pertaining to one reader
|
||||
@ -1204,6 +1206,10 @@ open_pcsc_reader (const char *portstr)
|
||||
pcsc_dword_t nreader;
|
||||
char *p;
|
||||
size_t n;
|
||||
membuf_t reader_mb;
|
||||
|
||||
xfree (pcsc.reader_list);
|
||||
pcsc.reader_list = NULL;
|
||||
|
||||
if (pcsc.context == -1)
|
||||
if (pcsc_init () < 0)
|
||||
@ -1212,6 +1218,7 @@ open_pcsc_reader (const char *portstr)
|
||||
if (DBG_READER)
|
||||
log_debug ("open_pcsc_reader(portstr=%s)\n", portstr);
|
||||
|
||||
|
||||
slot = new_reader_slot ();
|
||||
if (slot == -1)
|
||||
return -1; /* No need to cleanup here. */
|
||||
@ -1243,6 +1250,8 @@ open_pcsc_reader (const char *portstr)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
init_membuf (&reader_mb, 256);
|
||||
|
||||
p = list;
|
||||
while (nreader > 0)
|
||||
{
|
||||
@ -1260,11 +1269,17 @@ open_pcsc_reader (const char *portstr)
|
||||
}
|
||||
|
||||
log_info ("detected reader '%s'\n", p);
|
||||
put_membuf_str (&reader_mb, p);
|
||||
put_membuf (&reader_mb, "\n", 1);
|
||||
if (!rdrname && portstr && !strncmp (p, portstr, strlen (portstr)))
|
||||
rdrname = p;
|
||||
nreader -= n + 1;
|
||||
p += n + 1;
|
||||
}
|
||||
put_membuf (&reader_mb, "", 1);
|
||||
pcsc.reader_list = get_membuf (&reader_mb, NULL);
|
||||
if (!pcsc.reader_list)
|
||||
log_error ("error allocating memory for reader list\n");
|
||||
|
||||
if (!rdrname)
|
||||
rdrname = list;
|
||||
@ -3353,6 +3368,35 @@ apdu_get_reader_name (int slot)
|
||||
return reader_table[slot].rdrname;
|
||||
}
|
||||
|
||||
|
||||
/* Return the list of currently known readers. Caller must free the
|
||||
* returned value. Might return NULL. */
|
||||
char *
|
||||
apdu_get_reader_list (void)
|
||||
{
|
||||
membuf_t mb;
|
||||
char *ccidlist = NULL;
|
||||
|
||||
init_membuf (&mb, 256);
|
||||
#ifdef HAVE_LIBUSB
|
||||
ccidlist = ccid_get_reader_list ();
|
||||
#endif
|
||||
|
||||
if (ccidlist && *ccidlist)
|
||||
put_membuf_str (&mb, ccidlist);
|
||||
if (pcsc.reader_list && *pcsc.reader_list)
|
||||
{
|
||||
if (ccidlist && *ccidlist)
|
||||
put_membuf (&mb, "\n", 1);
|
||||
put_membuf_str (&mb, pcsc.reader_list);
|
||||
}
|
||||
xfree (ccidlist);
|
||||
put_membuf (&mb, "", 1);
|
||||
|
||||
return get_membuf (&mb, NULL);
|
||||
}
|
||||
|
||||
|
||||
gpg_error_t
|
||||
apdu_init (void)
|
||||
{
|
||||
@ -3362,6 +3406,7 @@ apdu_init (void)
|
||||
|
||||
pcsc.count = 0;
|
||||
pcsc.context = -1;
|
||||
pcsc.reader_list = NULL;
|
||||
|
||||
if (npth_mutex_init (&reader_table_lock, NULL))
|
||||
goto leave;
|
||||
|
@ -151,5 +151,6 @@ int apdu_send_direct (int slot, size_t extended_length,
|
||||
int handle_more, unsigned int *r_sw,
|
||||
unsigned char **retbuf, size_t *retbuflen);
|
||||
const char *apdu_get_reader_name (int slot);
|
||||
char *apdu_get_reader_list (void);
|
||||
|
||||
#endif /*APDU_H*/
|
||||
|
@ -36,9 +36,6 @@
|
||||
#include "iso7816.h"
|
||||
#include "apdu.h" /* Required for apdu_*_reader (). */
|
||||
#include "atr.h"
|
||||
#ifdef HAVE_LIBUSB
|
||||
#include "ccid-driver.h"
|
||||
#endif
|
||||
#include "../common/asshelp.h"
|
||||
#include "../common/server-help.h"
|
||||
|
||||
@ -1401,6 +1398,45 @@ cmd_unlock (assuan_context_t ctx, char *line)
|
||||
}
|
||||
|
||||
|
||||
/* Ease reading of Assuan data ;ines by sending a physical line after
|
||||
* each LF. */
|
||||
static gpg_error_t
|
||||
pretty_assuan_send_data (assuan_context_t ctx,
|
||||
const void *buffer_arg, size_t size)
|
||||
{
|
||||
const char *buffer = buffer_arg;
|
||||
const char *p;
|
||||
size_t n, nbytes;
|
||||
gpg_error_t err;
|
||||
|
||||
nbytes = size;
|
||||
do
|
||||
{
|
||||
p = memchr (buffer, '\n', nbytes);
|
||||
n = p ? (p - buffer) + 1 : nbytes;
|
||||
err = assuan_send_data (ctx, buffer, n);
|
||||
if (err)
|
||||
{
|
||||
/* We also set ERRNO in case this function is used by a
|
||||
* custom estream I/O handler. */
|
||||
gpg_err_set_errno (EIO);
|
||||
goto leave;
|
||||
}
|
||||
buffer += n;
|
||||
nbytes -= n;
|
||||
if (nbytes && (err=assuan_send_data (ctx, NULL, 0))) /* Flush line. */
|
||||
{
|
||||
gpg_err_set_errno (EIO);
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
while (nbytes);
|
||||
|
||||
leave:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static const char hlp_getinfo[] =
|
||||
"GETINFO <what>\n"
|
||||
"\n"
|
||||
@ -1418,8 +1454,7 @@ static const char hlp_getinfo[] =
|
||||
" 'u' Usable card present.\n"
|
||||
" 'r' Card removed. A reset is necessary.\n"
|
||||
" These flags are exclusive.\n"
|
||||
" reader_list - Return a list of detected card readers. Does\n"
|
||||
" currently only work with the internal CCID driver.\n"
|
||||
" reader_list - Return a list of detected card readers.\n"
|
||||
" deny_admin - Returns OK if admin commands are not allowed or\n"
|
||||
" GPG_ERR_GENERAL if admin commands are allowed.\n"
|
||||
" app_list - Return a list of supported applications. One\n"
|
||||
@ -1474,14 +1509,9 @@ cmd_getinfo (assuan_context_t ctx, char *line)
|
||||
}
|
||||
else if (!strcmp (line, "reader_list"))
|
||||
{
|
||||
#ifdef HAVE_LIBUSB
|
||||
char *s = ccid_get_reader_list ();
|
||||
#else
|
||||
char *s = NULL;
|
||||
#endif
|
||||
|
||||
char *s = apdu_get_reader_list ();
|
||||
if (s)
|
||||
rc = assuan_send_data (ctx, s, strlen (s));
|
||||
rc = pretty_assuan_send_data (ctx, s, strlen (s));
|
||||
else
|
||||
rc = gpg_error (GPG_ERR_NO_DATA);
|
||||
xfree (s);
|
||||
|
Loading…
x
Reference in New Issue
Block a user