mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
Add a way to get a listing of available CCID readers.
This commit is contained in:
parent
12cc96a176
commit
3bbc481935
@ -1,4 +1,4 @@
|
|||||||
/* sexputil.c - Utility fnctions for S-expressions.
|
/* sexputil.c - Utility functions for S-expressions.
|
||||||
* Copyright (C) 2005 Free Software Foundation, Inc.
|
* Copyright (C) 2005 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
|
@ -501,7 +501,7 @@ checking of some root certificate requirements.
|
|||||||
|
|
||||||
As a special feature a line @code{include-default} will include a global
|
As a special feature a line @code{include-default} will include a global
|
||||||
list of trusted certificates (e.g. @file{/etc/gnupg/trustlist.txt}).
|
list of trusted certificates (e.g. @file{/etc/gnupg/trustlist.txt}).
|
||||||
This global list is also used if the local list ios not available.
|
This global list is also used if the local list is not available.
|
||||||
|
|
||||||
|
|
||||||
@item sshcontrol
|
@item sshcontrol
|
||||||
|
@ -251,6 +251,13 @@ readers might need a string here; run the program in verbose mode to get
|
|||||||
a list of available readers. The default is then the first reader
|
a list of available readers. The default is then the first reader
|
||||||
found.
|
found.
|
||||||
|
|
||||||
|
To get a list of available CCID readers you may use this command:
|
||||||
|
@smallexample
|
||||||
|
echo scd getinfo reader_list | gpg-connect-agent --decode | awk '/^D/ @{print $2@}'
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@item --disable-keypad
|
@item --disable-keypad
|
||||||
@opindex disable-keypad
|
@opindex disable-keypad
|
||||||
Even if a card reader features a keypad, do not try to use it.
|
Even if a card reader features a keypad, do not try to use it.
|
||||||
|
@ -955,6 +955,16 @@ When using @option{-S} or @option{--exec}, @command{gpg-connect-agent}
|
|||||||
connects to the assuan server in extended mode to allow descriptor
|
connects to the assuan server in extended mode to allow descriptor
|
||||||
passing. This option makes it use the old mode.
|
passing. This option makes it use the old mode.
|
||||||
|
|
||||||
|
@item --hex
|
||||||
|
@opindex hex
|
||||||
|
Print data lines in a hex format and the ASCII representation of
|
||||||
|
non-control characters.
|
||||||
|
|
||||||
|
@item --decode
|
||||||
|
@opindex decode
|
||||||
|
Decode data lines. That is to remove percent escapes but make sure that
|
||||||
|
a new line always starts with a D and a space.
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@mansect control commands
|
@mansect control commands
|
||||||
@ -995,6 +1005,14 @@ input source for other commands.
|
|||||||
@item /recvfd
|
@item /recvfd
|
||||||
Not yet implemented.
|
Not yet implemented.
|
||||||
|
|
||||||
|
@item /hex
|
||||||
|
@itemx /nohex
|
||||||
|
Same as the command line option @option{--hex}.
|
||||||
|
|
||||||
|
@item /decode
|
||||||
|
@itemx /nodecode
|
||||||
|
Same as the command line option @option{--decode}.
|
||||||
|
|
||||||
@item /help
|
@item /help
|
||||||
Print a list of available control commands.
|
Print a list of available control commands.
|
||||||
|
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
2007-04-03 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* command.c (cmd_getinfo): New subcommand "reader_list".
|
||||||
|
* ccid-driver.c (scan_or_find_devices): Ignore EBUSY in scan mode
|
||||||
|
for special transports.
|
||||||
|
|
||||||
2007-03-07 Werner Koch <wk@g10code.com>
|
2007-03-07 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* app-dinsig.c: Include i18n.h.
|
* app-dinsig.c: Include i18n.h.
|
||||||
|
@ -989,7 +989,13 @@ scan_or_find_devices (int readerno, const char *readerid,
|
|||||||
char *rid, *p;
|
char *rid, *p;
|
||||||
|
|
||||||
fd = open (transports[i].name, O_RDWR);
|
fd = open (transports[i].name, O_RDWR);
|
||||||
if (fd == -1)
|
if (fd == -1 && scan_mode && errno == EBUSY)
|
||||||
|
{
|
||||||
|
/* Ignore this error in scan mode because it indicates that
|
||||||
|
the device exists but is already open (most likely by us)
|
||||||
|
and thus in general suitable as a reader. */
|
||||||
|
}
|
||||||
|
else if (fd == -1)
|
||||||
{
|
{
|
||||||
DEBUGOUT_2 ("failed to open `%s': %s\n",
|
DEBUGOUT_2 ("failed to open `%s': %s\n",
|
||||||
transports[i].name, strerror (errno));
|
transports[i].name, strerror (errno));
|
||||||
@ -999,7 +1005,8 @@ scan_or_find_devices (int readerno, const char *readerid,
|
|||||||
rid = malloc (strlen (transports[i].name) + 30 + 10);
|
rid = malloc (strlen (transports[i].name) + 30 + 10);
|
||||||
if (!rid)
|
if (!rid)
|
||||||
{
|
{
|
||||||
close (fd);
|
if (fd != -1)
|
||||||
|
close (fd);
|
||||||
free (rid_list);
|
free (rid_list);
|
||||||
return -1; /* Error. */
|
return -1; /* Error. */
|
||||||
}
|
}
|
||||||
@ -1010,7 +1017,8 @@ scan_or_find_devices (int readerno, const char *readerid,
|
|||||||
p = malloc ((rid_list? strlen (rid_list):0) + 1 + strlen (rid) + 1);
|
p = malloc ((rid_list? strlen (rid_list):0) + 1 + strlen (rid) + 1);
|
||||||
if (!p)
|
if (!p)
|
||||||
{
|
{
|
||||||
close (fd);
|
if (fd != -1)
|
||||||
|
close (fd);
|
||||||
free (rid_list);
|
free (rid_list);
|
||||||
free (rid);
|
free (rid);
|
||||||
return -1; /* Error. */
|
return -1; /* Error. */
|
||||||
@ -1046,7 +1054,8 @@ scan_or_find_devices (int readerno, const char *readerid,
|
|||||||
--readerno;
|
--readerno;
|
||||||
}
|
}
|
||||||
free (rid);
|
free (rid);
|
||||||
close (fd);
|
if (fd != -1)
|
||||||
|
close (fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scan_mode)
|
if (scan_mode)
|
||||||
|
@ -38,6 +38,9 @@
|
|||||||
#include "app-common.h"
|
#include "app-common.h"
|
||||||
#include "apdu.h" /* Required for apdu_*_reader (). */
|
#include "apdu.h" /* Required for apdu_*_reader (). */
|
||||||
#include "exechelp.h"
|
#include "exechelp.h"
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
#include "ccid-driver.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */
|
/* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */
|
||||||
#define MAXLEN_PIN 100
|
#define MAXLEN_PIN 100
|
||||||
@ -1382,12 +1385,16 @@ cmd_unlock (assuan_context_t ctx, char *line)
|
|||||||
Supported values of WHAT are:
|
Supported values of WHAT are:
|
||||||
|
|
||||||
socket_name - Return the name of the socket.
|
socket_name - Return the name of the socket.
|
||||||
|
|
||||||
status - Return the status of the current slot (in the future, may
|
status - Return the status of the current slot (in the future, may
|
||||||
also return the status of all slots). The status is a list of
|
also return the status of all slots). The status is a list of
|
||||||
one-character flags. The following flags are currently defined:
|
one-character flags. The following flags are currently defined:
|
||||||
'u' Usable card present. This is the normal state during operation.
|
'u' Usable card present. This is the normal state during operation.
|
||||||
'r' Card removed. A reset is necessary.
|
'r' Card removed. A reset is necessary.
|
||||||
These flags are exclusive.
|
These flags are exclusive.
|
||||||
|
|
||||||
|
reader_list - Return a list of detected card readers. Does
|
||||||
|
currently only work with the internal CCID driver.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1427,6 +1434,20 @@ cmd_getinfo (assuan_context_t ctx, char *line)
|
|||||||
}
|
}
|
||||||
rc = assuan_send_data (ctx, &flag, 1);
|
rc = assuan_send_data (ctx, &flag, 1);
|
||||||
}
|
}
|
||||||
|
else if (!strcmp (line, "reader_list"))
|
||||||
|
{
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
char *s = ccid_get_reader_list ();
|
||||||
|
#else
|
||||||
|
char *s = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (s)
|
||||||
|
rc = assuan_send_data (ctx, s, strlen (s));
|
||||||
|
else
|
||||||
|
rc = gpg_error (GPG_ERR_NO_DATA);
|
||||||
|
xfree (s);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
|
rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
as much memory as required.
|
as much memory as required.
|
||||||
(gpgsm_get_keygrip_hexstring): Use bin2hex.
|
(gpgsm_get_keygrip_hexstring): Use bin2hex.
|
||||||
|
|
||||||
* certchain.c (gpgsm_validate_chain): Keep terack of the
|
* certchain.c (gpgsm_validate_chain): Keep track of the
|
||||||
certificate chain and reset the ephemeral flags.
|
certificate chain and reset the ephemeral flags.
|
||||||
* keydb.c (keydb_set_cert_flags): New args EPHEMERAL MASK.
|
* keydb.c (keydb_set_cert_flags): New args EPHEMERAL and MASK.
|
||||||
Changed caller to use a mask of ~0. Return a proper error code if
|
Changed caller to use a mask of ~0. Return a proper error code if
|
||||||
the certificate is not available.
|
the certificate is not available.
|
||||||
|
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
2007-04-03 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* gpg-connect-agent.c (main): New option --decode and commands
|
||||||
|
decode and undecode.
|
||||||
|
(read_and_print_response): Implement option.
|
||||||
|
|
||||||
2007-03-20 Werner Koch <wk@g10code.com>
|
2007-03-20 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* gpgconf-comp.c (gc_options_gpgsm): Add p12-charset.
|
* gpgconf-comp.c (gc_options_gpgsm): Add p12-charset.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* gpg-connect-agent.c - Tool to connect to the agent.
|
/* gpg-connect-agent.c - Tool to connect to the agent.
|
||||||
* Copyright (C) 2005 Free Software Foundation, Inc.
|
* Copyright (C) 2005, 2007 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -46,6 +46,7 @@ enum cmd_and_opt_values
|
|||||||
oNoVerbose = 500,
|
oNoVerbose = 500,
|
||||||
oHomedir,
|
oHomedir,
|
||||||
oHex,
|
oHex,
|
||||||
|
oDecode,
|
||||||
oNoExtConnect
|
oNoExtConnect
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -59,6 +60,7 @@ static ARGPARSE_OPTS opts[] =
|
|||||||
{ oVerbose, "verbose", 0, N_("verbose") },
|
{ oVerbose, "verbose", 0, N_("verbose") },
|
||||||
{ oQuiet, "quiet", 0, N_("quiet") },
|
{ oQuiet, "quiet", 0, N_("quiet") },
|
||||||
{ oHex, "hex", 0, N_("print data out hex encoded") },
|
{ oHex, "hex", 0, N_("print data out hex encoded") },
|
||||||
|
{ oDecode,"decode", 0, N_("decode received data lines") },
|
||||||
{ oRawSocket, "raw-socket", 2, N_("|NAME|connect to Assuan socket NAME")},
|
{ oRawSocket, "raw-socket", 2, N_("|NAME|connect to Assuan socket NAME")},
|
||||||
{ oExec, "exec", 0, N_("run the Assuan server given on the command line")},
|
{ oExec, "exec", 0, N_("run the Assuan server given on the command line")},
|
||||||
{ oNoExtConnect, "no-ext-connect",
|
{ oNoExtConnect, "no-ext-connect",
|
||||||
@ -78,6 +80,7 @@ struct
|
|||||||
int quiet; /* Be extra quiet. */
|
int quiet; /* Be extra quiet. */
|
||||||
const char *homedir; /* Configuration directory name */
|
const char *homedir; /* Configuration directory name */
|
||||||
int hex; /* Print data lines in hex format. */
|
int hex; /* Print data lines in hex format. */
|
||||||
|
int decode; /* Decode received data lines. */
|
||||||
const char *raw_socket; /* Name of socket to connect in raw mode. */
|
const char *raw_socket; /* Name of socket to connect in raw mode. */
|
||||||
int exec; /* Run the pgm given on the command line. */
|
int exec; /* Run the pgm given on the command line. */
|
||||||
unsigned int connect_flags; /* Flags used for connecting. */
|
unsigned int connect_flags; /* Flags used for connecting. */
|
||||||
@ -306,6 +309,7 @@ main (int argc, char **argv)
|
|||||||
case oNoVerbose: opt.verbose = 0; break;
|
case oNoVerbose: opt.verbose = 0; break;
|
||||||
case oHomedir: opt.homedir = pargs.r.ret_str; break;
|
case oHomedir: opt.homedir = pargs.r.ret_str; break;
|
||||||
case oHex: opt.hex = 1; break;
|
case oHex: opt.hex = 1; break;
|
||||||
|
case oDecode: opt.decode = 1; break;
|
||||||
case oRawSocket: opt.raw_socket = pargs.r.ret_str; break;
|
case oRawSocket: opt.raw_socket = pargs.r.ret_str; break;
|
||||||
case oExec: opt.exec = 1; break;
|
case oExec: opt.exec = 1; break;
|
||||||
case oNoExtConnect: opt.connect_flags &= ~(1); break;
|
case oNoExtConnect: opt.connect_flags &= ~(1); break;
|
||||||
@ -436,6 +440,14 @@ main (int argc, char **argv)
|
|||||||
do_recvfd (ctx, p);
|
do_recvfd (ctx, p);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if (!strcmp (cmd, "hex"))
|
||||||
|
opt.hex = 1;
|
||||||
|
else if (!strcmp (cmd, "nohex"))
|
||||||
|
opt.hex = 0;
|
||||||
|
else if (!strcmp (cmd, "decode"))
|
||||||
|
opt.decode = 1;
|
||||||
|
else if (!strcmp (cmd, "nodecode"))
|
||||||
|
opt.decode = 0;
|
||||||
else if (!strcmp (cmd, "help"))
|
else if (!strcmp (cmd, "help"))
|
||||||
{
|
{
|
||||||
puts (
|
puts (
|
||||||
@ -451,7 +463,9 @@ main (int argc, char **argv)
|
|||||||
"/cleardef Delete all definitions.\n"
|
"/cleardef Delete all definitions.\n"
|
||||||
"/sendfd FILE MODE Open FILE and pass descriptor to server.\n"
|
"/sendfd FILE MODE Open FILE and pass descriptor to server.\n"
|
||||||
"/recvfd Receive FD from server and print. \n"
|
"/recvfd Receive FD from server and print. \n"
|
||||||
"/help Print this help.");
|
"/[no]hex Enable hex dumping of received data lines.\n"
|
||||||
|
"/[no]decode Enable decoding of received data lines.\n"
|
||||||
|
"/help Print this help.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
log_error (_("unknown command `%s'\n"), cmd );
|
log_error (_("unknown command `%s'\n"), cmd );
|
||||||
@ -577,6 +591,7 @@ read_and_print_response (assuan_context_t ctx)
|
|||||||
size_t linelen;
|
size_t linelen;
|
||||||
assuan_error_t rc;
|
assuan_error_t rc;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
int need_lf = 0;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@ -628,56 +643,92 @@ read_and_print_response (assuan_context_t ctx)
|
|||||||
putchar ('\n');
|
putchar ('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (opt.decode)
|
||||||
|
{
|
||||||
|
const unsigned char *s;
|
||||||
|
int need_d = 1;
|
||||||
|
int c = 0;
|
||||||
|
|
||||||
|
for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
|
||||||
|
{
|
||||||
|
if (need_d)
|
||||||
|
{
|
||||||
|
fputs ("D ", stdout);
|
||||||
|
need_d = 0;
|
||||||
|
}
|
||||||
|
if (*s == '%' && j+2 < linelen)
|
||||||
|
{
|
||||||
|
s++; j++;
|
||||||
|
c = xtoi_2 ( s );
|
||||||
|
s++; j++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
c = *s;
|
||||||
|
if (c == '\n')
|
||||||
|
need_d = 1;
|
||||||
|
putchar (c);
|
||||||
|
}
|
||||||
|
need_lf = (c != '\n');
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fwrite (line, linelen, 1, stdout);
|
fwrite (line, linelen, 1, stdout);
|
||||||
putchar ('\n');
|
putchar ('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (linelen >= 1
|
else
|
||||||
&& line[0] == 'S'
|
|
||||||
&& (line[1] == '\0' || line[1] == ' '))
|
|
||||||
{
|
{
|
||||||
fwrite (line, linelen, 1, stdout);
|
if (need_lf)
|
||||||
putchar ('\n');
|
{
|
||||||
}
|
putchar ('\n');
|
||||||
else if (linelen >= 2
|
need_lf = 0;
|
||||||
&& line[0] == 'O' && line[1] == 'K'
|
}
|
||||||
&& (line[2] == '\0' || line[2] == ' '))
|
|
||||||
{
|
if (linelen >= 1
|
||||||
fwrite (line, linelen, 1, stdout);
|
&& line[0] == 'S'
|
||||||
putchar ('\n');
|
&& (line[1] == '\0' || line[1] == ' '))
|
||||||
return 0;
|
{
|
||||||
|
fwrite (line, linelen, 1, stdout);
|
||||||
|
putchar ('\n');
|
||||||
|
}
|
||||||
|
else if (linelen >= 2
|
||||||
|
&& line[0] == 'O' && line[1] == 'K'
|
||||||
|
&& (line[2] == '\0' || line[2] == ' '))
|
||||||
|
{
|
||||||
|
fwrite (line, linelen, 1, stdout);
|
||||||
|
putchar ('\n');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (linelen >= 3
|
||||||
|
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
|
||||||
|
&& (line[3] == '\0' || line[3] == ' '))
|
||||||
|
{
|
||||||
|
fwrite (line, linelen, 1, stdout);
|
||||||
|
putchar ('\n');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (linelen >= 7
|
||||||
|
&& line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
|
||||||
|
&& line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
|
||||||
|
&& line[6] == 'E'
|
||||||
|
&& (line[7] == '\0' || line[7] == ' '))
|
||||||
|
{
|
||||||
|
fwrite (line, linelen, 1, stdout);
|
||||||
|
putchar ('\n');
|
||||||
|
if (!handle_inquire (ctx, line))
|
||||||
|
assuan_write_line (ctx, "CANCEL");
|
||||||
|
}
|
||||||
|
else if (linelen >= 3
|
||||||
|
&& line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
|
||||||
|
&& (line[3] == '\0' || line[3] == ' '))
|
||||||
|
{
|
||||||
|
fwrite (line, linelen, 1, stdout);
|
||||||
|
putchar ('\n');
|
||||||
|
/* Received from server, thus more responses are expected. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return gpg_error (GPG_ERR_ASS_INV_RESPONSE);
|
||||||
}
|
}
|
||||||
else if (linelen >= 3
|
|
||||||
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
|
|
||||||
&& (line[3] == '\0' || line[3] == ' '))
|
|
||||||
{
|
|
||||||
fwrite (line, linelen, 1, stdout);
|
|
||||||
putchar ('\n');
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (linelen >= 7
|
|
||||||
&& line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
|
|
||||||
&& line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
|
|
||||||
&& line[6] == 'E'
|
|
||||||
&& (line[7] == '\0' || line[7] == ' '))
|
|
||||||
{
|
|
||||||
fwrite (line, linelen, 1, stdout);
|
|
||||||
putchar ('\n');
|
|
||||||
if (!handle_inquire (ctx, line))
|
|
||||||
assuan_write_line (ctx, "CANCEL");
|
|
||||||
}
|
|
||||||
else if (linelen >= 3
|
|
||||||
&& line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
|
|
||||||
&& (line[3] == '\0' || line[3] == ' '))
|
|
||||||
{
|
|
||||||
fwrite (line, linelen, 1, stdout);
|
|
||||||
putchar ('\n');
|
|
||||||
/* Received from server, thus more responses are expected. */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return gpg_error (GPG_ERR_ASS_INV_RESPONSE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user