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:
parent
548cf72735
commit
3dacb2c626
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()\
|
||||
{ \
|
||||
|
|
Loading…
Reference in New Issue