static int load_parameters(sc_context_t *ctx, scconf_block *block, struct _sc_ctx_options *opts) { int err = 0; const scconf_list *list; const char *val, *s_internal = "internal"; int debug; int reopen; #ifdef _WIN32 char expanded_val[PATH_MAX]; DWORD expanded_len; #endif reopen = scconf_get_bool(block, "reopen_debug_file", 1); debug = scconf_get_int(block, "debug", ctx->debug); if (debug > ctx->debug) ctx->debug = debug; val = scconf_get_str(block, "debug_file", NULL); if (val) { #ifdef _WIN32 expanded_len = PATH_MAX; expanded_len = ExpandEnvironmentStringsA(val, expanded_val, expanded_len); if (expanded_len > 0) val = expanded_val; #endif if (reopen) ctx->debug_filename = strdup(val); sc_ctx_log_to_file(ctx, val); } ctx->paranoid_memory = scconf_get_bool (block, "paranoid-memory", ctx->paranoid_memory); ctx->enable_default_driver = scconf_get_bool (block, "enable_default_driver", ctx->enable_default_driver); val = scconf_get_str(block, "force_card_driver", NULL); if (val) { if (opts->forced_card_driver) free(opts->forced_card_driver); opts->forced_card_driver = strdup(val); } list = scconf_find_list(block, "card_drivers"); if (list != NULL) del_drvs(opts); while (list != NULL) { if (strcmp(list->data, s_internal) == 0) add_internal_drvs(opts); else add_drv(opts, list->data); list = list->next; } return err; }
static int load_parameters(sc_context_t *ctx, scconf_block *block, struct _sc_ctx_options *opts) { int err = 0; const scconf_list *list; const char *val; int debug; #ifdef _WIN32 char expanded_val[PATH_MAX]; DWORD expanded_len; #endif debug = scconf_get_int(block, "debug", ctx->debug); if (debug > ctx->debug) ctx->debug = debug; val = scconf_get_str(block, "debug_file", NULL); if (val) { #ifdef _WIN32 expanded_len = PATH_MAX; expanded_len = ExpandEnvironmentStringsA(val, expanded_val, expanded_len); if (0 < expanded_len && expanded_len < sizeof expanded_val) val = expanded_val; #endif sc_ctx_log_to_file(ctx, val); } else if (ctx->debug) { sc_ctx_log_to_file(ctx, NULL); } if (scconf_get_bool (block, "disable_popups", ctx->flags & SC_CTX_FLAG_DISABLE_POPUPS)) ctx->flags |= SC_CTX_FLAG_DISABLE_POPUPS; if (scconf_get_bool (block, "disable_colors", ctx->flags & SC_CTX_FLAG_DISABLE_COLORS)) ctx->flags |= SC_CTX_FLAG_DISABLE_COLORS; if (scconf_get_bool (block, "enable_default_driver", ctx->flags & SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER)) ctx->flags |= SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER; list = scconf_find_list(block, "card_drivers"); set_drivers(opts, list); return err; }
mapper_module * mapper_module_init(scconf_block *blk,const char *mapper_name) { #else mapper_module * uid_mapper_module_init(scconf_block *blk,const char *mapper_name) { #endif mapper_module *pt; if (blk) { debug= scconf_get_bool(blk,"debug",0); mapfile = scconf_get_str(blk,"mapfile",mapfile); ignorecase = scconf_get_bool(blk,"ignorecase",ignorecase); } else { DBG1("No block declaration for mapper '%s'", mapper_name); } set_debug_level(debug); pt= init_mapper_st(blk,mapper_name); if(pt) DBG3("UniqueID mapper started. debug: %d, mapfile: %s, icase: %d",debug,mapfile,ignorecase); else DBG("UniqueID mapper initialization failed"); return pt; }
mapper_module * mapper_module_init(scconf_block *ctx,const char *mapper_name) { #else mapper_module * null_mapper_module_init(scconf_block *ctx,const char *mapper_name) { #endif mapper_module *pt= NULL; if (ctx) { default_user = scconf_get_str( ctx,"default_user",default_user); match = scconf_get_bool( ctx,"default_match",0); debug = scconf_get_bool( ctx,"debug",0); } else { DBG1("No block declaration for mapper '%s'", mapper_name); } set_debug_level(debug); pt = init_mapper_st(ctx,mapper_name); if (pt) DBG1("Null mapper match set to '%s'",match?"always":"never"); else DBG("Null mapper initialization failed"); return pt; }
mapper_module * mapper_module_init(scconf_block *blk,const char *mapper_name) { #else mapper_module * krb_mapper_module_init(scconf_block *blk,const char *mapper_name) { #endif mapper_module *pt; if( blk) debug = scconf_get_bool(blk,"debug",0); set_debug_level(debug); pt=init_mapper_st(blk,mapper_name); if(pt) DBG("KPN mappper started"); else DBG("KPN mapper initialization failed"); return pt; }
/** * Parse configuration file to extract user consent flags */ static int get_user_consent_env(sc_context_t *ctx) { int i; scconf_block **blocks, *blk; for (i = 0; ctx->conf_blocks[i]; i++) { blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],"card_driver","dnie"); if (!blocks) continue; blk=blocks[0]; free(blocks); if (blk==NULL) continue; user_consent_app = scconf_get_str(blk,"user_consent_app",PIN_ENTRY); user_consent_enabled = scconf_get_bool(blk,"user_consent_enabled",1); } return SC_SUCCESS; }
void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t * ctx) { scconf_block *conf_block = NULL; char *unblock_style = NULL; /* Set defaults */ conf->plug_and_play = 1; conf->max_virtual_slots = 16; conf->slots_per_card = 4; conf->hide_empty_tokens = 1; conf->lock_login = 0; conf->soft_keygen_allowed = 0; conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_NOT_ALLOWED; conf->create_puk_slot = 0; conf->zero_ckaid_for_ca_certs = 0; conf_block = sc_get_conf_block(ctx, "pkcs11", NULL, 1); if (!conf_block) return; /* contains the defaults, if there is a "pkcs11" config block */ conf->plug_and_play = scconf_get_bool(conf_block, "plug_and_play", conf->plug_and_play); conf->max_virtual_slots = scconf_get_int(conf_block, "max_virtual_slots", conf->max_virtual_slots); conf->slots_per_card = scconf_get_int(conf_block, "slots_per_card", conf->slots_per_card); conf->hide_empty_tokens = scconf_get_bool(conf_block, "hide_empty_tokens", conf->hide_empty_tokens); conf->lock_login = scconf_get_bool(conf_block, "lock_login", conf->lock_login); conf->soft_keygen_allowed = scconf_get_bool(conf_block, "soft_keygen_allowed", conf->soft_keygen_allowed); unblock_style = (char *)scconf_get_str(conf_block, "user_pin_unblock_style", NULL); if (unblock_style && !strcmp(unblock_style, "set_pin_in_unlogged_session")) conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_UNLOGGED_SETPIN; else if (unblock_style && !strcmp(unblock_style, "set_pin_in_specific_context")) conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_SCONTEXT_SETPIN; else if (unblock_style && !strcmp(unblock_style, "init_pin_in_so_session")) conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_SO_LOGGED_INITPIN; conf->create_puk_slot = scconf_get_bool(conf_block, "create_puk_slot", conf->create_puk_slot); conf->zero_ckaid_for_ca_certs = scconf_get_bool(conf_block, "zero_ckaid_for_ca_certs", conf->zero_ckaid_for_ca_certs); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PKCS#11 options: plug_and_play=%d max_virtual_slots=%d slots_per_card=%d " "hide_empty_tokens=%d lock_login=%d pin_unblock_style=%d zero_ckaid_for_ca_certs=%d", conf->plug_and_play, conf->max_virtual_slots, conf->slots_per_card, conf->hide_empty_tokens, conf->lock_login, conf->pin_unblock_style, conf->zero_ckaid_for_ca_certs); }
static int read_config(scconf_block *blk) { int debug = scconf_get_bool(blk,"debug",0); const char *ssltls; ldaphost = scconf_get_str(blk,"ldaphost",ldaphost); ldapport = scconf_get_int(blk,"ldapport",ldapport); ldapURI = scconf_get_str(blk,"uri",ldapURI); scope = scconf_get_int(blk,"scope",scope); binddn = scconf_get_str(blk,"binddn",binddn); passwd = scconf_get_str(blk,"passwd",passwd); base = scconf_get_str(blk,"base",base); attribute = scconf_get_str(blk,"attribute",attribute); filter = scconf_get_str(blk,"filter",filter); ignorecase = scconf_get_bool(blk,"ignorecase",ignorecase); searchtimeout = scconf_get_int(blk,"searchtimeout",searchtimeout); ssltls = scconf_get_str(blk,"ssl","off"); if (! strncasecmp (ssltls, "tls", 3)) ssl_on = SSL_START_TLS; else if( ! strncasecmp (ssltls, "on", 2)) ssl_on = SSL_LDAPS; else if( ! strncasecmp (ssltls, "ssl", 3)) ssl_on = SSL_LDAPS; #if defined HAVE_LDAP_START_TLS_S || (defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS)) /* TLS specific options */ tls_randfile = scconf_get_str(blk,"tls_randfile",tls_randfile); tls_cacertfile = scconf_get_str(blk,"tls_cacertfile",tls_cacertfile); tls_cacertdir = scconf_get_str(blk,"tls_cacertdir",tls_cacertdir); tls_checkpeer=scconf_get_int(blk,"tls_checkpeer",tls_checkpeer); tls_ciphers = scconf_get_str(blk,"tls_ciphers",tls_ciphers); tls_cert = scconf_get_str(blk,"tls_cert",tls_cert); tls_key = scconf_get_str(blk,"tls_key",tls_key); #endif set_debug_level(debug); DBG1("test ssltls = %s", ssltls); DBG("LDAP mapper started."); DBG1("debug = %d", debug); DBG1("ignorecase = %d", ignorecase); DBG1("ldaphost = %s", ldaphost); DBG1("ldapport = %d", ldapport); DBG1("ldapURI = %s", ldapURI); DBG1("scope = %d", scope); DBG1("binddn = %s", binddn); DBG1("passwd = %s", passwd); DBG1("base = %s", base); DBG1("attribute = %s", attribute); DBG1("filter = %s", filter); DBG1("searchtimeout = %d", searchtimeout); DBG1("ssl_on = %d", ssl_on); #if defined HAVE_LDAP_START_TLS_S || (defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS)) DBG1("tls_randfile = %s", tls_randfile); DBG1("tls_cacertfile= %s", tls_cacertfile); DBG1("tls_cacertdir = %s", tls_cacertdir); DBG1("tls_checkpeer = %d", tls_checkpeer); DBG1("tls_ciphers = %s", tls_ciphers); DBG1("tls_cert = %s", tls_cert); DBG1("tls_key = %s", tls_key); #endif return 1; }
CK_RV card_detect(sc_reader_t *reader) { struct sc_pkcs11_card *p11card = NULL; int free_p11card = 0; int rc; CK_RV rv; unsigned int i; int j; sc_log(context, "%s: Detecting smart card", reader->name); /* Check if someone inserted a card */ again: rc = sc_detect_card_presence(reader); if (rc < 0) { sc_log(context, "%s: failed, %s", reader->name, sc_strerror(rc)); return sc_to_cryptoki_error(rc, NULL); } if (rc == 0) { sc_log(context, "%s: card absent", reader->name); card_removed(reader); /* Release all resources */ return CKR_TOKEN_NOT_PRESENT; } /* If the card was changed, disconnect the current one */ if (rc & SC_READER_CARD_CHANGED) { sc_log(context, "%s: Card changed", reader->name); /* The following should never happen - but if it * does we'll be stuck in an endless loop. * So better be fussy. if (!retry--) return CKR_TOKEN_NOT_PRESENT; */ card_removed(reader); goto again; } /* Locate a slot related to the reader */ for (i=0; i<list_size(&virtual_slots); i++) { sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); if (slot->reader == reader) { p11card = slot->p11card; break; } } /* Detect the card if it's not known already */ if (p11card == NULL) { sc_log(context, "%s: First seen the card ", reader->name); p11card = (struct sc_pkcs11_card *)calloc(1, sizeof(struct sc_pkcs11_card)); if (!p11card) return CKR_HOST_MEMORY; free_p11card = 1; p11card->reader = reader; } if (p11card->card == NULL) { sc_log(context, "%s: Connecting ... ", reader->name); rc = sc_connect_card(reader, &p11card->card); if (rc != SC_SUCCESS) { sc_log(context, "%s: SC connect card error %i", reader->name, rc); rv = sc_to_cryptoki_error(rc, NULL); goto fail; } /* escape commands are only guaranteed to be working with a card * inserted. That's why by now, after sc_connect_card() the reader's * metadata may have changed. We re-initialize the metadata for every * slot of this reader here. */ if (reader->flags & SC_READER_ENABLE_ESCAPE) { for (i = 0; i<list_size(&virtual_slots); i++) { sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); if (slot->reader == reader) init_slot_info(&slot->slot_info, reader); } } sc_log(context, "%s: Connected SC card %p", reader->name, p11card->card); } /* Detect the framework */ if (p11card->framework == NULL) { struct sc_app_info *app_generic = sc_pkcs15_get_application_by_type(p11card->card, "generic"); sc_log(context, "%s: Detecting Framework. %i on-card applications", reader->name, p11card->card->app_count); sc_log(context, "%s: generic application %s", reader->name, app_generic ? app_generic->label : "<none>"); for (i = 0; frameworks[i]; i++) if (frameworks[i]->bind != NULL) break; /*TODO: only first framework is used: pkcs15init framework is not reachable here */ if (frameworks[i] == NULL) { rv = CKR_GENERAL_ERROR; goto fail; } p11card->framework = frameworks[i]; /* Initialize framework */ sc_log(context, "%s: Detected framework %d. Creating tokens.", reader->name, i); /* Bind 'generic' application or (emulated?) card without applications */ if (app_generic || !p11card->card->app_count) { scconf_block *conf_block = NULL; int enable_InitToken = 0; conf_block = sc_match_atr_block(p11card->card->ctx, NULL, &p11card->reader->atr); if (!conf_block) /* check default block */ conf_block = sc_get_conf_block(context, "framework", "pkcs15", 1); enable_InitToken = scconf_get_bool(conf_block, "pkcs11_enable_InitToken", 0); sc_log(context, "%s: Try to bind 'generic' token.", reader->name); rv = frameworks[i]->bind(p11card, app_generic); if (rv == CKR_TOKEN_NOT_RECOGNIZED && enable_InitToken) { sc_log(context, "%s: 'InitToken' enabled -- accept non-binded card", reader->name); rv = CKR_OK; } if (rv != CKR_OK) { sc_log(context, "%s: cannot bind 'generic' token: rv 0x%lX", reader->name, rv); goto fail; } sc_log(context, "%s: Creating 'generic' token.", reader->name); rv = frameworks[i]->create_tokens(p11card, app_generic); if (rv != CKR_OK) { sc_log(context, "%s: create 'generic' token error 0x%lX", reader->name, rv); goto fail; } } /* Now bind the rest of applications that are not 'generic' */ for (j = 0; j < p11card->card->app_count; j++) { struct sc_app_info *app_info = p11card->card->app[j]; char *app_name = app_info ? app_info->label : "<anonymous>"; if (app_generic && app_generic == p11card->card->app[j]) continue; sc_log(context, "%s: Binding %s token.", reader->name, app_name); rv = frameworks[i]->bind(p11card, app_info); if (rv != CKR_OK) { sc_log(context, "%s: bind %s token error Ox%lX", reader->name, app_name, rv); continue; } sc_log(context, "%s: Creating %s token.", reader->name, app_name); rv = frameworks[i]->create_tokens(p11card, app_info); if (rv != CKR_OK) { sc_log(context, "%s: create %s token error 0x%lX", reader->name, app_name, rv); goto fail; } } } sc_log(context, "%s: Detection ended", reader->name); return CKR_OK; fail: if (free_p11card) { if (p11card->framework) p11card->framework->unbind(p11card); if (p11card->card != NULL) sc_disconnect_card(p11card->card); free(p11card); } return rv; }
static int pcsc_init(sc_context_t *ctx, void **reader_data) { struct pcsc_global_private_data *gpriv; scconf_block *conf_block = NULL; int ret = SC_ERROR_INTERNAL; *reader_data = NULL; gpriv = (struct pcsc_global_private_data *) calloc(1, sizeof(struct pcsc_global_private_data)); if (gpriv == NULL) { ret = SC_ERROR_OUT_OF_MEMORY; goto out; } /* Defaults */ gpriv->connect_reset = 1; gpriv->connect_exclusive = 0; gpriv->transaction_reset = 0; gpriv->enable_pinpad = 0; gpriv->provider_library = DEFAULT_PCSC_PROVIDER; gpriv->pcsc_ctx = -1; conf_block = sc_get_conf_block(ctx, "reader_driver", "pcsc", 1); if (conf_block) { gpriv->connect_reset = scconf_get_bool(conf_block, "connect_reset", gpriv->connect_reset); gpriv->connect_exclusive = scconf_get_bool(conf_block, "connect_exclusive", gpriv->connect_exclusive); gpriv->transaction_reset = scconf_get_bool(conf_block, "transaction_reset", gpriv->transaction_reset); gpriv->enable_pinpad = scconf_get_bool(conf_block, "enable_pinpad", gpriv->enable_pinpad); gpriv->provider_library = scconf_get_str(conf_block, "provider_library", gpriv->provider_library); } gpriv->dlhandle = lt_dlopen(gpriv->provider_library); if (gpriv->dlhandle == NULL) { ret = SC_ERROR_CANNOT_LOAD_MODULE; goto out; } gpriv->SCardEstablishContext = (SCardEstablishContext_t)lt_dlsym(gpriv->dlhandle, "SCardEstablishContext"); gpriv->SCardReleaseContext = (SCardReleaseContext_t)lt_dlsym(gpriv->dlhandle, "SCardReleaseContext"); gpriv->SCardConnect = (SCardConnect_t)lt_dlsym(gpriv->dlhandle, "SCardConnect"); gpriv->SCardReconnect = (SCardReconnect_t)lt_dlsym(gpriv->dlhandle, "SCardReconnect"); gpriv->SCardDisconnect = (SCardDisconnect_t)lt_dlsym(gpriv->dlhandle, "SCardDisconnect"); gpriv->SCardBeginTransaction = (SCardBeginTransaction_t)lt_dlsym(gpriv->dlhandle, "SCardBeginTransaction"); gpriv->SCardEndTransaction = (SCardEndTransaction_t)lt_dlsym(gpriv->dlhandle, "SCardEndTransaction"); gpriv->SCardStatus = (SCardStatus_t)lt_dlsym(gpriv->dlhandle, "SCardStatus"); gpriv->SCardGetStatusChange = (SCardGetStatusChange_t)lt_dlsym(gpriv->dlhandle, "SCardGetStatusChange"); gpriv->SCardTransmit = (SCardTransmit_t)lt_dlsym(gpriv->dlhandle, "SCardTransmit"); gpriv->SCardListReaders = (SCardListReaders_t)lt_dlsym(gpriv->dlhandle, "SCardListReaders"); if (gpriv->SCardConnect == NULL) gpriv->SCardConnect = (SCardConnect_t)lt_dlsym(gpriv->dlhandle, "SCardConnectA"); if (gpriv->SCardStatus == NULL) gpriv->SCardStatus = (SCardStatus_t)lt_dlsym(gpriv->dlhandle, "SCardStatusA"); if (gpriv->SCardGetStatusChange == NULL) gpriv->SCardGetStatusChange = (SCardGetStatusChange_t)lt_dlsym(gpriv->dlhandle, "SCardGetStatusChangeA"); if (gpriv->SCardListReaders == NULL) gpriv->SCardListReaders = (SCardListReaders_t)lt_dlsym(gpriv->dlhandle, "SCardListReadersA"); /* If we have SCardGetAttrib it is correct API */ if (lt_dlsym(gpriv->dlhandle, "SCardGetAttrib") != NULL) { #ifdef __APPLE__ gpriv->SCardControl = (SCardControl_t)lt_dlsym(gpriv->dlhandle, "SCardControl132"); #endif if (gpriv->SCardControl == NULL) { gpriv->SCardControl = (SCardControl_t)lt_dlsym(gpriv->dlhandle, "SCardControl"); } } else { gpriv->SCardControlOLD = (SCardControlOLD_t)lt_dlsym(gpriv->dlhandle, "SCardControl"); } if ( gpriv->SCardReleaseContext == NULL || gpriv->SCardConnect == NULL || gpriv->SCardReconnect == NULL || gpriv->SCardDisconnect == NULL || gpriv->SCardBeginTransaction == NULL || gpriv->SCardEndTransaction == NULL || gpriv->SCardStatus == NULL || gpriv->SCardGetStatusChange == NULL || (gpriv->SCardControl == NULL && gpriv->SCardControlOLD == NULL) || gpriv->SCardTransmit == NULL || gpriv->SCardListReaders == NULL ) { ret = SC_ERROR_CANNOT_LOAD_MODULE; goto out; } *reader_data = gpriv; gpriv = NULL; ret = SC_SUCCESS; out: if (gpriv != NULL) { if (gpriv->dlhandle != NULL) lt_dlclose(gpriv->dlhandle); free(gpriv); } return ret; }
static int parse_type(const scconf_context * config, const scconf_block * block, scconf_entry * entry, int depth) { void *parm = entry->parm; size_t *len = (size_t *) entry->arg; int (*callback_func) (const scconf_context * config, const scconf_block * block, scconf_entry * entry, int depth) = (int (*)(const scconf_context *, const scconf_block *, scconf_entry *, int)) parm; int r = 0; if (config->debug) { fprintf(stderr, "decoding '%s'\n", entry->name); } switch (entry->type) { case SCCONF_CALLBACK: if (parm) { r = callback_func(config, block, entry, depth); } break; case SCCONF_BLOCK: if (parm) { r = parse_entries(config, block, (scconf_entry *) parm, depth + 1); } break; case SCCONF_LIST: { const scconf_list *val = scconf_find_list(block, entry->name); if (!val) { r = 1; break; } if (parm) { if (entry->flags & SCCONF_ALLOC) { scconf_list *dest = NULL; for (; val != NULL; val = val->next) { if (!scconf_list_add(&dest, val->data)) { r = 1; break; } } *((scconf_list **) parm) = dest; } else { *((const scconf_list **) parm) = val; } } if (entry->flags & SCCONF_VERBOSE) { char *buf = scconf_list_strdup(val, ", "); printf("%s = %s\n", entry->name, buf); free(buf); } } break; case SCCONF_BOOLEAN: { int val = scconf_get_bool(block, entry->name, 0); if (parm) { *((int *) parm) = val; } if (entry->flags & SCCONF_VERBOSE) { printf("%s = %s\n", entry->name, val == 0 ? "false" : "true"); } } break; case SCCONF_INTEGER: { int val = scconf_get_int(block, entry->name, 0); if (parm) { *((int *) parm) = val; } if (entry->flags & SCCONF_VERBOSE) { printf("%s = %i\n", entry->name, val); } } break; case SCCONF_STRING: { const char *val = scconf_get_str(block, entry->name, NULL); int vallen = val ? strlen(val) : 0; if (!vallen) { r = 1; break; } if (parm) { if (entry->flags & SCCONF_ALLOC) { char **buf = (char **) parm; *buf = malloc(vallen + 1); if (*buf == NULL) { r = 1; break; } memset(*buf, 0, vallen + 1); if (len) { *len = vallen; } parm = *buf; } memcpy((char *) parm, val, vallen); } if (entry->flags & SCCONF_VERBOSE) { printf("%s = %s\n", entry->name, val); } } break; default: fprintf(stderr, "invalid configuration type: %d\n", entry->type); } if (r) { fprintf(stderr, "decoding of configuration entry '%s' failed.\n", entry->name); return r; } entry->flags |= SCCONF_PRESENT; return 0; }
int sc_pkcs15_bind(sc_card_t *card, struct sc_pkcs15_card **p15card_out) { struct sc_pkcs15_card *p15card = NULL; sc_context_t *ctx; scconf_block *conf_block = NULL, **blocks; int i, r, emu_first, enable_emu; assert(sc_card_valid(card) && p15card_out != NULL); ctx = card->ctx; SC_FUNC_CALLED(ctx, 1); p15card = sc_pkcs15_card_new(); if (p15card == NULL) return SC_ERROR_OUT_OF_MEMORY; p15card->card = card; for (i = 0; ctx->conf_blocks[i] != NULL; i++) { blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i], "framework", "pkcs15"); if (blocks && blocks[0] != NULL) conf_block = blocks[0]; free(blocks); } if (conf_block) { p15card->opts.use_cache = scconf_get_bool(conf_block, "use_caching", 0); } r = sc_lock(card); if (r) { sc_error(ctx, "sc_lock() failed: %s\n", sc_strerror(r)); sc_pkcs15_card_free(p15card); SC_FUNC_RETURN(ctx, 1, r); } enable_emu = scconf_get_bool(conf_block, "enable_pkcs15_emulation", 1); if (enable_emu) { emu_first = scconf_get_bool(conf_block, "try_emulation_first", 0); if (emu_first || sc_pkcs15_is_emulation_only(card)) { r = sc_pkcs15_bind_synthetic(p15card); if (r == SC_SUCCESS) goto done; r = sc_pkcs15_bind_internal(p15card); if (r < 0) goto error; } else { r = sc_pkcs15_bind_internal(p15card); if (r == SC_SUCCESS) goto done; r = sc_pkcs15_bind_synthetic(p15card); if (r < 0) goto error; } } else { r = sc_pkcs15_bind_internal(p15card); if (r < 0) goto error; } done: *p15card_out = p15card; sc_unlock(card); return 0; error: sc_unlock(card); sc_pkcs15_card_free(p15card); SC_FUNC_RETURN(ctx, 1, r); }
int sc_pkcs15_bind_synthetic(sc_pkcs15_card_t *p15card) { sc_context_t *ctx = p15card->card->ctx; scconf_block *conf_block, **blocks, *blk; sc_pkcs15emu_opt_t opts; int i, r = SC_ERROR_WRONG_CARD; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); memset(&opts, 0, sizeof(opts)); conf_block = NULL; conf_block = sc_get_conf_block(ctx, "framework", "pkcs15", 1); if (!conf_block) { /* no conf file found => try bultin drivers */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "no conf file (or section), trying all builtin emulators\n"); for (i = 0; builtin_emulators[i].name; i++) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "trying %s\n", builtin_emulators[i].name); r = builtin_emulators[i].handler(p15card, &opts); if (r == SC_SUCCESS) /* we got a hit */ goto out; } } else { /* we have a conf file => let's use it */ int builtin_enabled; const scconf_list *list, *item; builtin_enabled = scconf_get_bool(conf_block, "enable_builtin_emulation", 1); list = scconf_find_list(conf_block, "builtin_emulators"); /* FIXME: rename to enabled_emulators */ if (builtin_enabled && list) { /* get the list of enabled emulation drivers */ for (item = list; item; item = item->next) { /* go through the list of builtin drivers */ const char *name = item->data; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "trying %s\n", name); for (i = 0; builtin_emulators[i].name; i++) if (!strcmp(builtin_emulators[i].name, name)) { r = builtin_emulators[i].handler(p15card, &opts); if (r == SC_SUCCESS) /* we got a hit */ goto out; } } } else if (builtin_enabled) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "no emulator list in config file, trying all builtin emulators\n"); for (i = 0; builtin_emulators[i].name; i++) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "trying %s\n", builtin_emulators[i].name); r = builtin_emulators[i].handler(p15card, &opts); if (r == SC_SUCCESS) /* we got a hit */ goto out; } } /* search for 'emulate foo { ... }' entries in the conf file */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "searching for 'emulate foo { ... }' blocks\n"); blocks = scconf_find_blocks(ctx->conf, conf_block, "emulate", NULL); for (i = 0; blocks && (blk = blocks[i]) != NULL; i++) { const char *name = blk->name->data; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "trying %s\n", name); r = parse_emu_block(p15card, blk); if (r == SC_SUCCESS) { free(blocks); goto out; } } if (blocks) free(blocks); } /* Total failure */ return SC_ERROR_WRONG_CARD; out: if (r == SC_SUCCESS) { p15card->magic = SC_PKCS15_CARD_MAGIC; p15card->flags |= SC_PKCS15_CARD_FLAG_EMULATED; } else if (r != SC_ERROR_WRONG_CARD) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Failed to load card emulator: %s\n", sc_strerror(r)); } return r; }
static int belpic_init(sc_card_t *card) { struct belpic_priv_data *priv = NULL; scconf_block *conf_block; #ifdef BELPIC_PIN_PAD int r; #endif sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Belpic V%s", BELPIC_VERSION); #ifdef HAVE_GUI sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, " with GUI support"); #endif #ifdef BELPIC_PIN_PAD sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, " with support for pin pad reader libs"); #endif sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "\n"); if (card->type < 0) card->type = SC_CARD_TYPE_BELPIC_EID; /* Unknown card: assume it's the Belpic Card */ priv = calloc(1, sizeof(struct belpic_priv_data)); if (priv == NULL) return SC_ERROR_OUT_OF_MEMORY; card->drv_data = priv; card->cla = 0x00; if (card->type == SC_CARD_TYPE_BELPIC_EID) { _sc_card_add_rsa_alg(card, 1024, SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE, 0); } /* V1 applets have a problem: if the card sends a 6C XX (only XX bytes available), * and we resend the command too soon (i.e. the reader is too fast), the card * doesn't respond. So we build in a delay. */ card->wait_resend_apdu = 40; /* State that we have an RNG */ card->caps |= SC_CARD_CAP_RNG; /* State that we don't return FCI (no file type, no file size, ...) */ card->caps |= SC_CARD_CAP_NO_FCI; /* Language prefences */ priv->lang = -1; conf_block = get_belpic_conf(card->ctx, "belpic_general"); if (conf_block != NULL) { char *lang = (char *) scconf_get_str(conf_block, "force_language", NULL); if (lang != NULL && strlen(lang) == 2) priv->lang = str2lang(card->ctx, lang); } #ifdef GET_LANG_FROM_CARD if (priv->lang == -1) priv->lang = get_language(card); #endif card->max_pin_len = BELPIC_MAX_USER_PIN_LEN; #ifdef HAVE_GUI r = scgui_init(); if (r != 0) sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "scgui_init() returned error %d\n", i); #endif #ifdef BELPIC_PIN_PAD r = belpic_detect_pin_pad(card, priv); if (r == 1) card->reader->capabilities |= SC_READER_CAP_PIN_PAD; else if (r < 0) return r; /* error loading/initing pin pad lib */ conf_block = get_belpic_conf(card->ctx, "belpic_pin_pad"); if (conf_block != NULL) { if (scconf_get_bool(conf_block, "msg_auth_pin", 1)) priv->options |= PP_MSG_AUTH_PIN; if (scconf_get_bool(conf_block, "msg_wrong_pin", 1)) priv->options |= PP_MSG_WRONG_PIN; if (scconf_get_bool(conf_block, "msg_changepin_mismatch", 1)) priv->options |= PP_MSG_CHANGEPIN_MISMATCH; if (scconf_get_bool(conf_block, "msg_pin_blocked", 1)) priv->options |= PP_MSG_PIN_BLOCKED; } #endif 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; scconf_block *conf_block = NULL; 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_log(ctx, "No ports configured."); return -1; } val = conf->name->data; dlh = sc_dlopen(val); if (!dlh) { sc_log(ctx, "Unable to open shared library '%s': %s", 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); if (!mod) goto symerr; 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_log(ctx, "Port '%s' is not a number.", list->data); continue; } rv = funcs.CT_init((unsigned short)mod->ctn_count, (unsigned short)port); if (rv) { sc_log(ctx, "CT_init() failed with %d", 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; reader->max_send_size = SC_READER_SHORT_APDU_MAX_SEND_SIZE; reader->max_recv_size = SC_READER_SHORT_APDU_MAX_RECV_SIZE; conf_block = sc_get_conf_block(ctx, "reader_driver", "ctapi", 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 (scconf_get_bool(conf_block, "enable_escape", 0)) reader->flags |= SC_READER_ENABLE_ESCAPE; } 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_log(reader->ctx, "Error getting status of terminal: %d, using defaults", 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_log(reader->ctx, "Invalid data object returned on CTBCS_P2_STATUS_TFU: 0x%x", rbuf[0]); } NumUnits = rbuf[1]; if (NumUnits + 4 > lr) { sc_log(reader->ctx, "Invalid data returned: %d functional units, size %d", 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_log(reader->ctx, "Found slot id 0x%x", rbuf[i+2]); break; case CTBCS_P1_DISPLAY: priv->ctapi_functional_units |= CTAPI_FU_DISPLAY; sc_log(reader->ctx, "Display detected"); break; case CTBCS_P1_KEYPAD: priv->ctapi_functional_units |= CTAPI_FU_KEYBOARD; sc_log(reader->ctx, "Keypad detected"); break; case CTBCS_P1_PRINTER: priv->ctapi_functional_units |= CTAPI_FU_PRINTER; sc_log(reader->ctx, "Printer detected"); 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_log(reader->ctx, "Biometric sensor detected"); break; default: sc_log(reader->ctx, "Unknown functional unit 0x%x", 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_log(ctx, "Unable to resolve CT-API symbols."); sc_dlclose(dlh); return -1; }
void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t * ctx) { scconf_block *conf_block = NULL; char *unblock_style = NULL; char *create_slots_for_pins = NULL, *op, *tmp; /* Set defaults */ conf->plug_and_play = 1; conf->max_virtual_slots = 16; if (strcmp(ctx->app_name, "onepin-opensc-pkcs11") == 0) { conf->slots_per_card = 1; } else { conf->slots_per_card = 4; } conf->hide_empty_tokens = 1; conf->lock_login = 0; conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_NOT_ALLOWED; conf->create_puk_slot = 0; conf->zero_ckaid_for_ca_certs = 0; conf->create_slots_flags = SC_PKCS11_SLOT_CREATE_ALL; conf_block = sc_get_conf_block(ctx, "pkcs11", NULL, 1); if (!conf_block) return; /* contains the defaults, if there is a "pkcs11" config block */ conf->plug_and_play = scconf_get_bool(conf_block, "plug_and_play", conf->plug_and_play); conf->max_virtual_slots = scconf_get_int(conf_block, "max_virtual_slots", conf->max_virtual_slots); conf->slots_per_card = scconf_get_int(conf_block, "slots_per_card", conf->slots_per_card); conf->hide_empty_tokens = scconf_get_bool(conf_block, "hide_empty_tokens", conf->hide_empty_tokens); conf->lock_login = scconf_get_bool(conf_block, "lock_login", conf->lock_login); unblock_style = (char *)scconf_get_str(conf_block, "user_pin_unblock_style", NULL); if (unblock_style && !strcmp(unblock_style, "set_pin_in_unlogged_session")) conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_UNLOGGED_SETPIN; else if (unblock_style && !strcmp(unblock_style, "set_pin_in_specific_context")) conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_SCONTEXT_SETPIN; else if (unblock_style && !strcmp(unblock_style, "init_pin_in_so_session")) conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_SO_LOGGED_INITPIN; conf->create_puk_slot = scconf_get_bool(conf_block, "create_puk_slot", conf->create_puk_slot); conf->zero_ckaid_for_ca_certs = scconf_get_bool(conf_block, "zero_ckaid_for_ca_certs", conf->zero_ckaid_for_ca_certs); create_slots_for_pins = (char *)scconf_get_str(conf_block, "create_slots_for_pins", "all"); conf->create_slots_flags = 0; tmp = strdup(create_slots_for_pins); op = strtok(tmp, " ,"); while (op) { if (!strcmp(op, "user")) conf->create_slots_flags |= SC_PKCS11_SLOT_FOR_PIN_USER; else if (!strcmp(op, "sign")) conf->create_slots_flags |= SC_PKCS11_SLOT_FOR_PIN_SIGN; else if (!strcmp(op, "application")) conf->create_slots_flags |= SC_PKCS11_SLOT_FOR_APPLICATION; else if (!strcmp(op, "all")) conf->create_slots_flags |= SC_PKCS11_SLOT_CREATE_ALL; op = strtok(NULL, " ,"); } free(tmp); sc_log(ctx, "PKCS#11 options: plug_and_play=%d max_virtual_slots=%d slots_per_card=%d " "hide_empty_tokens=%d lock_login=%d pin_unblock_style=%d " "zero_ckaid_for_ca_certs=%d create_slots_flags=0x%X", conf->plug_and_play, conf->max_virtual_slots, conf->slots_per_card, conf->hide_empty_tokens, conf->lock_login, conf->pin_unblock_style, conf->zero_ckaid_for_ca_certs, conf->create_slots_flags); }