aboutsummaryrefslogtreecommitdiffstats
path: root/scd
diff options
context:
space:
mode:
Diffstat (limited to 'scd')
-rw-r--r--scd/ChangeLog13
-rw-r--r--scd/apdu.c39
-rw-r--r--scd/apdu.h3
-rw-r--r--scd/app.c19
-rw-r--r--scd/ccid-driver.c114
-rw-r--r--scd/ccid-driver.h2
-rw-r--r--scd/iso7816.c1
-rw-r--r--scd/scdaemon.c6
-rw-r--r--scd/scdaemon.h2
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
};
diff --git a/scd/app.c b/scd/app.c
index a9a9243eb..b3a13f19a 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -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;