Changeset 3506 for trunk

Show
Ignore:
Timestamp:
04/29/08 17:01:19 (9 months ago)
Author:
alonbl
Message:

Plug&Play support

This is not the best solution, but focus on smallest code change.

Changes:

1. Add detect_readers() to reader opts, this adds new readers to the end

of the readers list until list is full.

2. Add sc_ctx_detect_readers() that calls readers' detect_readers().

3. Fixup pcsc_lock() so that it reconnect to the card and report proper

error so caller may be notified if session was lost.

4. Allow context to be created without readers.

5. Call sc_ctx_detect_readers() from PKCS#11 C_GetSlotList with NULL_PTR.

6. Allow no reader at detect_card, as reader my be removed.

7. Since I broke ABI, I updated the external module version requirement

to match OpenSC version. In the future a separate version should be
maintained for each interface, this should be unrelated to the package
version.

Alon

---

svn merge -r 3480:3505 https://www.opensc-project.org/svn/opensc/branches/alonbl/pnp

M src/tools/opensc-tool.c
M src/pkcs11/pkcs11-global.c
M src/pkcs11/slot.c
M src/libopensc/reader-pcsc.c
M src/libopensc/internal-winscard.h
M src/libopensc/ctx.c
M src/libopensc/reader-ctapi.c
M src/libopensc/libopensc.exports
M src/libopensc/reader-openct.c
M src/libopensc/opensc.h

Location:
trunk/src
Files:
10 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/libopensc/ctx.c

    r3495 r3506  
    355355        /* verify module version */ 
    356356        version = modversion(); 
    357         if (version == NULL || strncmp(version, "0.9.", strlen("0.9.")) > 0) { 
     357        /* XXX: We really need to have ABI version for each interface */ 
     358        if (version == NULL || strncmp(version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)) != 0) { 
    358359                sc_error(ctx,"dynamic library '%s': invalid module version\n",libname); 
    359360                lt_dlclose(handle); 
     
    638639} 
    639640 
     641int sc_ctx_detect_readers(sc_context_t *ctx) 
     642{ 
     643        int i; 
     644 
     645        sc_mutex_lock(ctx, ctx->mutex); 
     646 
     647        for (i = 0; ctx->reader_drivers[i] != NULL; i++) { 
     648                const struct sc_reader_driver *drv = ctx->reader_drivers[i]; 
     649 
     650                if (drv->ops->detect_readers != NULL) 
     651                        drv->ops->detect_readers(ctx, ctx->reader_drv_data[i]); 
     652        } 
     653 
     654        sc_mutex_unlock(ctx, ctx->mutex); 
     655 
     656        /* XXX: Do not ignore erros? */ 
     657        return SC_SUCCESS; 
     658} 
     659 
    640660sc_reader_t *sc_ctx_get_reader(sc_context_t *ctx, unsigned int i) 
    641661{ 
     
    725745        del_drvs(&opts, 0); 
    726746        del_drvs(&opts, 1); 
    727         if (ctx->reader_count == 0) { 
    728                 sc_release_context(ctx); 
    729                 return SC_ERROR_NO_READERS_FOUND; 
    730         } 
     747        sc_ctx_detect_readers(ctx); 
    731748        *ctx_out = ctx; 
    732749        return SC_SUCCESS; 
  • trunk/src/libopensc/internal-winscard.h

    r3460 r3506  
    5252 
    5353#define SCARD_S_SUCCESS                 0x00000000 /**< No error was encountered. */ 
     54#define SCARD_E_INVALID_HANDLE          0x80100003 /**< The supplied handle was invalid. */ 
    5455#define SCARD_E_TIMEOUT                 0x8010000A /**< The user-specified timeout value has expired. */ 
    5556#define SCARD_E_SHARING_VIOLATION       0x8010000B /**< The smart card cannot be accessed because of other connections outstanding. */ 
    5657#define SCARD_E_NOT_TRANSACTED          0x80100016 /**< An attempt was made to end a non-existent transaction. */ 
     58#define SCARD_E_READER_UNAVAILABLE      0x80100017 /**< The specified reader is not currently available for use. */ 
    5759#define SCARD_E_NO_READERS_AVAILABLE    0x8010002E /**< Cannot find a smart card reader. */ 
    5860#define SCARD_W_UNRESPONSIVE_CARD       0x80100066 /**< The smart card is not responding to a reset. */ 
  • trunk/src/libopensc/libopensc.exports

    r3478 r3506  
    3838sc_copy_asn1_entry 
    3939sc_create_file 
     40sc_ctx_detect_readers 
    4041sc_ctx_get_reader 
    4142sc_ctx_get_reader_count 
  • trunk/src/libopensc/opensc.h

    r3304 r3506  
    374374         * deallocate the private data and any resources. */ 
    375375        int (*finish)(struct sc_context *ctx, void *priv_data); 
     376        /* Called when library wish to detect new readers 
     377         * should add only new readers. */ 
     378        int (*detect_readers)(struct sc_context *ctx, void *priv_data); 
    376379        /* Called when releasing a reader.  release() has to 
    377380         * deallocate the private data.  Other fields will be 
     
    726729 */ 
    727730int sc_release_context(sc_context_t *ctx); 
     731 
     732/** 
     733 * Detect new readers available on system. 
     734 * @param  ctx  OpenSC context 
     735 * @return SC_SUCCESS on success and an error code otherwise. 
     736 */ 
     737int sc_ctx_detect_readers(sc_context_t *ctx); 
    728738 
    729739/** 
  • trunk/src/libopensc/reader-ctapi.c

    r3084 r3506  
    612612        ctapi_ops.init = ctapi_init; 
    613613        ctapi_ops.finish = ctapi_finish; 
     614        ctapi_ops.detect_readers = NULL; 
    614615        ctapi_ops.transmit = ctapi_transmit; 
    615616        ctapi_ops.detect_card_presence = ctapi_detect_card_presence; 
  • trunk/src/libopensc/reader-openct.c

    r3405 r3506  
    480480        openct_ops.init = openct_reader_init; 
    481481        openct_ops.finish = openct_reader_finish; 
     482        openct_ops.detect_readers = NULL; 
    482483        openct_ops.release = openct_reader_release; 
    483484        openct_ops.detect_card_presence = openct_reader_detect_card_presence; 
  • trunk/src/libopensc/reader-pcsc.c

    r3502 r3506  
    645645        rv = priv->gpriv->SCardBeginTransaction(pslot->pcsc_card); 
    646646 
    647         if ((unsigned int)rv == SCARD_W_RESET_CARD) { 
    648                 /* try to reconnect if the card was reset by some other application */ 
    649                 rv = pcsc_reconnect(reader, slot, 0); 
    650                 if (rv != SCARD_S_SUCCESS) { 
    651                         PCSC_ERROR(reader->ctx, "SCardReconnect failed", rv); 
     647        switch (rv) { 
     648                case SCARD_E_INVALID_HANDLE: 
     649                case SCARD_E_READER_UNAVAILABLE: 
     650                        rv = pcsc_connect(reader, slot); 
     651                        if (rv != SCARD_S_SUCCESS) { 
     652                                PCSC_ERROR(reader->ctx, "SCardConnect failed", rv); 
     653                                return pcsc_ret_to_error(rv); 
     654                        } 
     655                        /* return failure so that upper layers will be notified and try to lock again */ 
     656                        return SC_ERROR_READER_REATTACHED; 
     657                case SCARD_W_RESET_CARD: 
     658                        /* try to reconnect if the card was reset by some other application */ 
     659                        rv = pcsc_reconnect(reader, slot, 0); 
     660                        if (rv != SCARD_S_SUCCESS) { 
     661                                PCSC_ERROR(reader->ctx, "SCardReconnect failed", rv); 
     662                                return pcsc_ret_to_error(rv); 
     663                        } 
     664                        /* return failure so that upper layers will be notified and try to lock again */ 
     665                        return SC_ERROR_CARD_RESET; 
     666                case SCARD_S_SUCCESS: 
     667                        pslot->locked = 1; 
     668                        return SC_SUCCESS; 
     669                default: 
     670                        PCSC_ERROR(reader->ctx, "SCardBeginTransaction failed", rv); 
    652671                        return pcsc_ret_to_error(rv); 
    653                 } 
    654                 /* Now try to begin a new transaction after we reconnected and we fail if 
    655                  some other program was faster to lock the reader */ 
    656                 rv = priv->gpriv->SCardBeginTransaction(pslot->pcsc_card); 
    657         } 
    658  
    659         if (rv != SCARD_S_SUCCESS) { 
    660                 PCSC_ERROR(reader->ctx, "SCardBeginTransaction failed", rv); 
    661                 return pcsc_ret_to_error(rv); 
    662         } 
    663  
    664         pslot->locked = 1; 
    665          
    666         return SC_SUCCESS; 
     672        } 
    667673} 
    668674 
     
    732738{ 
    733739        LONG rv; 
    734         DWORD reader_buf_size; 
    735         char *reader_buf = NULL, *p; 
    736         const char *mszGroups = NULL; 
    737         int r; 
    738740        struct pcsc_global_private_data *gpriv; 
    739741        scconf_block *conf_block = NULL; 
     
    754756        gpriv->enable_pinpad = 0; 
    755757        gpriv->provider_library = DEFAULT_PCSC_PROVIDER; 
     758        gpriv->pcsc_ctx = -1; 
    756759         
    757760        conf_block = sc_get_conf_block(ctx, "reader_driver", "pcsc", 1); 
     
    819822        } 
    820823 
    821         rv = gpriv->SCardEstablishContext(SCARD_SCOPE_USER, 
    822                               NULL, NULL, &gpriv->pcsc_ctx); 
    823         if (rv != SCARD_S_SUCCESS) { 
    824                 ret = pcsc_ret_to_error(rv); 
     824        *reader_data = gpriv; 
     825        gpriv = NULL; 
     826        ret = SC_SUCCESS; 
     827 
     828out: 
     829        if (ret != SC_SUCCESS) { 
     830                if (gpriv->pcsc_ctx != 0) 
     831                        gpriv->SCardReleaseContext(gpriv->pcsc_ctx); 
     832                if (gpriv->dlhandle != NULL) 
     833                        lt_dlclose(gpriv->dlhandle); 
     834                if (gpriv != NULL) 
     835                        free(gpriv); 
     836        } 
     837 
     838        return 0; 
     839} 
     840 
     841static int pcsc_finish(sc_context_t *ctx, void *prv_data) 
     842{ 
     843        struct pcsc_global_private_data *priv = (struct pcsc_global_private_data *) prv_data; 
     844 
     845        if (priv) { 
     846                priv->SCardReleaseContext(priv->pcsc_ctx); 
     847                lt_dlclose(priv->dlhandle); 
     848                free(priv); 
     849        } 
     850 
     851        return 0; 
     852} 
     853 
     854static int pcsc_detect_readers(sc_context_t *ctx, void *prv_data) 
     855{ 
     856        struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) prv_data; 
     857        LONG rv; 
     858        DWORD reader_buf_size; 
     859        char *reader_buf = NULL, *p; 
     860        const char *mszGroups = NULL; 
     861        int ret = SC_ERROR_INTERNAL; 
     862        int again; 
     863 
     864        if (!prv_data) { 
     865                ret = SC_ERROR_NO_READERS_FOUND; 
    825866                goto out; 
    826867        } 
    827         rv = gpriv->SCardListReaders(gpriv->pcsc_ctx, NULL, NULL, 
    828                               (LPDWORD) &reader_buf_size); 
    829         if (rv != SCARD_S_SUCCESS || reader_buf_size < 2) { 
    830                 ret = pcsc_ret_to_error(rv);    /* No readers configured */ 
    831                 goto out; 
    832         } 
     868 
     869        do { 
     870                rv = gpriv->SCardListReaders(gpriv->pcsc_ctx, NULL, NULL, 
     871                                      (LPDWORD) &reader_buf_size); 
     872                if (rv != SCARD_S_SUCCESS) { 
     873                        if (rv != SCARD_E_INVALID_HANDLE) { 
     874                                ret = pcsc_ret_to_error(rv); 
     875                                goto out; 
     876                        } 
     877 
     878                        rv = gpriv->SCardEstablishContext(SCARD_SCOPE_USER, 
     879                                              NULL, NULL, &gpriv->pcsc_ctx); 
     880                        if (rv != SCARD_S_SUCCESS) { 
     881                                ret = pcsc_ret_to_error(rv); 
     882                                goto out; 
     883                        } 
     884 
     885                        rv = SCARD_E_INVALID_HANDLE; 
     886                } 
     887        } while (rv != SCARD_S_SUCCESS); 
    833888 
    834889        reader_buf = (char *) malloc(sizeof(char) * reader_buf_size); 
     
    843898                goto out; 
    844899        } 
    845         p = reader_buf; 
    846         do { 
    847                 sc_reader_t *reader = (sc_reader_t *) calloc(1, sizeof(sc_reader_t)); 
    848                 struct pcsc_private_data *priv = (struct pcsc_private_data *) malloc(sizeof(struct pcsc_private_data)); 
    849                 struct pcsc_slot_data *pslot = (struct pcsc_slot_data *) malloc(sizeof(struct pcsc_slot_data)); 
    850                 sc_slot_info_t *slot; 
    851  
    852                 if (reader == NULL || priv == NULL || pslot == NULL) { 
    853                         if (reader) 
    854                                 free(reader); 
    855                         if (priv) 
    856                                 free(priv); 
    857                         if (pslot) 
    858                                 free(pslot); 
    859                         break; 
     900        for (p = reader_buf; *p != '\x0'; p += strlen (p) + 1) { 
     901                sc_reader_t *reader = NULL; 
     902                struct pcsc_private_data *priv = NULL; 
     903                struct pcsc_slot_data *pslot = NULL; 
     904                sc_slot_info_t *slot = NULL; 
     905                int i; 
     906                int found = 0; 
     907 
     908                for (i=0;i < sc_ctx_get_reader_count (ctx) && !found;i++) { 
     909                        sc_reader_t *reader = sc_ctx_get_reader (ctx, i); 
     910                        if (reader == NULL) { 
     911                                ret = SC_ERROR_INTERNAL; 
     912                                goto err1; 
     913                        } 
     914                        if (reader->ops == &pcsc_ops && !strcmp (reader->name, p)) { 
     915                                found = 1; 
     916                        } 
     917                } 
     918 
     919                /* Reader already available, skip */ 
     920                if (found) { 
     921                        continue; 
     922                } 
     923 
     924                if ((reader = (sc_reader_t *) calloc(1, sizeof(sc_reader_t))) == NULL) { 
     925                        ret = SC_ERROR_OUT_OF_MEMORY; 
     926                        goto err1; 
     927                } 
     928                if ((priv = (struct pcsc_private_data *) malloc(sizeof(struct pcsc_private_data))) == NULL) { 
     929                        ret = SC_ERROR_OUT_OF_MEMORY; 
     930                        goto err1; 
     931                } 
     932                if ((pslot = (struct pcsc_slot_data *) malloc(sizeof(struct pcsc_slot_data))) == NULL) { 
     933                        ret = SC_ERROR_OUT_OF_MEMORY; 
     934                        goto err1; 
    860935                } 
    861936 
     
    864939                reader->driver = &pcsc_drv; 
    865940                reader->slot_count = 1; 
    866                 reader->name = strdup(p); 
     941                if ((reader->name = strdup(p)) == NULL) { 
     942                        ret = SC_ERROR_OUT_OF_MEMORY; 
     943                        goto err1; 
     944                } 
    867945                priv->gpriv = gpriv; 
    868                 priv->reader_name = strdup(p); 
    869                 r = _sc_add_reader(ctx, reader); 
    870                 if (r) { 
    871                         free(priv->reader_name); 
    872                         free(priv); 
    873                         free(reader->name); 
    874                         free(reader); 
    875                         free(pslot); 
    876                         break; 
     946                if ((priv->reader_name = strdup(p)) == NULL) { 
     947                        ret = SC_ERROR_OUT_OF_MEMORY; 
     948                        goto err1; 
    877949                } 
    878950                slot = &reader->slot[0]; 
     
    880952                slot->drv_data = pslot; 
    881953                memset(pslot, 0, sizeof(*pslot)); 
     954                if (_sc_add_reader(ctx, reader)) { 
     955                        ret = SC_SUCCESS;       /* silent ignore */ 
     956                        goto err1; 
     957                } 
    882958                refresh_slot_attributes(reader, slot); 
    883959 
    884                 while (*p++ != 0); 
    885         } while (p < (reader_buf + reader_buf_size - 1)); 
    886  
    887         *reader_data = gpriv; 
    888         gpriv = NULL; 
     960                continue; 
     961         
     962        err1: 
     963                if (priv != NULL) { 
     964                        if (priv->reader_name) 
     965                                free(priv->reader_name); 
     966                        free(priv); 
     967                } 
     968                if (reader != NULL) { 
     969                        if (reader->name) 
     970                                free(reader->name); 
     971                        free(reader); 
     972                } 
     973                if (slot != NULL) 
     974                        free(pslot); 
     975 
     976                goto out; 
     977        } 
     978 
    889979        ret = SC_SUCCESS; 
    890980 
    891981out: 
    892         if (ret != SC_SUCCESS) { 
    893                 if (gpriv->pcsc_ctx != 0) 
    894                         gpriv->SCardReleaseContext(gpriv->pcsc_ctx); 
    895                 if (reader_buf != NULL) 
    896                         free(reader_buf); 
    897                 if (gpriv->dlhandle != NULL) 
    898                         lt_dlclose(gpriv->dlhandle); 
    899                 if (gpriv != NULL) 
    900                         free(gpriv); 
    901         } 
    902  
    903         return 0; 
    904 } 
    905  
    906 static int pcsc_finish(sc_context_t *ctx, void *prv_data) 
    907 { 
    908         struct pcsc_global_private_data *priv = (struct pcsc_global_private_data *) prv_data; 
    909  
    910         if (priv) { 
    911                 priv->SCardReleaseContext(priv->pcsc_ctx); 
    912                 lt_dlclose(priv->dlhandle); 
    913                 free(priv); 
    914         } 
    915  
    916         return 0; 
     982 
     983        if (reader_buf != NULL) 
     984                free (reader_buf); 
     985 
     986        return ret; 
    917987} 
    918988 
     
    9321002        pcsc_ops.init = pcsc_init; 
    9331003        pcsc_ops.finish = pcsc_finish; 
     1004        pcsc_ops.detect_readers = pcsc_detect_readers; 
    9341005        pcsc_ops.transmit = pcsc_transmit; 
    9351006        pcsc_ops.detect_card_presence = pcsc_detect_card_presence; 
  • trunk/src/pkcs11/pkcs11-global.c

    r3459 r3506  
    348348 
    349349        sc_debug(context, "Getting slot listing\n"); 
     350        if (pSlotList == NULL_PTR) { 
     351                sc_ctx_detect_readers(context); 
     352        } 
    350353        card_detect_all(); 
    351354 
  • trunk/src/pkcs11/slot.c

    r3404 r3506  
    8787 
    8888                if (rdr == NULL) 
    89                         return CKR_GENERAL_ERROR; 
     89                        return CKR_TOKEN_NOT_PRESENT; 
    9090                slot = virtual_slots + card->first_slot + i; 
    9191                strcpy_bp(slot->slot_info.slotDescription, rdr->name, 64); 
  • trunk/src/tools/opensc-tool.c

    r3472 r3506  
    247247         
    248248        if (rcount == 0) { 
    249                 printf("No readers configured!\n"); 
     249                printf("No readers found.\n"); 
    250250                return 0; 
    251251        }