Exemplo n.º 1
0
static int
openct_add_reader(sc_context_t *ctx, unsigned int num, ct_info_t *info)
{
	sc_reader_t	*reader;
	scconf_block *conf_block;
	struct driver_data *data;
	int		rc;

	if (!(reader = calloc(1, sizeof(*reader)))
	 || !(data = (calloc(1, sizeof(*data))))) {
		if (reader)
			free(reader);
		return SC_ERROR_OUT_OF_MEMORY;
	}

	if (info) {
		data->info = *info;
	} else {
		strcpy(data->info.ct_name, "OpenCT reader (detached)");
		data->info.ct_slots = 1;
	}
	data->num = num;

	reader->driver = &openct_reader_driver;
	reader->ops = &openct_ops;
	reader->drv_data = data;
	reader->name = strdup(data->info.ct_name);

	conf_block = sc_get_conf_block(ctx, "reader_driver", "openct", 1);
	if (conf_block) {
		reader->max_send_size = scconf_get_int(conf_block, "max_send_size", reader->max_send_size);
		reader->max_recv_size = scconf_get_int(conf_block, "max_recv_size", reader->max_recv_size);
	}

	if ((rc = _sc_add_reader(ctx, reader)) < 0) {
		free(data);
		free(reader->name);
		free(reader);
		return rc;
	}

	if (data->info.ct_display)
		reader->capabilities |= SC_READER_CAP_DISPLAY;
	if (data->info.ct_keypad)
		reader->capabilities |= SC_READER_CAP_PIN_PAD;
	return 0;
}
static int
openct_add_reader(sc_context_t *ctx, unsigned int num, ct_info_t *info)
{
	sc_reader_t	*reader;
	struct driver_data *data;
	int		rc, i;

	if (!(reader = calloc(1, sizeof(*reader)))
	 || !(data = (calloc(1, sizeof(*data))))) {
		if (reader)
			free(reader);
		return SC_ERROR_OUT_OF_MEMORY;
	}

	if (info) {
		data->info = *info;
	} else {
		strcpy(data->info.ct_name, "OpenCT reader (detached)");
		data->info.ct_slots = 1;
	}
	data->num = num;

	reader->driver = &openct_reader_driver;
	reader->ops = &openct_ops;
	reader->drv_data = data;
	reader->name = strdup(data->info.ct_name);
	reader->slot_count = data->info.ct_slots;

	if ((rc = _sc_add_reader(ctx, reader)) < 0) { 
		free(data);
		free(reader->name);
		free(reader);
		return rc;
	}

	for (i = 0; i < SC_MAX_SLOTS; i++) {
		reader->slot[i].drv_data = calloc(1, sizeof(struct slot_data));
		reader->slot[i].id = i;
		if (data->info.ct_display)
			reader->slot[i].capabilities |= SC_SLOT_CAP_DISPLAY;
		if (data->info.ct_keypad)
			reader->slot[i].capabilities |= SC_SLOT_CAP_PIN_PAD;
	}

	return 0;
}
Exemplo n.º 3
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;
}
static int pcsc_detect_readers(sc_context_t *ctx, void *prv_data)
{
	struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) prv_data;
	LONG rv;
	DWORD reader_buf_size;
	char *reader_buf = NULL, *reader_name;
	const char *mszGroups = NULL;
	int ret = SC_ERROR_INTERNAL;

	SC_FUNC_CALLED(ctx, 3);

	if (!gpriv) {
		ret = SC_ERROR_NO_READERS_FOUND;
		goto out;
	}

	sc_debug(ctx, "Probing pcsc readers");

	do {
		if (gpriv->pcsc_ctx == -1) {
			/*
			 * Cannot call SCardListReaders with -1
			 * context as in Windows ERROR_INVALID_HANDLE
			 * is returned instead of SCARD_E_INVALID_HANDLE
			 */
			rv = SCARD_E_INVALID_HANDLE;
		}
		else {
			rv = gpriv->SCardListReaders(gpriv->pcsc_ctx, NULL, NULL,
					      (LPDWORD) &reader_buf_size);
		}
		if (rv != SCARD_S_SUCCESS) {
			if (rv != SCARD_E_INVALID_HANDLE) {
				PCSC_ERROR(ctx, "SCardListReaders failed", rv);
				ret = pcsc_ret_to_error(rv);
				goto out;
			}

			sc_debug(ctx, "Establish pcsc context");

			rv = gpriv->SCardEstablishContext(SCARD_SCOPE_USER,
					      NULL, NULL, &gpriv->pcsc_ctx);
			if (rv != SCARD_S_SUCCESS) {
				PCSC_ERROR(ctx, "SCardEstablishContext failed", rv);
				ret = pcsc_ret_to_error(rv);
				goto out;
			}

			rv = SCARD_E_INVALID_HANDLE;
		}
	} while (rv != SCARD_S_SUCCESS);

	reader_buf = (char *) malloc(sizeof(char) * reader_buf_size);
	if (!reader_buf) {
		ret = SC_ERROR_OUT_OF_MEMORY;
		goto out;
	}
	rv = gpriv->SCardListReaders(gpriv->pcsc_ctx, mszGroups, reader_buf,
	                      (LPDWORD) &reader_buf_size);
	if (rv != SCARD_S_SUCCESS) {
		PCSC_ERROR(ctx, "SCardListReaders failed", rv);
		ret = pcsc_ret_to_error(rv);
		goto out;
	}
	for (reader_name = reader_buf; *reader_name != '\x0'; reader_name += strlen (reader_name) + 1) {
		sc_reader_t *reader = NULL;
		struct pcsc_private_data *priv = NULL;
		struct pcsc_slot_data *pslot = NULL;
		sc_slot_info_t *slot = NULL;
		unsigned int i;
		int found = 0;

		for (i=0;i < sc_ctx_get_reader_count (ctx) && !found;i++) {
			sc_reader_t *reader2 = sc_ctx_get_reader (ctx, i);
			if (reader2 == NULL) {
				ret = SC_ERROR_INTERNAL;
				goto err1;
			}
			if (reader2->ops == &pcsc_ops && !strcmp (reader2->name, reader_name)) {
				found = 1;
			}
		}

		/* Reader already available, skip */
		if (found) {
			continue;
		}

		sc_debug(ctx, "Found new pcsc reader '%s'", reader_name);

		if ((reader = (sc_reader_t *) calloc(1, sizeof(sc_reader_t))) == NULL) {
			ret = SC_ERROR_OUT_OF_MEMORY;
			goto err1;
		}
		if ((priv = (struct pcsc_private_data *) malloc(sizeof(struct pcsc_private_data))) == NULL) {
			ret = SC_ERROR_OUT_OF_MEMORY;
			goto err1;
		}
		if ((pslot = (struct pcsc_slot_data *) malloc(sizeof(struct pcsc_slot_data))) == NULL) {
			ret = SC_ERROR_OUT_OF_MEMORY;
			goto err1;
		}

		reader->drv_data = priv;
		reader->ops = &pcsc_ops;
		reader->driver = &pcsc_drv;
		reader->slot_count = 1;
		if ((reader->name = strdup(reader_name)) == NULL) {
			ret = SC_ERROR_OUT_OF_MEMORY;
			goto err1;
		}
		priv->gpriv = gpriv;
		if ((priv->reader_name = strdup(reader_name)) == NULL) {
			ret = SC_ERROR_OUT_OF_MEMORY;
			goto err1;
		}
		slot = &reader->slot[0];
		memset(slot, 0, sizeof(*slot));
		slot->drv_data = pslot;
		memset(pslot, 0, sizeof(*pslot));
		if (_sc_add_reader(ctx, reader)) {
			ret = SC_SUCCESS;	/* silent ignore */
			goto err1;
		}
		refresh_slot_attributes(reader, slot);

		continue;
	
	err1:
		if (priv != NULL) {
			if (priv->reader_name)
				free(priv->reader_name);
			free(priv);
		}
		if (reader != NULL) {
			if (reader->name)
				free(reader->name);
			free(reader);
		}
		if (slot != NULL)
			free(pslot);

		goto out;
	}

	ret = SC_SUCCESS;

out:

	if (reader_buf != NULL)
		free (reader_buf);

	SC_FUNC_RETURN(ctx, 3, ret);
}