int find_slot_by_slotlabel_and_tokenlabel(pkcs11_handle_t *h, const char *wanted_slot_label, const char *wanted_token_label, unsigned int *slot_num) { SECMODModule *module = h->module; PK11SlotInfo *slot; unsigned long i; int rv; if (slot_num == NULL || module == NULL) return (-1); if (wanted_token_label == NULL){ rv = find_slot_by_slotlabel(h, wanted_slot_label, slot_num); return (rv); } /* wanted_token_label != NULL */ if (strcmp(wanted_slot_label, "none") == 0) { for (i = 0; i < module->slotCount; i++) { if (module->slots[i] && PK11_IsPresent(module->slots[i])) { const char *token_label; slot = PK11_ReferenceSlot(module->slots[i]); token_label = PK11_GetTokenName(slot); if (memcmp_pad_max((void *) token_label, strlen(token_label), (void *)wanted_token_label, strlen(wanted_token_label), 33) == 0) { h->slot = slot; *slot_num = PK11_GetSlotID(slot); return (0); } } } return (-1); } else { for (i = 0; i < module->slotCount; i++) { if (module->slots[i] && PK11_IsPresent(module->slots[i])) { const char *slot_label; const char *token_label; slot = PK11_ReferenceSlot(module->slots[i]); slot_label = PK11_GetSlotName(slot); token_label = PK11_GetTokenName(slot); if ((memcmp_pad_max((void *)slot_label, strlen(slot_label), (void *)wanted_slot_label, strlen(wanted_slot_label), 64) == 0) && (memcmp_pad_max((void *)token_label, strlen(token_label), (void *)wanted_token_label, strlen(wanted_token_label), 33) == 0)) { h->slot = slot; *slot_num = PK11_GetSlotID(slot); return (0); } } } return (-1); } }
static void sync_initial_tokens_from_driver (GsdSmartcardManager *self, SECMODModule *driver, GHashTable *smartcards, GCancellable *cancellable) { GsdSmartcardManagerPrivate *priv = self->priv; int i; for (i = 0; i < driver->slotCount; i++) { PK11SlotInfo *card; card = driver->slots[i]; if (PK11_IsPresent (card)) { CK_SLOT_ID slot_id; slot_id = PK11_GetSlotID (card); g_debug ("Detected smartcard in slot %d at start up", (int) slot_id); g_hash_table_replace (smartcards, GINT_TO_POINTER ((int) slot_id), PK11_ReferenceSlot (card)); gsd_smartcard_service_sync_token (priv->service, card, cancellable); } } }
static CURLcode nss_load_key(struct connectdata *conn, int sockindex, char *key_file) { PK11SlotInfo *slot; SECStatus status; CURLcode rv; struct ssl_connect_data *ssl = conn->ssl; (void)sockindex; /* unused */ rv = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE); if(CURLE_OK != rv) { PR_SetError(SEC_ERROR_BAD_KEY, 0); return rv; } slot = PK11_FindSlotByName("PEM Token #1"); if(!slot) return CURLE_SSL_CERTPROBLEM; /* This will force the token to be seen as re-inserted */ SECMOD_WaitForAnyTokenEvent(mod, 0, 0); PK11_IsPresent(slot); status = PK11_Authenticate(slot, PR_TRUE, conn->data->set.str[STRING_KEY_PASSWD]); PK11_FreeSlot(slot); return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM; }
static int nss_load_key(struct connectdata *conn, int sockindex, char *key_file) { #ifdef HAVE_PK11_CREATEGENERICOBJECT PK11SlotInfo * slot = NULL; CK_ATTRIBUTE *attrs; CK_ATTRIBUTE theTemplate[20]; CK_BBOOL cktrue = CK_TRUE; CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY; CK_SLOT_ID slotID; char slotname[SLOTSIZE]; struct ssl_connect_data *sslconn = &conn->ssl[sockindex]; attrs = theTemplate; /* FIXME: grok the various file types */ slotID = 1; /* hardcoded for now */ snprintf(slotname, sizeof(slotname), "PEM Token #%ld", slotID); slot = PK11_FindSlotByName(slotname); if(!slot) return 0; PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass) ); attrs++; PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); attrs++; PK11_SETATTRS(attrs, CKA_LABEL, (unsigned char *)key_file, strlen(key_file)+1); attrs++; /* When adding an encrypted key the PKCS#11 will be set as removed */ sslconn->key = PK11_CreateGenericObject(slot, theTemplate, 3, PR_FALSE /* isPerm */); if(sslconn->key == NULL) { PR_SetError(SEC_ERROR_BAD_KEY, 0); return 0; } /* This will force the token to be seen as re-inserted */ SECMOD_WaitForAnyTokenEvent(mod, 0, 0); PK11_IsPresent(slot); /* parg is initialized in nss_Init_Tokens() */ if(PK11_Authenticate(slot, PR_TRUE, conn->data->set.str[STRING_KEY_PASSWD]) != SECSuccess) { PK11_FreeSlot(slot); return 0; } PK11_FreeSlot(slot); return 1; #else /* If we don't have PK11_CreateGenericObject then we can't load a file-based * key. */ (void)conn; /* unused */ (void)key_file; /* unused */ return 0; #endif }
static int nss_load_key(struct connectdata *conn, int sockindex, char *key_file) { #ifdef HAVE_PK11_CREATEGENERICOBJECT PK11SlotInfo *slot; SECStatus status; struct ssl_connect_data *ssl = conn->ssl; if(CURLE_OK != nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE)) { PR_SetError(SEC_ERROR_BAD_KEY, 0); return 0; } slot = PK11_FindSlotByName("PEM Token #1"); if(!slot) return 0; /* This will force the token to be seen as re-inserted */ SECMOD_WaitForAnyTokenEvent(mod, 0, 0); PK11_IsPresent(slot); status = PK11_Authenticate(slot, PR_TRUE, conn->data->set.str[STRING_KEY_PASSWD]); PK11_FreeSlot(slot); return (SECSuccess == status) ? 1 : 0; #else /* If we don't have PK11_CreateGenericObject then we can't load a file-based * key. */ (void)conn; /* unused */ (void)key_file; /* unused */ return 0; #endif }
/* Re-insert of a card that has been removed by force removal */ VCardEmulError vcard_emul_force_card_insert(VReader *vreader) { VReaderEmul *vreader_emul; VCard *vcard; if (!nss_emul_init || (vreader_card_is_present(vreader) == VREADER_OK)) { return VCARD_EMUL_FAIL; /* card is already removed */ } vreader_emul = vreader_get_private(vreader); /* if it's a softcard, get the saved vcard from the reader emul structure */ if (vreader_emul->saved_vcard) { vcard = vcard_reference(vreader_emul->saved_vcard); } else { /* it must be a physical card, rebuild it */ if (!PK11_IsPresent(vreader_emul->slot)) { /* physical card has been removed, not way to reinsert it */ return VCARD_EMUL_FAIL; } vcard = vcard_emul_mirror_card(vreader); } vreader_insert_card(vreader, vcard); vcard_free(vcard); return VCARD_EMUL_OK; }
PK11SlotInfo * SECMOD_FindSlot(SECMODModule *module,const char *name) { int i; char *string; PK11SlotInfo *retSlot = NULL; if (!moduleLock) { PORT_SetError(SEC_ERROR_NOT_INITIALIZED); return retSlot; } SECMOD_GetReadLock(moduleLock); for (i=0; i < module->slotCount; i++) { PK11SlotInfo *slot = module->slots[i]; if (PK11_IsPresent(slot)) { string = PK11_GetTokenName(slot); } else { string = PK11_GetSlotName(slot); } if (PORT_Strcmp(name,string) == 0) { retSlot = PK11_ReferenceSlot(slot); break; } } SECMOD_ReleaseReadLock(moduleLock); if (retSlot == NULL) { PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED); } return retSlot; }
int open_pkcs11_session(pkcs11_handle_t *h, unsigned int slot_num) { /* NSS manages the sessions under the covers, use this function to * select a slot */ if (h->slot != NULL) { /* we've already selected the slot */ if (PK11_GetSlotID(h->slot) == slot_num) { return 0; } /* the slot we've selected isn't the one we want to open */ PK11_FreeSlot(h->slot); h->slot = NULL; } /* look the slot up */ h->slot = SECMOD_LookupSlot(h->module->moduleID, slot_num); if (h->slot == NULL) { return -1; } /* make sure it is present */ if (!PK11_IsPresent(h->slot)) { PK11_FreeSlot(h->slot); h->slot = NULL; return -1; } return 0; }
static void on_all_drivers_activated (GsdSmartcardManager *self, GAsyncResult *result, GTask *task) { GError *error = NULL; gboolean driver_activated; PK11SlotInfo *login_token; driver_activated = activate_all_drivers_async_finish (self, result, &error); if (!driver_activated) { g_task_return_error (task, error); return; } login_token = gsd_smartcard_manager_get_login_token (self); if (login_token || g_getenv ("PKCS11_LOGIN_TOKEN_NAME") != NULL) { /* The card used to log in was removed before login completed. * Do removal action immediately */ if (!login_token || !PK11_IsPresent (login_token)) gsd_smartcard_manager_do_remove_action (self); } g_task_return_boolean (task, TRUE); g_object_unref (task); }
/* * This thread looks for card and reader insertions and puts events on the * event queue */ static void vcard_emul_event_thread(void *arg) { PK11SlotInfo *slot; VReader *vreader; VReaderEmul *vreader_emul; VCard *vcard; SECMODModule *module = (SECMODModule *)arg; do { slot = SECMOD_WaitForAnyTokenEvent(module, 0, 500); if (slot == NULL) { break; } vreader = vcard_emul_find_vreader_from_slot(slot); if (vreader == NULL) { /* new vreader */ vreader_emul = vreader_emul_new(slot, default_card_type, default_type_params); vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul, vreader_emul_delete); PK11_FreeSlot(slot); slot = NULL; vreader_add_reader(vreader); vreader_free(vreader); continue; } /* card remove/insert */ vreader_emul = vreader_get_private(vreader); if (PK11_IsPresent(slot)) { int series = PK11_GetSlotSeries(slot); if (series != vreader_emul->series) { if (vreader_emul->present) { vreader_insert_card(vreader, NULL); } vcard = vcard_emul_mirror_card(vreader); vreader_insert_card(vreader, vcard); vcard_free(vcard); } vreader_emul->series = series; vreader_emul->present = 1; vreader_free(vreader); PK11_FreeSlot(slot); continue; } if (vreader_emul->present) { vreader_insert_card(vreader, NULL); } vreader_emul->series = 0; vreader_emul->present = 0; PK11_FreeSlot(slot); vreader_free(vreader); } while (1); }
/* if the card is inserted when we start up, make sure our state is correct */ static void vcard_emul_init_series(VReader *vreader, VCard *vcard) { VReaderEmul *vreader_emul = vreader_get_private(vreader); PK11SlotInfo *slot = vreader_emul->slot; vreader_emul->present = PK11_IsPresent(slot); vreader_emul->series = PK11_GetSlotSeries(slot); if (vreader_emul->present == 0) { vreader_insert_card(vreader, NULL); } }
static GList * get_inserted_tokens_for_operation (GsdSmartcardManager *self, WatchSmartcardsOperation *operation) { GList *inserted_tokens = NULL; GHashTableIter iter; gpointer key, value; g_hash_table_iter_init (&iter, operation->smartcards); while (g_hash_table_iter_next (&iter, &key, &value)) { PK11SlotInfo *card_slot; card_slot = (PK11SlotInfo *) value; if (PK11_IsPresent (card_slot)) inserted_tokens = g_list_prepend (inserted_tokens, card_slot); } return inserted_tokens; }
NS_IMETHODIMP nsPKCS11Slot::GetStatus(uint32_t *_retval) { nsNSSShutDownPreventionLock locker; if (isAlreadyShutDown()) return NS_ERROR_NOT_AVAILABLE; if (PK11_IsDisabled(mSlot)) *_retval = SLOT_DISABLED; else if (!PK11_IsPresent(mSlot)) *_retval = SLOT_NOT_PRESENT; else if (PK11_NeedLogin(mSlot) && PK11_NeedUserInit(mSlot)) *_retval = SLOT_UNINITIALIZED; else if (PK11_NeedLogin(mSlot) && !PK11_IsLoggedIn(mSlot, nullptr)) *_retval = SLOT_NOT_LOGGED_IN; else if (PK11_NeedLogin(mSlot)) *_retval = SLOT_LOGGED_IN; else *_retval = SLOT_READY; return NS_OK; }
/* readonly attribute wstring tokenName; */ NS_IMETHODIMP nsPKCS11Slot::GetTokenName(char16_t **aName) { nsNSSShutDownPreventionLock locker; if (isAlreadyShutDown()) return NS_ERROR_NOT_AVAILABLE; if (!PK11_IsPresent(mSlot)) { *aName = nullptr; return NS_OK; } if (mSeries != PK11_GetSlotSeries(mSlot)) { refreshSlotInfo(); } *aName = ToNewUnicode(NS_ConvertUTF8toUTF16(PK11_GetTokenName(mSlot))); if (!*aName) return NS_ERROR_OUT_OF_MEMORY; return NS_OK; }
/* * This function will search the slot list to find a slot based on the slot * label. If the wanted_slot_label is "none", then we will return the first * slot with the token presented. * * This function return 0 if it found a matching slot; otherwise, it returns * -1. */ int find_slot_by_slotlabel(pkcs11_handle_t *h, const char *wanted_slot_label, unsigned int *slotID) { SECMODModule *module = h->module; PK11SlotInfo *slot; int rv; int i; if (slotID == NULL || wanted_slot_label == NULL || strlen(wanted_slot_label) == 0 || module == NULL) return (-1); if (strcmp(wanted_slot_label, "none") == 0) { rv = find_slot_by_number(h, 0, slotID); return (rv); } else { /* wanted_slot_label is not "none" */ for (i = 0; i < module->slotCount; i++) { if (module->slots[i] && PK11_IsPresent(module->slots[i])) { const char *slot_label; slot = PK11_ReferenceSlot(module->slots[i]); slot_label = PK11_GetSlotName(slot); if (memcmp_pad_max((void *)slot_label, strlen(slot_label), (void *)wanted_slot_label, strlen(wanted_slot_label), 64) == 0) { h->slot = slot; *slotID = PK11_GetSlotID(slot); return 0; } } } } return (-1); }
static int nss_load_key(struct connectdata *conn, char *key_file) { #ifdef HAVE_PK11_CREATEGENERICOBJECT PK11SlotInfo * slot = NULL; PK11GenericObject *rv; CK_ATTRIBUTE *attrs; CK_ATTRIBUTE theTemplate[20]; CK_BBOOL cktrue = CK_TRUE; CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY; CK_SLOT_ID slotID; char *slotname = NULL; pphrase_arg_t *parg = NULL; attrs = theTemplate; /* FIXME: grok the various file types */ slotID = 1; /* hardcoded for now */ slotname = (char *)malloc(SLOTSIZE); snprintf(slotname, SLOTSIZE, "PEM Token #%ld", slotID); slot = PK11_FindSlotByName(slotname); free(slotname); if(!slot) return 0; PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass) ); attrs++; PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); attrs++; PK11_SETATTRS(attrs, CKA_LABEL, (unsigned char *)key_file, strlen(key_file)+1); attrs++; /* When adding an encrypted key the PKCS#11 will be set as removed */ rv = PK11_CreateGenericObject(slot, theTemplate, 3, PR_FALSE /* isPerm */); if(rv == NULL) { PR_SetError(SEC_ERROR_BAD_KEY, 0); return 0; } /* This will force the token to be seen as re-inserted */ SECMOD_WaitForAnyTokenEvent(mod, 0, 0); PK11_IsPresent(slot); parg = (pphrase_arg_t *) malloc(sizeof(*parg)); parg->retryCount = 0; parg->data = conn->data; /* parg is initialized in nss_Init_Tokens() */ if(PK11_Authenticate(slot, PR_TRUE, parg) != SECSuccess) { free(parg); return 0; } free(parg); return 1; #else /* If we don't have PK11_CreateGenericObject then we can't load a file-based * key. */ (void)conn; /* unused */ (void)key_file; /* unused */ return 0; #endif }
// // This is the main loop. // void SmartCardMonitoringThread::Execute() { PK11SlotInfo *slot; const char *tokenName = nsnull; // // populate token names for already inserted tokens. // PK11SlotList *sl = PK11_FindSlotsByNames(mModule->dllName, nsnull, nsnull, true); PK11SlotListElement *sle; if (sl) { for (sle=PK11_GetFirstSafe(sl); sle; sle=PK11_GetNextSafe(sl,sle,false)) { SetTokenName(PK11_GetSlotID(sle->slot), PK11_GetTokenName(sle->slot), PK11_GetSlotSeries(sle->slot)); } PK11_FreeSlotList(sl); } // loop starts.. do { slot = SECMOD_WaitForAnyTokenEvent(mModule, 0, PR_SecondsToInterval(1) ); if (slot == nsnull) { break; } // now we have a potential insertion or removal event, see if the slot // is present to determine which it is... if (PK11_IsPresent(slot)) { // insertion CK_SLOT_ID slotID = PK11_GetSlotID(slot); PRUint32 series = PK11_GetSlotSeries(slot); // skip spurious insertion events... if (series != GetTokenSeries(slotID)) { // if there's a token name, then we have not yet issued a remove // event for the previous token, do so now... tokenName = GetTokenName(slotID); if (tokenName) { SendEvent(NS_LITERAL_STRING(SMARTCARDEVENT_REMOVE), tokenName); } tokenName = PK11_GetTokenName(slot); // save the token name and series SetTokenName(slotID, tokenName, series); SendEvent(NS_LITERAL_STRING(SMARTCARDEVENT_INSERT), tokenName); } } else { // retrieve token name CK_SLOT_ID slotID = PK11_GetSlotID(slot); tokenName = GetTokenName(slotID); // if there's not a token name, then the software isn't expecting // a (or another) remove event. if (tokenName) { SendEvent(NS_LITERAL_STRING(SMARTCARDEVENT_REMOVE), tokenName); // clear the token name (after we send it) SetTokenName(slotID, nsnull, 0); } } PK11_FreeSlot(slot); } while (1); }
int find_slot_by_number(pkcs11_handle_t *h, unsigned int slot_num, unsigned int *slotID) { SECMODModule *module = h->module; int i; /* if module is null, * any of the PKCS #11 modules specified in the system config * is available, find one */ if (module == NULL) { PK11SlotList *list; PK11SlotListElement *le; PK11SlotInfo *slot = NULL; /* find a slot, we haven't specifically selected a module, * so find an appropriate one. */ /* get them all */ list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_TRUE, NULL); if (list == NULL) { return -1; } for (le = list->head; le; le = le->next) { CK_SLOT_INFO slInfo; SECStatus rv; slInfo.flags = 0; rv = PK11_GetSlotInfo(le->slot, &slInfo); if (rv == SECSuccess && (slInfo.flags & CKF_REMOVABLE_DEVICE)) { slot = PK11_ReferenceSlot(le->slot); module = SECMOD_ReferenceModule(PK11_GetModule(le->slot)); break; } } PK11_FreeSlotList(list); if (slot == NULL) { return -1; } h->slot = slot; h->module = module; *slotID = PK11_GetSlotID(slot); return 0; } /* * we're configured with a specific module, look for a present slot * on that module. */ if (slot_num == 0) { /* threaded applications should also acquire the * DefaultModuleListLock */ for (i=0; i < module->slotCount; i++) { if (module->slots[i] && PK11_IsPresent(module->slots[i])) { h->slot = PK11_ReferenceSlot(module->slots[i]); *slotID = PK11_GetSlotID(h->slot); return 0; } } } /* we're configured for a specific module and token, see if it's present */ slot_num--; if (slot_num < module->slotCount && module->slots && module->slots[slot_num] && PK11_IsPresent(module->slots[slot_num])) { h->slot = PK11_ReferenceSlot(module->slots[slot_num]); *slotID = PK11_GetSlotID(h->slot); return 0; } return -1; }
VCardEmulError vcard_emul_init(const VCardEmulOptions *options) { SECStatus rv; PRBool ret, has_readers = PR_FALSE; VReader *vreader; VReaderEmul *vreader_emul; SECMODListLock *module_lock; SECMODModuleList *module_list; SECMODModuleList *mlp; int i; if (vcard_emul_init_called) { return VCARD_EMUL_INIT_ALREADY_INITED; } vcard_emul_init_called = 1; vreader_init(); vevent_queue_init(); if (options == NULL) { options = &default_options; } /* first initialize NSS */ if (options->nss_db) { rv = NSS_Init(options->nss_db); } else { gchar *path; #ifndef _WIN32 path = g_strdup("/etc/pki/nssdb"); #else if (g_get_system_config_dirs() == NULL || g_get_system_config_dirs()[0] == NULL) { return VCARD_EMUL_FAIL; } path = g_build_filename( g_get_system_config_dirs()[0], "pki", "nssdb", NULL); #endif rv = NSS_Init(path); g_free(path); } if (rv != SECSuccess) { return VCARD_EMUL_FAIL; } /* Set password callback function */ PK11_SetPasswordFunc(vcard_emul_get_password); /* set up soft cards emulated by software certs rather than physical cards * */ for (i = 0; i < options->vreader_count; i++) { int j; int cert_count; unsigned char **certs; int *cert_len; VCardKey **keys; PK11SlotInfo *slot; slot = PK11_FindSlotByName(options->vreader[i].name); if (slot == NULL) { continue; } vreader_emul = vreader_emul_new(slot, options->vreader[i].card_type, options->vreader[i].type_params); vreader = vreader_new(options->vreader[i].vname, vreader_emul, vreader_emul_delete); vreader_add_reader(vreader); cert_count = options->vreader[i].cert_count; ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, options->vreader[i].cert_count); if (ret == PR_FALSE) { continue; } cert_count = 0; for (j = 0; j < options->vreader[i].cert_count; j++) { /* we should have a better way of identifying certs than by * nickname here */ CERTCertificate *cert = PK11_FindCertFromNickname( options->vreader[i].cert_name[j], NULL); if (cert == NULL) { continue; } certs[cert_count] = cert->derCert.data; cert_len[cert_count] = cert->derCert.len; keys[cert_count] = vcard_emul_make_key(slot, cert); /* this is safe because the key is still holding a cert reference */ CERT_DestroyCertificate(cert); cert_count++; } if (cert_count) { VCard *vcard = vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count); vreader_insert_card(vreader, vcard); vcard_emul_init_series(vreader, vcard); /* allow insertion and removal of soft cards */ vreader_emul->saved_vcard = vcard_reference(vcard); vcard_free(vcard); vreader_free(vreader); has_readers = PR_TRUE; } g_free(certs); g_free(cert_len); g_free(keys); } /* if we aren't suppose to use hw, skip looking up hardware tokens */ if (!options->use_hw) { nss_emul_init = has_readers; return has_readers ? VCARD_EMUL_OK : VCARD_EMUL_FAIL; } /* make sure we have some PKCS #11 module loaded */ module_lock = SECMOD_GetDefaultModuleListLock(); module_list = SECMOD_GetDefaultModuleList(); SECMOD_GetReadLock(module_lock); for (mlp = module_list; mlp; mlp = mlp->next) { SECMODModule *module = mlp->module; if (module_has_removable_hw_slots(module)) { break; } } SECMOD_ReleaseReadLock(module_lock); /* now examine all the slots, finding which should be readers */ /* We should control this with options. For now we mirror out any * removable hardware slot */ default_card_type = options->hw_card_type; default_type_params = g_strdup(options->hw_type_params); SECMOD_GetReadLock(module_lock); for (mlp = module_list; mlp; mlp = mlp->next) { SECMODModule *module = mlp->module; /* Ignore the internal module */ if (module == NULL || module == SECMOD_GetInternalModule()) { continue; } for (i = 0; i < module->slotCount; i++) { PK11SlotInfo *slot = module->slots[i]; /* only map removable HW slots */ if (slot == NULL || !PK11_IsRemovable(slot) || !PK11_IsHW(slot)) { continue; } if (strcmp("E-Gate 0 0", PK11_GetSlotName(slot)) == 0) { /* * coolkey <= 1.1.0-20 emulates this reader if it can't find * any hardware readers. This causes problems, warn user of * problems. */ fprintf(stderr, "known bad coolkey version - see " "https://bugzilla.redhat.com/show_bug.cgi?id=802435\n"); continue; } vreader_emul = vreader_emul_new(slot, options->hw_card_type, options->hw_type_params); vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul, vreader_emul_delete); vreader_add_reader(vreader); if (PK11_IsPresent(slot)) { VCard *vcard; vcard = vcard_emul_mirror_card(vreader); vreader_insert_card(vreader, vcard); vcard_emul_init_series(vreader, vcard); vcard_free(vcard); } } vcard_emul_new_event_thread(module); } SECMOD_ReleaseReadLock(module_lock); nss_emul_init = PR_TRUE; return VCARD_EMUL_OK; }
VCardEmulError vcard_emul_init(const VCardEmulOptions *options) { SECStatus rv; PRBool ret, has_readers = PR_FALSE, need_coolkey_module; VReader *vreader; VReaderEmul *vreader_emul; SECMODListLock *module_lock; SECMODModuleList *module_list; SECMODModuleList *mlp; int i; if (vcard_emul_init_called) { return VCARD_EMUL_INIT_ALREADY_INITED; } vcard_emul_init_called = 1; vreader_init(); vevent_queue_init(); if (options == NULL) { options = &default_options; } /* first initialize NSS */ if (options->nss_db) { rv = NSS_Init(options->nss_db); } else { rv = NSS_Init("sql:/etc/pki/nssdb"); } if (rv != SECSuccess) { return VCARD_EMUL_FAIL; } /* Set password callback function */ PK11_SetPasswordFunc(vcard_emul_get_password); /* set up soft cards emulated by software certs rather than physical cards * */ for (i = 0; i < options->vreader_count; i++) { int j; int cert_count; unsigned char **certs; int *cert_len; VCardKey **keys; PK11SlotInfo *slot; slot = PK11_FindSlotByName(options->vreader[i].name); if (slot == NULL) { continue; } vreader_emul = vreader_emul_new(slot, options->vreader[i].card_type, options->vreader[i].type_params); vreader = vreader_new(options->vreader[i].vname, vreader_emul, vreader_emul_delete); vreader_add_reader(vreader); cert_count = options->vreader[i].cert_count; ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, options->vreader[i].cert_count); if (ret == PR_FALSE) { continue; } cert_count = 0; for (j = 0; j < options->vreader[i].cert_count; j++) { /* we should have a better way of identifying certs than by * nickname here */ CERTCertificate *cert = PK11_FindCertFromNickname( options->vreader[i].cert_name[j], NULL); if (cert == NULL) { continue; } certs[cert_count] = cert->derCert.data; cert_len[cert_count] = cert->derCert.len; keys[cert_count] = vcard_emul_make_key(slot, cert); /* this is safe because the key is still holding a cert reference */ CERT_DestroyCertificate(cert); cert_count++; } if (cert_count) { VCard *vcard = vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count); vreader_insert_card(vreader, vcard); vcard_emul_init_series(vreader, vcard); /* allow insertion and removal of soft cards */ vreader_emul->saved_vcard = vcard_reference(vcard); vcard_free(vcard); vreader_free(vreader); has_readers = PR_TRUE; } g_free(certs); g_free(cert_len); g_free(keys); } /* if we aren't suppose to use hw, skip looking up hardware tokens */ if (!options->use_hw) { nss_emul_init = has_readers; return has_readers ? VCARD_EMUL_OK : VCARD_EMUL_FAIL; } /* make sure we have some PKCS #11 module loaded */ module_lock = SECMOD_GetDefaultModuleListLock(); module_list = SECMOD_GetDefaultModuleList(); need_coolkey_module = !has_readers; SECMOD_GetReadLock(module_lock); for (mlp = module_list; mlp; mlp = mlp->next) { SECMODModule *module = mlp->module; if (module_has_removable_hw_slots(module)) { need_coolkey_module = PR_FALSE; break; } } SECMOD_ReleaseReadLock(module_lock); if (need_coolkey_module) { SECMODModule *module; module = SECMOD_LoadUserModule( (char *)"library=libcoolkeypk11.so name=Coolkey", NULL, PR_FALSE); if (module == NULL) { return VCARD_EMUL_FAIL; } SECMOD_DestroyModule(module); /* free our reference, Module will still * be on the list. * until we destroy it */ } /* now examine all the slots, finding which should be readers */ /* We should control this with options. For now we mirror out any * removable hardware slot */ default_card_type = options->hw_card_type; default_type_params = strdup(options->hw_type_params); SECMOD_GetReadLock(module_lock); for (mlp = module_list; mlp; mlp = mlp->next) { SECMODModule *module = mlp->module; PRBool has_emul_slots = PR_FALSE; if (module == NULL) { continue; } for (i = 0; i < module->slotCount; i++) { PK11SlotInfo *slot = module->slots[i]; /* only map removable HW slots */ if (slot == NULL || !PK11_IsRemovable(slot) || !PK11_IsHW(slot)) { continue; } vreader_emul = vreader_emul_new(slot, options->hw_card_type, options->hw_type_params); vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul, vreader_emul_delete); vreader_add_reader(vreader); has_readers = PR_TRUE; has_emul_slots = PR_TRUE; if (PK11_IsPresent(slot)) { VCard *vcard; vcard = vcard_emul_mirror_card(vreader); vreader_insert_card(vreader, vcard); vcard_emul_init_series(vreader, vcard); vcard_free(vcard); } } if (has_emul_slots) { vcard_emul_new_event_thread(module); } } SECMOD_ReleaseReadLock(module_lock); nss_emul_init = has_readers; return VCARD_EMUL_OK; }
/* * this handles modules that do not support C_WaitForSlotEvent(). * The internal flags are stored. Note that C_WaitForSlotEvent() does not * have a timeout, so we don't have one for handleWaitForSlotEvent() either. */ PK11SlotInfo * secmod_HandleWaitForSlotEvent(SECMODModule *mod, unsigned long flags, PRIntervalTime latency) { PRBool removableSlotsFound = PR_FALSE; int i; int error = SEC_ERROR_NO_EVENT; if (!moduleLock) { PORT_SetError(SEC_ERROR_NOT_INITIALIZED); return NULL; } PZ_Lock(mod->refLock); if (mod->evControlMask & SECMOD_END_WAIT) { mod->evControlMask &= ~SECMOD_END_WAIT; PZ_Unlock(mod->refLock); PORT_SetError(SEC_ERROR_NO_EVENT); return NULL; } mod->evControlMask |= SECMOD_WAIT_SIMULATED_EVENT; while (mod->evControlMask & SECMOD_WAIT_SIMULATED_EVENT) { PZ_Unlock(mod->refLock); /* now is a good time to see if new slots have been added */ SECMOD_UpdateSlotList(mod); /* loop through all the slots on a module */ SECMOD_GetReadLock(moduleLock); for (i=0; i < mod->slotCount; i++) { PK11SlotInfo *slot = mod->slots[i]; PRUint16 series; PRBool present; /* perm modules do not change */ if (slot->isPerm) { continue; } removableSlotsFound = PR_TRUE; /* simulate the PKCS #11 module flags. are the flags different * from the last time we called? */ series = slot->series; present = PK11_IsPresent(slot); if ((slot->flagSeries != series) || (slot->flagState != present)) { slot->flagState = present; slot->flagSeries = series; SECMOD_ReleaseReadLock(moduleLock); PZ_Lock(mod->refLock); mod->evControlMask &= ~SECMOD_END_WAIT; PZ_Unlock(mod->refLock); return PK11_ReferenceSlot(slot); } } SECMOD_ReleaseReadLock(moduleLock); /* if everything was perm modules, don't lock up forever */ if ((mod->slotCount !=0) && !removableSlotsFound) { error =SEC_ERROR_NO_SLOT_SELECTED; PZ_Lock(mod->refLock); break; } if (flags & CKF_DONT_BLOCK) { PZ_Lock(mod->refLock); break; } PR_Sleep(latency); PZ_Lock(mod->refLock); } mod->evControlMask &= ~SECMOD_END_WAIT; PZ_Unlock(mod->refLock); PORT_SetError(error); return NULL; }
/* * This thread looks for card and reader insertions and puts events on the * event queue */ static void vcard_emul_event_thread(void *arg) { PK11SlotInfo *slot; VReader *vreader; VReaderEmul *vreader_emul; VCard *vcard; SECMODModule *module = (SECMODModule *)arg; do { /* * XXX - the latency value doesn't matter one bit. you only get no * blocking (flags |= CKF_DONT_BLOCK) or PKCS11_WAIT_LATENCY (==500), * hard coded in coolkey. And it isn't coolkey's fault - the timeout * value we pass get's dropped on the floor before C_WaitForSlotEvent * is called. */ slot = SECMOD_WaitForAnyTokenEvent(module, 0, 500); if (slot == NULL) { /* this could be just a no event indication */ if (PORT_GetError() == SEC_ERROR_NO_EVENT) { continue; } break; } vreader = vcard_emul_find_vreader_from_slot(slot); if (vreader == NULL) { /* new vreader */ vreader_emul = vreader_emul_new(slot, default_card_type, default_type_params); vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul, vreader_emul_delete); PK11_FreeSlot(slot); slot = NULL; vreader_add_reader(vreader); vreader_free(vreader); continue; } /* card remove/insert */ vreader_emul = vreader_get_private(vreader); if (PK11_IsPresent(slot)) { int series = PK11_GetSlotSeries(slot); if (series != vreader_emul->series) { if (vreader_emul->present) { vreader_insert_card(vreader, NULL); } vcard = vcard_emul_mirror_card(vreader); vreader_insert_card(vreader, vcard); vcard_free(vcard); } vreader_emul->series = series; vreader_emul->present = 1; vreader_free(vreader); PK11_FreeSlot(slot); continue; } if (vreader_emul->present) { vreader_insert_card(vreader, NULL); } vreader_emul->series = 0; vreader_emul->present = 0; PK11_FreeSlot(slot); vreader_free(vreader); } while (1); }
static gboolean watch_one_event_from_driver (GsdSmartcardManager *self, WatchSmartcardsOperation *operation, GCancellable *cancellable, GError **error) { GsdSmartcardManagerPrivate *priv = self->priv; PK11SlotInfo *card, *old_card; CK_SLOT_ID slot_id; gulong handler_id; int old_slot_series = -1, slot_series; handler_id = g_cancellable_connect (cancellable, G_CALLBACK (on_watch_cancelled), operation, NULL); card = SECMOD_WaitForAnyTokenEvent (operation->driver, 0, PR_SecondsToInterval (1)); g_cancellable_disconnect (cancellable, handler_id); if (g_cancellable_set_error_if_cancelled (cancellable, error)) { g_warning ("smartcard event function cancelled"); return FALSE; } if (card == NULL) { int error_code; error_code = PORT_GetError (); operation->number_of_consecutive_errors++; if (operation->number_of_consecutive_errors > 10) { g_warning ("Got %d consecutive smartcard errors, so giving up.", operation->number_of_consecutive_errors); g_set_error (error, GSD_SMARTCARD_MANAGER_ERROR, GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS, "encountered unexpected error while " "waiting for smartcard events (error %x)", error_code); return FALSE; } g_warning ("Got potentially spurious smartcard event error: %x.", error_code); g_usleep (0.5 * G_USEC_PER_SEC); return TRUE; } operation->number_of_consecutive_errors = 0; slot_id = PK11_GetSlotID (card); slot_series = PK11_GetSlotSeries (card); old_card = g_hash_table_lookup (operation->smartcards, GINT_TO_POINTER ((int) slot_id)); /* If there is a different card in the slot now than * there was before, then we need to emit a removed signal * for the old card */ if (old_card != NULL) { old_slot_series = PK11_GetSlotSeries (old_card); if (old_slot_series != slot_series) { /* Card registered with slot previously is * different than this card, so update its * exported state to track the implicit missed * removal */ gsd_smartcard_service_sync_token (priv->service, old_card, cancellable); } g_hash_table_remove (operation->smartcards, GINT_TO_POINTER ((int) slot_id)); } if (PK11_IsPresent (card)) { g_debug ("Detected smartcard insertion event in slot %d", (int) slot_id); g_hash_table_replace (operation->smartcards, GINT_TO_POINTER ((int) slot_id), PK11_ReferenceSlot (card)); gsd_smartcard_service_sync_token (priv->service, card, cancellable); } else if (old_card == NULL) { /* If the just removed smartcard is not known to us then * ignore the removal event. NSS sends a synthentic removal * event for slots that are empty at startup */ g_debug ("Detected slot %d is empty in reader", (int) slot_id); } else { g_debug ("Detected smartcard removal event in slot %d", (int) slot_id); /* If the just removed smartcard is known to us then * we need to update its exported state to reflect the * removal */ if (old_slot_series == slot_series) gsd_smartcard_service_sync_token (priv->service, card, cancellable); } PK11_FreeSlot (card); return TRUE; }