[Spice-devel] [PATCH 04/12] Add a VCARD_DIRECT implemention to the libcacard smartcard support

Christophe Fergeau cfergeau at redhat.com
Fri Oct 9 07:34:29 PDT 2015


On Thu, Oct 08, 2015 at 05:40:33PM +0200, marcandre.lureau at redhat.com wrote:
> From: Jeremy White <jwhite at codeweavers.com>
> 
> This uses libpcsclite to provide direct communication with a smartcard.
> 
> Signed-off-by: Jeremy White <jwhite at codeweavers.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau at redhat.com>
> ---
>  Makefile.am           |   9 +-
>  configure.ac          |   1 +
>  src/capcsc.c          | 505 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/capcsc.h          |  18 ++
>  src/card_7816.c       |   2 +-
>  src/card_7816.h       |   4 +-
>  src/libcacard.syms    |   2 +
>  src/vcard.c           |   2 +-
>  src/vcard.h           |   2 +-
>  src/vcard_emul_nss.c  |  11 +-
>  src/vcard_emul_type.c |   1 +
>  11 files changed, 549 insertions(+), 8 deletions(-)
>  create mode 100644 src/capcsc.c
>  create mode 100644 src/capcsc.h
> 
> diff --git a/Makefile.am b/Makefile.am
> index 7939079..b1e257f 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -15,9 +15,14 @@ libcacard_la_SOURCES =				\
>  	src/vreader.c				\
>  	$(NULL)
>  
> +if ENABLE_PCSC
> +libcacard_la_SOURCES += src/capcsc.c
> +endif
> +
>  libcacard_includedir = $(includedir)/cacard
>  libcacard_include_HEADERS =			\
>  	src/cac.h				\
> +	src/capcsc.h				\
>  	src/card_7816.h				\
>  	src/card_7816t.h			\
>  	src/eventt.h				\
> @@ -32,7 +37,7 @@ libcacard_include_HEADERS =			\
>  	src/vscard_common.h			\
>  	$(NULL)
>  
> -libcacard_la_LIBADD = $(CACARD_LIBS)
> +libcacard_la_LIBADD = $(CACARD_LIBS) $(PCSC_LIBS)
>  libcacard_la_LDFLAGS =					\
>  	-export-symbols $(srcdir)/src/libcacard.syms	\
>  	-no-undefined					\
> @@ -56,7 +61,7 @@ if OS_WIN32
>  vscclient_CFLAGS += -D__USE_MINGW_ANSI_STDIO=1
>  endif
>  
> -AM_CPPFLAGS = $(CACARD_CFLAGS) $(WARN_CFLAGS)
> +AM_CPPFLAGS = $(CACARD_CFLAGS) $(PCSC_CFLAGS) $(WARN_CFLAGS)
>  EXTRA_DIST =					\
>  	NEWS					\
>  	README.md				\
> diff --git a/configure.ac b/configure.ac
> index b878526..6a0a73d 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -49,6 +49,7 @@ if test "x$enable_pcsc" != "xno"; then
>     fi
>     if test "x$have_pcsc" = "xyes"; then
>        enable_pcsc=yes
> +      AC_DEFINE([ENABLE_PCSC], 1, [pcsc support])
>     fi
>  fi

This could go in the patch adding the configure check.

>  AM_CONDITIONAL(ENABLE_PCSC, test "x$enable_pcsc" = "xyes")
> diff --git a/src/capcsc.c b/src/capcsc.c
> new file mode 100644
> index 0000000..3b68ee3
> --- /dev/null
> +++ b/src/capcsc.c
> @@ -0,0 +1,505 @@
> +/*
> + * Supply a vreader using the PC/SC interface.
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
> + * See the COPYING.LIB file in the top-level directory.
> + */
> +
> +#include "glib-compat.h"
> +#include <string.h>
> +#include <stdio.h>
> +
> +#include "vcard.h"
> +#include "card_7816.h"
> +#include "capcsc.h"
> +#include "vreader.h"
> +#include "vevent.h"
> +
> +#include <PCSC/wintypes.h>
> +#include <PCSC/winscard.h>
> +
> +
> +typedef struct _PCSCContext PCSCContext;
> +
> +typedef struct {
> +    PCSCContext *context;
> +    int index;
> +    char *name;
> +    DWORD protocol;
> +    DWORD state;
> +    SCARDHANDLE card;
> +    BYTE atr[MAX_ATR_SIZE];
> +    DWORD atrlen;
> +    int card_connected;
> +    unsigned long request_count;
> +} SCardReader;
> +
> +typedef struct _PCSCContext {
> +    SCARDCONTEXT context;
> +    SCardReader readers[CAPCSC_MAX_READERS];
> +    int reader_count;
> +    int readers_changed;
> +    GThread *thread;
> +    CompatGMutex lock;
> +} PCSCContext;
> +
> +
> +static void delete_reader(PCSCContext *pc, int i)
> +{
> +    SCardReader *r = &pc->readers[i];
> +    g_free(r->name);
> +    r->name = NULL;
> +
> +    if (i < (pc->reader_count - 1)) {
> +        int rem = pc->reader_count - i - 1;
> +        memmove(&pc->readers[i], &pc->readers[i + 1],
> +                sizeof(SCardReader) * rem);
> +    }

Since libcacard is using glib, I think GArray/GPtrArray might be usable
to avoid manual memory juggling. There are few places where memory is
moved around though, so I'm fine if this stays this way.


> +
> +    pc->reader_count--;
> +}
> +
> +static void delete_reader_cb(VReaderEmul *ve)
> +{
> +    SCardReader *r = (SCardReader *) ve;
> +
> +    g_mutex_lock(&r->context->lock);
> +    delete_reader(r->context, r->index);
> +    g_mutex_unlock(&r->context->lock);
> +}
> +
> +static int new_reader(PCSCContext *pc, const char *name, DWORD state)
> +{
> +    SCardReader *r;
> +    VReader *vreader;
> +
> +    if (pc->reader_count >= CAPCSC_MAX_READERS - 1) {
> +        return 1;
> +    }
> +
> +    r = &pc->readers[pc->reader_count];
> +    memset(r, 0, sizeof(*r));
> +    r->index = pc->reader_count++;
> +    r->context = pc;
> +    r->name = g_strdup(name);
> +
> +    vreader = vreader_new(name, (VReaderEmul *) r, delete_reader_cb);
> +    vreader_add_reader(vreader);
> +    vreader_free(vreader);
> +
> +    return 0;
> +}
> +
> +static int find_reader(PCSCContext *pc, const char *name)
> +{
> +    int i;
> +    for (i = 0; i < pc->reader_count; i++)
> +        if (strcmp(pc->readers[i].name, name) == 0) {
> +            return i;
> +        }
> +
> +    return -1;
> +}
> +
> +
> +static int scan_for_readers(PCSCContext *pc)
> +{
> +    LONG rc;
> +
> +    int i;
> +    char buf[8192];
> +    DWORD buflen = sizeof(buf);
> +
> +    char *p;
> +    int matches[CAPCSC_MAX_READERS];
> +
> +    g_mutex_lock(&pc->lock);
> +
> +    for (i = 0; i < CAPCSC_MAX_READERS; i++) {
> +        matches[i] = 0;
> +    }

Why not int matches[..] = { 0, }; or a memset?

>   * destructor for VCardResponse.
> diff --git a/src/libcacard.syms b/src/libcacard.syms
> index 2f9d423..1b78f8d 100644
> --- a/src/libcacard.syms
> +++ b/src/libcacard.syms
> @@ -1,4 +1,5 @@
>  cac_card_init
> +capcsc_init
>  vcard_add_applet
>  vcard_apdu_delete
>  vcard_apdu_new

I don't think you need to export capcsc_init as it's called by
vcard_emul_init() when needed?

> @@ -40,6 +41,7 @@ vcard_response_new
>  vcard_response_new_bytes
>  vcard_response_new_data
>  vcard_response_new_status_bytes
> +vcard_response_set_status_bytes
>  vcard_select_applet
>  vcard_set_applet_private
>  vcard_set_atr_func
> diff --git a/src/vcard.c b/src/vcard.c
> index 667f30a..2edf1d0 100644
> --- a/src/vcard.c
> +++ b/src/vcard.c
> @@ -97,7 +97,7 @@ vcard_reset(VCard *card, VCardPower power)
>  VCardApplet *
>  vcard_new_applet(VCardProcessAPDU applet_process_function,
>                   VCardResetApplet applet_reset_function,
> -                 unsigned char *aid, int aid_len)
> +                 const unsigned char *aid, int aid_len)
>  {
>      VCardApplet *applet;
>  
> diff --git a/src/vcard.h b/src/vcard.h
> index 16a23b5..1364dfb 100644
> --- a/src/vcard.h
> +++ b/src/vcard.h
> @@ -30,7 +30,7 @@ void vcard_reset(VCard *card, VCardPower power);
>   */
>  VCardApplet *vcard_new_applet(VCardProcessAPDU applet_process_function,
>                                VCardResetApplet applet_reset_function,
> -                              unsigned char *aid, int aid_len);
> +                              const unsigned char *aid, int aid_len);
>  
>  /*
>   * destructor for a VCardApplet
> diff --git a/src/vcard_emul_nss.c b/src/vcard_emul_nss.c
> index 7ffa0b4..d046ea9 100644
> --- a/src/vcard_emul_nss.c
> +++ b/src/vcard_emul_nss.c
> @@ -9,6 +9,7 @@
>   * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
>   * See the COPYING file in the top-level directory.
>   */
> +#include "config.h"
>  
>  /*
>   * NSS headers
> @@ -1253,7 +1254,12 @@ vcard_emul_options(const char *args)
>              opts->hw_card_type = VCARD_EMUL_CAC;
>              opts->use_hw = PR_TRUE;
>              args = find_blank(args + 7);
> -        /* nssemul */
> +#if defined(ENABLE_PCSC)
> +        } else if (strncmp(args, "passthru", 8) == 0) {
> +            opts->hw_card_type = VCARD_EMUL_PASSTHRU;
> +            opts->use_hw = PR_TRUE;
> +            args = find_blank(args + 8);
> +#endif
>          } else {
>              fprintf(stderr, "Error: Unknown smartcard specification.\n");
>              return NULL;
> @@ -1273,6 +1279,9 @@ vcard_emul_usage(void)
>  " hw_type={card_type_to_emulate}  (default CAC)\n"
>  " hw_param={param_for_card}       (default \"\")\n"
>  " nssemul                         (alias for use_hw=yes, hw_type=CAC)\n"
> +#if defined(ENABLE_PCSC)
> +" passthru                        (alias for use_hw=yes, hw_type=PASSTHRU)\n"
> +#endif
>  " soft=({slot_name},{vreader_name},{card_type_to_emulate},{params_for_card},\n"
>  "       {cert1},{cert2},{cert3}    (default none)\n"
>  "\n"

This is the passthru alias mentioned in another commit log.

> diff --git a/src/vcard_emul_type.c b/src/vcard_emul_type.c
> index 04e8d99..385e121 100644
> --- a/src/vcard_emul_type.c
> +++ b/src/vcard_emul_type.c
> @@ -7,6 +7,7 @@
>   * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
>   * See the COPYING file in the top-level directory.
>   */
> +#include "config.h"
>  
>  #include <strings.h>
>  #include "vcardt.h"

Is this hunk required as part of this commit?

Christophe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/spice-devel/attachments/20151009/c6b87bba/attachment.sig>


More information about the Spice-devel mailing list