implement dynamic card/reader support

from Juan Antonio Martinez (with some input from me)


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1944 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
nils 2004-10-18 08:24:12 +00:00
parent 548cf72735
commit 3dacb2c626
4 changed files with 133 additions and 32 deletions

View File

@ -52,6 +52,10 @@
Nils Larsch <email>larsch@trustcenter.de</email>
</listitem>
<listitem>
Juan Antonio Martinez <email>jonsito@teleline.es</email>
</listitem>
<listitem>
Ville Skyttä
</listitem>

View File

@ -35,6 +35,8 @@ app default {
# internal) driver is supplied, a separate configuration
# configuration block has to be written for the driver.
# Default: internal
# NOTE: if "internal" keyword is used, must be the
# last entry in reader_drivers list
#
# reader_drivers = openct, pcsc, ctapi;
@ -90,25 +92,17 @@ app default {
# internal) driver is supplied, a separate configuration
# configuration block has to be written for the driver.
# Default: internal
# NOTE: When "internal" keyword is used, must be last entry
#
# card_drivers = internal, customcos;
# card_drivers = customcos, internal;
# Card driver configuration blocks.
# Card driver configuration blocks. For card drivers loaded
# from an external shared library/DLL, you need to specify
# the path name of the module, and the name of the constructor
# function.
# WARNING: this is not implemented yet.
#
# For all drivers, you can specify ATRs of cards that
# should be handled by this driver (in addition to the
# list of compiled-in ATRs). To do so, specify
# list of compiled-in ATRs).
#
# card_driver foo {
# atr = 00:11:22:33:44;
# atr = 55:66:77:88:99:aa:bb;
# }
#
# The card driver names are
# The supported internal card driver names are
# flex Cryptoflex/Multiflex
# setcos Setec
# etoken Aladdin eToken and other CardOS based cards
@ -119,17 +113,21 @@ app default {
# tcos TCOS 2.0
# emv EMV compatible cards
# card_driver customcos {
# The location of the driver library
#
# module = /usr/lib/opensc/drivers/card_customcos.so
# }
# GPK card driver
# GPK card driver additional ATR entry:
card_driver gpk {
# atr = 00:11:22;
}
# For card drivers loaded from an external shared library/DLL,
# you need to specify the path name of the module
#
# card_driver customcos {
# The location of the driver library
# module = /usr/lib/opensc/drivers/card_customcos.so;
# atr = 00:11:22:33:44;
# atr = 55:66:77:88:99:aa:bb;
# }
# Force using specific card driver
#
# If this option is present, OpenSC will use the supplied

View File

@ -27,6 +27,8 @@
#include <sys/stat.h>
#include <limits.h>
#include <opensc/scdl.h>
/* Default value for apdu_masquerade option */
#ifndef _WIN32
# define DEF_APDU_MASQ SC_APDU_MASQUERADE_NONE
@ -307,6 +309,87 @@ static void load_reader_driver_options(sc_context_t *ctx,
}
}
/**
* find library module for provided driver in configuration file
* if not found assume library name equals to module name
*/
static const char *find_library(struct sc_context *ctx, const char *name, int type)
{
int i;
const char *libname = NULL;
scconf_block **blocks, *blk;
for (i = 0; ctx->conf_blocks[i]; i++) {
blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],
(type==0) ? "reader_driver" : "card_driver", name);
blk = blocks[0];
free(blocks);
if (blk == NULL)
continue;
libname = scconf_get_str(blk, "module", name);
#ifdef _WIN32
if (libname && libname[0] != '\\' ) {
#else
if (libname && libname[0] != '/' ) {
#endif
sc_debug(ctx, "warning: relative path to driver '%s' used\n",
libname);
}
break;
}
return libname;
}
/**
* load card/reader driver modules
* Every module should contain a function " void * sc_module_init(char *) "
* that returns a pointer to the function _sc_get_xxxx_driver()
* used to initialize static modules
* Also, an exported "char *sc_module_version" variable should exist in module
* type=1 -> carddriver Type=0 -> readerdriver
*/
static void *load_dynamic_driver(struct sc_context *ctx, void **dll,
const char *name, int type)
{
const char *version, *libname;
void *handler;
void *(*modinit)(const char *) = NULL;
const char *(*modversion)(void) = NULL;
if (name == NULL) { /* should not occurr, but... */
sc_error(ctx,"No module specified\n",name);
return NULL;
}
libname = find_library(ctx, name, type);
if (libname == NULL)
return NULL;
handler = scdl_open(libname);
if (handler == NULL) {
sc_error(ctx, "Module %s: cannot load %s library\n",name,libname);
return NULL;
}
/* verify correctness of module */
modinit = scdl_get_address(handler, "sc_module_init");
modversion = scdl_get_address(handler, "sc_driver_version");
if (modinit == NULL || modversion == NULL) {
sc_error(ctx, "dynamic library '%s' is not a OpenSC module\n",libname);
scdl_close(handler);
return NULL;
}
/* verify module version */
version = modversion();
if (version == NULL || strncmp(version, "0.9.", strlen("0.9.")) > 0) {
sc_error(ctx,"dynamic library '%s': invalid module version\n",libname);
scdl_close(handler);
return NULL;
}
*dll = handler;
sc_debug(ctx, "successfully loaded %s driver '%s'\n",
type ? "card" : "reader", name);
return modinit(name);
}
static int load_reader_drivers(struct sc_context *ctx,
struct _sc_ctx_options *opts)
{
@ -319,7 +402,8 @@ static int load_reader_drivers(struct sc_context *ctx,
for (i = 0; i < opts->rcount; i++) {
struct sc_reader_driver *driver;
struct sc_reader_driver * (*func)(void) = NULL;
int j;
int j;
void *dll = NULL;
ent = &opts->rdrv[i];
for (j = 0; internal_reader_drivers[j].name != NULL; j++)
@ -327,14 +411,16 @@ static int load_reader_drivers(struct sc_context *ctx,
func = (struct sc_reader_driver * (*)(void)) internal_reader_drivers[j].func;
break;
}
/* if not initialized assume external module */
if (func == NULL)
func = load_dynamic_driver(ctx, &dll, ent->name, 0);
/* if still null, assume driver not found */
if (func == NULL) {
/* External driver */
/* FIXME: Load shared library */
sc_error(ctx, "Unable to load '%s'. External drivers not supported yet.\n",
ent->name);
sc_error(ctx, "Unable to load '%s'.\n", ent->name);
continue;
}
driver = func();
driver->dll = dll;
load_reader_driver_options(ctx, driver);
driver->ops->init(ctx, &ctx->reader_drv_data[i]);
@ -394,7 +480,8 @@ static int load_card_drivers(struct sc_context *ctx,
for (i = 0; i < opts->ccount; i++) {
struct sc_card_driver * (* func)(void) = NULL;
int j;
void *dll = NULL;
int j;
ent = &opts->cdrv[i];
for (j = 0; internal_card_drivers[j].name != NULL; j++)
@ -402,14 +489,17 @@ static int load_card_drivers(struct sc_context *ctx,
func = (struct sc_card_driver * (*)(void)) internal_card_drivers[j].func;
break;
}
/* if not initialized assume external module */
if (func == NULL)
func = load_dynamic_driver(ctx, &dll, ent->name, 1);
/* if still null, assume driver not found */
if (func == NULL) {
/* External driver */
/* FIXME: Load shared library */
sc_error(ctx, "Unable to load '%s'. External drivers not supported yet.\n",
ent->name);
sc_error(ctx, "Unable to load '%s'.\n", ent->name);
continue;
}
ctx->card_drivers[drv_count] = func();
ctx->card_drivers[drv_count]->dll = dll;
load_card_driver_options(ctx, ctx->card_drivers[drv_count]);
drv_count++;
@ -523,6 +613,13 @@ int sc_release_context(struct sc_context *ctx)
if (drv->ops->finish != NULL)
drv->ops->finish(ctx, ctx->reader_drv_data[i]);
if (drv->dll)
scdl_close(drv->dll);
}
for (i = 0; ctx->card_drivers[i]; i++) {
struct sc_card_driver *drv = ctx->card_drivers[i];
if (drv->dll)
scdl_close(drv->dll);
}
ctx->debug_file = ctx->error_file = NULL;
if (ctx->preferred_language)

View File

@ -261,6 +261,7 @@ struct sc_reader_driver {
size_t max_send_size, max_recv_size;
int apdu_masquerade;
unsigned int forced_protocol;
void *dll;
};
#define SC_APDU_MASQUERADE_NONE 0x00
#define SC_APDU_MASQUERADE_4AS3 0x01
@ -600,6 +601,7 @@ struct sc_card_driver {
struct sc_card_operations *ops;
struct sc_atr_table *atr_map;
unsigned int natrs;
void *dll;
};
struct sc_context {
@ -865,7 +867,7 @@ struct sc_card_error {
extern const char *sc_get_version(void);
#define IMPLEMENT_DRIVER_VERSION(a) \
#define SC_IMPLEMENT_DRIVER_VERSION(a) \
static const char *drv_version = (a); \
const char *sc_driver_version()\
{ \