int util_connect_card(sc_context_t *ctx, sc_card_t **cardp, int reader_id, int slot_id, int wait, int verbose) { sc_reader_t *reader; sc_card_t *card; int r; if (wait) { sc_reader_t *readers[16]; int slots[16]; unsigned int i; int j, k, found; unsigned int event; for (i = k = 0; i < sc_ctx_get_reader_count(ctx); i++) { if (reader_id >= 0 && (unsigned int)reader_id != i) continue; reader = sc_ctx_get_reader(ctx, i); for (j = 0; j < reader->slot_count; j++, k++) { readers[k] = reader; slots[k] = j; } } //printf("Waiting for card to be inserted...\n"); r = sc_wait_for_event(readers, slots, k, SC_EVENT_CARD_INSERTED, &found, &event, -1); if (r < 0) { syslog(LOG_ERR, "Error while waiting for card: %s\n", sc_strerror(r)); return 3; } reader = readers[found]; slot_id = slots[found]; } else { if (sc_ctx_get_reader_count(ctx) == 0) { syslog(LOG_ERR, "No smart card readers found.\n"); return 1; } if (reader_id < 0) { unsigned int i; /* Automatically try to skip to a reader with a card if reader not specified */ for (i = 0; i < sc_ctx_get_reader_count(ctx); i++) { reader = sc_ctx_get_reader(ctx, i); if (sc_detect_card_presence(reader, 0) & SC_SLOT_CARD_PRESENT) { reader_id = i; syslog(LOG_NOTICE, "Using reader with a card: %s\n", reader->name); goto autofound; } } reader_id = 0; } autofound: if ((unsigned int)reader_id >= sc_ctx_get_reader_count(ctx)) { syslog(LOG_ERR, "Illegal reader number. " "Only %d reader(s) configured.\n", sc_ctx_get_reader_count(ctx)); return 1; } reader = sc_ctx_get_reader(ctx, reader_id); slot_id = 0; if (sc_detect_card_presence(reader, 0) <= 0) { syslog(LOG_ERR, "Card not present.\n"); return 3; } } if (verbose) printf("Connecting to card in reader %s...\n", reader->name); if ((r = sc_connect_card(reader, slot_id, &card)) < 0) { syslog(LOG_ERR, "Failed to connect to card: %s\n", sc_strerror(r)); return 1; } if (verbose) printf("Using card driver %s.\n", card->driver->name); if ((r = sc_lock(card)) < 0) { syslog(LOG_ERR, "Failed to lock card: %s\n", sc_strerror(r)); sc_disconnect_card(card, 0); return 1; } *cardp = card; return 0; }
CK_RV C_WaitForSlotEvent(CK_FLAGS flags, /* blocking/nonblocking flag */ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */ CK_VOID_PTR pReserved) /* reserved. Should be NULL_PTR */ { sc_reader_t *found; unsigned int mask, events; void *reader_states = NULL; CK_SLOT_ID slot_id; CK_RV rv; int r; if (pReserved != NULL_PTR) return CKR_ARGUMENTS_BAD; sc_log(context, "C_WaitForSlotEvent(block=%d)", !(flags & CKF_DONT_BLOCK)); /* Not all pcsc-lite versions implement consistently used functions as they are */ /* FIXME: add proper checking into build to check correct pcsc-lite version for SCardStatusChange/SCardCancel */ if (!(flags & CKF_DONT_BLOCK)) return CKR_FUNCTION_NOT_SUPPORTED; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; mask = SC_EVENT_CARD_EVENTS; /* Detect and add new slots for added readers v2.20 */ if (sc_pkcs11_conf.plug_and_play) { mask |= SC_EVENT_READER_EVENTS; } rv = slot_find_changed(&slot_id, mask); if ((rv == CKR_OK) || (flags & CKF_DONT_BLOCK)) goto out; again: sc_log(context, "C_WaitForSlotEvent() reader_states:%p", reader_states); sc_pkcs11_unlock(); r = sc_wait_for_event(context, mask, &found, &events, -1, &reader_states); if (sc_pkcs11_conf.plug_and_play && events & SC_EVENT_READER_ATTACHED) { /* NSS/Firefox Triggers a C_GetSlotList(NULL) only if a slot ID is returned that it does not know yet Change the first hotplug slot id on every call to make this happen. */ sc_pkcs11_slot_t *hotplug_slot = list_get_at(&virtual_slots, 0); *pSlot= hotplug_slot->id -1; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; goto out; } /* Was C_Finalize called ? */ if (in_finalize == 1) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((rv = sc_pkcs11_lock()) != CKR_OK) return rv; if (r != SC_SUCCESS) { sc_log(context, "sc_wait_for_event() returned %d\n", r); rv = sc_to_cryptoki_error(r, "C_WaitForSlotEvent"); goto out; } /* If no changed slot was found (maybe an unsupported card * was inserted/removed) then go waiting again */ rv = slot_find_changed(&slot_id, mask); if (rv != CKR_OK) goto again; out: if (pSlot) *pSlot = slot_id; /* Free allocated readers states holder */ if (reader_states) { sc_log(context, "free reader states"); sc_wait_for_event(context, 0, NULL, NULL, -1, &reader_states); } sc_log(context, "C_WaitForSlotEvent() = %s", lookup_enum (RV_T, rv)); sc_pkcs11_unlock(); return rv; }
CK_RV C_WaitForSlotEvent(CK_FLAGS flags, /* blocking/nonblocking flag */ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */ CK_VOID_PTR pReserved) /* reserved. Should be NULL_PTR */ { sc_reader_t *found; unsigned int mask, events; void *reader_states = NULL; CK_SLOT_ID slot_id; CK_RV rv; int r; if (pReserved != NULL_PTR) return CKR_ARGUMENTS_BAD; sc_log(context, "C_WaitForSlotEvent(block=%d)", !(flags & CKF_DONT_BLOCK)); #ifndef PCSCLITE_GOOD /* Not all pcsc-lite versions implement consistently used functions as they are */ if (!(flags & CKF_DONT_BLOCK)) return CKR_FUNCTION_NOT_SUPPORTED; #endif /* PCSCLITE_GOOD */ rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; mask = SC_EVENT_CARD_EVENTS | SC_EVENT_READER_EVENTS; /* Detect and add new slots for added readers v2.20 */ rv = slot_find_changed(&slot_id, mask); if ((rv == CKR_OK) || (flags & CKF_DONT_BLOCK)) goto out; again: sc_log(context, "C_WaitForSlotEvent() reader_states:%p", reader_states); sc_pkcs11_unlock(); r = sc_wait_for_event(context, mask, &found, &events, -1, &reader_states); if (events & SC_EVENT_READER_ATTACHED) { rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; goto out; } /* Was C_Finalize called ? */ if (in_finalize == 1) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((rv = sc_pkcs11_lock()) != CKR_OK) return rv; if (r != SC_SUCCESS) { sc_log(context, "sc_wait_for_event() returned %d\n", r); rv = sc_to_cryptoki_error(r, "C_WaitForSlotEvent"); goto out; } /* If no changed slot was found (maybe an unsupported card * was inserted/removed) then go waiting again */ rv = slot_find_changed(&slot_id, mask); if (rv != CKR_OK) goto again; out: if (pSlot) *pSlot = slot_id; /* Free allocated readers states holder */ if (reader_states) { sc_log(context, "free reader states"); sc_wait_for_event(context, 0, NULL, NULL, -1, &reader_states); } sc_log(context, "C_WaitForSlotEvent() = %s", lookup_enum (RV_T, rv)); sc_pkcs11_unlock(); return rv; }