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; }
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); }