예제 #1
0
/* 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;
}
예제 #2
0
/* Force a card removal even if the card is not physically removed */
VCardEmulError
vcard_emul_force_card_remove(VReader *vreader)
{
    if (!nss_emul_init || (vreader_card_is_present(vreader) != VREADER_OK)) {
        return VCARD_EMUL_FAIL; /* card is already removed */
    }

    /* OK, remove it */
    vreader_insert_card(vreader, NULL);
    return VCARD_EMUL_OK;
}
예제 #3
0
/*
 *  This is the main work of the emulator, handling the thread that looks for
 *  changes in the readers and the cards.
 */
static void *
passthru_emul_event_thread(void *args)
{
    char *reader_list = NULL;
    int reader_list_len = 0;
    SCARD_READERSTATE_A *reader_states = NULL;
    int reader_count = 0;     /* number of active readers */
    int max_reader_count = 0; /* size of the reader_state array (including
                                 inactive readers) */
    LONG rv;
    int timeout=1000;
    int i;

    do {
        /* variables to hold on to our new values until we are ready to replace
         * our old values */
        char *new_reader_list = NULL;
        int new_reader_list_len = 0;
        int new_reader_count = 0;

        /* other temps */
        char * reader_entry;
        VReader *reader;

        /*
         * First check to see if the reader list has changed
         */
        rv = SCardListReaders(global_context, NULL, NULL, &new_reader_list_len);
        if (rv !=  SCARD_S_SUCCESS) {
           goto next;
        }
        /*
         * If the names have changed, we need to update our list and states.
         * This is where we detect reader insertions and removals.
         */
        if (new_reader_list_len != reader_list_len) {
            /* update the list */
            new_reader_list = (char *)malloc(new_reader_list_len);
            if (new_reader_list == NULL) {
                goto next;
            }
            rv = SCardListReaders(global_context, NULL, new_reader_list,
                                  &new_reader_list_len);
            if (rv !=  SCARD_S_SUCCESS) {
                free(new_reader_list);
                goto next;
            }
            /* clear out our event state */
            for (i=0; i < reader_count; i++) {
                    reader_states[i].dwEventState = 0;
            }
            /* count the readers and mark the ones that are still with us */
            for (reader_entry = new_reader_list; *reader_entry;
                 reader_entry += strlen(reader_entry)+1) {
                SCARD_READERSTATE_A *this_state;
                new_reader_count++;
                /* if the reader is still on the list, mark it present */
                this_state = passthru_get_reader_state(reader_states,
                                                       reader_count,
                                                       reader_entry);
                if (this_state) {
                    this_state->dwEventState = SCARD_STATE_PRESENT;
                }
            }
            /* eject any removed readers */
            for (i=0; i < reader_count; i++) {
                if (reader_states[i].dwEventState == SCARD_STATE_PRESENT) {
                    reader_states[i].dwEventState = 0;
                    continue;
                }
                reader = vreader_get_reader_by_name(reader_states[i].szReader);
                vreader_remove_reader(reader);
                vreader_free(reader);
                reader_states[i].szReader = NULL;
            }
            /* handle the shrinking list */
            if (new_reader_count < reader_count) {
                /* fold all the valid entries at the end of our reader_states
                 * array up into those locations vacated by ejected readers. */
                for (i=reader_count-1; i < (new_reader_count -1); i--) {
                        if (reader_states[i].szReader) {
                            SCARD_READERSTATE_A *blank_reader;
                            blank_reader =
                                passthru_get_blank_reader(reader_states,
                                                          new_reader_count);
                            assert(blank_reader);
                            *blank_reader = reader_states[i];
                            reader_states[i].szReader = NULL;
                        }
                 }
            }
            /* handle the growing list */
            if (new_reader_count >  max_reader_count) {
                SCARD_READERSTATE_A *new_reader_states;

                /* grow the list */
                new_reader_states =
                    (SCARD_READERSTATE_A *)realloc(reader_states,
                        sizeof(SCARD_READERSTATE_A)*new_reader_count);
                if (new_reader_states) {
                    /* successful, update our current state */
                    reader_states = new_reader_states;
                    max_reader_count = new_reader_count;
                } else {
                    new_reader_count = max_reader_count; /* couldn't get enough
                                                          * space to handle
                                                          * all the new readers
                                                          * */
                }
                /* mark our new entries as empty */
                for (i=reader_count; i > new_reader_count; i++) {
                    reader_states[i].szReader = NULL;
                }
            }
            /* now walk the reader list, updating the state */
            for (reader_entry = new_reader_list; *reader_entry;
                 reader_entry += strlen(reader_entry)+1) {
                SCARD_READERSTATE_A *this_state;
                this_state = passthru_get_reader_state(reader_states,
                                                       new_reader_count,
                                                       reader_entry);
                if (this_state) {
                    /* replace the old copy of the string with the new copy.
                     * This will allow us to free reader_list at the end */
                    reader_states->szReader = reader_entry;
                    continue;
                }
                /* this is a new reader, add it to the list */
                this_state =
                    passthru_get_blank_reader(reader_states, new_reader_count);
                if (!this_state) {
                    continue; /* this can happen of we couldn't get enough
                                 slots in the grow list */
                }
                this_state->szReader = reader_entry;
                this_state->dwCurrentState = SCARD_STATE_UNAWARE;
                reader = vreader_new(reader_entry, NULL, NULL);
                if (reader) {
                    vreader_add_reader(reader);
                }
                vreader_free(reader);
            }
            /* finally update our current variables */
            free(reader_list);
            reader_list = new_reader_list;
            reader_list_len = new_reader_list_len;
            reader_count = new_reader_count;
        }
next:
        rv = SCardGetStatusChange(global_context, timeout,
                                  reader_states, reader_count);
        if (rv == SCARD_E_TIMEOUT) {
            continue; /* check for new readers */
        }
        if (rv != SCARD_S_SUCCESS) {
            static int restarts = 0;
            VCardStatus status;

            /* try resetting the pcsc_lite subsystem */
            SCardReleaseContext(global_context);
            global_context = 0; /* should close it */
            printf("***** SCard failure %x\n", rv);
            restarts++;
            if (restarts >= 3) {
                printf("***** SCard failed %d times\n", restarts);
                return; /* exit thread */
            }
            status = passthru_pcsc_lite_init();
            assert(status == CARD_DONE);
            sleep(1);
            continue;
        }
        /* deal with card insertion/removal */
        for (i=0; i < reader_count ; i++) {
            if ((reader_states[i].dwEventState & SCARD_STATE_CHANGED) == 0) {
                continue;
            }
            reader_states[i].dwCurrentState = reader_states[i].dwEventState;
            reader = vreader_get_reader_by_name(reader_states[i].szReader);
            if (reader == NULL) {
                continue;
            }
            if (reader_states[i].dwEventState & SCARD_STATE_EMPTY) {
                if (vreader_card_is_present(reader) == VREADER_OK) {
                    vreader_insert_card(reader, NULL);
                }
            }
            if (reader_states[i].dwEventState & SCARD_STATE_PRESENT) {
                VCard *card;
                VCardStatus status = VCARD_FAIL;
                /* if there already was a card present, eject it before we
                 * insert the new one */
                if (vreader_card_is_present(reader) == VREADER_OK) {
                    vreader_insert_card(reader, NULL);
                }

                card = vcard_new(NULL, NULL);
                if (card != NULL) {
                    status = passthru_card_init(reader, card, "",
                                                NULL, NULL, NULL, 0);
                    passthru_card_set_atr(card, reader_states[i].rgbAtr,
                                  reader_states[i].cbAtr);
                    vcard_set_atr_func(card, passthru_card_get_atr);
                }
                if (status == VCARD_DONE) {
                    vreader_insert_card(reader, card);
                }
                vcard_free(card);
            }
            vreader_free(reader);
        }

     } while (1);
     return NULL;
}
예제 #4
0
static void
do_command(void)
{
    char inbuf[255];
    char *string;
    VCardEmulError error;
    static unsigned int default_reader_id;
    unsigned int reader_id;
    VReader *reader = NULL;

    reader_id = default_reader_id;
    string = fgets(inbuf, sizeof(inbuf), stdin);
    if (string != NULL) {
        if (strncmp(string, "exit", 4) == 0) {
            /* remove all the readers */
            VReaderList *list = vreader_get_reader_list();
            VReaderListEntry *reader_entry;
            printf("Active Readers:\n");
            for (reader_entry = vreader_list_get_first(list); reader_entry;
                 reader_entry = vreader_list_get_next(reader_entry)) {
                VReader *reader = vreader_list_get_reader(reader_entry);
                vreader_id_t reader_id;
                reader_id = vreader_get_id(reader);
                if (reader_id == -1) {
                    continue;
                }
                /* be nice and signal card removal first (qemu probably should
                 * do this itself) */
                if (vreader_card_is_present(reader) == VREADER_OK) {
                    send_msg(VSC_CardRemove, reader_id, NULL, 0);
                }
                send_msg(VSC_ReaderRemove, reader_id, NULL, 0);
            }
            exit(0);
        } else if (strncmp(string, "insert", 6) == 0) {
            if (string[6] == ' ') {
                reader_id = get_id_from_string(&string[7], reader_id);
            }
            reader = vreader_get_reader_by_id(reader_id);
            if (reader != NULL) {
                error = vcard_emul_force_card_insert(reader);
                printf("insert %s, returned %d\n",
                       reader ? vreader_get_name(reader)
                       : "invalid reader", error);
            } else {
                printf("no reader by id %u found\n", reader_id);
            }
        } else if (strncmp(string, "remove", 6) == 0) {
            if (string[6] == ' ') {
                reader_id = get_id_from_string(&string[7], reader_id);
            }
            reader = vreader_get_reader_by_id(reader_id);
            if (reader != NULL) {
                error = vcard_emul_force_card_remove(reader);
                printf("remove %s, returned %d\n",
                        reader ? vreader_get_name(reader)
                        : "invalid reader", error);
            } else {
                printf("no reader by id %u found\n", reader_id);
            }
        } else if (strncmp(string, "select", 6) == 0) {
            if (string[6] == ' ') {
                reader_id = get_id_from_string(&string[7],
                                               VSCARD_UNDEFINED_READER_ID);
            }
            if (reader_id != VSCARD_UNDEFINED_READER_ID) {
                reader = vreader_get_reader_by_id(reader_id);
            }
            if (reader) {
                printf("Selecting reader %u, %s\n", reader_id,
                        vreader_get_name(reader));
                default_reader_id = reader_id;
            } else {
                printf("Reader with id %u not found\n", reader_id);
            }
        } else if (strncmp(string, "debug", 5) == 0) {
            if (string[5] == ' ') {
                verbose = get_id_from_string(&string[6], 0);
            }
            printf("debug level = %d\n", verbose);
        } else if (strncmp(string, "list", 4) == 0) {
            VReaderList *list = vreader_get_reader_list();
            VReaderListEntry *reader_entry;
            printf("Active Readers:\n");
            for (reader_entry = vreader_list_get_first(list); reader_entry;
                 reader_entry = vreader_list_get_next(reader_entry)) {
                VReader *reader = vreader_list_get_reader(reader_entry);
                vreader_id_t reader_id;
                reader_id = vreader_get_id(reader);
                if (reader_id == -1) {
                    continue;
                }
                printf("%3u %s %s\n", reader_id,
                       vreader_card_is_present(reader) == VREADER_OK ?
                       "CARD_PRESENT" : "            ",
                       vreader_get_name(reader));
            }
            printf("Inactive Readers:\n");
            for (reader_entry = vreader_list_get_first(list); reader_entry;
                 reader_entry = vreader_list_get_next(reader_entry)) {
                VReader *reader = vreader_list_get_reader(reader_entry);
                vreader_id_t reader_id;
                reader_id = vreader_get_id(reader);
                if (reader_id != -1) {
                    continue;
                }

                printf("INA %s %s\n",
                       vreader_card_is_present(reader) == VREADER_OK ?
                       "CARD_PRESENT" : "            ",
                       vreader_get_name(reader));
            }
        } else if (*string != 0) {
            printf("valid commands:\n");
            printf("insert [reader_id]\n");
            printf("remove [reader_id]\n");
            printf("select reader_id\n");
            printf("list\n");
            printf("debug [level]\n");
            printf("exit\n");
        }
    }
    vreader_free(reader);
    printf("> ");
    fflush(stdout);
}