diff options
Diffstat (limited to 'scd')
-rw-r--r-- | scd/ChangeLog | 13 | ||||
-rw-r--r-- | scd/apdu.c | 39 | ||||
-rw-r--r-- | scd/apdu.h | 3 | ||||
-rw-r--r-- | scd/app.c | 19 | ||||
-rw-r--r-- | scd/ccid-driver.c | 114 | ||||
-rw-r--r-- | scd/ccid-driver.h | 2 | ||||
-rw-r--r-- | scd/iso7816.c | 1 | ||||
-rw-r--r-- | scd/scdaemon.c | 6 | ||||
-rw-r--r-- | scd/scdaemon.h | 2 |
9 files changed, 181 insertions, 18 deletions
diff --git a/scd/ChangeLog b/scd/ChangeLog index b0f07dc82..80b244ef1 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,16 @@ +2004-08-05 Werner Koch <[email protected]> + + * scdaemon.c (main): New option --disable-application. + * app.c (is_app_allowed): New. + (select_application): Use it to check for disabled applications. + + * ccid-driver.h (CCID_DRIVER_ERR_ABORTED): New. + * ccid-driver.c (ccid_open_reader): Support the stable 0.1 version + of libusb. + (ccid_get_atr): Handle short messages. + + * apdu.c (my_rapdu_get_status): Implemented. + 2004-07-27 Moritz Schulte <[email protected]> * apdu.c: Include <signal.h>. diff --git a/scd/apdu.c b/scd/apdu.c index 7898452c4..5f800c983 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -19,7 +19,6 @@ */ #include <config.h> - #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -296,6 +295,7 @@ host_sw_string (long err) case SW_HOST_CARD_IO_ERROR: return "card I/O error"; case SW_HOST_GENERAL_ERROR: return "general error"; case SW_HOST_NO_READER: return "no reader"; + case SW_HOST_ABORTED: return "aborted"; default: return "unknown host status error"; } } @@ -1633,7 +1633,42 @@ reset_rapdu_reader (int slot) static int my_rapdu_get_status (int slot, unsigned int *status) { - return SW_HOST_NOT_SUPPORTED; + int err; + reader_table_t slotp; + rapdu_msg_t msg = NULL; + int oldslot; + + slotp = reader_table + slot; + + oldslot = rapdu_set_reader (slotp->rapdu.handle, slot); + err = rapdu_send_cmd (slotp->rapdu.handle, RAPDU_CMD_GET_STATUS); + rapdu_set_reader (slotp->rapdu.handle, oldslot); + if (err) + { + log_error ("sending rapdu command GET_STATUS failed: %s\n", + err < 0 ? strerror (errno): rapdu_strerror (err)); + return rapdu_status_to_sw (err); + } + err = rapdu_read_msg (slotp->rapdu.handle, &msg); + if (err) + { + log_error ("receiving rapdu message failed: %s\n", + err < 0 ? strerror (errno): rapdu_strerror (err)); + rapdu_msg_release (msg); + return rapdu_status_to_sw (err); + } + if (msg->cmd != RAPDU_STATUS_SUCCESS || !msg->datalen) + { + int sw = rapdu_status_to_sw (msg->cmd); + log_error ("rapdu command GET_STATUS failed: %s\n", + rapdu_strerror (msg->cmd)); + rapdu_msg_release (msg); + return sw; + } + *status = msg->data[0]; + + rapdu_msg_release (msg); + return 0; } diff --git a/scd/apdu.h b/scd/apdu.h index a2b781266..a0654a242 100644 --- a/scd/apdu.h +++ b/scd/apdu.h @@ -58,7 +58,8 @@ enum { SW_HOST_CARD_INACTIVE = 0x10009, SW_HOST_CARD_IO_ERROR = 0x1000a, SW_HOST_GENERAL_ERROR = 0x1000b, - SW_HOST_NO_READER = 0x1000c + SW_HOST_NO_READER = 0x1000c, + SW_HOST_ABORTED = 0x1000d }; @@ -32,6 +32,19 @@ #include "tlv.h" +/* Check wether the application NAME is allowed. This does not mean + we have support for it though. */ +static int +is_app_allowed (const char *name) +{ + strlist_t l; + + for (l=opt.disabled_applications; l; l = l->next) + if (!strcmp (l->d, name)) + return 0; /* no */ + return 1; /* yes */ +} + /* If called with NAME as NULL, select the best fitting application and return a context; otherwise select the application with NAME and return a context. SLOT identifies the reader device. Returns @@ -84,11 +97,11 @@ select_application (ctrl_t ctrl, int slot, const char *name) rc = gpg_error (GPG_ERR_NOT_FOUND); - if (!name || !strcmp (name, "openpgp")) + if (rc && is_app_allowed ("openpgp") && (!name || !strcmp (name, "openpgp"))) rc = app_select_openpgp (app); - if (rc && (!name || !strcmp (name, "nks"))) + if (rc && is_app_allowed ("nks") && (!name || !strcmp (name, "nks"))) rc = app_select_nks (app); - if (rc && (!name || !strcmp (name, "dinsig"))) + if (rc && is_app_allowed ("dinsig") && (!name || !strcmp (name, "dinsig"))) rc = app_select_dinsig (app); if (rc && name) rc = gpg_error (GPG_ERR_NOT_SUPPORTED); diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 4751b8cdb..0fc168590 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -412,7 +412,13 @@ read_device_info (ccid_driver_t handle, struct usb_device *dev) { int cfg_no; - for (cfg_no=0; cfg_no < dev->descriptor->bNumConfigurations; cfg_no++) + for (cfg_no=0; cfg_no < +#ifdef HAVE_USB_CREATE_MATCH + dev->descriptor->bNumConfigurations +#else + dev->descriptor.bNumConfigurations +#endif + ; cfg_no++) { struct usb_config_descriptor *config = dev->config + cfg_no; int ifc_no; @@ -451,8 +457,9 @@ read_device_info (ccid_driver_t handle, struct usb_device *dev) int ccid_open_reader (ccid_driver_t *handle, int readerno) { +#ifdef HAVE_USB_CREATE_MATCH + /* This is the development version of libusb. */ static int initialized; - int rc; usb_match_handle *match = NULL; struct usb_device *dev = NULL; @@ -471,7 +478,7 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) DEBUGOUT_1 ("usb_create_match failed: %d\n", rc); return CCID_DRIVER_ERR_NO_READER; } - + while (usb_find_device(match, dev, &dev) >= 0) { DEBUGOUT_3 ("%-40s %04X/%04X\n", dev->filename, @@ -530,7 +537,6 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) readerno--; } - leave: if (idev) usb_close (idev); @@ -542,6 +548,96 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) rc = -1; /* In case we didn't enter the while loop at all. */ return rc; +#else /* Stable 0.1 version of libusb. */ + static int initialized; + int rc = 0; + struct usb_bus *busses, *bus; + struct usb_device *dev = NULL; + usb_dev_handle *idev = NULL; + + *handle = NULL; + if (!initialized) + { + usb_init (); + initialized = 1; + } + + usb_find_busses(); + usb_find_devices(); + busses = usb_get_busses(); + + for (bus = busses; bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + DEBUGOUT_3 ("%-40s %04X/%04X\n", dev->filename, + dev->descriptor.idVendor, dev->descriptor.idProduct); + + if (!readerno) + { + *handle = calloc (1, sizeof **handle); + if (!*handle) + { + DEBUGOUT ("out of memory\n"); + rc = CCID_DRIVER_ERR_OUT_OF_CORE; + free (*handle); + *handle = NULL; + goto leave; + } + + rc = read_device_info (*handle, dev); + if (rc) + { + DEBUGOUT ("device not supported\n"); + free (*handle); + *handle = NULL; + continue; + } + + idev = usb_open (dev); + if (!idev) + { + DEBUGOUT_1 ("usb_open failed: %s\n", strerror (errno)); + free (*handle); + *handle = NULL; + rc = CCID_DRIVER_ERR_CARD_IO_ERROR; + goto leave; + } + + /* fixme: Do we need to claim and set the interface as + determined by read_device_info ()? */ + rc = usb_claim_interface (idev, 0); + if (rc) + { + DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); + free (*handle); + *handle = NULL; + rc = CCID_DRIVER_ERR_CARD_IO_ERROR; + goto leave; + } + + (*handle)->idev = idev; + idev = NULL; + /* FIXME: Do we need to get the endpoint addresses from the + structure and store them with the handle? */ + + goto leave; /* ready. */ + } + readerno--; + } + } + + leave: + if (idev) + usb_close (idev); + /* fixme: Do we need to release dev or is it supposed to be a + shallow copy of the list created internally by usb_init ? */ + + if (!rc && !*handle) + rc = -1; /* In case we didn't enter the while loop at all. */ + + return rc; +#endif /* Stable version 0.1 of libusb. */ } @@ -894,10 +990,7 @@ ccid_get_atr (ccid_driver_t handle, tpdulen = msglen - 10; if (tpdulen < 4) - { - DEBUGOUT ("cannot yet handle short blocks!\n"); - return -1; - } + return CCID_DRIVER_ERR_ABORTED; #ifdef DEBUG_T1 fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", @@ -1092,10 +1185,9 @@ ccid_transceive (ccid_driver_t handle, if (tpdulen < 4) { - DEBUGOUT ("cannot yet handle short blocks!\n"); - return CCID_DRIVER_ERR_NOT_SUPPORTED; + usb_clear_halt (handle->idev, 0x82); + return CCID_DRIVER_ERR_ABORTED; } - #ifdef DEBUG_T1 fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", ((msg[11] & 0xc0) == 0x80)? 'R' : diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h index 0b108f16d..0cb52e1c3 100644 --- a/scd/ccid-driver.h +++ b/scd/ccid-driver.h @@ -70,7 +70,7 @@ #define CCID_DRIVER_ERR_CARD_IO_ERROR 0x1000a #define CCID_DRIVER_ERR_GENERAL_ERROR 0x1000b #define CCID_DRIVER_ERR_NO_READER 0x1000c - +#define CCID_DRIVER_ERR_ABORTED 0x1000d struct ccid_driver_s; typedef struct ccid_driver_s *ccid_driver_t; diff --git a/scd/iso7816.c b/scd/iso7816.c index d5db607f8..cbb314eb2 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -90,6 +90,7 @@ map_sw (int sw) case SW_HOST_CARD_IO_ERROR: ec = GPG_ERR_EIO; break; case SW_HOST_GENERAL_ERROR: ec = GPG_ERR_GENERAL; break; case SW_HOST_NO_READER: ec = GPG_ERR_ENODEV; break; + case SW_HOST_ABORTED: ec = GPG_ERR_CANCELED; break; default: if ((sw & 0x010000)) diff --git a/scd/scdaemon.c b/scd/scdaemon.c index f647aecc2..b54a63816 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -80,6 +80,7 @@ enum cmd_and_opt_values oDisableOpenSC, oAllowAdmin, oDenyAdmin, + oDisableApplication, aTest }; @@ -124,6 +125,7 @@ static ARGPARSE_OPTS opts[] = { /* end --disable-opensc */}, { oAllowAdmin, "allow-admin", 0, N_("allow the use of admin card commands")}, { oDenyAdmin, "deny-admin", 0, "@" }, + { oDisableApplication, "disable-application", 2, "@"}, {0} }; @@ -493,6 +495,10 @@ main (int argc, char **argv ) case oAllowAdmin: opt.allow_admin = 1; break; case oDenyAdmin: opt.allow_admin = 0; break; + case oDisableApplication: + add_to_strlist (&opt.disabled_applications, pargs.r.ret_str); + break; + default : pargs.err = configfp? 1:2; break; } } diff --git a/scd/scdaemon.h b/scd/scdaemon.h index 1dd32ae90..c8d78c88b 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -52,6 +52,8 @@ struct { int disable_ccid; /* Disable the use of the internal CCID driver. */ int allow_admin; /* Allow the use of admin commands for certain cards. */ + strlist_t disabled_applications; /* card applications we do not + want to use. */ } opt; |