aboutsummaryrefslogtreecommitdiffstats
path: root/scd/command.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2005-02-24 17:36:11 +0000
committerWerner Koch <[email protected]>2005-02-24 17:36:11 +0000
commit3af261572bdf938f0a2fdde4d9aec82153a7e0e4 (patch)
tree97ea3ee2c40c6a3288182c6e95e92377e3e7a794 /scd/command.c
parent* command-ssh.c (get_passphrase): Removed. (diff)
downloadgnupg-3af261572bdf938f0a2fdde4d9aec82153a7e0e4.tar.gz
gnupg-3af261572bdf938f0a2fdde4d9aec82153a7e0e4.zip
* gpg-agent.c (handle_connections): Need to check for events if
select returns with -1. * tools.texi (gpg-connect-agent): New. * app-openpgp.c (get_one_do): Never try to get a non cacheable object from the cache. (get_one_do): Add new arg to return an error code. Changed all callers. (do_getattr): Let it return a proper error code. * app.c (select_application): Return an error code and the application context in an new arg. * command.c (open_card): Adjusted for that. Don't use the fallback if no card is present. Return an error if the card has been removed without a reset. (do_reset, cmd_serialno): Clear that error flag. (TEST_CARD_REMOVAL): New. Use it with all command handlers. * scdaemon.c (ticker_thread): Termintate if a shutdown is pending. * apdu.c: Added some PCSC error codes. (pcsc_error_to_sw): New. (reset_pcsc_reader, pcsc_get_status, pcsc_send_apdu) (open_pcsc_reader): Do proper error code mapping. * gpg-connect-agent.c: New. * Makefile.am: Add it.
Diffstat (limited to '')
-rw-r--r--scd/command.c81
1 files changed, 63 insertions, 18 deletions
diff --git a/scd/command.c b/scd/command.c
index 72f48b2b8..a4fb968cf 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -45,10 +45,24 @@ static ctrl_t primary_connection;
#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
+
+/* Macro to flag a a removed card. */
+#define TEST_CARD_REMOVAL(c,r) \
+ do { \
+ int _r = (r); \
+ if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \
+ || gpg_err_code (_r) == GPG_ERR_CARD_REMOVED) \
+ (c)->server_local->card_removed = 1; \
+ } while (0)
+
+
/* Data used to associate an Assuan context with local server data */
struct server_local_s {
- ASSUAN_CONTEXT assuan_ctx;
+ assuan_context_t assuan_ctx;
int event_signal; /* Or 0 if not used. */
+ int card_removed; /* True if the card has been removed and a
+ reset is required to continue
+ operation. */
};
@@ -89,6 +103,7 @@ do_reset (ctrl_t ctrl, int do_close)
ctrl->reader_slot = -1;
}
}
+ ctrl->server_local->card_removed = 0;
}
@@ -122,11 +137,18 @@ option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
/* 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 */
-static AssuanError
+static assuan_error_t
open_card (ctrl_t ctrl, const char *apptype)
{
+ gpg_error_t err;
int slot;
+ /* 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. */
+ if (ctrl->server_local->card_removed)
+ return map_to_assuan_status (gpg_error (GPG_ERR_CARD_REMOVED));
+
if (ctrl->app_ctx)
return 0; /* Already initialized for one specific application. */
if (ctrl->card_ctx)
@@ -137,24 +159,28 @@ open_card (ctrl_t ctrl, const char *apptype)
else
slot = apdu_open_reader (opt.reader_port);
ctrl->reader_slot = slot;
- if (slot != -1)
- ctrl->app_ctx = select_application (ctrl, slot, apptype);
- if (!ctrl->app_ctx)
- { /* No application found - fall back to old mode. */
+ if (slot == -1)
+ err = gpg_error (GPG_ERR_CARD);
+ else
+ err = select_application (ctrl, slot, apptype, &ctrl->app_ctx);
+ if (!ctrl->app_ctx
+ && gpg_err_code (err) != GPG_ERR_CARD_NOT_PRESENT)
+ {
+ /* No application found - fall back to old mode. */
/* Note that we should rework the old code to use the
application paradigma too. */
- int rc;
-
/* If an APPTYPE was requested and it is not pkcs#15, we return
an error here. */
if (apptype && !(!strcmp (apptype, "P15") || !strcmp (apptype, "p15")))
- rc = gpg_error (GPG_ERR_NOT_SUPPORTED);
+ err = gpg_error (GPG_ERR_NOT_SUPPORTED);
else
- rc = card_open (&ctrl->card_ctx);
- if (rc)
- return map_to_assuan_status (rc);
+ err = card_open (&ctrl->card_ctx);
}
- return 0;
+
+ if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)
+ ctrl->server_local->card_removed = 1;
+
+ return map_to_assuan_status (err);
}
@@ -215,12 +241,15 @@ percent_plus_unescape (unsigned char *string)
static int
cmd_serialno (ASSUAN_CONTEXT ctx, char *line)
{
- CTRL ctrl = assuan_get_pointer (ctx);
+ ctrl_t ctrl = assuan_get_pointer (ctx);
int rc = 0;
char *serial_and_stamp;
char *serial;
time_t stamp;
+ /* Clear the remove flag so that the open_card is able to reread it. */
+ ctrl->server_local->card_removed = 0;
+
if ((rc = open_card (ctrl, *line? line:NULL)))
return rc;
@@ -443,6 +472,7 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line)
if (rc == -1)
rc = 0;
+ TEST_CARD_REMOVAL (ctrl, rc);
return map_to_assuan_status (rc);
}
@@ -485,6 +515,7 @@ cmd_readcert (ASSUAN_CONTEXT ctx, char *line)
return rc;
}
+ TEST_CARD_REMOVAL (ctrl, rc);
return map_to_assuan_status (rc);
}
@@ -575,6 +606,7 @@ cmd_readkey (assuan_context_t ctx, char *line)
leave:
ksba_cert_release (kc);
xfree (cert);
+ TEST_CARD_REMOVAL (ctrl, rc);
return map_to_assuan_status (rc);
}
@@ -697,6 +729,7 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
return rc; /* that is already an assuan error code */
}
+ TEST_CARD_REMOVAL (ctrl, rc);
return map_to_assuan_status (rc);
}
@@ -743,6 +776,7 @@ cmd_pkauth (ASSUAN_CONTEXT ctx, char *line)
return rc; /* that is already an assuan error code */
}
+ TEST_CARD_REMOVAL (ctrl, rc);
return map_to_assuan_status (rc);
}
@@ -789,6 +823,7 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
return rc; /* that is already an assuan error code */
}
+ TEST_CARD_REMOVAL (ctrl, rc);
return map_to_assuan_status (rc);
}
@@ -824,6 +859,7 @@ cmd_getattr (ASSUAN_CONTEXT ctx, char *line)
rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
+ TEST_CARD_REMOVAL (ctrl, rc);
return map_to_assuan_status (rc);
}
@@ -871,6 +907,7 @@ cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line)
rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx, line, nbytes);
xfree (linebuf);
+ TEST_CARD_REMOVAL (ctrl, rc);
return map_to_assuan_status (rc);
}
@@ -927,6 +964,8 @@ cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
return ASSUAN_Out_Of_Core;
rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0, pin_cb, ctx);
xfree (keyno);
+
+ TEST_CARD_REMOVAL (ctrl, rc);
return map_to_assuan_status (rc);
}
@@ -966,6 +1005,7 @@ cmd_random (ASSUAN_CONTEXT ctx, char *line)
}
xfree (buffer);
+ TEST_CARD_REMOVAL (ctrl, rc);
return map_to_assuan_status (rc);
}
@@ -1010,6 +1050,8 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
if (rc)
log_error ("command passwd failed: %s\n", gpg_strerror (rc));
xfree (chvnostr);
+
+ TEST_CARD_REMOVAL (ctrl, rc);
return map_to_assuan_status (rc);
}
@@ -1044,6 +1086,7 @@ cmd_checkpin (ASSUAN_CONTEXT ctx, char *line)
if (rc)
log_error ("app_check_pin failed: %s\n", gpg_strerror (rc));
+ TEST_CARD_REMOVAL (ctrl, rc);
return map_to_assuan_status (rc);
}
@@ -1226,7 +1269,9 @@ send_status_info (CTRL ctrl, const char *keyword, ...)
}
-
+/* This fucntion is called by the ticker thread to check for changes
+ of the reader stati. It updates the reader status files and if
+ requested by the caller also send a signal to the caller. */
void
scd_update_reader_status_file (void)
{
@@ -1239,10 +1284,10 @@ scd_update_reader_status_file (void)
int used;
unsigned int status, changed;
- /* Note, that we only try to get the status, becuase it does not
+ /* 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
- so busy working with the card, delays in the status file updated
- are should be acceptable. */
+ busy working with a card, delays in the status file update should
+ be acceptable. */
for (slot=0; (slot < DIM(last)
&&!apdu_enum_reader (slot, &used)); slot++)
if (used && !apdu_get_status (slot, 0, &status, &changed))