summaryrefslogtreecommitdiff
path: root/scd/command.c
diff options
context:
space:
mode:
authorKévin THIERRY <kevin.thierry@open.eurogiciel.org>2014-11-13 09:26:18 +0100
committerKévin THIERRY <kevin.thierry@open.eurogiciel.org>2014-11-13 09:26:18 +0100
commite87a22655de485af790db1d4c51f4bc166a2bbd6 (patch)
tree93d088c2bc13d9a26e6f24b70936d998bd1404df /scd/command.c
parent6576640b55777bd811a12a188b9b1f3c63653799 (diff)
downloadgpg2-e87a22655de485af790db1d4c51f4bc166a2bbd6.tar.gz
gpg2-e87a22655de485af790db1d4c51f4bc166a2bbd6.tar.bz2
gpg2-e87a22655de485af790db1d4c51f4bc166a2bbd6.zip
Imported Upstream version 2.0.26upstream/2.0.26
Diffstat (limited to 'scd/command.c')
-rw-r--r--scd/command.c295
1 files changed, 160 insertions, 135 deletions
diff --git a/scd/command.c b/scd/command.c
index 52b22c6..fc1f5a2 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -34,6 +34,7 @@
#include <assuan.h>
#include <ksba.h>
#include "app-common.h"
+#include "iso7816.h"
#include "apdu.h" /* Required for apdu_*_reader (). */
#include "exechelp.h"
#ifdef HAVE_LIBUSB
@@ -46,6 +47,9 @@
/* Maximum allowed size of key data as used in inquiries. */
#define MAXLEN_KEYDATA 4096
+/* Maximum allowed total data size for SETDATA. */
+#define MAXLEN_SETDATA 4096
+
/* Maximum allowed size of certificate data as used in inquiries. */
#define MAXLEN_CERTDATA 16384
@@ -60,6 +64,7 @@
int _r = (r); \
if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \
|| gpg_err_code (_r) == GPG_ERR_CARD_REMOVED \
+ || gpg_err_code (_r) == GPG_ERR_CARD_RESET \
|| gpg_err_code (_r) == GPG_ERR_ENODEV ) \
update_card_removed ((c)->reader_slot, 1); \
} while (0)
@@ -70,12 +75,8 @@
&& (c)->reader_slot == locked_session->ctrl_backlink->reader_slot)
-/* Flag indicating that the reader has been disabled. */
-static int reader_disabled;
-
-
/* This structure is used to keep track of open readers (slots). */
-struct slot_status_s
+struct slot_status_s
{
int valid; /* True if the other objects are valid. */
int slot; /* Slot number of the reader or -1 if not open. */
@@ -92,11 +93,11 @@ struct slot_status_s
/* Data used to associate an Assuan context with local server data.
This object describes the local properties of one session. */
-struct server_local_s
+struct server_local_s
{
/* We keep a list of all active sessions with the anchor at
SESSION_LIST (see below). This field is used for linking. */
- struct server_local_s *next_session;
+ struct server_local_s *next_session;
/* This object is usually assigned to a CTRL object (which is
globally visible). While enumerating all sessions we sometimes
@@ -112,10 +113,10 @@ struct server_local_s
#else
int event_signal; /* Or 0 if not used. */
#endif
-
+
/* True if the card has been removed and a reset is required to
continue operation. */
- int card_removed;
+ int card_removed;
/* Flag indicating that the application context needs to be released
at the next opportunity. */
@@ -126,7 +127,7 @@ struct server_local_s
/* If set to true we will be terminate ourself at the end of the
this session. */
- int stopme;
+ int stopme;
};
@@ -180,6 +181,9 @@ update_card_removed (int slot, int value)
{
struct server_local_s *sl;
+ if (slot == -1)
+ return;
+
for (sl=session_list; sl; sl = sl->next_session)
if (sl->ctrl_backlink
&& sl->ctrl_backlink->reader_slot == slot)
@@ -256,7 +260,7 @@ hex_to_buffer (const char *string, size_t *r_length)
return NULL;
for (s=string, n=0; *s; s++)
{
- if (spacep (s) || *s == ':')
+ if (spacep (s) || *s == ':')
continue;
if (hexdigitp (s) && hexdigitp (s+1))
{
@@ -293,7 +297,7 @@ do_reset (ctrl_t ctrl, int send_reset)
if (send_reset)
{
struct server_local_s *sl;
-
+
for (sl=session_list; sl; sl = sl->next_session)
if (sl->ctrl_backlink
&& sl->ctrl_backlink->reader_slot == slot)
@@ -307,11 +311,19 @@ do_reset (ctrl_t ctrl, int send_reset)
tell the application layer about it. */
if (slot != -1 && send_reset && !IS_LOCKED (ctrl) )
{
- if (apdu_reset (slot))
- {
- slot_table[slot].valid = 0;
- }
application_notify_card_reset (slot);
+ switch (apdu_reset (slot))
+ {
+ case 0:
+ break;
+ case SW_HOST_NO_CARD:
+ case SW_HOST_CARD_INACTIVE:
+ break;
+ default:
+ apdu_close_reader (slot);
+ slot_table[slot].slot = -1;
+ break;
+ }
}
/* If we hold a lock, unlock now. */
@@ -345,7 +357,7 @@ do_reset (ctrl_t ctrl, int send_reset)
static gpg_error_t
reset_notify (assuan_context_t ctx, char *line)
{
- ctrl_t ctrl = assuan_get_pointer (ctx);
+ ctrl_t ctrl = assuan_get_pointer (ctx);
(void) line;
@@ -399,39 +411,29 @@ get_reader_slot (void)
/* Try to open the reader. */
if (ss->slot == -1)
{
- int no_service_flag;
- ss->slot = apdu_open_reader (opt.reader_port, &no_service_flag);
+ ss->slot = apdu_open_reader (opt.reader_port);
/* If we still don't have a slot, we have no readers.
Invalidate for now until a reader is attached. */
if(ss->slot == -1)
{
ss->valid = 0;
+ return -1;
}
-
- if (no_service_flag)
- {
- log_info ("no card services - disabling scdaemon\n");
- reader_disabled = 1;
- }
}
/* Return the slot_table index. */
return 0;
}
-/* If the card has not yet been opened, do it. Note that this
- function returns an Assuan error, so don't map the error a second
- time. */
+
+/* If the card has not yet been opened, do it. */
static gpg_error_t
open_card (ctrl_t ctrl, const char *apptype)
{
gpg_error_t err;
int slot;
- if (reader_disabled)
- return gpg_error (GPG_ERR_NOT_OPERATIONAL);
-
/* If we ever got a card not present error code, return that. Only
the SERIALNO command and a reset are able to clear from that
state. */
@@ -464,7 +466,7 @@ open_card (ctrl_t ctrl, const char *apptype)
slot = get_reader_slot ();
ctrl->reader_slot = slot;
if (slot == -1)
- err = gpg_error (reader_disabled? GPG_ERR_NOT_OPERATIONAL: GPG_ERR_CARD);
+ err = gpg_error (GPG_ERR_CARD);
else
{
/* Fixme: We should move the apdu_connect call to
@@ -477,6 +479,8 @@ open_card (ctrl_t ctrl, const char *apptype)
{
if (sw == SW_HOST_NO_CARD)
err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
+ else if (sw == SW_HOST_CARD_INACTIVE)
+ err = gpg_error (GPG_ERR_CARD_RESET);
else
err = gpg_error (GPG_ERR_CARD);
}
@@ -489,7 +493,7 @@ open_card (ctrl_t ctrl, const char *apptype)
}
-static const char hlp_serialno[] =
+static const char hlp_serialno[] =
"SERIALNO [<apptype>]\n"
"\n"
"Return the serial number of the card using a status reponse. This\n"
@@ -516,9 +520,11 @@ cmd_serialno (assuan_context_t ctx, char *line)
char *serial_and_stamp;
char *serial;
time_t stamp;
+ int retries = 0;
/* Clear the remove flag so that the open_card is able to reread it. */
- if (!reader_disabled && ctrl->server_local->card_removed)
+ retry:
+ if (ctrl->server_local->card_removed)
{
if ( IS_LOCKED (ctrl) )
return gpg_error (GPG_ERR_LOCKED);
@@ -526,7 +532,12 @@ cmd_serialno (assuan_context_t ctx, char *line)
}
if ((rc = open_card (ctrl, *line? line:NULL)))
- return rc;
+ {
+ /* In case of an inactive card, retry once. */
+ if (gpg_err_code (rc) == GPG_ERR_CARD_RESET && retries++ < 1)
+ goto retry;
+ return rc;
+ }
rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
if (rc)
@@ -544,7 +555,7 @@ cmd_serialno (assuan_context_t ctx, char *line)
}
-static const char hlp_learn[] =
+static const char hlp_learn[] =
"LEARN [--force] [--keypairinfo]\n"
"\n"
"Learn all useful information of the currently inserted card. When\n"
@@ -632,7 +643,7 @@ cmd_learn (assuan_context_t ctx, char *line)
char *serial_and_stamp;
char *serial;
time_t stamp;
-
+
rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
if (rc)
return rc;
@@ -643,11 +654,11 @@ cmd_learn (assuan_context_t ctx, char *line)
return out_of_core ();
rc = 0;
assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
-
+
if (!has_option (line, "--force"))
{
char *command;
-
+
rc = estream_asprintf (&command, "KNOWNCARDP %s", serial_and_stamp);
if (rc < 0)
{
@@ -655,7 +666,7 @@ cmd_learn (assuan_context_t ctx, char *line)
return out_of_core ();
}
rc = 0;
- rc = assuan_inquire (ctx, command, NULL, NULL, 0);
+ rc = assuan_inquire (ctx, command, NULL, NULL, 0);
xfree (command);
if (rc)
{
@@ -663,13 +674,13 @@ cmd_learn (assuan_context_t ctx, char *line)
log_error ("inquire KNOWNCARDP failed: %s\n",
gpg_strerror (rc));
xfree (serial_and_stamp);
- return rc;
+ return rc;
}
/* Not canceled, so we have to proceeed. */
}
xfree (serial_and_stamp);
}
-
+
/* Let the application print out its collection of useful status
information. */
if (!rc)
@@ -715,7 +726,7 @@ cmd_readcert (assuan_context_t ctx, char *line)
}
-static const char hlp_readkey[] =
+static const char hlp_readkey[] =
"READKEY <keyid>\n"
"\n"
"Return the public key for the given cert or key ID as a standard\n"
@@ -753,7 +764,7 @@ cmd_readkey (assuan_context_t ctx, char *line)
if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION)
log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
- else
+ else
{
rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
if (rc)
@@ -763,7 +774,7 @@ cmd_readkey (assuan_context_t ctx, char *line)
line = NULL;
if (rc)
goto leave;
-
+
rc = ksba_cert_new (&kc);
if (rc)
{
@@ -798,18 +809,25 @@ cmd_readkey (assuan_context_t ctx, char *line)
-static const char hlp_setdata[] =
- "SETDATA <hexstring> \n"
+static const char hlp_setdata[] =
+ "SETDATA [--append] <hexstring>\n"
"\n"
- "The client should use this command to tell us the data he want to sign.";
+ "The client should use this command to tell us the data he want to sign.\n"
+ "With the option --append, the data is appended to the data set by a\n"
+ "previous SETDATA command.";
static gpg_error_t
cmd_setdata (assuan_context_t ctx, char *line)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
- int n;
+ int append;
+ int n, i, off;
char *p;
unsigned char *buf;
+ append = (ctrl->in_data.value && has_option (line, "--append"));
+
+ line = skip_options (line);
+
if (locked_session && locked_session != ctrl->server_local)
return gpg_error (GPG_ERR_LOCKED);
@@ -823,20 +841,36 @@ cmd_setdata (assuan_context_t ctx, char *line)
if ((n&1))
return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
n /= 2;
+ if (append)
+ {
+ if (ctrl->in_data.valuelen + n > MAXLEN_SETDATA)
+ return set_error (GPG_ERR_TOO_LARGE,
+ "limit on total size of data reached");
+ buf = xtrymalloc (ctrl->in_data.valuelen + n);
+ }
+ else
buf = xtrymalloc (n);
if (!buf)
return out_of_core ();
+ if (append)
+ {
+ memcpy (buf, ctrl->in_data.value, ctrl->in_data.valuelen);
+ off = ctrl->in_data.valuelen;
+ }
+ else
+ off = 0;
+ for (p=line, i=0; i < n; p += 2, i++)
+ buf[off+i] = xtoi_2 (p);
+
ctrl->in_data.value = buf;
- ctrl->in_data.valuelen = n;
- for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++)
- buf[n] = xtoi_2 (p);
+ ctrl->in_data.valuelen = off + n;
return 0;
}
-static gpg_error_t
+static gpg_error_t
pin_cb (void *opaque, const char *info, char **retstr)
{
assuan_context_t ctx = opaque;
@@ -847,23 +881,23 @@ pin_cb (void *opaque, const char *info, char **retstr)
if (!retstr)
{
- /* We prompt for keypad entry. To make sure that the popup has
+ /* We prompt for pinpad entry. To make sure that the popup has
been show we use an inquire and not just a status message.
We ignore any value returned. */
if (info)
{
- log_debug ("prompting for keypad entry '%s'\n", info);
- rc = estream_asprintf (&command, "POPUPKEYPADPROMPT %s", info);
+ log_debug ("prompting for pinpad entry '%s'\n", info);
+ rc = estream_asprintf (&command, "POPUPPINPADPROMPT %s", info);
if (rc < 0)
return gpg_error (gpg_err_code_from_errno (errno));
- rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
- xfree (command);
+ rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
+ xfree (command);
}
else
{
- log_debug ("dismiss keypad entry prompt\n");
- rc = assuan_inquire (ctx, "DISMISSKEYPADPROMPT",
- &value, &valuelen, MAXLEN_PIN);
+ log_debug ("dismiss pinpad entry prompt\n");
+ rc = assuan_inquire (ctx, "DISMISSPINPADPROMPT",
+ &value, &valuelen, MAXLEN_PIN);
}
if (!rc)
xfree (value);
@@ -879,8 +913,8 @@ pin_cb (void *opaque, const char *info, char **retstr)
/* Fixme: Write an inquire function which returns the result in
secure memory and check all further handling of the PIN. */
- rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
- xfree (command);
+ rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
+ xfree (command);
if (rc)
return rc;
@@ -895,7 +929,7 @@ pin_cb (void *opaque, const char *info, char **retstr)
}
-static const char hlp_pksign[] =
+static const char hlp_pksign[] =
"PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5]] <hexified_id>\n"
"\n"
"The --hash option is optional; the default is SHA1.";
@@ -924,7 +958,7 @@ cmd_pksign (assuan_context_t ctx, char *line)
else if (has_option (line, "--hash=md5"))
hash_algo = GCRY_MD_MD5;
else if (!strstr (line, "--"))
- hash_algo = GCRY_MD_SHA1;
+ hash_algo = GCRY_MD_SHA1;
else
return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
@@ -942,7 +976,7 @@ cmd_pksign (assuan_context_t ctx, char *line)
keyidstr = xtrystrdup (line);
if (!keyidstr)
return out_of_core ();
-
+
rc = app_sign (ctrl->app_ctx,
keyidstr, hash_algo,
pin_cb, ctx,
@@ -967,7 +1001,7 @@ cmd_pksign (assuan_context_t ctx, char *line)
}
-static const char hlp_pkauth[] =
+static const char hlp_pkauth[] =
"PKAUTH <hexified_id>";
static gpg_error_t
cmd_pkauth (assuan_context_t ctx, char *line)
@@ -993,7 +1027,7 @@ cmd_pkauth (assuan_context_t ctx, char *line)
keyidstr = xtrystrdup (line);
if (!keyidstr)
return out_of_core ();
-
+
rc = app_auth (ctrl->app_ctx,
keyidstr,
pin_cb, ctx,
@@ -1017,7 +1051,7 @@ cmd_pkauth (assuan_context_t ctx, char *line)
}
-static const char hlp_pkdecrypt[] =
+static const char hlp_pkdecrypt[] =
"PKDECRYPT <hexified_id>";
static gpg_error_t
cmd_pkdecrypt (assuan_context_t ctx, char *line)
@@ -1038,7 +1072,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
if (!keyidstr)
return out_of_core ();
rc = app_decipher (ctrl->app_ctx,
- keyidstr,
+ keyidstr,
pin_cb, ctx,
ctrl->in_data.value, ctrl->in_data.valuelen,
&outdata, &outdatalen);
@@ -1061,7 +1095,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
}
-static const char hlp_getattr[] =
+static const char hlp_getattr[] =
"GETATTR <name>\n"
"\n"
"This command is used to retrieve data from a smartcard. The\n"
@@ -1100,7 +1134,7 @@ cmd_getattr (assuan_context_t ctx, char *line)
}
-static const char hlp_setattr[] =
+static const char hlp_setattr[] =
"SETATTR <name> <value> \n"
"\n"
"This command is used to store data on a a smartcard. The allowed\n"
@@ -1153,7 +1187,7 @@ cmd_setattr (assuan_context_t ctx, char *orig_line)
}
-static const char hlp_writecert[] =
+static const char hlp_writecert[] =
"WRITECERT <hexified_certid>\n"
"\n"
"This command is used to store a certifciate on a smartcard. The\n"
@@ -1205,7 +1239,7 @@ cmd_writecert (assuan_context_t ctx, char *line)
}
/* Write the certificate to the card. */
- rc = app_writecert (ctrl->app_ctx, ctrl, certid,
+ rc = app_writecert (ctrl->app_ctx, ctrl, certid,
pin_cb, ctx, certdata, certdatalen);
xfree (certid);
xfree (certdata);
@@ -1215,7 +1249,7 @@ cmd_writecert (assuan_context_t ctx, char *line)
}
-static const char hlp_writekey[] =
+static const char hlp_writekey[] =
"WRITEKEY [--force] <keyid> \n"
"\n"
"This command is used to store a secret key on a a smartcard. The\n"
@@ -1282,7 +1316,7 @@ cmd_writekey (assuan_context_t ctx, char *line)
}
-static const char hlp_genkey[] =
+static const char hlp_genkey[] =
"GENKEY [--force] [--timestamp=<isodate>] <no>\n"
"\n"
"Generate a key on-card identified by NO, which is application\n"
@@ -1360,7 +1394,7 @@ cmd_genkey (assuan_context_t ctx, char *line)
}
-static const char hlp_random[] =
+static const char hlp_random[] =
"RANDOM <nbytes>\n"
"\n"
"Get NBYTES of random from the card and send them back as data.\n"
@@ -1377,7 +1411,7 @@ cmd_random (assuan_context_t ctx, char *line)
unsigned char *buffer;
if (!*line)
- return set_error (GPG_ERR_ASS_PARAMETER,
+ return set_error (GPG_ERR_ASS_PARAMETER,
"number of requested bytes missing");
nbytes = strtoul (line, NULL, 0);
@@ -1443,7 +1477,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
if (!ctrl->app_ctx)
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
-
+
chvnostr = xtrystrdup (chvnostr);
if (!chvnostr)
return out_of_core ();
@@ -1457,7 +1491,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
}
-static const char hlp_checkpin[] =
+static const char hlp_checkpin[] =
"CHECKPIN <idstr>\n"
"\n"
"Perform a VERIFY operation without doing anything else. This may\n"
@@ -1511,7 +1545,7 @@ cmd_checkpin (assuan_context_t ctx, char *line)
idstr = xtrystrdup (line);
if (!idstr)
return out_of_core ();
-
+
rc = app_check_pin (ctrl->app_ctx, idstr, pin_cb, ctx);
xfree (idstr);
if (rc)
@@ -1522,7 +1556,7 @@ cmd_checkpin (assuan_context_t ctx, char *line)
}
-static const char hlp_lock[] =
+static const char hlp_lock[] =
"LOCK [--wait]\n"
"\n"
"Grant exclusive card access to this session. Note that there is\n"
@@ -1559,14 +1593,14 @@ cmd_lock (assuan_context_t ctx, char *line)
goto retry;
}
#endif /*USE_GNU_PTH*/
-
+
if (rc)
log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
return rc;
}
-static const char hlp_unlock[] =
+static const char hlp_unlock[] =
"UNLOCK\n"
"\n"
"Release exclusive card access.";
@@ -1594,7 +1628,7 @@ cmd_unlock (assuan_context_t ctx, char *line)
}
-static const char hlp_getinfo[] =
+static const char hlp_getinfo[] =
"GETINFO <what>\n"
"\n"
"Multi purpose command to return certain information. \n"
@@ -1656,16 +1690,13 @@ cmd_getinfo (assuan_context_t ctx, char *line)
if (!ctrl->server_local->card_removed && slot != -1)
{
struct slot_status_s *ss;
-
+
if (!(slot >= 0 && slot < DIM(slot_table)))
BUG ();
ss = &slot_table[slot];
- if (!ss->valid)
- BUG ();
-
- if (ss->any && (ss->status & 1))
+ if (ss->valid && ss->any && (ss->status & 1))
flag = 'u';
}
rc = assuan_send_data (ctx, &flag, 1);
@@ -1677,7 +1708,7 @@ cmd_getinfo (assuan_context_t ctx, char *line)
#else
char *s = NULL;
#endif
-
+
if (s)
rc = assuan_send_data (ctx, s, strlen (s));
else
@@ -1701,7 +1732,7 @@ cmd_getinfo (assuan_context_t ctx, char *line)
}
-static const char hlp_restart[] =
+static const char hlp_restart[] =
"RESTART\n"
"\n"
"Restart the current connection; this is a kind of warm reset. It\n"
@@ -1732,7 +1763,7 @@ cmd_restart (assuan_context_t ctx, char *line)
}
-static const char hlp_disconnect[] =
+static const char hlp_disconnect[] =
"DISCONNECT\n"
"\n"
"Disconnect the card if it is not any longer used by other\n"
@@ -1743,14 +1774,14 @@ cmd_disconnect (assuan_context_t ctx, char *line)
ctrl_t ctrl = assuan_get_pointer (ctx);
(void)line;
-
+
ctrl->server_local->disconnect_allowed = 1;
return 0;
}
-static const char hlp_apdu[] =
+static const char hlp_apdu[] =
"APDU [--atr] [--more] [--exlen[=N]] [hexstring]\n"
"\n"
"Send an APDU to the current reader. This command bypasses the high\n"
@@ -1807,7 +1838,7 @@ cmd_apdu (assuan_context_t ctx, char *line)
unsigned char *atr;
size_t atrlen;
char hexbuf[400];
-
+
atr = apdu_get_atr (ctrl->reader_slot, &atrlen);
if (!atr || atrlen > sizeof hexbuf - 2 )
{
@@ -1849,7 +1880,7 @@ cmd_apdu (assuan_context_t ctx, char *line)
}
-static const char hlp_killscd[] =
+static const char hlp_killscd[] =
"KILLSCD\n"
"\n"
"Commit suicide.";
@@ -1883,8 +1914,8 @@ register_commands (assuan_context_t ctx)
{ "PKSIGN", cmd_pksign, hlp_pksign },
{ "PKAUTH", cmd_pkauth, hlp_pkauth },
{ "PKDECRYPT", cmd_pkdecrypt,hlp_pkdecrypt },
- { "INPUT", NULL },
- { "OUTPUT", NULL },
+ { "INPUT", NULL },
+ { "OUTPUT", NULL },
{ "GETATTR", cmd_getattr, hlp_getattr },
{ "SETATTR", cmd_setattr, hlp_setattr },
{ "WRITECERT", cmd_writecert,hlp_writecert },
@@ -1910,7 +1941,7 @@ register_commands (assuan_context_t ctx)
table[i].help);
if (rc)
return rc;
- }
+ }
assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
assuan_register_reset_notify (ctx, reset_notify);
@@ -1928,7 +1959,7 @@ scd_command_handler (ctrl_t ctrl, int fd)
int rc;
assuan_context_t ctx = NULL;
int stopme;
-
+
rc = assuan_new (&ctx);
if (rc)
{
@@ -1996,7 +2027,7 @@ scd_command_handler (ctrl_t ctrl, int fd)
log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
break;
}
-
+
rc = assuan_process (ctx);
if (rc)
{
@@ -2006,7 +2037,7 @@ scd_command_handler (ctrl_t ctrl, int fd)
}
/* Cleanup. We don't send an explicit reset to the card. */
- do_reset (ctrl, 0);
+ do_reset (ctrl, 0);
/* Release the server object. */
if (session_list == ctrl->server_local)
@@ -2014,7 +2045,7 @@ scd_command_handler (ctrl_t ctrl, int fd)
else
{
struct server_local_s *sl;
-
+
for (sl=session_list; sl->next_session; sl = sl->next_session)
if (sl->next_session == ctrl->server_local)
break;
@@ -2022,7 +2053,7 @@ scd_command_handler (ctrl_t ctrl, int fd)
BUG ();
sl->next_session = ctrl->server_local->next_session;
}
- stopme = ctrl->server_local->stopme || reader_disabled;
+ stopme = ctrl->server_local->stopme;
xfree (ctrl->server_local);
ctrl->server_local = NULL;
@@ -2049,10 +2080,10 @@ send_status_info (ctrl_t ctrl, const char *keyword, ...)
char buf[950], *p;
size_t n;
assuan_context_t ctx = ctrl->server_local->assuan_ctx;
-
+
va_start (arg_ptr, keyword);
- p = buf;
+ p = buf;
n = 0;
while ( (value = va_arg (arg_ptr, const unsigned char *)) )
{
@@ -2102,17 +2133,17 @@ static void
send_client_notifications (void)
{
struct {
- pid_t pid;
+ pid_t pid;
#ifdef HAVE_W32_SYSTEM
HANDLE handle;
#else
- int signo;
+ int signo;
#endif
} killed[50];
int killidx = 0;
int kidx;
struct server_local_s *sl;
-
+
for (sl=session_list; sl; sl = sl->next_session)
{
if (sl->event_signal && sl->assuan_ctx)
@@ -2120,9 +2151,9 @@ send_client_notifications (void)
pid_t pid = assuan_get_pid (sl->assuan_ctx);
#ifdef HAVE_W32_SYSTEM
HANDLE handle = (void *)sl->event_signal;
-
+
for (kidx=0; kidx < killidx; kidx++)
- if (killed[kidx].pid == pid
+ if (killed[kidx].pid == pid
&& killed[kidx].handle == handle)
break;
if (kidx < killidx)
@@ -2144,11 +2175,11 @@ send_client_notifications (void)
}
#else /*!HAVE_W32_SYSTEM*/
int signo = sl->event_signal;
-
+
if (pid != (pid_t)(-1) && pid && signo > 0)
{
for (kidx=0; kidx < killidx; kidx++)
- if (killed[kidx].pid == pid
+ if (killed[kidx].pid == pid
&& killed[kidx].signo == signo)
break;
if (kidx < killidx)
@@ -2182,11 +2213,6 @@ update_reader_status_file (int set_card_removed_flag)
int idx;
unsigned int status, changed;
- /* Make sure that the reader has been opened. Like get_reader_slot,
- this part of the code assumes that there is only one reader. */
- if (!slot_table[0].valid)
- (void)get_reader_slot ();
-
/* Note, that we only try to get the status, because it does not
make sense to wait here for a operation to complete. If we are
busy working with a card, delays in the status file update should
@@ -2199,11 +2225,12 @@ update_reader_status_file (int set_card_removed_flag)
if (!ss->valid || ss->slot == -1)
continue; /* Not valid or reader not yet open. */
-
+
sw_apdu = apdu_get_status (ss->slot, 0, &status, &changed);
if (sw_apdu == SW_HOST_NO_READER)
{
/* Most likely the _reader_ has been unplugged. */
+ application_notify_card_reset (ss->slot);
apdu_close_reader (ss->slot);
ss->valid = 0;
status = 0;
@@ -2212,7 +2239,7 @@ update_reader_status_file (int set_card_removed_flag)
else if (sw_apdu)
{
/* Get status failed. Ignore that. */
- continue;
+ continue;
}
if (!ss->any || ss->status != status || ss->changed != changed )
@@ -2241,14 +2268,14 @@ update_reader_status_file (int set_card_removed_flag)
fclose (fp);
}
xfree (fname);
-
+
/* If a status script is executable, run it. */
{
const char *args[9], *envs[2];
char numbuf1[30], numbuf2[30], numbuf3[30];
char *homestr, *envstr;
gpg_error_t err;
-
+
homestr = make_filename (opt.homedir, NULL);
if (estream_asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
log_error ("out of core while building environment\n");
@@ -2261,16 +2288,16 @@ update_reader_status_file (int set_card_removed_flag)
sprintf (numbuf2, "0x%04X", ss->status);
sprintf (numbuf3, "0x%04X", status);
args[0] = "--reader-port";
- args[1] = numbuf1;
+ args[1] = numbuf1;
args[2] = "--old-code";
- args[3] = numbuf2;
+ args[3] = numbuf2;
args[4] = "--new-code";
- args[5] = numbuf3;
+ args[5] = numbuf3;
args[6] = "--status";
args[7] = ((status & 1)? "USABLE":
(status & 4)? "ACTIVE":
(status & 2)? "PRESENT": "NOCARD");
- args[8] = NULL;
+ args[8] = NULL;
fname = make_filename (opt.homedir, "scd-event", NULL);
err = gnupg_spawn_process_detached (fname, args, envs);
@@ -2283,24 +2310,22 @@ update_reader_status_file (int set_card_removed_flag)
xfree (homestr);
}
- /* Set the card removed flag for all current sessions. We
- will set this on any card change because a reset or
- SERIALNO request must be done in any case. */
- if (ss->any && set_card_removed_flag)
+ /* Set the card removed flag for all current sessions. */
+ if (ss->any && ss->status == 0 && set_card_removed_flag)
update_card_removed (idx, 1);
-
+
ss->any = 1;
/* Send a signal to all clients who applied for it. */
send_client_notifications ();
}
-
+
/* Check whether a disconnect is pending. */
if (opt.card_timeout)
{
for (sl=session_list; sl; sl = sl->next_session)
if (!sl->disconnect_allowed)
- break;
+ break;
if (session_list && !sl)
{
/* FIXME: Use a real timeout. */
@@ -2309,7 +2334,7 @@ update_reader_status_file (int set_card_removed_flag)
apdu_disconnect (ss->slot);
}
}
-
+
}
}