- Moved functions from sc.c to ctx.c
- Card and reader drivers are now configurable git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@387 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
ec6f8961b0
commit
cd4e3650a4
|
@ -1,17 +1,77 @@
|
||||||
# Configuration file for OpenSC
|
# Configuration file for OpenSC
|
||||||
# Example configuration file
|
# Example configuration file
|
||||||
|
|
||||||
# Default values for any application
|
# NOTE: All key-value pairs must be terminated by a semicolon.
|
||||||
# These can be overrided by the application
|
|
||||||
# specific configuration block.
|
|
||||||
|
|
||||||
|
# Default values for any application
|
||||||
|
# These can be overrided by an application
|
||||||
|
# specific configuration block.
|
||||||
app default {
|
app default {
|
||||||
|
# Amount of debug info to print
|
||||||
|
#
|
||||||
|
# A greater value means more debug info.
|
||||||
|
# Default: 0
|
||||||
|
#
|
||||||
debug = 0;
|
debug = 0;
|
||||||
#debug_file = "/tmp/opensc-debug.log";
|
|
||||||
#error_file = "/tmp/opensc-errors.log";
|
# The file to which debug output will be written
|
||||||
|
#
|
||||||
|
# A special value of 'stdout' is recognized.
|
||||||
|
# Default: stdout
|
||||||
|
#
|
||||||
|
# debug_file = /tmp/opensc-debug.log;
|
||||||
|
|
||||||
|
# The file to which errors will be written
|
||||||
|
#
|
||||||
|
# A special value of 'stderr' is recognized.
|
||||||
|
# Default: stderr
|
||||||
|
#
|
||||||
|
# error_file = /tmp/opensc-errors.log;
|
||||||
|
|
||||||
|
# What reader drivers to load at start-up
|
||||||
|
#
|
||||||
|
# A special value of 'internal' will load all
|
||||||
|
# statically linked drivers. If an unknown (ie. not
|
||||||
|
# internal) driver is supplied, a separate configuration
|
||||||
|
# configuration block has to be written for the driver.
|
||||||
|
# Default: internal
|
||||||
|
#
|
||||||
|
# reader_drivers = pcsc, ctapi;
|
||||||
|
|
||||||
|
# What reader drivers to load at start-up
|
||||||
|
#
|
||||||
|
# A special value of 'internal' will load all
|
||||||
|
# statically linked drivers. If an unknown (ie. not
|
||||||
|
# internal) driver is supplied, a separate configuration
|
||||||
|
# configuration block has to be written for the driver.
|
||||||
|
# Default: internal
|
||||||
|
#
|
||||||
|
# card_drivers = internal, customcos;
|
||||||
|
|
||||||
|
# card_driver customcos {
|
||||||
|
# The location of the driver library
|
||||||
|
#
|
||||||
|
# module = /usr/lib/opensc/drivers/card_customcos.so
|
||||||
|
# }
|
||||||
|
|
||||||
|
# Below are the framework specific configuration blocks.
|
||||||
|
|
||||||
|
# PKCS #15
|
||||||
|
framework pkcs15 {
|
||||||
|
# Whether to use the cache files in the user's
|
||||||
|
# home directory.
|
||||||
|
|
||||||
|
# WARNING: This shouldn't be used in setuid root
|
||||||
|
# applications.
|
||||||
|
# Default: false
|
||||||
|
#
|
||||||
|
use_caching = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# For applications that use SCAM (pam_opensc, sia_opensc)
|
# For applications that use SCAM (pam_opensc, sia_opensc)
|
||||||
app scam {
|
app scam {
|
||||||
use_cache = false;
|
framework pkcs15 {
|
||||||
|
use_caching = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,9 @@ INCLUDES = $(PCSC_FLAGS)
|
||||||
bin_SCRIPTS = opensc-config
|
bin_SCRIPTS = opensc-config
|
||||||
|
|
||||||
lib_LTLIBRARIES = libopensc.la
|
lib_LTLIBRARIES = libopensc.la
|
||||||
libopensc_la_SOURCES = asn1.c base64.c sec.c log.c sc.c card.c iso7816.c \
|
libopensc_la_SOURCES = sc.c ctx.c asn1.c base64.c sec.c log.c \
|
||||||
dir.c pkcs15.c pkcs15-cert.c pkcs15-pin.c \
|
card.c iso7816.c dir.c \
|
||||||
|
pkcs15.c pkcs15-cert.c pkcs15-pin.c \
|
||||||
pkcs15-prkey.c pkcs15-pubkey.c pkcs15-sec.c \
|
pkcs15-prkey.c pkcs15-pubkey.c pkcs15-sec.c \
|
||||||
pkcs15-cache.c $(PCSC_SRC) \
|
pkcs15-cache.c $(PCSC_SRC) \
|
||||||
card-setcos.c card-miocos.c card-flex.c card-gpk.c \
|
card-setcos.c card-miocos.c card-flex.c card-gpk.c \
|
||||||
|
|
|
@ -0,0 +1,390 @@
|
||||||
|
/*
|
||||||
|
* ctx.c: Context related functions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002 Juha Yrjölä <juha.yrjola@iki.fi>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
#include "sc-internal.h"
|
||||||
|
#include "sc-log.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
int _sc_add_reader(struct sc_context *ctx, struct sc_reader *reader)
|
||||||
|
{
|
||||||
|
assert(reader != NULL);
|
||||||
|
reader->ctx = ctx;
|
||||||
|
if (ctx->reader_count == SC_MAX_READERS)
|
||||||
|
return SC_ERROR_TOO_MANY_OBJECTS;
|
||||||
|
ctx->reader[ctx->reader_count] = reader;
|
||||||
|
ctx->reader_count++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _sc_driver_entry {
|
||||||
|
char *name;
|
||||||
|
void *func;
|
||||||
|
char *libpath;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct _sc_driver_entry internal_card_drivers[] = {
|
||||||
|
{ "setcos", sc_get_setcos_driver },
|
||||||
|
{ "miocos", sc_get_miocos_driver },
|
||||||
|
{ "flex", sc_get_flex_driver },
|
||||||
|
{ "tcos", sc_get_tcos_driver },
|
||||||
|
{ "emv", sc_get_emv_driver },
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
{ "gpk", sc_get_gpk_driver },
|
||||||
|
#endif
|
||||||
|
/* The default driver should be last, as it handles all the
|
||||||
|
* unrecognized cards. */
|
||||||
|
{ "default", sc_get_default_driver },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct _sc_driver_entry internal_reader_drivers[] = {
|
||||||
|
#ifdef HAVE_LIBPCSCLITE
|
||||||
|
{ "pcsc", sc_get_pcsc_driver },
|
||||||
|
#endif
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _sc_ctx_options {
|
||||||
|
struct _sc_driver_entry rdrv[16];
|
||||||
|
int rcount;
|
||||||
|
struct _sc_driver_entry cdrv[16];
|
||||||
|
int ccount;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void set_defaults(struct sc_context *ctx, struct _sc_ctx_options *opts)
|
||||||
|
{
|
||||||
|
ctx->debug = 0;
|
||||||
|
if (ctx->debug_file)
|
||||||
|
fclose(ctx->debug_file);
|
||||||
|
ctx->debug_file = NULL;
|
||||||
|
ctx->log_errors = 1;
|
||||||
|
ctx->error_file = stderr;
|
||||||
|
ctx->forced_driver = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void del_drvs(struct _sc_ctx_options *opts, int type)
|
||||||
|
{
|
||||||
|
struct _sc_driver_entry *lst;
|
||||||
|
int *cp, i;
|
||||||
|
|
||||||
|
if (type == 0) {
|
||||||
|
lst = opts->rdrv;
|
||||||
|
cp = &opts->rcount;
|
||||||
|
} else {
|
||||||
|
lst = opts->cdrv;
|
||||||
|
cp = &opts->ccount;
|
||||||
|
}
|
||||||
|
for (i = 0; i < *cp; i++) {
|
||||||
|
free(lst[i].name);
|
||||||
|
if (lst[i].libpath)
|
||||||
|
free(lst[i].libpath);
|
||||||
|
}
|
||||||
|
*cp = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_drv(struct _sc_ctx_options *opts, int type, const char *name)
|
||||||
|
{
|
||||||
|
struct _sc_driver_entry *lst;
|
||||||
|
int *cp, i;
|
||||||
|
|
||||||
|
if (type == 0) {
|
||||||
|
lst = opts->rdrv;
|
||||||
|
cp = &opts->rcount;
|
||||||
|
} else {
|
||||||
|
lst = opts->cdrv;
|
||||||
|
cp = &opts->ccount;
|
||||||
|
}
|
||||||
|
if (*cp == 16) /* No space for more drivers... */
|
||||||
|
return;
|
||||||
|
for (i = 0; i < *cp; i++)
|
||||||
|
if (strcmp(name, lst[i].name) == 0)
|
||||||
|
return;
|
||||||
|
lst[*cp].name = strdup(name);
|
||||||
|
|
||||||
|
*cp = *cp + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_internal_drvs(struct _sc_ctx_options *opts, int type)
|
||||||
|
{
|
||||||
|
const struct _sc_driver_entry *lst;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (type == 0)
|
||||||
|
lst = internal_reader_drivers;
|
||||||
|
else
|
||||||
|
lst = internal_card_drivers;
|
||||||
|
i = 0;
|
||||||
|
while (lst[i].name != NULL) {
|
||||||
|
add_drv(opts, type, lst[i].name);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int load_parameters(struct sc_context *ctx, const char *app,
|
||||||
|
struct _sc_ctx_options *opts)
|
||||||
|
{
|
||||||
|
scconf_block **blocks = NULL;
|
||||||
|
int i, err = 0;
|
||||||
|
|
||||||
|
blocks = scconf_find_blocks(ctx->conf, NULL, "app");
|
||||||
|
for (i = 0; blocks[i]; i++) {
|
||||||
|
scconf_block *block = blocks[i];
|
||||||
|
const scconf_list *list;
|
||||||
|
const char *val;
|
||||||
|
const char *s_internal = "internal";
|
||||||
|
|
||||||
|
if (!block->name && strcmp(block->name->data, app))
|
||||||
|
continue;
|
||||||
|
val = scconf_find_value_first(block, "debug");
|
||||||
|
if (val)
|
||||||
|
sscanf(val, "%d", &ctx->debug);
|
||||||
|
val = scconf_find_value_first(block, "debug_file");
|
||||||
|
if (val) {
|
||||||
|
if (ctx->debug_file && ctx->debug_file != stdout)
|
||||||
|
fclose(ctx->debug_file);
|
||||||
|
if (strcmp(val, "stdout") == 0)
|
||||||
|
ctx->debug_file = fopen(val, "a");
|
||||||
|
else
|
||||||
|
ctx->debug_file = stdout;
|
||||||
|
}
|
||||||
|
val = scconf_find_value_first(block, "error_file");
|
||||||
|
if (val) {
|
||||||
|
if (ctx->error_file && ctx->error_file != stderr)
|
||||||
|
fclose(ctx->error_file);
|
||||||
|
if (strcmp(val, "stderr") != 0)
|
||||||
|
ctx->error_file = fopen(val, "a");
|
||||||
|
else
|
||||||
|
ctx->error_file = stderr;
|
||||||
|
}
|
||||||
|
|
||||||
|
list = scconf_find_value(block, "reader_drivers");
|
||||||
|
if (list == NULL) {
|
||||||
|
if (opts->rcount == 0) /* Add the internal drivers */
|
||||||
|
add_internal_drvs(opts, 0);
|
||||||
|
} else
|
||||||
|
del_drvs(opts, 0);
|
||||||
|
while (list != NULL) {
|
||||||
|
if (strcmp(list->data, s_internal) == 0)
|
||||||
|
add_internal_drvs(opts, 1);
|
||||||
|
else
|
||||||
|
add_drv(opts, 0, list->data);
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
if (err)
|
||||||
|
break;
|
||||||
|
|
||||||
|
list = scconf_find_value(block, "card_drivers");
|
||||||
|
if (list == NULL) {
|
||||||
|
if (opts->ccount == 0) /* Add the internal drivers */
|
||||||
|
add_internal_drvs(opts, 1);
|
||||||
|
} else
|
||||||
|
del_drvs(opts, 1);
|
||||||
|
while (list != NULL) {
|
||||||
|
if (strcmp(list->data, s_internal) == 0)
|
||||||
|
add_internal_drvs(opts, 1);
|
||||||
|
else
|
||||||
|
add_drv(opts, 1, list->data);
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
if (err)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(blocks);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int load_reader_drivers(struct sc_context *ctx,
|
||||||
|
struct _sc_ctx_options *opts)
|
||||||
|
{
|
||||||
|
const struct _sc_driver_entry *ent;
|
||||||
|
int drv_count;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (drv_count = 0; ctx->reader_drivers[drv_count] != NULL; drv_count++);
|
||||||
|
|
||||||
|
for (i = 0; i < opts->rcount; i++) {
|
||||||
|
const struct sc_reader_driver * (* func)(void) = NULL;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
ent = &opts->rdrv[i];
|
||||||
|
for (j = 0; internal_reader_drivers[j].name != NULL; j++)
|
||||||
|
if (strcmp(ent->name, internal_reader_drivers[j].name) == 0) {
|
||||||
|
func = internal_reader_drivers[j].func;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (func == NULL) {
|
||||||
|
/* External driver */
|
||||||
|
/* FIXME: Load shared library */
|
||||||
|
error(ctx, "Unable to load '%s'. External drivers not supported yet.\n",
|
||||||
|
ent->name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ctx->reader_drivers[drv_count] = func();
|
||||||
|
ctx->reader_drivers[drv_count]->ops->init(ctx, &ctx->reader_drv_data[i]);
|
||||||
|
drv_count++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int load_card_drivers(struct sc_context *ctx,
|
||||||
|
struct _sc_ctx_options *opts)
|
||||||
|
{
|
||||||
|
const struct _sc_driver_entry *ent;
|
||||||
|
int drv_count;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (drv_count = 0; ctx->card_drivers[drv_count] != NULL; drv_count++);
|
||||||
|
|
||||||
|
for (i = 0; i < opts->ccount; i++) {
|
||||||
|
const struct sc_card_driver * (* func)(void) = NULL;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
ent = &opts->cdrv[i];
|
||||||
|
for (j = 0; internal_card_drivers[j].name != NULL; j++)
|
||||||
|
if (strcmp(ent->name, internal_card_drivers[j].name) == 0) {
|
||||||
|
func = internal_card_drivers[j].func;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (func == NULL) {
|
||||||
|
/* External driver */
|
||||||
|
/* FIXME: Load shared library */
|
||||||
|
error(ctx, "Unable to load '%s'. External drivers not supported yet.\n",
|
||||||
|
ent->name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ctx->card_drivers[drv_count] = func();
|
||||||
|
drv_count++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sc_establish_context(struct sc_context **ctx_out, const char *app_name)
|
||||||
|
{
|
||||||
|
const char *default_app = "default";
|
||||||
|
struct sc_context *ctx;
|
||||||
|
struct _sc_ctx_options opts;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(ctx_out != NULL);
|
||||||
|
ctx = malloc(sizeof(struct sc_context));
|
||||||
|
if (ctx == NULL)
|
||||||
|
return SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
memset(ctx, 0, sizeof(struct sc_context));
|
||||||
|
memset(&opts, 0, sizeof(opts));
|
||||||
|
set_defaults(ctx, &opts);
|
||||||
|
ctx->app_name = app_name ? strdup(app_name) : strdup(default_app);
|
||||||
|
ctx->conf = scconf_init(OPENSC_CONF_PATH);
|
||||||
|
if (ctx->conf) {
|
||||||
|
r = scconf_parse(ctx->conf);
|
||||||
|
if (r < 1) {
|
||||||
|
scconf_deinit(ctx->conf);
|
||||||
|
ctx->conf = NULL;
|
||||||
|
} else {
|
||||||
|
load_parameters(ctx, default_app, &opts);
|
||||||
|
if (strcmp(default_app, ctx->app_name)) {
|
||||||
|
load_parameters(ctx, ctx->app_name, &opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef HAVE_PTHREAD
|
||||||
|
pthread_mutex_init(&ctx->mutex, NULL);
|
||||||
|
#endif
|
||||||
|
load_reader_drivers(ctx, &opts);
|
||||||
|
load_card_drivers(ctx, &opts);
|
||||||
|
|
||||||
|
*ctx_out = ctx;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sc_release_context(struct sc_context *ctx)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert(ctx != NULL);
|
||||||
|
SC_FUNC_CALLED(ctx, 1);
|
||||||
|
for (i = 0; i < ctx->reader_count; i++) {
|
||||||
|
struct sc_reader *rdr = ctx->reader[i];
|
||||||
|
|
||||||
|
if (rdr->ops->release != NULL)
|
||||||
|
rdr->ops->release(rdr);
|
||||||
|
free(rdr->name);
|
||||||
|
free(rdr);
|
||||||
|
}
|
||||||
|
for (i = 0; ctx->reader_drivers[i] != NULL; i++) {
|
||||||
|
const struct sc_reader_driver *drv = ctx->reader_drivers[i];
|
||||||
|
|
||||||
|
if (drv->ops->finish != NULL)
|
||||||
|
drv->ops->finish(ctx->reader_drv_data[i]);
|
||||||
|
}
|
||||||
|
ctx->debug_file = ctx->error_file = NULL;
|
||||||
|
if (ctx->conf)
|
||||||
|
scconf_deinit(ctx->conf);
|
||||||
|
free(ctx->app_name);
|
||||||
|
free(ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sc_set_card_driver(struct sc_context *ctx, const char *short_name)
|
||||||
|
{
|
||||||
|
int i = 0, match = 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_PTHREAD
|
||||||
|
pthread_mutex_lock(&ctx->mutex);
|
||||||
|
#endif
|
||||||
|
if (short_name == NULL) {
|
||||||
|
ctx->forced_driver = NULL;
|
||||||
|
match = 1;
|
||||||
|
} else while (ctx->card_drivers[i] != NULL && i < SC_MAX_CARD_DRIVERS) {
|
||||||
|
const struct sc_card_driver *drv = ctx->card_drivers[i];
|
||||||
|
|
||||||
|
if (strcmp(short_name, drv->short_name) == 0) {
|
||||||
|
ctx->forced_driver = drv;
|
||||||
|
match = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_PTHREAD
|
||||||
|
pthread_mutex_unlock(&ctx->mutex);
|
||||||
|
#endif
|
||||||
|
if (match == 0)
|
||||||
|
return SC_ERROR_OBJECT_NOT_FOUND; /* FIXME: invent error */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sc_get_cache_dir(struct sc_context *ctx, char *buf, size_t bufsize)
|
||||||
|
{
|
||||||
|
char *homedir;
|
||||||
|
const char *cache_dir = ".eid/cache";
|
||||||
|
|
||||||
|
homedir = getenv("HOME");
|
||||||
|
if (homedir == NULL)
|
||||||
|
return SC_ERROR_INTERNAL;
|
||||||
|
if (snprintf(buf, bufsize, "%s/%s", homedir, cache_dir) < 0)
|
||||||
|
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -331,6 +331,8 @@ static int pcsc_init(struct sc_context *ctx, void **reader_data)
|
||||||
reader->driver = &pcsc_drv;
|
reader->driver = &pcsc_drv;
|
||||||
reader->slot_count = 1;
|
reader->slot_count = 1;
|
||||||
reader->name = strdup(p);
|
reader->name = strdup(p);
|
||||||
|
priv->pcsc_ctx = pcsc_ctx;
|
||||||
|
priv->reader_name = strdup(p);
|
||||||
r = _sc_add_reader(ctx, reader);
|
r = _sc_add_reader(ctx, reader);
|
||||||
if (r) {
|
if (r) {
|
||||||
free(priv->reader_name);
|
free(priv->reader_name);
|
||||||
|
@ -345,8 +347,6 @@ static int pcsc_init(struct sc_context *ctx, void **reader_data)
|
||||||
slot->atr_len = 0;
|
slot->atr_len = 0;
|
||||||
slot->drv_data = NULL;
|
slot->drv_data = NULL;
|
||||||
|
|
||||||
priv->pcsc_ctx = pcsc_ctx;
|
|
||||||
priv->reader_name = strdup(p);
|
|
||||||
while (*p++ != 0);
|
while (*p++ != 0);
|
||||||
} while (p < (reader_buf + reader_buf_size - 1));
|
} while (p < (reader_buf + reader_buf_size - 1));
|
||||||
free(reader_buf);
|
free(reader_buf);
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#ifdef VERSION
|
#ifdef VERSION
|
||||||
const char *sc_version = VERSION;
|
const char *sc_version = VERSION;
|
||||||
|
@ -67,18 +66,6 @@ int sc_hex_to_bin(const char *in, u8 *out, size_t *outlen)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _sc_add_reader(struct sc_context *ctx, struct sc_reader *reader)
|
|
||||||
{
|
|
||||||
assert(reader != NULL);
|
|
||||||
reader->ctx = ctx;
|
|
||||||
if (ctx->reader_count == SC_MAX_READERS)
|
|
||||||
return SC_ERROR_TOO_MANY_OBJECTS;
|
|
||||||
ctx->reader[ctx->reader_count] = reader;
|
|
||||||
ctx->reader_count++;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sc_slot_info * _sc_get_slot_info(struct sc_reader *reader, int slot_id)
|
struct sc_slot_info * _sc_get_slot_info(struct sc_reader *reader, int slot_id)
|
||||||
{
|
{
|
||||||
assert(reader != NULL);
|
assert(reader != NULL);
|
||||||
|
@ -142,173 +129,6 @@ int sc_wait_for_card(struct sc_context *ctx, int reader, int timeout)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void set_defaults(struct sc_context *ctx)
|
|
||||||
{
|
|
||||||
ctx->debug = 0;
|
|
||||||
if (ctx->debug_file)
|
|
||||||
fclose(ctx->debug_file);
|
|
||||||
ctx->debug_file = NULL;
|
|
||||||
ctx->log_errors = 1;
|
|
||||||
ctx->error_file = stderr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int load_parameters(struct sc_context *ctx, const char *app)
|
|
||||||
{
|
|
||||||
scconf_block **blocks = NULL;
|
|
||||||
const char *val;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
blocks = scconf_find_blocks(ctx->conf, NULL, "app");
|
|
||||||
for (i = 0; blocks[i]; i++) {
|
|
||||||
scconf_block *block = blocks[i];
|
|
||||||
|
|
||||||
if (!block->name && strcmp(block->name->data, app))
|
|
||||||
continue;
|
|
||||||
val = scconf_find_value_first(block, "debug");
|
|
||||||
sscanf(val, "%d", &ctx->debug);
|
|
||||||
val = scconf_find_value_first(block, "debug_file");
|
|
||||||
if (ctx->debug_file)
|
|
||||||
fclose(ctx->debug_file);
|
|
||||||
if (strcmp(val, "stdout") == 0)
|
|
||||||
ctx->debug_file = fopen(val, "a");
|
|
||||||
val = scconf_find_value_first(block, "error_file");
|
|
||||||
if (ctx->error_file)
|
|
||||||
fclose(ctx->error_file);
|
|
||||||
if (strcmp(val, "stderr") != 0)
|
|
||||||
ctx->error_file = fopen(val, "a");
|
|
||||||
}
|
|
||||||
free(blocks);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sc_establish_context(struct sc_context **ctx_out, const char *app_name)
|
|
||||||
{
|
|
||||||
const char *default_app = "default";
|
|
||||||
struct sc_context *ctx;
|
|
||||||
int i, r;
|
|
||||||
|
|
||||||
assert(ctx_out != NULL);
|
|
||||||
ctx = malloc(sizeof(struct sc_context));
|
|
||||||
if (ctx == NULL)
|
|
||||||
return SC_ERROR_OUT_OF_MEMORY;
|
|
||||||
memset(ctx, 0, sizeof(struct sc_context));
|
|
||||||
set_defaults(ctx);
|
|
||||||
ctx->app_name = app_name ? strdup(app_name) : strdup(default_app);
|
|
||||||
ctx->conf = scconf_init(OPENSC_CONF_PATH);
|
|
||||||
if (ctx->conf) {
|
|
||||||
r = scconf_parse(ctx->conf);
|
|
||||||
if (r < 1) {
|
|
||||||
scconf_deinit(ctx->conf);
|
|
||||||
ctx->conf = NULL;
|
|
||||||
} else {
|
|
||||||
load_parameters(ctx, default_app);
|
|
||||||
if (strcmp(default_app, ctx->app_name)) {
|
|
||||||
load_parameters(ctx, ctx->app_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef HAVE_PTHREAD
|
|
||||||
pthread_mutex_init(&ctx->mutex, NULL);
|
|
||||||
#endif
|
|
||||||
for (i = 0; i < SC_MAX_READER_DRIVERS+1; i++)
|
|
||||||
ctx->reader_drivers[i] = NULL;
|
|
||||||
i = 0;
|
|
||||||
#if 1 && defined(HAVE_LIBPCSCLITE)
|
|
||||||
ctx->reader_drivers[i++] = sc_get_pcsc_driver();
|
|
||||||
#endif
|
|
||||||
i = 0;
|
|
||||||
while (ctx->reader_drivers[i] != NULL) {
|
|
||||||
ctx->reader_drivers[i]->ops->init(ctx, &ctx->reader_drv_data[i]);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->forced_driver = NULL;
|
|
||||||
for (i = 0; i < SC_MAX_CARD_DRIVERS+1; i++)
|
|
||||||
ctx->card_drivers[i] = NULL;
|
|
||||||
i = 0;
|
|
||||||
#if 1
|
|
||||||
ctx->card_drivers[i++] = sc_get_setcos_driver();
|
|
||||||
#endif
|
|
||||||
#if 1
|
|
||||||
ctx->card_drivers[i++] = sc_get_miocos_driver();
|
|
||||||
#endif
|
|
||||||
#if 1
|
|
||||||
ctx->card_drivers[i++] = sc_get_flex_driver();
|
|
||||||
#endif
|
|
||||||
#if 1
|
|
||||||
ctx->card_drivers[i++] = sc_get_emv_driver();
|
|
||||||
#endif
|
|
||||||
#if 1
|
|
||||||
ctx->card_drivers[i++] = sc_get_tcos_driver();
|
|
||||||
#endif
|
|
||||||
#if defined(HAVE_OPENSSL)
|
|
||||||
ctx->card_drivers[i++] = sc_get_gpk_driver();
|
|
||||||
#endif
|
|
||||||
#if 1
|
|
||||||
/* this should be last in line */
|
|
||||||
ctx->card_drivers[i++] = sc_get_default_driver();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*ctx_out = ctx;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sc_release_context(struct sc_context *ctx)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
assert(ctx != NULL);
|
|
||||||
SC_FUNC_CALLED(ctx, 1);
|
|
||||||
for (i = 0; i < ctx->reader_count; i++) {
|
|
||||||
struct sc_reader *rdr = ctx->reader[i];
|
|
||||||
|
|
||||||
if (rdr->ops->release != NULL)
|
|
||||||
rdr->ops->release(rdr);
|
|
||||||
free(rdr->name);
|
|
||||||
free(rdr);
|
|
||||||
}
|
|
||||||
for (i = 0; ctx->reader_drivers[i] != NULL; i++) {
|
|
||||||
const struct sc_reader_driver *drv = ctx->reader_drivers[i];
|
|
||||||
|
|
||||||
if (drv->ops->finish != NULL)
|
|
||||||
drv->ops->finish(ctx->reader_drv_data[i]);
|
|
||||||
}
|
|
||||||
ctx->debug_file = ctx->error_file = NULL;
|
|
||||||
if (ctx->conf)
|
|
||||||
scconf_deinit(ctx->conf);
|
|
||||||
free(ctx->app_name);
|
|
||||||
free(ctx);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sc_set_card_driver(struct sc_context *ctx, const char *short_name)
|
|
||||||
{
|
|
||||||
int i = 0, match = 0;
|
|
||||||
|
|
||||||
#ifdef HAVE_PTHREAD
|
|
||||||
pthread_mutex_lock(&ctx->mutex);
|
|
||||||
#endif
|
|
||||||
if (short_name == NULL) {
|
|
||||||
ctx->forced_driver = NULL;
|
|
||||||
match = 1;
|
|
||||||
} else while (ctx->card_drivers[i] != NULL && i < SC_MAX_CARD_DRIVERS) {
|
|
||||||
const struct sc_card_driver *drv = ctx->card_drivers[i];
|
|
||||||
|
|
||||||
if (strcmp(short_name, drv->short_name) == 0) {
|
|
||||||
ctx->forced_driver = drv;
|
|
||||||
match = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
#ifdef HAVE_PTHREAD
|
|
||||||
pthread_mutex_unlock(&ctx->mutex);
|
|
||||||
#endif
|
|
||||||
if (match == 0)
|
|
||||||
return SC_ERROR_OBJECT_NOT_FOUND; /* FIXME: invent error */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sc_format_path(const char *str, struct sc_path *path)
|
void sc_format_path(const char *str, struct sc_path *path)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
@ -353,19 +173,6 @@ int sc_append_path_id(struct sc_path *dest, const u8 *id, size_t idlen)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sc_get_cache_dir(struct sc_context *ctx, char *buf, size_t bufsize)
|
|
||||||
{
|
|
||||||
char *homedir;
|
|
||||||
const char *cache_dir = ".eid/cache";
|
|
||||||
|
|
||||||
homedir = getenv("HOME");
|
|
||||||
if (homedir == NULL)
|
|
||||||
return SC_ERROR_INTERNAL;
|
|
||||||
if (snprintf(buf, bufsize, "%s/%s", homedir, cache_dir) < 0)
|
|
||||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *sc_strerror(int error)
|
const char *sc_strerror(int error)
|
||||||
{
|
{
|
||||||
const char *errors[] = {
|
const char *errors[] = {
|
||||||
|
|
Loading…
Reference in New Issue