예제 #1
0
파일: ctx.c 프로젝트: AktivCo/OpenSC
/**
 * 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
 */
static void *load_dynamic_driver(sc_context_t *ctx, void **dll, const char *name)
{
	const char *version, *libname;
	void *handle;
	void *(*modinit)(const char *) = NULL;
	void *(**tmodi)(const char *) = &modinit;
	const char *(*modversion)(void) = NULL;
	const char *(**tmodv)(void) = &modversion;

	if (dll == NULL) {
		sc_log(ctx, "No dll parameter specified");
		return NULL;
	}
	if (name == NULL) { /* should not occur, but... */
		sc_log(ctx, "No module specified");
		return NULL;
	}
	libname = find_library(ctx, name);
	if (libname == NULL)
		return NULL;
	handle = sc_dlopen(libname);
	if (handle == NULL) {
		sc_log(ctx, "Module %s: cannot load %s library: %s", name, libname, sc_dlerror());
		return NULL;
	}

	/* verify correctness of module */
	*(void **)tmodi = sc_dlsym(handle, "sc_module_init");
	*(void **)tmodv = sc_dlsym(handle, "sc_driver_version");
	if (modinit == NULL || modversion == NULL) {
		sc_log(ctx, "dynamic library '%s' is not a OpenSC module",libname);
		sc_dlclose(handle);
		return NULL;
	}
	/* verify module version */
	version = modversion();
	/* XXX: We really need to have ABI version for each interface */
	if (version == NULL || strncmp(version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)) != 0) {
		sc_log(ctx, "dynamic library '%s': invalid module version", libname);
		sc_dlclose(handle);
		return NULL;
	}

	*dll = handle;
	sc_log(ctx, "successfully loaded card driver '%s'", name);
	return modinit(name);
}
예제 #2
0
파일: card.c 프로젝트: AktivCo/OpenSC
static int
sc_card_sm_unload(struct sc_card *card)
{
	if (card->sm_ctx.module.ops.module_cleanup)
		card->sm_ctx.module.ops.module_cleanup(card->ctx);

	if (card->sm_ctx.module.handle)
		sc_dlclose(card->sm_ctx.module.handle);
	card->sm_ctx.module.handle = NULL;
	return 0;
}
예제 #3
0
파일: ctx.c 프로젝트: velter/OpenSC
static int load_card_drivers(sc_context_t *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++) {
		struct sc_card_driver *(*func)(void) = NULL;
		struct sc_card_driver *(**tfunc)(void) = &func;
		void *dll = NULL;
		int  j;

		if (drv_count >= SC_MAX_CARD_DRIVERS - 1)   {
			sc_log(ctx, "Not more then %i card drivers allowed.", SC_MAX_CARD_DRIVERS);
			break;
		}

		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 = (struct sc_card_driver *(*)(void)) internal_card_drivers[j].func;
				break;
			}
		/* if not initialized assume external module */
		if (func == NULL)
			*(void **)(tfunc) = load_dynamic_driver(ctx, &dll, ent->name);
		/* if still null, assume driver not found */
		if (func == NULL) {
			sc_log(ctx, "Unable to load '%s'.", ent->name);
			if (dll)
				sc_dlclose(dll);
			continue;
		}

		ctx->card_drivers[drv_count] = func();
		ctx->card_drivers[drv_count]->dll = dll;

		ctx->card_drivers[drv_count]->atr_map = NULL;
		ctx->card_drivers[drv_count]->natrs = 0;

		load_card_driver_options(ctx, ctx->card_drivers[drv_count]);

		/* Ensure that the list is always terminated by NULL */
		ctx->card_drivers[drv_count + 1] = NULL;

		drv_count++;
	}
	return SC_SUCCESS;
}
예제 #4
0
/*
 * Unload a pkcs11 module.
 * The calling application is responsible for cleaning up
 * and calling C_Finalize
 */
CK_RV
C_UnloadModule(void *module)
{
	sc_pkcs11_module_t *mod = (sc_pkcs11_module_t *) module;

	if (!mod || mod->_magic != MAGIC)
		return CKR_ARGUMENTS_BAD;

	if (mod->handle != NULL && sc_dlclose(mod->handle) < 0)
		return CKR_FUNCTION_FAILED;

	memset(mod, 0, sizeof(*mod));
	free(mod);
	return CKR_OK;
}
예제 #5
0
파일: ctx.c 프로젝트: AktivCo/OpenSC
int sc_release_context(sc_context_t *ctx)
{
	unsigned int i;

	if (ctx == NULL) {
		return SC_ERROR_INVALID_ARGUMENTS;
	}
	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
	while (list_size(&ctx->readers)) {
		sc_reader_t *rdr = (sc_reader_t *) list_get_at(&ctx->readers, 0);
		_sc_delete_reader(ctx, rdr);
	}

	if (ctx->reader_driver->ops->finish != NULL)
		ctx->reader_driver->ops->finish(ctx);

	for (i = 0; ctx->card_drivers[i]; i++) {
		struct sc_card_driver *drv = ctx->card_drivers[i];

		if (drv->atr_map)
			_sc_free_atr(ctx, drv);
		if (drv->dll)
			sc_dlclose(drv->dll);
	}
	if (ctx->preferred_language != NULL)
		free(ctx->preferred_language);
	if (ctx->mutex != NULL) {
		int r = sc_mutex_destroy(ctx, ctx->mutex);
		if (r != SC_SUCCESS) {
			sc_log(ctx, "unable to destroy mutex");
			return r;
		}
	}
	if (ctx->conf != NULL)
		scconf_free(ctx->conf);
	if (ctx->debug_file && (ctx->debug_file != stdout && ctx->debug_file != stderr))
		fclose(ctx->debug_file);
	if (ctx->debug_filename != NULL)
		free(ctx->debug_filename);
	if (ctx->app_name != NULL)
		free(ctx->app_name);
	list_destroy(&ctx->readers);
	sc_mem_clear(ctx, sizeof(*ctx));
	free(ctx);
	return SC_SUCCESS;
}
예제 #6
0
static int ctapi_finish(sc_context_t *ctx)
{
	struct ctapi_global_private_data *priv = (struct ctapi_global_private_data *) ctx->reader_drv_data;

	if (priv) {
		int i;
		
		for (i = 0; i < priv->module_count; i++) {
			struct ctapi_module *mod = &priv->modules[i];
			
			free(mod->name);
			sc_dlclose(mod->dlhandle);
		}
		if (priv->module_count)
			free(priv->modules);
		free(priv);
	}
	
	return 0;
}
예제 #7
0
static int ctapi_load_module(sc_context_t *ctx,
			     struct ctapi_global_private_data *gpriv,
			     scconf_block *conf)
{
	const char *val;
	struct ctapi_functions funcs;
	struct ctapi_module *mod;
	const scconf_list *list;
	void *dlh;
	int r, i, NumUnits;
	u8 cmd[5], rbuf[256], sad, dad;
	unsigned short lr;

	
	
	list = scconf_find_list(conf, "ports");
	if (list == NULL) {
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "No ports configured.\n");
		return -1;
	}

	val = conf->name->data;
	dlh = sc_dlopen(val);
	if (!dlh) {
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unable to open shared library '%s': %s\n", val, sc_dlerror());
		return -1;
	}

	funcs.CT_init = (CT_INIT_TYPE *) sc_dlsym(dlh, "CT_init");
	if (!funcs.CT_init)
		goto symerr;
	funcs.CT_close = (CT_CLOSE_TYPE *) sc_dlsym(dlh, "CT_close");
	if (!funcs.CT_close)
		goto symerr;
	funcs.CT_data = (CT_DATA_TYPE *) sc_dlsym(dlh, "CT_data");
	if (!funcs.CT_data)
		goto symerr;

	mod = add_module(gpriv, val, dlh);
	for (; list != NULL; list = list->next) {
		int port;
		char namebuf[128];
		char rv;
		sc_reader_t *reader;
		struct ctapi_private_data *priv;
		
		if (sscanf(list->data, "%d", &port) != 1) {
			sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Port '%s' is not a number.\n", list->data);
			continue;
		}
		rv = funcs.CT_init((unsigned short)mod->ctn_count, (unsigned short)port);
		if (rv) {
			sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "CT_init() failed with %d\n", rv);
			continue;
		}
		
		reader = calloc(1, sizeof(sc_reader_t));
		priv = calloc(1, sizeof(struct ctapi_private_data));
		if (!priv || !reader) {
			free(reader);
			free(priv);
			return SC_ERROR_OUT_OF_MEMORY;
		}
		reader->drv_data = priv;
		reader->ops = &ctapi_ops;
		reader->driver = &ctapi_drv;
		snprintf(namebuf, sizeof(namebuf), "CT-API %s, port %d", mod->name, port);
		reader->name = strdup(namebuf);
		priv->funcs = funcs;
		priv->ctn = mod->ctn_count;
		r = _sc_add_reader(ctx, reader);
		if (r) {
			funcs.CT_close((unsigned short)mod->ctn_count);
			free(priv);
			free(reader->name);
			free(reader);
			break;
		}
		
		/* Detect functional units of the reader according to CT-BCS spec version 1.0 
		(14.04.2004, http://www.teletrust.de/down/mct1-0_t4.zip) */	
		cmd[0] = CTBCS_CLA;
		cmd[1] = CTBCS_INS_STATUS;
		cmd[2] = CTBCS_P1_CT_KERNEL;
		cmd[3] = CTBCS_P2_STATUS_TFU;
		cmd[4] = 0x00;
		dad = 1;
		sad = 2;
		lr = 256;
		
		rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, 5, cmd, &lr, rbuf);
		if (rv || (lr < 4) || (rbuf[lr-2] != 0x90)) {
			sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "Error getting status of terminal: %d, using defaults\n", rv);
		}
		if (rbuf[0] != CTBCS_P2_STATUS_TFU) {
			/* Number of slots might also detected by using CTBCS_P2_STATUS_ICC.
			   If you think that's important please do it... ;) */
			sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "Invalid data object returnd on CTBCS_P2_STATUS_TFU: 0x%x\n", rbuf[0]);
		}
		NumUnits = rbuf[1];
		if (NumUnits + 4 > lr) {
			sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "Invalid data returnd: %d functional units, size %d\n", NumUnits, rv);
		}
		priv->ctapi_functional_units = 0;
		for(i = 0; i < NumUnits; i++) {
			switch(rbuf[i+2]) {
				case CTBCS_P1_INTERFACE1:
				case CTBCS_P1_INTERFACE2:
				case CTBCS_P1_INTERFACE3:
				case CTBCS_P1_INTERFACE4:
				case CTBCS_P1_INTERFACE5:
				case CTBCS_P1_INTERFACE6:
				case CTBCS_P1_INTERFACE7:
				case CTBCS_P1_INTERFACE8:
				case CTBCS_P1_INTERFACE9:
				case CTBCS_P1_INTERFACE10:
				case CTBCS_P1_INTERFACE11:
				case CTBCS_P1_INTERFACE12:
				case CTBCS_P1_INTERFACE13:
				case CTBCS_P1_INTERFACE14:
				/* Maybe a weak point here if multiple interfaces are present and not returned
				   in the "canonical" order. This is not forbidden by the specs, but why should
				   anyone want to do that? */
					sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "Found slot id 0x%x\n", rbuf[i+2]);
					break;

				case CTBCS_P1_DISPLAY:
					priv->ctapi_functional_units |= CTAPI_FU_DISPLAY;
					sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "Display detected\n");
					break;

				case CTBCS_P1_KEYPAD:
					priv->ctapi_functional_units |= CTAPI_FU_KEYBOARD;
					sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "Keypad detected\n");
					break;

				case CTBCS_P1_PRINTER:
					priv->ctapi_functional_units |= CTAPI_FU_PRINTER;
					sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "Printer detected\n");
					break;

				case CTBCS_P1_FINGERPRINT:
				case CTBCS_P1_VOICEPRINT:
				case CTBCS_P1_DSV:
				case CTBCS_P1_FACE_RECOGNITION:
				case CTBCS_P1_IRISSCAN:
					priv->ctapi_functional_units |= CTAPI_FU_BIOMETRIC;
					sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "Biometric sensor detected\n");
					break;

				default:
					sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "Unknown functional unit 0x%x\n", rbuf[i+2]);
			}
		}
		/* CT-BCS does not define Keyboard/Display for each slot, so I assume
		those additional units can be used for each slot */
		if (priv->ctapi_functional_units) {
			if (priv->ctapi_functional_units & CTAPI_FU_KEYBOARD)
				reader->capabilities |= SC_READER_CAP_PIN_PAD;
			if (priv->ctapi_functional_units & CTAPI_FU_DISPLAY)
				reader->capabilities |= SC_READER_CAP_DISPLAY;
		}
		
		ctapi_reset(reader);
		refresh_attributes(reader);
		mod->ctn_count++;
	}
	return 0;
symerr:
	sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unable to resolve CT-API symbols.\n");
	sc_dlclose(dlh);
	return -1;
}
예제 #8
0
/**
 * find library module for provided driver in configuration file
 * if not found assume library name equals to module name
 */
static const char *find_library(sc_context_t *ctx, const char *name)
{
	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], "card_driver", name);
		if (!blocks)
			continue;
		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, SC_LOG_DEBUG_NORMAL, "warning: relative path to driver '%s' used",
				 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
 */
static void *load_dynamic_driver(sc_context_t *ctx, void **dll, const char *name)
{
	const char *version, *libname;
	void *handle;
	void *(*modinit)(const char *) = NULL;
	void *(**tmodi)(const char *) = &modinit;
	const char *(*modversion)(void) = NULL;
	const char *(**tmodv)(void) = &modversion;

	if (name == NULL) { /* should not occurr, but... */
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"No module specified",name);
		return NULL;
	}
	libname = find_library(ctx, name);
	if (libname == NULL)
		return NULL;
	handle = sc_dlopen(libname);
	if (handle == NULL) {
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Module %s: cannot load %s library: %s", name, libname, sc_dlerror());
		return NULL;
	}

	/* verify correctness of module */
	*(void **)tmodi = sc_dlsym(handle, "sc_module_init");
	*(void **)tmodv = sc_dlsym(handle, "sc_driver_version");
	if (modinit == NULL || modversion == NULL) {
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "dynamic library '%s' is not a OpenSC module",libname);
		sc_dlclose(handle);
		return NULL;
	}
	/* verify module version */
	version = modversion();
	/* XXX: We really need to have ABI version for each interface */
	if (version == NULL || strncmp(version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)) != 0) {
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"dynamic library '%s': invalid module version",libname);
		sc_dlclose(handle);
		return NULL;
	}
	*dll = handle;
	sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "successfully loaded card driver '%s'", name);
	return modinit(name);
}

static int load_card_driver_options(sc_context_t *ctx,
				    struct sc_card_driver *driver)
{
	scconf_block **blocks, *blk;
	int i;

	for (i = 0; ctx->conf_blocks[i]; i++) {
		blocks = scconf_find_blocks(ctx->conf,
					ctx->conf_blocks[i],
					"card_driver", driver->short_name);
		if (!blocks)
			continue;
		blk = blocks[0];
		free(blocks);

		if (blk == NULL)
			continue;

		/* no options at the moment */
	}
	return SC_SUCCESS;
}
예제 #9
0
static int parse_emu_block(sc_pkcs15_card_t *p15card, scconf_block *conf)
{
	sc_card_t	*card = p15card->card;
	sc_context_t	*ctx = card->ctx;
	sc_pkcs15emu_opt_t opts;
	void *handle = NULL;
	int		(*init_func)(sc_pkcs15_card_t *);
	int		(*init_func_ex)(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
	int		r, force = 0;
	const char	*driver, *module_name;

	driver = conf->name->data;

	init_func    = NULL;
	init_func_ex = NULL;

	memset(&opts, 0, sizeof(opts));
	opts.blk     = conf;
	if (force != 0)
		opts.flags   = SC_PKCS15EMU_FLAGS_NO_CHECK;

	module_name = scconf_get_str(conf, "module", builtin_name);
	if (!strcmp(module_name, "builtin")) {
		int	i;

		/* This function is built into libopensc itself.
		 * Look it up in the table of emulators */
		module_name = driver;
		for (i = 0; builtin_emulators[i].name; i++) {
			if (!strcmp(builtin_emulators[i].name, module_name)) {
				init_func_ex = builtin_emulators[i].handler;
				break;
			}
		}
	} else {
		const char *(*get_version)(void);
		const char *name = NULL;
		void	*address;

		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Loading %s\n", module_name);
		
		/* try to open dynamic library */
		handle = sc_dlopen(module_name);
		if (!handle) {
			sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "unable to open dynamic library '%s': %s\n",
			         module_name, sc_dlerror());
			return SC_ERROR_INTERNAL;
		}
		/* try to get version of the driver/api */
		get_version =  (const char *(*)(void)) sc_dlsym(handle, "sc_driver_version");
		if (!get_version || strcmp(get_version(), "0.9.3") < 0) {
			/* no sc_driver_version function => assume old style
			 * init function (note: this should later give an error
			 */
			/* get the init function name */
			name = scconf_get_str(conf, "function", func_name);

			address = sc_dlsym(handle, name);
			if (address)
				init_func = (int (*)(sc_pkcs15_card_t *)) address;
		} else {
			name = scconf_get_str(conf, "function", exfunc_name);

			address = sc_dlsym(handle, name);
			if (address)
				init_func_ex = (int (*)(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *)) address;
		}
	}
	/* try to initialize the pkcs15 structures */
	if (init_func_ex)
		r = init_func_ex(p15card, &opts);
	else if (init_func)
		r = init_func(p15card);
	else
		r = SC_ERROR_WRONG_CARD;

	if (r >= 0) {
		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "%s succeeded, card bound\n",
				module_name);
		p15card->dll_handle = handle;
	} else {
		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "%s failed: %s\n",
				module_name, sc_strerror(r));
		/* clear pkcs15 card */
		sc_pkcs15_card_clear(p15card);
		if (handle)
			sc_dlclose(handle);
	}

	return r;
}