Support windows 7 smartcard using guests and clients - (bz #917860 rhel 6.5)

This commit is contained in:
Alon Levy 2013-08-18 13:25:16 +03:00
parent d4960498b1
commit 4d1515ab5b
32 changed files with 3335 additions and 1 deletions

View File

@ -0,0 +1,113 @@
From 4190f44bbdde97adb467c9c0c625bdc2f89f4af7 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Fri, 15 Mar 2013 17:14:24 +0100
Subject: [PATCH 211/241] qemu-socket: Make socket_optslist public
Allow other users to create the QemuOpts needed for inet_connect_opts().
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit e62be8888a83aa0ab7f50eeb954deb2ec4e7201d)
---
include/qemu/sockets.h | 2 ++
util/qemu-sockets.c | 22 +++++++++++-----------
2 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 42ca690..6eed34e 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -31,6 +31,8 @@ int inet_aton(const char *cp, struct in_addr *ia);
#include "qapi/qmp/qerror.h"
#include "char/char.h"
+extern QemuOptsList socket_optslist;
+
/* misc helpers */
int qemu_socket(int domain, int type, int protocol);
int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index cd54fb4..b32510a 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -33,10 +33,10 @@
static const int on=1, off=0;
-/* used temporarely until all users are converted to QemuOpts */
-static QemuOptsList dummy_opts = {
- .name = "dummy",
- .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head),
+/* used temporarily until all users are converted to QemuOpts */
+QemuOptsList socket_optslist = {
+ .name = "socket",
+ .head = QTAILQ_HEAD_INITIALIZER(socket_optslist.head),
.desc = {
{
.name = "path",
@@ -579,7 +579,7 @@ int inet_listen(const char *str, char *ostr, int olen,
addr = inet_parse(str, errp);
if (addr != NULL) {
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
inet_addr_to_opts(opts, addr);
qapi_free_InetSocketAddress(addr);
sock = inet_listen_opts(opts, port_offset, errp);
@@ -652,7 +652,7 @@ int inet_nonblocking_connect(const char *str,
addr = inet_parse(str, errp);
if (addr != NULL) {
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
inet_addr_to_opts(opts, addr);
qapi_free_InetSocketAddress(addr);
sock = inet_connect_opts(opts, errp, callback, opaque);
@@ -795,7 +795,7 @@ int unix_listen(const char *str, char *ostr, int olen, Error **errp)
char *path, *optstr;
int sock, len;
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
optstr = strchr(str, ',');
if (optstr) {
@@ -823,7 +823,7 @@ int unix_connect(const char *path, Error **errp)
QemuOpts *opts;
int sock;
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
qemu_opt_set(opts, "path", path);
sock = unix_connect_opts(opts, errp, NULL, NULL);
qemu_opts_del(opts);
@@ -840,7 +840,7 @@ int unix_nonblocking_connect(const char *path,
g_assert(callback != NULL);
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
qemu_opt_set(opts, "path", path);
sock = unix_connect_opts(opts, errp, callback, opaque);
qemu_opts_del(opts);
@@ -891,7 +891,7 @@ int socket_connect(SocketAddress *addr, Error **errp,
QemuOpts *opts;
int fd;
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
switch (addr->kind) {
case SOCKET_ADDRESS_KIND_INET:
inet_addr_to_opts(opts, addr->inet);
@@ -923,7 +923,7 @@ int socket_listen(SocketAddress *addr, Error **errp)
QemuOpts *opts;
int fd;
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
switch (addr->kind) {
case SOCKET_ADDRESS_KIND_INET:
inet_addr_to_opts(opts, addr->inet);
--
1.8.3.1

View File

@ -0,0 +1,38 @@
From ec22a81dc76492a729695a54e32a837ab6384e65 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau@redhat.com>
Date: Sun, 2 Dec 2012 22:00:55 +0100
Subject: [PATCH 212/241] libcacard: correct T0 historical bytes size
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The VCARD_ATR_PREFIX macro adds a prefix of 6 characters only.
pcsc_scan was complaining before the patch:
+ Historical bytes: 56 43 41 52 44 5F 4E 53 53
ERROR! ATR is truncated: 2 byte(s) is/are missing
Signed-off-by: Marc-André Lureau <mlureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit e2fd2115ce26049335d66ae0ae5e5c0ad06fb498)
---
libcacard/vcardt.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
index d3e9522..538bdde 100644
--- a/libcacard/vcardt.h
+++ b/libcacard/vcardt.h
@@ -26,7 +26,7 @@ typedef struct VCardEmulStruct VCardEmul;
#define MAX_CHANNEL 4
/* create an ATR with appropriate historical bytes */
-#define VCARD_ATR_PREFIX(size) 0x3b, 0x68+(size), 0x00, 0xff, \
+#define VCARD_ATR_PREFIX(size) 0x3b, 0x66+(size), 0x00, 0xff, \
'V', 'C', 'A', 'R', 'D', '_'
--
1.8.3.1

View File

@ -0,0 +1,40 @@
From 142383e938fddcf7ed4f81aa30a1e7c1a968cef8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau@redhat.com>
Date: Wed, 21 Nov 2012 14:16:08 +0100
Subject: [PATCH 213/241] ccid-card-emul: do not crash if backend is not
provided
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Program received signal SIGSEGV, Segmentation fault.
__strcmp_sse42 () at ../sysdeps/x86_64/multiarch/strcmp-sse42.S:164
164 movdqu (%rsi), %xmm2
(gdb) bt
at /home/elmarco/320g/src/qemu/hw/ccid-card-emulated.c:477
at /home/elmarco/320g/src/qemu/hw/ccid-card-emulated.c:503
Signed-off-by: Marc-André Lureau <mlureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit d0ebd78890fba2ab458ec34763dae8566ccb1b72)
---
hw/ccid-card-emulated.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c
index c8f8ba3..210433e 100644
--- a/hw/ccid-card-emulated.c
+++ b/hw/ccid-card-emulated.c
@@ -473,6 +473,9 @@ static uint32_t parse_enumeration(char *str,
{
uint32_t ret = not_found_value;
+ if (str == NULL)
+ return 0;
+
while (table->name != NULL) {
if (strcmp(table->name, str) == 0) {
ret = table->value;
--
1.8.3.1

View File

@ -0,0 +1,50 @@
From e72e97097d1c619774cb07326496e38c0de46ef0 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering@redhat.com>
Date: Mon, 21 May 2012 21:56:20 +0200
Subject: [PATCH 214/241] ccid: make backend_enum_table "static const" and
adjust users
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Jim Meyering <meyering@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit d18c7117467aa5fae95a7c6eaffcf50618197e79)
---
hw/ccid-card-emulated.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c
index 210433e..cb9ef10 100644
--- a/hw/ccid-card-emulated.c
+++ b/hw/ccid-card-emulated.c
@@ -462,14 +462,14 @@ typedef struct EnumTable {
uint32_t value;
} EnumTable;
-EnumTable backend_enum_table[] = {
+static const EnumTable backend_enum_table[] = {
{BACKEND_NSS_EMULATED_NAME, BACKEND_NSS_EMULATED},
{BACKEND_CERTIFICATES_NAME, BACKEND_CERTIFICATES},
{NULL, 0},
};
static uint32_t parse_enumeration(char *str,
- EnumTable *table, uint32_t not_found_value)
+ const EnumTable *table, uint32_t not_found_value)
{
uint32_t ret = not_found_value;
@@ -490,7 +490,7 @@ static int emulated_initfn(CCIDCardState *base)
{
EmulatedState *card = DO_UPCAST(EmulatedState, base, base);
VCardEmulError ret;
- EnumTable *ptable;
+ const EnumTable *ptable;
QSIMPLEQ_INIT(&card->event_list);
QSIMPLEQ_INIT(&card->guest_apdu_list);
--
1.8.3.1

View File

@ -0,0 +1,32 @@
From 0a8bbcf1c62e0cf12188eaad871b23633a336f73 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering@redhat.com>
Date: Mon, 21 May 2012 21:51:33 +0200
Subject: [PATCH 215/241] ccid: declare DEFAULT_ATR table to be "static const"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Jim Meyering <meyering@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit da000a4867749434e03896a5072321771736352a)
---
hw/ccid-card-passthru.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
index 0dde761..62070db 100644
--- a/hw/ccid-card-passthru.c
+++ b/hw/ccid-card-passthru.c
@@ -27,7 +27,7 @@ do { \
#define D_VERBOSE 4
/* TODO: do we still need this? */
-uint8_t DEFAULT_ATR[] = {
+static const uint8_t DEFAULT_ATR[] = {
/*
* From some example somewhere
* 0x3B, 0xB0, 0x18, 0x00, 0xD1, 0x81, 0x05, 0xB1, 0x40, 0x38, 0x1F, 0x03, 0x28
--
1.8.3.1

View File

@ -0,0 +1,51 @@
From 2b60d2a60e98747e46e6addb89bf9a7f923ae499 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau@redhat.com>
Date: Wed, 27 Feb 2013 21:08:06 +0100
Subject: [PATCH 216/241] libcacard: use system config directory for nss db on
win32
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
It's a bit nicer to look for default database under
CSIDL_COMMON_APPDATA\pki\nss rather that /etc/pki/nss.
Signed-off-by: Marc-André Lureau <mlureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit e2d9c5e769d59f2bca649b8286892d49bdcfc2b1)
---
libcacard/vcard_emul_nss.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index df79476..21d4689 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -893,7 +893,23 @@ vcard_emul_init(const VCardEmulOptions *options)
if (options->nss_db) {
rv = NSS_Init(options->nss_db);
} else {
- rv = NSS_Init("sql:/etc/pki/nssdb");
+ gchar *path, *db;
+#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
+ db = g_strdup_printf("sql:%s", path);
+
+ rv = NSS_Init(db);
+ g_free(db);
+ g_free(path);
}
if (rv != SECSuccess) {
return VCARD_EMUL_FAIL;
--
1.8.3.1

View File

@ -0,0 +1,97 @@
From 2f2068568e87fc1f20bc891cce18b4e65965b091 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Mon, 25 Feb 2013 23:31:11 +0100
Subject: [PATCH 217/241] util: move socket_init() to osdep.c
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
vscclient needs to call socket_init() for portability.
Moving to osdep.c since it has no internal dependency.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit d3bf825e59125bc6a0accec0dca119ea0155cb82)
Conflicts:
util/qemu-sockets.c
---
util/osdep.c | 23 +++++++++++++++++++++++
util/qemu-sockets.c | 26 +-------------------------
2 files changed, 24 insertions(+), 25 deletions(-)
diff --git a/util/osdep.c b/util/osdep.c
index 5b51a03..3c1a0a3 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -400,3 +400,26 @@ bool fips_get_state(void)
return fips_enabled;
}
+#ifdef _WIN32
+static void socket_cleanup(void)
+{
+ WSACleanup();
+}
+#endif
+
+int socket_init(void)
+{
+#ifdef _WIN32
+ WSADATA Data;
+ int ret, err;
+
+ ret = WSAStartup(MAKEWORD(2, 2), &Data);
+ if (ret != 0) {
+ err = WSAGetLastError();
+ fprintf(stderr, "WSAStartup: %d\n", err);
+ return -1;
+ }
+ atexit(socket_cleanup);
+#endif
+ return 0;
+}
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index b32510a..7909381 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -618,7 +618,7 @@ int inet_connect(const char *str, Error **errp)
addr = inet_parse(str, errp);
if (addr != NULL) {
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
inet_addr_to_opts(opts, addr);
qapi_free_InetSocketAddress(addr);
sock = inet_connect_opts(opts, errp, NULL, NULL);
@@ -945,27 +945,3 @@ int socket_listen(SocketAddress *addr, Error **errp)
qemu_opts_del(opts);
return fd;
}
-
-#ifdef _WIN32
-static void socket_cleanup(void)
-{
- WSACleanup();
-}
-#endif
-
-int socket_init(void)
-{
-#ifdef _WIN32
- WSADATA Data;
- int ret, err;
-
- ret = WSAStartup(MAKEWORD(2,2), &Data);
- if (ret != 0) {
- err = WSAGetLastError();
- fprintf(stderr, "WSAStartup: %d\n", err);
- return -1;
- }
- atexit(socket_cleanup);
-#endif
- return 0;
-}
--
1.8.3.1

View File

@ -0,0 +1,73 @@
From 989623664fb428748a5efedbab162d75e1eb0432 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau@redhat.com>
Date: Mon, 25 Feb 2013 23:31:12 +0100
Subject: [PATCH 218/241] build-sys: must link with -fstack-protector
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
It is needed to give that flag to the linker as well, but latest
libtool 2.4.2 still swallows that argument, so let's pass it with
libtool -Wc argument.
qemu-1.4.0/stubs/arch-query-cpu-def.c:6: undefined reference to `__stack_chk_guard'
Signed-off-by: Marc-André Lureau <mlureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit 37746c5eacf309fa019ea0fa45f776c36c561457)
Conflicts:
configure
---
configure | 8 +++++++-
rules.mak | 1 +
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/configure b/configure
index 2996e1d..e8633c5 100755
--- a/configure
+++ b/configure
@@ -1197,7 +1197,7 @@ fi
gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
-gcc_flags="-fstack-protector-all -Wendif-labels $gcc_flags"
+gcc_flags="-Wendif-labels $gcc_flags"
gcc_flags="-Wno-initializer-overrides $gcc_flags"
# Note that we do not add -Werror to gcc_flags here, because that would
# enable it for all configure tests. If a configure test failed due
@@ -1216,6 +1216,11 @@ for flag in $gcc_flags; do
fi
done
+if compile_prog "-Werror -fstack-protector-all" "" ; then
+ QEMU_CFLAGS="$QEMU_CFLAGS -fstack-protector-all"
+ LIBTOOLFLAGS="$LIBTOOLFLAGS -Wc,-fstack-protector-all"
+fi
+
# Workaround for http://gcc.gnu.org/PR55489. Happens with -fPIE/-fPIC and
# large functions that use global variables. The bug is in all releases of
# GCC, but it became particularly acute in 4.6.x and 4.7.x. It is fixed in
@@ -3832,6 +3837,7 @@ fi
echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
echo "ARLIBS_BEGIN=$arlibs_begin" >> $config_host_mak
echo "ARLIBS_END=$arlibs_end" >> $config_host_mak
+echo "LIBTOOLFLAGS=$LIBTOOLFLAGS" >> $config_host_mak
echo "LIBS+=$LIBS" >> $config_host_mak
echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
echo "EXESUF=$EXESUF" >> $config_host_mak
diff --git a/rules.mak b/rules.mak
index edc2552..36aba2d 100644
--- a/rules.mak
+++ b/rules.mak
@@ -36,6 +36,7 @@ LINK = $(call quiet-command,\
$(if $(filter %.lo %.la,$^),$(LIBTOOL) --mode=link --tag=CC \
)$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
$(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \
+ $(if $(filter %.lo %.la,$^),$(LIBTOOLFLAGS)) \
$(LIBS),$(if $(filter %.lo %.la,$^),"lt LINK ", " LINK ")"$(TARGET_DIR)$@")
endif
--
1.8.3.1

View File

@ -0,0 +1,57 @@
From cc5a2202bc5484aba302a684fb75106da506b1f0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau@redhat.com>
Date: Mon, 25 Feb 2013 23:31:13 +0100
Subject: [PATCH 219/241] libcacard: fix mingw64 cross-compilation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Compile and link with version.lo
Signed-off-by: Marc-André Lureau <mlureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit 5354e4d242175e067bb70732f694ae9322a81351)
---
Makefile | 8 ++++++--
rules.mak | 3 ++-
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/Makefile b/Makefile
index 0d9099a..751cf1d 100644
--- a/Makefile
+++ b/Makefile
@@ -148,11 +148,15 @@ recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES)
bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
-version.o: $(SRC_PATH)/version.rc config-host.h
+version.o: $(SRC_PATH)/version.rc config-host.h | version.lo
$(call quiet-command,$(WINDRES) -I. -o $@ $<," RC $(TARGET_DIR)$@")
+version.lo: $(SRC_PATH)/version.rc config-host.h
+ $(call quiet-command,$(LIBTOOL) --mode=compile --tag=RC $(WINDRES) -I. -o $@ $<,"lt RC $(TARGET_DIR)$@")
version-obj-$(CONFIG_WIN32) += version.o
-Makefile: $(version-obj-y)
+version-lobj-$(CONFIG_WIN32) += $(if $(LIBTOOL),version.lo)
+Makefile: $(version-obj-y) $(version-lobj-y)
+
######################################################################
# Build libraries
diff --git a/rules.mak b/rules.mak
index 36aba2d..292a422 100644
--- a/rules.mak
+++ b/rules.mak
@@ -35,7 +35,8 @@ LIBTOOL += $(if $(V),,--quiet)
LINK = $(call quiet-command,\
$(if $(filter %.lo %.la,$^),$(LIBTOOL) --mode=link --tag=CC \
)$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
- $(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \
+ $(sort $(filter %.o, $1)) $(filter-out %.o, $1) \
+ $(if $(filter %.lo %.la,$^),$(version-lobj-y),$(version-obj-y)) \
$(if $(filter %.lo %.la,$^),$(LIBTOOLFLAGS)) \
$(LIBS),$(if $(filter %.lo %.la,$^),"lt LINK ", " LINK ")"$(TARGET_DIR)$@")
endif
--
1.8.3.1

View File

@ -0,0 +1,377 @@
From 2898705c820b4b0c6bbd196bccce55dd3d64f62c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Mon, 25 Feb 2013 23:31:14 +0100
Subject: [PATCH 220/241] libcacard: split vscclient main() from socket reading
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit a50b831ae1fe039b7c22793f307e0b8afdf50589)
---
libcacard/vscclient.c | 314 ++++++++++++++++++++++++++------------------------
1 file changed, 162 insertions(+), 152 deletions(-)
diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
index 9b744f2..5e00db3 100644
--- a/libcacard/vscclient.c
+++ b/libcacard/vscclient.c
@@ -211,6 +211,166 @@ get_id_from_string(char *string, unsigned int default_id)
return id;
}
+static int
+on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
+{
+ uint32_t *capabilities = (incoming->capabilities);
+ int num_capabilities =
+ 1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
+ int i;
+ int rv;
+ pthread_t thread_id;
+
+ incoming->version = ntohl(incoming->version);
+ if (incoming->version != VSCARD_VERSION) {
+ if (verbose > 0) {
+ printf("warning: host has version %d, we have %d\n",
+ verbose, VSCARD_VERSION);
+ }
+ }
+ if (incoming->magic != VSCARD_MAGIC) {
+ printf("unexpected magic: got %d, expected %d\n",
+ incoming->magic, VSCARD_MAGIC);
+ return -1;
+ }
+ for (i = 0 ; i < num_capabilities; ++i) {
+ capabilities[i] = ntohl(capabilities[i]);
+ }
+ /* Future: check capabilities */
+ /* remove whatever reader might be left in qemu,
+ * in case of an unclean previous exit. */
+ send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
+ /* launch the event_thread. This will trigger reader adds for all the
+ * existing readers */
+ rv = pthread_create(&thread_id, NULL, event_thread, NULL);
+ if (rv < 0) {
+ perror("pthread_create");
+ return rv;
+ }
+ return 0;
+}
+
+#define APDUBufSize 270
+
+static int
+do_socket_read(void)
+{
+ int rv;
+ int dwSendLength;
+ int dwRecvLength;
+ uint8_t pbRecvBuffer[APDUBufSize];
+ uint8_t pbSendBuffer[APDUBufSize];
+ VReaderStatus reader_status;
+ VReader *reader = NULL;
+ VSCMsgHeader mhHeader;
+ VSCMsgError *error_msg;
+
+ rv = read(sock, &mhHeader, sizeof(mhHeader));
+ if (rv < sizeof(mhHeader)) {
+ /* Error */
+ if (rv < 0) {
+ perror("header read error\n");
+ } else {
+ fprintf(stderr, "header short read %d\n", rv);
+ }
+ return -1;
+ }
+ mhHeader.type = ntohl(mhHeader.type);
+ mhHeader.reader_id = ntohl(mhHeader.reader_id);
+ mhHeader.length = ntohl(mhHeader.length);
+ if (verbose) {
+ printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
+ mhHeader.type, mhHeader.reader_id, mhHeader.length,
+ mhHeader.length);
+ }
+ switch (mhHeader.type) {
+ case VSC_APDU:
+ case VSC_Flush:
+ case VSC_Error:
+ case VSC_Init:
+ rv = read(sock, pbSendBuffer, mhHeader.length);
+ break;
+ default:
+ fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
+ return -1;
+ }
+ switch (mhHeader.type) {
+ case VSC_APDU:
+ if (rv < 0) {
+ /* Error */
+ fprintf(stderr, "read error\n");
+ close(sock);
+ return -1;
+ }
+ if (verbose) {
+ printf(" recv APDU: ");
+ print_byte_array(pbSendBuffer, mhHeader.length);
+ }
+ /* Transmit received APDU */
+ dwSendLength = mhHeader.length;
+ dwRecvLength = sizeof(pbRecvBuffer);
+ reader = vreader_get_reader_by_id(mhHeader.reader_id);
+ reader_status = vreader_xfr_bytes(reader,
+ pbSendBuffer, dwSendLength,
+ pbRecvBuffer, &dwRecvLength);
+ if (reader_status == VREADER_OK) {
+ mhHeader.length = dwRecvLength;
+ if (verbose) {
+ printf(" send response: ");
+ print_byte_array(pbRecvBuffer, mhHeader.length);
+ }
+ send_msg(VSC_APDU, mhHeader.reader_id,
+ pbRecvBuffer, dwRecvLength);
+ } else {
+ rv = reader_status; /* warning: not meaningful */
+ send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
+ }
+ vreader_free(reader);
+ reader = NULL; /* we've freed it, don't use it by accident
+ again */
+ break;
+ case VSC_Flush:
+ /* TODO: actually flush */
+ send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
+ break;
+ case VSC_Error:
+ error_msg = (VSCMsgError *) pbSendBuffer;
+ if (error_msg->code == VSC_SUCCESS) {
+ qemu_mutex_lock(&pending_reader_lock);
+ if (pending_reader) {
+ vreader_set_id(pending_reader, mhHeader.reader_id);
+ vreader_free(pending_reader);
+ pending_reader = NULL;
+ qemu_cond_signal(&pending_reader_condition);
+ }
+ qemu_mutex_unlock(&pending_reader_lock);
+ break;
+ }
+ printf("warning: qemu refused to add reader\n");
+ if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
+ /* clear pending reader, qemu can't handle any more */
+ qemu_mutex_lock(&pending_reader_lock);
+ if (pending_reader) {
+ pending_reader = NULL;
+ /* make sure the event loop doesn't hang */
+ qemu_cond_signal(&pending_reader_condition);
+ }
+ qemu_mutex_unlock(&pending_reader_lock);
+ }
+ break;
+ case VSC_Init:
+ if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
+ return -1;
+ }
+ break;
+ default:
+ printf("Default\n");
+ return -1;
+ }
+
+ return 0;
+}
+
static void
do_command(void)
{
@@ -339,8 +499,6 @@ do_command(void)
}
-#define APDUBufSize 270
-
/* just for ease of parsing command line arguments. */
#define MAX_CERTS 100
@@ -385,44 +543,6 @@ connect_to_qemu(
return sock;
}
-static int on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
-{
- uint32_t *capabilities = (incoming->capabilities);
- int num_capabilities =
- 1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
- int i;
- int rv;
- pthread_t thread_id;
-
- incoming->version = ntohl(incoming->version);
- if (incoming->version != VSCARD_VERSION) {
- if (verbose > 0) {
- printf("warning: host has version %d, we have %d\n",
- verbose, VSCARD_VERSION);
- }
- }
- if (incoming->magic != VSCARD_MAGIC) {
- printf("unexpected magic: got %d, expected %d\n",
- incoming->magic, VSCARD_MAGIC);
- return -1;
- }
- for (i = 0 ; i < num_capabilities; ++i) {
- capabilities[i] = ntohl(capabilities[i]);
- }
- /* Future: check capabilities */
- /* remove whatever reader might be left in qemu,
- * in case of an unclean previous exit. */
- send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
- /* launch the event_thread. This will trigger reader adds for all the
- * existing readers */
- rv = pthread_create(&thread_id, NULL, event_thread, NULL);
- if (rv < 0) {
- perror("pthread_create");
- return rv;
- }
- return 0;
-}
-
int
main(
int argc,
@@ -431,21 +551,13 @@ main(
char *qemu_host;
char *qemu_port;
VSCMsgHeader mhHeader;
- VSCMsgError *error_msg;
- int rv;
- int dwSendLength;
- int dwRecvLength;
- uint8_t pbRecvBuffer[APDUBufSize];
- uint8_t pbSendBuffer[APDUBufSize];
- VReaderStatus reader_status;
- VReader *reader = NULL;
VCardEmulOptions *command_line_options = NULL;
char *cert_names[MAX_CERTS];
char *emul_args = NULL;
int cert_count = 0;
- int c;
+ int c, rv;
while ((c = getopt(argc, argv, "c:e:pd:")) != -1) {
switch (c) {
@@ -548,109 +660,7 @@ main(
if (!FD_ISSET(sock, &fds)) {
continue;
}
-
- rv = read(sock, &mhHeader, sizeof(mhHeader));
- if (rv < sizeof(mhHeader)) {
- /* Error */
- if (rv < 0) {
- perror("header read error\n");
- } else {
- fprintf(stderr, "header short read %d\n", rv);
- }
- return 8;
- }
- mhHeader.type = ntohl(mhHeader.type);
- mhHeader.reader_id = ntohl(mhHeader.reader_id);
- mhHeader.length = ntohl(mhHeader.length);
- if (verbose) {
- printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
- mhHeader.type, mhHeader.reader_id, mhHeader.length,
- mhHeader.length);
- }
- switch (mhHeader.type) {
- case VSC_APDU:
- case VSC_Flush:
- case VSC_Error:
- case VSC_Init:
- rv = read(sock, pbSendBuffer, mhHeader.length);
- break;
- default:
- fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
- return 0;
- }
- switch (mhHeader.type) {
- case VSC_APDU:
- if (rv < 0) {
- /* Error */
- fprintf(stderr, "read error\n");
- close(sock);
- return 8;
- }
- if (verbose) {
- printf(" recv APDU: ");
- print_byte_array(pbSendBuffer, mhHeader.length);
- }
- /* Transmit received APDU */
- dwSendLength = mhHeader.length;
- dwRecvLength = sizeof(pbRecvBuffer);
- reader = vreader_get_reader_by_id(mhHeader.reader_id);
- reader_status = vreader_xfr_bytes(reader,
- pbSendBuffer, dwSendLength,
- pbRecvBuffer, &dwRecvLength);
- if (reader_status == VREADER_OK) {
- mhHeader.length = dwRecvLength;
- if (verbose) {
- printf(" send response: ");
- print_byte_array(pbRecvBuffer, mhHeader.length);
- }
- send_msg(VSC_APDU, mhHeader.reader_id,
- pbRecvBuffer, dwRecvLength);
- } else {
- rv = reader_status; /* warning: not meaningful */
- send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
- }
- vreader_free(reader);
- reader = NULL; /* we've freed it, don't use it by accident
- again */
- break;
- case VSC_Flush:
- /* TODO: actually flush */
- send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
- break;
- case VSC_Error:
- error_msg = (VSCMsgError *) pbSendBuffer;
- if (error_msg->code == VSC_SUCCESS) {
- qemu_mutex_lock(&pending_reader_lock);
- if (pending_reader) {
- vreader_set_id(pending_reader, mhHeader.reader_id);
- vreader_free(pending_reader);
- pending_reader = NULL;
- qemu_cond_signal(&pending_reader_condition);
- }
- qemu_mutex_unlock(&pending_reader_lock);
- break;
- }
- printf("warning: qemu refused to add reader\n");
- if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
- /* clear pending reader, qemu can't handle any more */
- qemu_mutex_lock(&pending_reader_lock);
- if (pending_reader) {
- pending_reader = NULL;
- /* make sure the event loop doesn't hang */
- qemu_cond_signal(&pending_reader_condition);
- }
- qemu_mutex_unlock(&pending_reader_lock);
- }
- break;
- case VSC_Init:
- if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
- return -1;
- }
- break;
- default:
- printf("Default\n");
- return 0;
- }
+ rv = do_socket_read();
} while (rv >= 0);
return 0;
--
1.8.3.1

View File

@ -0,0 +1,46 @@
From dc54f4b260b2fe57af5ad57326f0a67a82f977d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Mon, 25 Feb 2013 23:31:15 +0100
Subject: [PATCH 221/241] libcacard: vscclient to use QemuThread for
portability
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit 930c8ad472ec00d40cfbf1e9b1395946bf0dd392)
---
libcacard/vscclient.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
index 5e00db3..5f47634 100644
--- a/libcacard/vscclient.c
+++ b/libcacard/vscclient.c
@@ -218,8 +218,7 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
int num_capabilities =
1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
int i;
- int rv;
- pthread_t thread_id;
+ QemuThread thread_id;
incoming->version = ntohl(incoming->version);
if (incoming->version != VSCARD_VERSION) {
@@ -242,11 +241,7 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
/* launch the event_thread. This will trigger reader adds for all the
* existing readers */
- rv = pthread_create(&thread_id, NULL, event_thread, NULL);
- if (rv < 0) {
- perror("pthread_create");
- return rv;
- }
+ qemu_thread_create(&thread_id, event_thread, NULL, 0);
return 0;
}
--
1.8.3.1

View File

@ -0,0 +1,548 @@
From d5830145bc9af4b8df2eddd5a6ece27c4010b3d6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau@redhat.com>
Date: Mon, 25 Feb 2013 23:31:16 +0100
Subject: [PATCH 222/241] libcacard: teach vscclient to use GMainLoop for
portability
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This version handles non-blocking sending and receiving from the
socket.
Signed-off-by: Marc-André Lureau <mlureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit c9495ee9eb57786f5a60d4591bb186b23f6b6bef)
---
libcacard/vscclient.c | 391 +++++++++++++++++++++++++++++++-------------------
1 file changed, 246 insertions(+), 145 deletions(-)
diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
index 5f47634..ac23647 100644
--- a/libcacard/vscclient.c
+++ b/libcacard/vscclient.c
@@ -10,7 +10,10 @@
* See the COPYING.LIB file in the top-level directory.
*/
+#ifndef _WIN32
#include <netdb.h>
+#endif
+#include <glib.h>
#include "qemu-common.h"
#include "qemu/thread.h"
@@ -22,9 +25,7 @@
#include "vcard_emul.h"
#include "vevent.h"
-int verbose;
-
-int sock;
+static int verbose;
static void
print_byte_array(
@@ -51,7 +52,47 @@ print_usage(void) {
vcard_emul_usage();
}
-static QemuMutex write_lock;
+static GIOChannel *channel_socket;
+static GByteArray *socket_to_send;
+static QemuMutex socket_to_send_lock;
+static guint socket_tag;
+
+static void
+update_socket_watch(gboolean out);
+
+static gboolean
+do_socket_send(GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
+{
+ gsize bw;
+ GError *err = NULL;
+
+ g_return_val_if_fail(socket_to_send->len != 0, FALSE);
+ g_return_val_if_fail(condition & G_IO_OUT, FALSE);
+
+ g_io_channel_write_chars(channel_socket,
+ (gchar *)socket_to_send->data, socket_to_send->len, &bw, &err);
+ if (err != NULL) {
+ g_error("Error while sending socket %s", err->message);
+ return FALSE;
+ }
+ g_byte_array_remove_range(socket_to_send, 0, bw);
+
+ if (socket_to_send->len == 0) {
+ update_socket_watch(FALSE);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+socket_prepare_sending(gpointer user_data)
+{
+ update_socket_watch(TRUE);
+
+ return FALSE;
+}
static int
send_msg(
@@ -60,10 +101,9 @@ send_msg(
const void *msg,
unsigned int length
) {
- int rv;
VSCMsgHeader mhHeader;
- qemu_mutex_lock(&write_lock);
+ qemu_mutex_lock(&socket_to_send_lock);
if (verbose > 10) {
printf("sending type=%d id=%u, len =%u (0x%x)\n",
@@ -73,23 +113,11 @@ send_msg(
mhHeader.type = htonl(type);
mhHeader.reader_id = 0;
mhHeader.length = htonl(length);
- rv = write(sock, &mhHeader, sizeof(mhHeader));
- if (rv < 0) {
- /* Error */
- fprintf(stderr, "write header error\n");
- close(sock);
- qemu_mutex_unlock(&write_lock);
- return 16;
- }
- rv = write(sock, msg, length);
- if (rv < 0) {
- /* Error */
- fprintf(stderr, "write error\n");
- close(sock);
- qemu_mutex_unlock(&write_lock);
- return 16;
- }
- qemu_mutex_unlock(&write_lock);
+ g_byte_array_append(socket_to_send, (guint8 *)&mhHeader, sizeof(mhHeader));
+ g_byte_array_append(socket_to_send, (guint8 *)msg, length);
+ g_idle_add(socket_prepare_sending, NULL);
+
+ qemu_mutex_unlock(&socket_to_send_lock);
return 0;
}
@@ -245,139 +273,203 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
return 0;
}
+
+enum {
+ STATE_HEADER,
+ STATE_MESSAGE,
+};
+
#define APDUBufSize 270
-static int
-do_socket_read(void)
+static gboolean
+do_socket_read(GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
{
int rv;
int dwSendLength;
int dwRecvLength;
uint8_t pbRecvBuffer[APDUBufSize];
- uint8_t pbSendBuffer[APDUBufSize];
+ static uint8_t pbSendBuffer[APDUBufSize];
VReaderStatus reader_status;
VReader *reader = NULL;
- VSCMsgHeader mhHeader;
+ static VSCMsgHeader mhHeader;
VSCMsgError *error_msg;
+ GError *err = NULL;
- rv = read(sock, &mhHeader, sizeof(mhHeader));
- if (rv < sizeof(mhHeader)) {
- /* Error */
- if (rv < 0) {
- perror("header read error\n");
- } else {
- fprintf(stderr, "header short read %d\n", rv);
- }
- return -1;
- }
- mhHeader.type = ntohl(mhHeader.type);
- mhHeader.reader_id = ntohl(mhHeader.reader_id);
- mhHeader.length = ntohl(mhHeader.length);
- if (verbose) {
- printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
- mhHeader.type, mhHeader.reader_id, mhHeader.length,
- mhHeader.length);
- }
- switch (mhHeader.type) {
- case VSC_APDU:
- case VSC_Flush:
- case VSC_Error:
- case VSC_Init:
- rv = read(sock, pbSendBuffer, mhHeader.length);
- break;
- default:
- fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
- return -1;
+ static gchar *buf;
+ static gsize br, to_read;
+ static int state = STATE_HEADER;
+
+ if (state == STATE_HEADER && to_read == 0) {
+ buf = (gchar *)&mhHeader;
+ to_read = sizeof(mhHeader);
}
- switch (mhHeader.type) {
- case VSC_APDU:
- if (rv < 0) {
- /* Error */
- fprintf(stderr, "read error\n");
- close(sock);
- return -1;
+
+ if (to_read > 0) {
+ g_io_channel_read_chars(source, (gchar *)buf, to_read, &br, &err);
+ if (err != NULL) {
+ g_error("error while reading: %s", err->message);
}
+ buf += br;
+ to_read -= br;
+ if (to_read != 0) {
+ return TRUE;
+ }
+ }
+
+ if (state == STATE_HEADER) {
+ mhHeader.type = ntohl(mhHeader.type);
+ mhHeader.reader_id = ntohl(mhHeader.reader_id);
+ mhHeader.length = ntohl(mhHeader.length);
if (verbose) {
- printf(" recv APDU: ");
- print_byte_array(pbSendBuffer, mhHeader.length);
+ printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
+ mhHeader.type, mhHeader.reader_id, mhHeader.length,
+ mhHeader.length);
}
- /* Transmit received APDU */
- dwSendLength = mhHeader.length;
- dwRecvLength = sizeof(pbRecvBuffer);
- reader = vreader_get_reader_by_id(mhHeader.reader_id);
- reader_status = vreader_xfr_bytes(reader,
- pbSendBuffer, dwSendLength,
- pbRecvBuffer, &dwRecvLength);
- if (reader_status == VREADER_OK) {
- mhHeader.length = dwRecvLength;
+ switch (mhHeader.type) {
+ case VSC_APDU:
+ case VSC_Flush:
+ case VSC_Error:
+ case VSC_Init:
+ buf = (gchar *)pbSendBuffer;
+ to_read = mhHeader.length;
+ state = STATE_MESSAGE;
+ return TRUE;
+ default:
+ fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
+ return FALSE;
+ }
+ }
+
+ if (state == STATE_MESSAGE) {
+ switch (mhHeader.type) {
+ case VSC_APDU:
if (verbose) {
- printf(" send response: ");
- print_byte_array(pbRecvBuffer, mhHeader.length);
+ printf(" recv APDU: ");
+ print_byte_array(pbSendBuffer, mhHeader.length);
}
- send_msg(VSC_APDU, mhHeader.reader_id,
- pbRecvBuffer, dwRecvLength);
- } else {
- rv = reader_status; /* warning: not meaningful */
- send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
- }
- vreader_free(reader);
- reader = NULL; /* we've freed it, don't use it by accident
- again */
- break;
- case VSC_Flush:
- /* TODO: actually flush */
- send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
- break;
- case VSC_Error:
- error_msg = (VSCMsgError *) pbSendBuffer;
- if (error_msg->code == VSC_SUCCESS) {
- qemu_mutex_lock(&pending_reader_lock);
- if (pending_reader) {
- vreader_set_id(pending_reader, mhHeader.reader_id);
- vreader_free(pending_reader);
- pending_reader = NULL;
- qemu_cond_signal(&pending_reader_condition);
+ /* Transmit received APDU */
+ dwSendLength = mhHeader.length;
+ dwRecvLength = sizeof(pbRecvBuffer);
+ reader = vreader_get_reader_by_id(mhHeader.reader_id);
+ reader_status = vreader_xfr_bytes(reader,
+ pbSendBuffer, dwSendLength,
+ pbRecvBuffer, &dwRecvLength);
+ if (reader_status == VREADER_OK) {
+ mhHeader.length = dwRecvLength;
+ if (verbose) {
+ printf(" send response: ");
+ print_byte_array(pbRecvBuffer, mhHeader.length);
+ }
+ send_msg(VSC_APDU, mhHeader.reader_id,
+ pbRecvBuffer, dwRecvLength);
+ } else {
+ rv = reader_status; /* warning: not meaningful */
+ send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
}
- qemu_mutex_unlock(&pending_reader_lock);
+ vreader_free(reader);
+ reader = NULL; /* we've freed it, don't use it by accident
+ again */
break;
- }
- printf("warning: qemu refused to add reader\n");
- if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
- /* clear pending reader, qemu can't handle any more */
- qemu_mutex_lock(&pending_reader_lock);
- if (pending_reader) {
- pending_reader = NULL;
- /* make sure the event loop doesn't hang */
- qemu_cond_signal(&pending_reader_condition);
+ case VSC_Flush:
+ /* TODO: actually flush */
+ send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
+ break;
+ case VSC_Error:
+ error_msg = (VSCMsgError *) pbSendBuffer;
+ if (error_msg->code == VSC_SUCCESS) {
+ qemu_mutex_lock(&pending_reader_lock);
+ if (pending_reader) {
+ vreader_set_id(pending_reader, mhHeader.reader_id);
+ vreader_free(pending_reader);
+ pending_reader = NULL;
+ qemu_cond_signal(&pending_reader_condition);
+ }
+ qemu_mutex_unlock(&pending_reader_lock);
+ break;
}
- qemu_mutex_unlock(&pending_reader_lock);
+ printf("warning: qemu refused to add reader\n");
+ if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
+ /* clear pending reader, qemu can't handle any more */
+ qemu_mutex_lock(&pending_reader_lock);
+ if (pending_reader) {
+ pending_reader = NULL;
+ /* make sure the event loop doesn't hang */
+ qemu_cond_signal(&pending_reader_condition);
+ }
+ qemu_mutex_unlock(&pending_reader_lock);
+ }
+ break;
+ case VSC_Init:
+ if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
+ return FALSE;
+ }
+ break;
+ default:
+ g_warn_if_reached();
+ return FALSE;
}
- break;
- case VSC_Init:
- if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
- return -1;
+
+ state = STATE_HEADER;
+ }
+
+
+ return TRUE;
+}
+
+static gboolean
+do_socket(GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
+{
+ /* not sure if two watches work well with a single win32 sources */
+ if (condition & G_IO_OUT) {
+ if (!do_socket_send(source, condition, data)) {
+ return FALSE;
}
- break;
- default:
- printf("Default\n");
- return -1;
}
- return 0;
+ if (condition & G_IO_IN) {
+ if (!do_socket_read(source, condition, data)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
}
static void
-do_command(void)
+update_socket_watch(gboolean out)
+{
+ if (socket_tag != 0) {
+ g_source_remove(socket_tag);
+ }
+
+ socket_tag = g_io_add_watch(channel_socket,
+ G_IO_IN | (out ? G_IO_OUT : 0), do_socket, NULL);
+}
+
+static gboolean
+do_command(GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
{
- char inbuf[255];
char *string;
VCardEmulError error;
static unsigned int default_reader_id;
unsigned int reader_id;
VReader *reader = NULL;
+ GError *err = NULL;
+
+ g_assert(condition & G_IO_IN);
reader_id = default_reader_id;
- string = fgets(inbuf, sizeof(inbuf), stdin);
+ g_io_channel_read_line(source, &string, NULL, NULL, &err);
+ if (err != NULL) {
+ g_error("Error while reading command: %s", err->message);
+ }
+
if (string != NULL) {
if (strncmp(string, "exit", 4) == 0) {
/* remove all the readers */
@@ -491,6 +583,8 @@ do_command(void)
vreader_free(reader);
printf("> ");
fflush(stdout);
+
+ return TRUE;
}
@@ -504,7 +598,7 @@ connect_to_qemu(
) {
struct addrinfo hints;
struct addrinfo *server;
- int ret;
+ int ret, sock;
sock = qemu_socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
@@ -543,6 +637,8 @@ main(
int argc,
char *argv[]
) {
+ GMainLoop *loop;
+ GIOChannel *channel_stdin;
char *qemu_host;
char *qemu_port;
VSCMsgHeader mhHeader;
@@ -552,7 +648,10 @@ main(
char *cert_names[MAX_CERTS];
char *emul_args = NULL;
int cert_count = 0;
- int c, rv;
+ int c, sock;
+
+ if (socket_init() != 0)
+ return 1;
while ((c = getopt(argc, argv, "c:e:pd:")) != -1) {
switch (c) {
@@ -618,15 +717,33 @@ main(
exit(5);
}
- qemu_mutex_init(&write_lock);
+ socket_to_send = g_byte_array_new();
+ qemu_mutex_init(&socket_to_send_lock);
qemu_mutex_init(&pending_reader_lock);
qemu_cond_init(&pending_reader_condition);
vcard_emul_init(command_line_options);
+ loop = g_main_loop_new(NULL, true);
+
printf("> ");
fflush(stdout);
+#ifdef _WIN32
+ channel_stdin = g_io_channel_win32_new_fd(STDIN_FILENO);
+#else
+ channel_stdin = g_io_channel_unix_new(STDIN_FILENO);
+#endif
+ g_io_add_watch(channel_stdin, G_IO_IN, do_command, NULL);
+#ifdef _WIN32
+ channel_socket = g_io_channel_win32_new_socket(sock);
+#else
+ channel_socket = g_io_channel_unix_new(sock);
+#endif
+ g_io_channel_set_encoding(channel_socket, NULL, NULL);
+ /* we buffer ourself for thread safety reasons */
+ g_io_channel_set_buffered(channel_socket, FALSE);
+
/* Send init message, Host responds (and then we send reader attachments) */
VSCMsgInit init = {
.version = htonl(VSCARD_VERSION),
@@ -635,28 +752,12 @@ main(
};
send_msg(VSC_Init, mhHeader.reader_id, &init, sizeof(init));
- do {
- fd_set fds;
-
- FD_ZERO(&fds);
- FD_SET(1, &fds);
- FD_SET(sock, &fds);
+ g_main_loop_run(loop);
+ g_main_loop_unref(loop);
- /* waiting on input from the socket */
- rv = select(sock+1, &fds, NULL, NULL, NULL);
- if (rv < 0) {
- /* handle error */
- perror("select");
- return 7;
- }
- if (FD_ISSET(1, &fds)) {
- do_command();
- }
- if (!FD_ISSET(sock, &fds)) {
- continue;
- }
- rv = do_socket_read();
- } while (rv >= 0);
+ g_io_channel_unref(channel_stdin);
+ g_io_channel_unref(channel_socket);
+ g_byte_array_unref(socket_to_send);
return 0;
}
--
1.8.3.1

View File

@ -0,0 +1,47 @@
From 1975b2acbff807d88d494153db64882d19410724 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau@redhat.com>
Date: Wed, 20 Mar 2013 14:07:48 +0100
Subject: [PATCH 223/241] libcacard: remove sql: prefix
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
For some reason, with sql:/ prefix, the PKCS11 modules are not loaded.
This patch goes on top of Alon smartcard series.
Signed-off-by: Marc-André Lureau <mlureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit 667e0b4b6806d53e0b46e29a15d24427ef958c78)
---
libcacard/vcard_emul_nss.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 21d4689..6b1ca8a 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -893,7 +893,7 @@ vcard_emul_init(const VCardEmulOptions *options)
if (options->nss_db) {
rv = NSS_Init(options->nss_db);
} else {
- gchar *path, *db;
+ gchar *path;
#ifndef _WIN32
path = g_strdup("/etc/pki/nssdb");
#else
@@ -905,10 +905,8 @@ vcard_emul_init(const VCardEmulOptions *options)
path = g_build_filename(
g_get_system_config_dirs()[0], "pki", "nssdb", NULL);
#endif
- db = g_strdup_printf("sql:%s", path);
- rv = NSS_Init(db);
- g_free(db);
+ rv = NSS_Init(path);
g_free(path);
}
if (rv != SECSuccess) {
--
1.8.3.1

View File

@ -0,0 +1,64 @@
From 26acaa4bf064f7608dec08cff4d23769b167dced Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau@redhat.com>
Date: Wed, 20 Mar 2013 14:07:49 +0100
Subject: [PATCH 224/241] libcacard: remove default libcoolkey loading
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Use only the modules defined in the NSS database.
Signed-off-by: Marc-André Lureau <mlureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit ad2181f2b612cd8bf0a790faa2a1b51559f7234b)
---
libcacard/vcard_emul_nss.c | 17 +----------------
1 file changed, 1 insertion(+), 16 deletions(-)
diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 6b1ca8a..9ba80fb 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -870,7 +870,7 @@ VCardEmulError
vcard_emul_init(const VCardEmulOptions *options)
{
SECStatus rv;
- PRBool ret, has_readers = PR_FALSE, need_coolkey_module;
+ PRBool ret, has_readers = PR_FALSE;
VReader *vreader;
VReaderEmul *vreader_emul;
SECMODListLock *module_lock;
@@ -983,30 +983,15 @@ vcard_emul_init(const VCardEmulOptions *options)
/* 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 */
--
1.8.3.1

View File

@ -0,0 +1,54 @@
From c1a01e889c7562c5e61cbd2da7844697c56940bd Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Mon, 4 Mar 2013 18:45:49 +0200
Subject: [PATCH 225/241] dev-smartcard-reader: white space fixes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit 4543d43c6181d90f86fb528430f250810dde03d5)
---
hw/usb/dev-smartcard-reader.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 979a473..24c84ce 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -471,6 +471,7 @@ static const USBDesc desc_ccid = {
static const uint8_t *ccid_card_get_atr(CCIDCardState *card, uint32_t *len)
{
CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+
if (cc->get_atr) {
return cc->get_atr(card, len);
}
@@ -482,6 +483,7 @@ static void ccid_card_apdu_from_guest(CCIDCardState *card,
uint32_t len)
{
CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+
if (cc->apdu_from_guest) {
cc->apdu_from_guest(card, apdu, len);
}
@@ -490,6 +492,7 @@ static void ccid_card_apdu_from_guest(CCIDCardState *card,
static int ccid_card_exitfn(CCIDCardState *card)
{
CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+
if (cc->exitfn) {
return cc->exitfn(card);
}
@@ -499,6 +502,7 @@ static int ccid_card_exitfn(CCIDCardState *card)
static int ccid_card_initfn(CCIDCardState *card)
{
CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+
if (cc->initfn) {
return cc->initfn(card);
}
--
1.8.3.1

View File

@ -0,0 +1,144 @@
From bd39de640ffd3f552775bfb1a084657872acd114 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Mon, 4 Mar 2013 18:50:33 +0200
Subject: [PATCH 226/241] dev-smartcard-reader: nicer debug messages
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit 7e1ac5abe3fbbfee4ddfc2d9971a644bd787e055)
---
hw/usb/dev-smartcard-reader.c | 69 +++++++++++++++++++++++++++++++++++++++----
1 file changed, 63 insertions(+), 6 deletions(-)
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 24c84ce..173dcc9 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -639,13 +639,47 @@ static void ccid_handle_reset(USBDevice *dev)
ccid_reset(s);
}
+static const char *ccid_control_to_str(USBCCIDState *s, int request)
+{
+ switch (request) {
+ /* generic - should be factored out if there are other debugees */
+ case DeviceOutRequest | USB_REQ_SET_ADDRESS:
+ return "(generic) set address";
+ case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+ return "(generic) get descriptor";
+ case DeviceRequest | USB_REQ_GET_CONFIGURATION:
+ return "(generic) get configuration";
+ case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+ return "(generic) set configuration";
+ case DeviceRequest | USB_REQ_GET_STATUS:
+ return "(generic) get status";
+ case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
+ return "(generic) clear feature";
+ case DeviceOutRequest | USB_REQ_SET_FEATURE:
+ return "(generic) set_feature";
+ case InterfaceRequest | USB_REQ_GET_INTERFACE:
+ return "(generic) get interface";
+ case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
+ return "(generic) set interface";
+ /* class requests */
+ case ClassInterfaceOutRequest | CCID_CONTROL_ABORT:
+ return "ABORT";
+ case ClassInterfaceRequest | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
+ return "GET_CLOCK_FREQUENCIES";
+ case ClassInterfaceRequest | CCID_CONTROL_GET_DATA_RATES:
+ return "GET_DATA_RATES";
+ }
+ return "unknown";
+}
+
static void ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
int value, int index, int length, uint8_t *data)
{
USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
int ret;
- DPRINTF(s, 1, "got control %x, value %x\n", request, value);
+ DPRINTF(s, 1, "%s: got control %s (%x), value %x\n", __func__,
+ ccid_control_to_str(s, request), request, value);
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
if (ret >= 0) {
return;
@@ -695,7 +729,7 @@ static uint8_t ccid_calc_status(USBCCIDState *s)
* bmCommandStatus
*/
uint8_t ret = ccid_card_status(s) | (s->bmCommandStatus << 6);
- DPRINTF(s, D_VERBOSE, "status = %d\n", ret);
+ DPRINTF(s, D_VERBOSE, "%s: status = %d\n", __func__, ret);
return ret;
}
@@ -756,7 +790,7 @@ static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq,
p->b.bStatus = ccid_calc_status(s);
p->b.bError = s->bError;
if (p->b.bError) {
- DPRINTF(s, D_VERBOSE, "error %d", p->b.bError);
+ DPRINTF(s, D_VERBOSE, "error %d\n", p->b.bError);
}
memcpy(p->abData, data, len);
ccid_reset_error_status(s);
@@ -873,6 +907,28 @@ static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv)
}
}
+static const char *ccid_message_type_to_str(uint8_t type)
+{
+ switch (type) {
+ case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn: return "IccPowerOn";
+ case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff: return "IccPowerOff";
+ case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus: return "GetSlotStatus";
+ case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock: return "XfrBlock";
+ case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters: return "GetParameters";
+ case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters: return "ResetParameters";
+ case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters: return "SetParameters";
+ case CCID_MESSAGE_TYPE_PC_to_RDR_Escape: return "Escape";
+ case CCID_MESSAGE_TYPE_PC_to_RDR_IccClock: return "IccClock";
+ case CCID_MESSAGE_TYPE_PC_to_RDR_T0APDU: return "T0APDU";
+ case CCID_MESSAGE_TYPE_PC_to_RDR_Secure: return "Secure";
+ case CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical: return "Mechanical";
+ case CCID_MESSAGE_TYPE_PC_to_RDR_Abort: return "Abort";
+ case CCID_MESSAGE_TYPE_PC_to_RDR_SetDataRateAndClockFrequency:
+ return "SetDataRateAndClockFrequency";
+ }
+ return "unknown";
+}
+
static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
{
CCID_Header *ccid_header;
@@ -895,13 +951,15 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
"%s: bad USB_TOKEN_OUT length, should be at least 10 bytes\n",
__func__);
} else {
- DPRINTF(s, D_MORE_INFO, "%s %x\n", __func__, ccid_header->bMessageType);
+ DPRINTF(s, D_MORE_INFO, "%s %x %s\n", __func__,
+ ccid_header->bMessageType,
+ ccid_message_type_to_str(ccid_header->bMessageType));
switch (ccid_header->bMessageType) {
case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
ccid_write_slot_status(s, ccid_header);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
- DPRINTF(s, 1, "PowerOn: %d\n",
+ DPRINTF(s, 1, "%s: PowerOn: %d\n", __func__,
((CCID_IccPowerOn *)(ccid_header))->bPowerSelect);
s->powered = true;
if (!ccid_card_inserted(s)) {
@@ -911,7 +969,6 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
ccid_write_data_block_atr(s, ccid_header);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff:
- DPRINTF(s, 1, "PowerOff\n");
ccid_reset_error_status(s);
s->powered = false;
ccid_write_slot_status(s, ccid_header);
--
1.8.3.1

View File

@ -0,0 +1,71 @@
From 006440535dd1d581f0e5b7b15295fe511589c3e2 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Mon, 4 Mar 2013 18:55:07 +0200
Subject: [PATCH 227/241] dev-smartcard-reader: remove aborts (never triggered,
but just in case)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit 47bf53af7507986fc473cb308324340448fd85e7)
---
hw/usb/dev-smartcard-reader.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 173dcc9..54ea536 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -796,6 +796,12 @@ static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq,
ccid_reset_error_status(s);
}
+static void ccid_report_error_failed(USBCCIDState *s, uint8_t error)
+{
+ s->bmCommandStatus = COMMAND_STATUS_FAILED;
+ s->bError = error;
+}
+
static void ccid_write_data_block_answer(USBCCIDState *s,
const uint8_t *data, uint32_t len)
{
@@ -803,7 +809,9 @@ static void ccid_write_data_block_answer(USBCCIDState *s,
uint8_t slot;
if (!ccid_has_pending_answers(s)) {
- abort();
+ DPRINTF(s, D_WARN, "error: no pending answer to return to guest\n");
+ ccid_report_error_failed(s, ERROR_ICC_MUTE);
+ return;
}
ccid_remove_pending_answer(s, &slot, &seq);
ccid_write_data_block(s, slot, seq, data, len);
@@ -857,12 +865,6 @@ static void ccid_reset_parameters(USBCCIDState *s)
memcpy(s->abProtocolDataStructure, abDefaultProtocolDataStructure, len);
}
-static void ccid_report_error_failed(USBCCIDState *s, uint8_t error)
-{
- s->bmCommandStatus = COMMAND_STATUS_FAILED;
- s->bError = error;
-}
-
/* NOTE: only a single slot is supported (SLOT_0) */
static void ccid_on_slot_change(USBCCIDState *s, bool full)
{
@@ -1129,7 +1131,9 @@ void ccid_card_send_apdu_to_guest(CCIDCardState *card,
s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
answer = ccid_peek_next_answer(s);
if (answer == NULL) {
- abort();
+ DPRINTF(s, D_WARN, "%s: error: unexpected lack of answer\n", __func__);
+ ccid_report_error_failed(s, ERROR_HW_ERROR);
+ return;
}
DPRINTF(s, 1, "APDU returned to guest %d (answer seq %d, slot %d)\n",
len, answer->seq, answer->slot);
--
1.8.3.1

View File

@ -0,0 +1,38 @@
From 6339bbf28651cbcb5cf24bd1d53cd7b52028ff1b Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Mon, 4 Mar 2013 21:40:53 +0200
Subject: [PATCH 228/241] dev-smartcard-reader: support windows guest
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
By not advertising USB wakeup support (which we don't).
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit c5cd7c875608911ec74817d24cd12b825014ba19)
---
hw/usb/dev-smartcard-reader.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 54ea536..db5dd6d 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -359,11 +359,11 @@ static const uint8_t qemu_ccid_descriptor[] = {
* 20000 Short APDU level exchange with CCID
* 40000 Short and Extended APDU level exchange with CCID
*
- * + 100000 USB Wake up signaling supported on card
+ * 100000 USB Wake up signaling supported on card
* insertion and removal. Must set bit 5 in bmAttributes
* in Configuration descriptor if 100000 is set.
*/
- 0xfe, 0x04, 0x11, 0x00,
+ 0xfe, 0x04, 0x01, 0x00,
/*
* u32 dwMaxCCIDMessageLength; For extended APDU in
* [261 + 10 , 65544 + 10]. Otherwise the minimum is
--
1.8.3.1

View File

@ -0,0 +1,65 @@
From b7fd4cdb21c93be3a3e4b2d309f07e56d47eb2a4 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Tue, 5 Mar 2013 15:31:26 +0200
Subject: [PATCH 229/241] dev-smartcard-reader: reuse usb.h definitions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit 693e47738d05463b2743b0a652412d33cf254977)
---
hw/usb/dev-smartcard-reader.c | 16 +++++-----------
1 file changed, 5 insertions(+), 11 deletions(-)
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index db5dd6d..75f813c 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -68,12 +68,6 @@ do { \
#define BULK_IN_BUF_SIZE 384
#define BULK_IN_PENDING_NUM 8
-#define InterfaceOutClass \
- ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8)
-
-#define InterfaceInClass \
- ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8)
-
#define CCID_MAX_PACKET_SIZE 64
#define CCID_CONTROL_ABORT 0x1
@@ -410,8 +404,8 @@ static const USBDescStrings desc_strings = {
static const USBDescIface desc_iface0 = {
.bInterfaceNumber = 0,
.bNumEndpoints = 3,
- .bInterfaceClass = 0x0b,
- .bInterfaceSubClass = 0x00,
+ .bInterfaceClass = USB_CLASS_CSCID,
+ .bInterfaceSubClass = USB_SUBCLASS_UNDEFINED,
.bInterfaceProtocol = 0x00,
.iInterface = STR_INTERFACE,
.ndesc = 1,
@@ -687,15 +681,15 @@ static void ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
switch (request) {
/* Class specific requests. */
- case InterfaceOutClass | CCID_CONTROL_ABORT:
+ case ClassInterfaceOutRequest | CCID_CONTROL_ABORT:
DPRINTF(s, 1, "ccid_control abort UNIMPLEMENTED\n");
p->status = USB_RET_STALL;
break;
- case InterfaceInClass | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
+ case ClassInterfaceRequest | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
DPRINTF(s, 1, "ccid_control get clock frequencies UNIMPLEMENTED\n");
p->status = USB_RET_STALL;
break;
- case InterfaceInClass | CCID_CONTROL_GET_DATA_RATES:
+ case ClassInterfaceRequest | CCID_CONTROL_GET_DATA_RATES:
DPRINTF(s, 1, "ccid_control get data rates UNIMPLEMENTED\n");
p->status = USB_RET_STALL;
break;
--
1.8.3.1

View File

@ -0,0 +1,42 @@
From b3d57573e23a456b2c21f045b153e2c0a621f886 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Tue, 5 Mar 2013 15:35:24 +0200
Subject: [PATCH 230/241] libcacard: change default ATR
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit a26dfd95d33d650f9f9f93b6ee6f03be925db1a8)
---
libcacard/vcardt.h | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
index 538bdde..3b9a619 100644
--- a/libcacard/vcardt.h
+++ b/libcacard/vcardt.h
@@ -26,9 +26,17 @@ typedef struct VCardEmulStruct VCardEmul;
#define MAX_CHANNEL 4
/* create an ATR with appropriate historical bytes */
-#define VCARD_ATR_PREFIX(size) 0x3b, 0x66+(size), 0x00, 0xff, \
- 'V', 'C', 'A', 'R', 'D', '_'
+#define TS_DIRECT_CONVENTION 0x3b
+#define TA_PRESENT 0x10
+#define TB_PRESENT 0x20
+#define TC_PRESENT 0x40
+#define TD_PRESENT 0x80
+#define VCARD_ATR_PREFIX(size) \
+ TS_DIRECT_CONVENTION, \
+ TD_PRESENT + (6 + size), \
+ 0x00, \
+ 'V', 'C', 'A', 'R', 'D', '_'
typedef enum {
VCARD_DONE,
--
1.8.3.1

View File

@ -0,0 +1,95 @@
From 1c4d96f6622f00c4d4b84b5e17f8e42dcb5b7501 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Mon, 4 Mar 2013 18:39:09 +0200
Subject: [PATCH 231/241] ccid-card-passthru: add atr check
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit 0e61400c1941aabc9f45d5ff961b57337c7caac6)
---
hw/ccid-card-passthru.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
index 62070db..7fecd10 100644
--- a/hw/ccid-card-passthru.c
+++ b/hw/ccid-card-passthru.c
@@ -138,6 +138,59 @@ static void ccid_card_vscard_handle_init(
ccid_card_vscard_send_init(card);
}
+static int check_atr(PassthruState *card, uint8_t *data, int len)
+{
+ int historical_length, opt_bytes;
+ int td_count = 0;
+ int td;
+
+ if (len < 2) {
+ return 0;
+ }
+ historical_length = data[1] & 0xf;
+ opt_bytes = 0;
+ if (data[0] != 0x3b && data[0] != 0x3f) {
+ DPRINTF(card, D_WARN, "atr's T0 is 0x%X, not in {0x3b, 0x3f}\n",
+ data[0]);
+ return 0;
+ }
+ td_count = 0;
+ td = data[1] >> 4;
+ while (td && td_count < 2 && opt_bytes + historical_length + 2 < len) {
+ td_count++;
+ if (td & 0x1) {
+ opt_bytes++;
+ }
+ if (td & 0x2) {
+ opt_bytes++;
+ }
+ if (td & 0x4) {
+ opt_bytes++;
+ }
+ if (td & 0x8) {
+ opt_bytes++;
+ td = data[opt_bytes + 2] >> 4;
+ }
+ }
+ if (len < 2 + historical_length + opt_bytes) {
+ DPRINTF(card, D_WARN,
+ "atr too short: len %d, but historical_len %d, T1 0x%X\n",
+ len, historical_length, data[1]);
+ return 0;
+ }
+ if (len > 2 + historical_length + opt_bytes) {
+ DPRINTF(card, D_WARN,
+ "atr too long: len %d, but hist/opt %d/%d, T1 0x%X\n",
+ len, historical_length, opt_bytes, data[1]);
+ /* let it through */
+ }
+ DPRINTF(card, D_VERBOSE,
+ "atr passes check: %d total length, %d historical, %d optional\n",
+ len, historical_length, opt_bytes);
+
+ return 1;
+}
+
static void ccid_card_vscard_handle_message(PassthruState *card,
VSCMsgHeader *scr_msg_header)
{
@@ -152,6 +205,12 @@ static void ccid_card_vscard_handle_message(PassthruState *card,
VSC_GENERAL_ERROR);
break;
}
+ if (!check_atr(card, data, scr_msg_header->length)) {
+ error_report("ATR is inconsistent, ignoring");
+ ccid_card_vscard_send_error(card, scr_msg_header->reader_id,
+ VSC_GENERAL_ERROR);
+ break;
+ }
memcpy(card->atr, data, scr_msg_header->length);
card->atr_length = scr_msg_header->length;
ccid_card_card_inserted(&card->base);
--
1.8.3.1

View File

@ -0,0 +1,110 @@
From f462152289d55ae01456d1d9122e26ff63407520 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Mon, 4 Mar 2013 18:41:28 +0200
Subject: [PATCH 232/241] ccid-card-passthru, dev-smartcard-reader: add debug
environment variables
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Introduces a new utility function: parse_debug_env to avoid code
duplication.
This overrides whatever debug value is set on the corresponding devices
from the command line, and is meant to ease the usage with any
management stack. For libvirt you can set environment variables by
extending the dom namespace, i.e:
<domain type='kvm' id='3' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
<qemu:commandline>
<qemu:env name='QEMU_CCID_PASSTHRU_DEBUG' value='4'/>
<qemu:env name='QEMU_CCID_DEBUG' value='4'/>
</qemu:commandline>
</domain>
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit b16352acf3105000e14f194b556e159d5d06cff9)
Conflicts:
include/qemu-common.h
---
hw/ccid-card-passthru.c | 2 ++
hw/usb/dev-smartcard-reader.c | 1 +
include/qemu-common.h | 5 +++++
util/cutils.c | 23 +++++++++++++++++++++++
4 files changed, 31 insertions(+)
diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
index 7fecd10..4026ccd 100644
--- a/hw/ccid-card-passthru.c
+++ b/hw/ccid-card-passthru.c
@@ -353,6 +353,8 @@ static int passthru_initfn(CCIDCardState *base)
error_report("missing chardev");
return -1;
}
+ card->debug = parse_debug_env("QEMU_CCID_PASSTHRU_DEBUG", D_VERBOSE,
+ card->debug);
assert(sizeof(DEFAULT_ATR) <= MAX_ATR_SIZE);
memcpy(card->atr, DEFAULT_ATR, sizeof(DEFAULT_ATR));
card->atr_length = sizeof(DEFAULT_ATR);
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 75f813c..09c2403 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1260,6 +1260,7 @@ static int ccid_initfn(USBDevice *dev)
s->bulk_out_pos = 0;
ccid_reset_parameters(s);
ccid_reset(s);
+ s->debug = parse_debug_env("QEMU_CCID_DEBUG", D_VERBOSE, s->debug);
return 0;
}
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 80016ad..77d0980 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -430,4 +430,9 @@ int64_t pow2floor(int64_t value);
int uleb128_encode_small(uint8_t *out, uint32_t n);
int uleb128_decode_small(const uint8_t *in, uint32_t *n);
+/*
+ * helper to parse debug environment variables
+ */
+int parse_debug_env(const char *name, int max, int initial);
+
#endif
diff --git a/util/cutils.c b/util/cutils.c
index 1439da4..32e1f5b 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -422,3 +422,26 @@ int uleb128_decode_small(const uint8_t *in, uint32_t *n)
return 2;
}
}
+
+/*
+ * helper to parse debug environment variables
+ */
+int parse_debug_env(const char *name, int max, int initial)
+{
+ char *debug_env = getenv(name);
+ char *inv = NULL;
+ int debug;
+
+ if (!debug_env) {
+ return initial;
+ }
+ debug = strtol(debug_env, &inv, 10);
+ if (inv == debug_env) {
+ return initial;
+ }
+ if (debug < 0 || debug > max) {
+ fprintf(stderr, "warning: %s not in [0, %d]", name, max);
+ return initial;
+ }
+ return debug;
+}
--
1.8.3.1

View File

@ -0,0 +1,161 @@
From 4d36e75eb55c7ee557bebabd6fe33c5a65d52228 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Mon, 4 Mar 2013 18:57:45 +0200
Subject: [PATCH 233/241] dev-smartcard-reader: define structs for
CCID_Parameter internals
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit 4942d6c39477f441a106430ab11f85806b4532f5)
---
hw/usb/dev-smartcard-reader.c | 74 +++++++++++++++++++++++++++----------------
1 file changed, 47 insertions(+), 27 deletions(-)
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 09c2403..f2cab09 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -189,10 +189,34 @@ typedef struct QEMU_PACKED CCID_SlotStatus {
uint8_t bClockStatus;
} CCID_SlotStatus;
+typedef struct QEMU_PACKED CCID_T0ProtocolDataStructure {
+ uint8_t bmFindexDindex;
+ uint8_t bmTCCKST0;
+ uint8_t bGuardTimeT0;
+ uint8_t bWaitingIntegerT0;
+ uint8_t bClockStop;
+} CCID_T0ProtocolDataStructure;
+
+typedef struct QEMU_PACKED CCID_T1ProtocolDataStructure {
+ uint8_t bmFindexDindex;
+ uint8_t bmTCCKST1;
+ uint8_t bGuardTimeT1;
+ uint8_t bWaitingIntegerT1;
+ uint8_t bClockStop;
+ uint8_t bIFSC;
+ uint8_t bNadValue;
+} CCID_T1ProtocolDataStructure;
+
+typedef union CCID_ProtocolDataStructure {
+ CCID_T0ProtocolDataStructure t0;
+ CCID_T1ProtocolDataStructure t1;
+ uint8_t data[7]; /* must be = max(sizeof(t0), sizeof(t1)) */
+} CCID_ProtocolDataStructure;
+
typedef struct QEMU_PACKED CCID_Parameter {
CCID_BULK_IN b;
uint8_t bProtocolNum;
- uint8_t abProtocolDataStructure[0];
+ CCID_ProtocolDataStructure abProtocolDataStructure;
} CCID_Parameter;
typedef struct QEMU_PACKED CCID_DataBlock {
@@ -224,7 +248,7 @@ typedef struct QEMU_PACKED CCID_SetParameters {
CCID_Header hdr;
uint8_t bProtocolNum;
uint16_t abRFU;
- uint8_t abProtocolDataStructure[0];
+ CCID_ProtocolDataStructure abProtocolDataStructure;
} CCID_SetParameters;
typedef struct CCID_Notify_Slot_Change {
@@ -254,8 +278,6 @@ typedef struct CCIDBus {
BusState qbus;
} CCIDBus;
-#define MAX_PROTOCOL_SIZE 7
-
/*
* powered - defaults to true, changed by PowerOn/PowerOff messages
*/
@@ -279,7 +301,7 @@ typedef struct USBCCIDState {
uint8_t bError;
uint8_t bmCommandStatus;
uint8_t bProtocolNum;
- uint8_t abProtocolDataStructure[MAX_PROTOCOL_SIZE];
+ CCID_ProtocolDataStructure abProtocolDataStructure;
uint32_t ulProtocolDataStructureSize;
uint32_t state_vmstate;
uint32_t migration_target_ip;
@@ -765,7 +787,7 @@ static void ccid_write_parameters(USBCCIDState *s, CCID_Header *recv)
h->b.bStatus = ccid_calc_status(s);
h->b.bError = s->bError;
h->bProtocolNum = s->bProtocolNum;
- memcpy(h->abProtocolDataStructure, s->abProtocolDataStructure, len);
+ h->abProtocolDataStructure = s->abProtocolDataStructure;
ccid_reset_error_status(s);
}
@@ -825,38 +847,36 @@ static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv)
static void ccid_set_parameters(USBCCIDState *s, CCID_Header *recv)
{
CCID_SetParameters *ph = (CCID_SetParameters *) recv;
- uint32_t len = 0;
- if ((ph->bProtocolNum & 3) == 0) {
- len = 5;
- }
- if ((ph->bProtocolNum & 3) == 1) {
- len = 7;
- }
- if (len == 0) {
- s->bmCommandStatus = COMMAND_STATUS_FAILED;
- s->bError = 7; /* Protocol invalid or not supported */
+ uint32_t protocol_num = ph->bProtocolNum & 3;
+
+ if (protocol_num != 0 && protocol_num != 1) {
+ ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED);
return;
}
- s->bProtocolNum = ph->bProtocolNum;
- memcpy(s->abProtocolDataStructure, ph->abProtocolDataStructure, len);
- s->ulProtocolDataStructureSize = len;
- DPRINTF(s, 1, "%s: using len %d\n", __func__, len);
+ s->bProtocolNum = protocol_num;
+ s->abProtocolDataStructure = ph->abProtocolDataStructure;
}
/*
* must be 5 bytes for T=0, 7 bytes for T=1
* See page 52
*/
-static const uint8_t abDefaultProtocolDataStructure[7] = {
- 0x77, 0x00, 0x00, 0x00, 0x00, 0xfe /*IFSC*/, 0x00 /*NAD*/ };
+static const CCID_ProtocolDataStructure defaultProtocolDataStructure = {
+ .t1 = {
+ .bmFindexDindex = 0x77,
+ .bmTCCKST1 = 0x00,
+ .bGuardTimeT1 = 0x00,
+ .bWaitingIntegerT1 = 0x00,
+ .bClockStop = 0x00,
+ .bIFSC = 0xfe,
+ .bNadValue = 0x00,
+ }
+};
static void ccid_reset_parameters(USBCCIDState *s)
{
- uint32_t len = sizeof(abDefaultProtocolDataStructure);
-
s->bProtocolNum = 1; /* T=1 */
- s->ulProtocolDataStructureSize = len;
- memcpy(s->abProtocolDataStructure, abDefaultProtocolDataStructure, len);
+ s->abProtocolDataStructure = defaultProtocolDataStructure;
}
/* NOTE: only a single slot is supported (SLOT_0) */
@@ -1345,7 +1365,7 @@ static VMStateDescription ccid_vmstate = {
VMSTATE_UINT8(bError, USBCCIDState),
VMSTATE_UINT8(bmCommandStatus, USBCCIDState),
VMSTATE_UINT8(bProtocolNum, USBCCIDState),
- VMSTATE_BUFFER(abProtocolDataStructure, USBCCIDState),
+ VMSTATE_BUFFER(abProtocolDataStructure.data, USBCCIDState),
VMSTATE_UINT32(ulProtocolDataStructureSize, USBCCIDState),
VMSTATE_STRUCT_ARRAY(bulk_in_pending, USBCCIDState,
BULK_IN_PENDING_NUM, 1, bulk_in_vmstate, BulkIn),
--
1.8.3.1

View File

@ -0,0 +1,50 @@
From f7019fa4fc6d883f1922bb0e3b18ceb3a628b340 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Wed, 27 Mar 2013 10:14:15 +0200
Subject: [PATCH 234/241] dev-smartcard-reader: change default protocol to T=0
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We don't support T=1 so we shouldn't advertise it by default.
Two independent changes:
* Default ATR
sets T=0. This gets overwritten by the client provided ATR later.
* Class descriptor
changes dwAdvertise dwProtocols.PPPP to 0x1 and dwProtocols.RRRR=0 per spec.
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit d7d218ef02d87c637d20d64da8f575d434ff6f78)
---
hw/usb/dev-smartcard-reader.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index f2cab09..e97dfcb 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -335,8 +335,8 @@ static const uint8_t qemu_ccid_descriptor[] = {
*/
0x07, /* u8 bVoltageSupport; 01h - 5.0v, 02h - 3.0, 03 - 1.8 */
- 0x03, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/
- 0x00, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */
+ 0x00, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/
+ 0x01, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */
/* u32 dwDefaultClock; in kHZ (0x0fa0 is 4 MHz) */
0xa0, 0x0f, 0x00, 0x00,
/* u32 dwMaximumClock; */
@@ -875,7 +875,7 @@ static const CCID_ProtocolDataStructure defaultProtocolDataStructure = {
static void ccid_reset_parameters(USBCCIDState *s)
{
- s->bProtocolNum = 1; /* T=1 */
+ s->bProtocolNum = 0; /* T=0 */
s->abProtocolDataStructure = defaultProtocolDataStructure;
}
--
1.8.3.1

View File

@ -0,0 +1,85 @@
From 2e26deacddb52bb3f7eb100ac5fe9709d6089cf3 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Mon, 4 Mar 2013 18:58:29 +0200
Subject: [PATCH 235/241] dev-smartcard-reader: copy atr protocol to ccid
parameters
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Adds todos.
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit 2f8f916b6d4482976bb5cf179f65aa2cfcd1aec9)
---
hw/usb/dev-smartcard-reader.c | 45 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index e97dfcb..4e08f9b 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -833,14 +833,59 @@ static void ccid_write_data_block_answer(USBCCIDState *s,
ccid_write_data_block(s, slot, seq, data, len);
}
+static uint8_t atr_get_protocol_num(const uint8_t *atr, uint32_t len)
+{
+ int i;
+
+ if (len < 2 || !(atr[1] & 0x80)) {
+ /* too short or TD1 not included */
+ return 0; /* T=0, default */
+ }
+ i = 1 + !!(atr[1] & 0x10) + !!(atr[1] & 0x20) + !!(atr[1] & 0x40);
+ i += !!(atr[1] & 0x80);
+ return atr[i] & 0x0f;
+}
+
static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv)
{
const uint8_t *atr = NULL;
uint32_t len = 0;
+ uint8_t atr_protocol_num;
+ CCID_T0ProtocolDataStructure *t0 = &s->abProtocolDataStructure.t0;
+ CCID_T1ProtocolDataStructure *t1 = &s->abProtocolDataStructure.t1;
if (s->card) {
atr = ccid_card_get_atr(s->card, &len);
}
+ atr_protocol_num = atr_get_protocol_num(atr, len);
+ DPRINTF(s, D_VERBOSE, "%s: atr contains protocol=%d\n", __func__,
+ atr_protocol_num);
+ /* set parameters from ATR - see spec page 109 */
+ s->bProtocolNum = (atr_protocol_num <= 1 ? atr_protocol_num
+ : s->bProtocolNum);
+ switch (atr_protocol_num) {
+ case 0:
+ /* TODO: unimplemented ATR T0 parameters */
+ t0->bmFindexDindex = 0;
+ t0->bmTCCKST0 = 0;
+ t0->bGuardTimeT0 = 0;
+ t0->bWaitingIntegerT0 = 0;
+ t0->bClockStop = 0;
+ break;
+ case 1:
+ /* TODO: unimplemented ATR T1 parameters */
+ t1->bmFindexDindex = 0;
+ t1->bmTCCKST1 = 0;
+ t1->bGuardTimeT1 = 0;
+ t1->bWaitingIntegerT1 = 0;
+ t1->bClockStop = 0;
+ t1->bIFSC = 0;
+ t1->bNadValue = 0;
+ break;
+ default:
+ DPRINTF(s, D_WARN, "%s: error: unsupported ATR protocol %d\n",
+ __func__, atr_protocol_num);
+ }
ccid_write_data_block(s, recv->bSlot, recv->bSeq, atr, len);
}
--
1.8.3.1

View File

@ -0,0 +1,169 @@
From 71560a321c2c7678191f0f7da42f25917ed40974 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Tue, 5 Mar 2013 15:32:19 +0200
Subject: [PATCH 236/241] libcacard/vreader: add debugging messages for apdu
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Using g_debug with log domain libcacard
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit 7a6858962457c54be44715d6562504c765d9ea76)
---
libcacard/cac.c | 7 -----
libcacard/cac.h | 8 ++++++
libcacard/vreader.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 85 insertions(+), 7 deletions(-)
diff --git a/libcacard/cac.c b/libcacard/cac.c
index 927a4ca..5864539 100644
--- a/libcacard/cac.c
+++ b/libcacard/cac.c
@@ -12,13 +12,6 @@
#include "vcard_emul.h"
#include "card_7816.h"
-#define CAC_GET_PROPERTIES 0x56
-#define CAC_GET_ACR 0x4c
-#define CAC_READ_BUFFER 0x52
-#define CAC_UPDATE_BUFFER 0x58
-#define CAC_SIGN_DECRYPT 0x42
-#define CAC_GET_CERTIFICATE 0x36
-
/* private data for PKI applets */
typedef struct CACPKIAppletDataStruct {
unsigned char *cert;
diff --git a/libcacard/cac.h b/libcacard/cac.h
index 15a61be..d24a2a8 100644
--- a/libcacard/cac.h
+++ b/libcacard/cac.h
@@ -9,6 +9,14 @@
#define CAC_H 1
#include "vcard.h"
#include "vreader.h"
+
+#define CAC_GET_PROPERTIES 0x56
+#define CAC_GET_ACR 0x4c
+#define CAC_READ_BUFFER 0x52
+#define CAC_UPDATE_BUFFER 0x58
+#define CAC_SIGN_DECRYPT 0x42
+#define CAC_GET_CERTIFICATE 0x36
+
/*
* Initialize the cac card. This is the only public function in this file. All
* the rest are connected through function pointers.
diff --git a/libcacard/vreader.c b/libcacard/vreader.c
index f3efc27..5793d73 100644
--- a/libcacard/vreader.c
+++ b/libcacard/vreader.c
@@ -5,6 +5,12 @@
* See the COPYING.LIB file in the top-level directory.
*/
+#ifdef G_LOG_DOMAIN
+#undef G_LOG_DOMAIN
+#endif
+#define G_LOG_DOMAIN "libcacard"
+#include <glib.h>
+
#include "qemu-common.h"
#include "qemu/thread.h"
@@ -13,6 +19,9 @@
#include "card_7816.h"
#include "vreader.h"
#include "vevent.h"
+#include "cac.h" /* just for debugging defines */
+
+#define LIBCACARD_LOG_DOMAIN "libcacard"
struct VReaderStruct {
int reference_count;
@@ -24,6 +33,66 @@ struct VReaderStruct {
VReaderEmulFree reader_private_free;
};
+/*
+ * Debug helpers
+ */
+
+static const char *
+apdu_ins_to_string(int ins)
+{
+ switch (ins) {
+ case VCARD7816_INS_MANAGE_CHANNEL:
+ return "manage channel";
+ case VCARD7816_INS_EXTERNAL_AUTHENTICATE:
+ return "external authenticate";
+ case VCARD7816_INS_GET_CHALLENGE:
+ return "get challenge";
+ case VCARD7816_INS_INTERNAL_AUTHENTICATE:
+ return "internal authenticate";
+ case VCARD7816_INS_ERASE_BINARY:
+ return "erase binary";
+ case VCARD7816_INS_READ_BINARY:
+ return "read binary";
+ case VCARD7816_INS_WRITE_BINARY:
+ return "write binary";
+ case VCARD7816_INS_UPDATE_BINARY:
+ return "update binary";
+ case VCARD7816_INS_READ_RECORD:
+ return "read record";
+ case VCARD7816_INS_WRITE_RECORD:
+ return "write record";
+ case VCARD7816_INS_UPDATE_RECORD:
+ return "update record";
+ case VCARD7816_INS_APPEND_RECORD:
+ return "append record";
+ case VCARD7816_INS_ENVELOPE:
+ return "envelope";
+ case VCARD7816_INS_PUT_DATA:
+ return "put data";
+ case VCARD7816_INS_GET_DATA:
+ return "get data";
+ case VCARD7816_INS_SELECT_FILE:
+ return "select file";
+ case VCARD7816_INS_VERIFY:
+ return "verify";
+ case VCARD7816_INS_GET_RESPONSE:
+ return "get response";
+ case CAC_GET_PROPERTIES:
+ return "get properties";
+ case CAC_GET_ACR:
+ return "get acr";
+ case CAC_READ_BUFFER:
+ return "read buffer";
+ case CAC_UPDATE_BUFFER:
+ return "update buffer";
+ case CAC_SIGN_DECRYPT:
+ return "sign decrypt";
+ case CAC_GET_CERTIFICATE:
+ return "get certificate";
+ }
+ return "unknown";
+}
+
/* manage locking */
static inline void
vreader_lock(VReader *reader)
@@ -204,7 +273,15 @@ vreader_xfr_bytes(VReader *reader,
response = vcard_make_response(status);
card_status = VCARD_DONE;
} else {
+ g_debug("%s: CLS=0x%x,INS=0x%x,P1=0x%x,P2=0x%x,Lc=%d,Le=%d %s\n",
+ __func__, apdu->a_cla, apdu->a_ins, apdu->a_p1, apdu->a_p2,
+ apdu->a_Lc, apdu->a_Le, apdu_ins_to_string(apdu->a_ins));
card_status = vcard_process_apdu(card, apdu, &response);
+ if (response) {
+ g_debug("%s: status=%d sw1=0x%x sw2=0x%x len=%d (total=%d)\n",
+ __func__, response->b_status, response->b_sw1,
+ response->b_sw2, response->b_len, response->b_total_len);
+ }
}
assert(card_status == VCARD_DONE);
if (card_status == VCARD_DONE) {
--
1.8.3.1

View File

@ -0,0 +1,161 @@
From 703a72f26668f26f2bb98851f1a2edd9a8681f86 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Tue, 5 Mar 2013 16:27:43 +0200
Subject: [PATCH 237/241] libcacard: move atr setting from macro to function
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Only because qemu's checkpatch complains about it.
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit 0b6a16c1a47b622b1a692ab179013d9e30e9cf3b)
---
Makefile.objs | 1 +
libcacard/vcard_emul_nss.c | 14 +++++++++++---
libcacard/vcardt.c | 40 ++++++++++++++++++++++++++++++++++++++++
libcacard/vcardt.h | 13 -------------
libcacard/vcardt_internal.h | 6 ++++++
5 files changed, 58 insertions(+), 16 deletions(-)
create mode 100644 libcacard/vcardt.c
create mode 100644 libcacard/vcardt_internal.h
diff --git a/Makefile.objs b/Makefile.objs
index 3884790..729be2b 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -32,6 +32,7 @@ libcacard-y += libcacard/vcard.o libcacard/vreader.o
libcacard-y += libcacard/vcard_emul_nss.o
libcacard-y += libcacard/vcard_emul_type.o
libcacard-y += libcacard/card_7816.o
+libcacard-y += libcacard/vcardt.o
######################################################################
# Target independent part of system emulation. The long term path is to
diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 9ba80fb..1a3e568 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -33,6 +33,9 @@
#include "vreader.h"
#include "vevent.h"
+#include "libcacard/vcardt_internal.h"
+
+
typedef enum {
VCardEmulUnknown = -1,
VCardEmulFalse = 0,
@@ -519,18 +522,23 @@ vcard_emul_reader_get_slot(VReader *vreader)
}
/*
- * Card ATR's map to physical cards. VCARD_ATR_PREFIX will set appropriate
+ * Card ATR's map to physical cards. vcard_alloc_atr will set appropriate
* historical bytes for any software emulated card. The remaining bytes can be
* used to indicate the actual emulator
*/
-static const unsigned char nss_atr[] = { VCARD_ATR_PREFIX(3), 'N', 'S', 'S' };
+static unsigned char *nss_atr;
+static int nss_atr_len;
void
vcard_emul_get_atr(VCard *card, unsigned char *atr, int *atr_len)
{
- int len = MIN(sizeof(nss_atr), *atr_len);
+ int len;
assert(atr != NULL);
+ if (nss_atr == NULL) {
+ nss_atr = vcard_alloc_atr("NSS", &nss_atr_len);
+ }
+ len = MIN(nss_atr_len, *atr_len);
memcpy(atr, nss_atr, len);
*atr_len = len;
}
diff --git a/libcacard/vcardt.c b/libcacard/vcardt.c
new file mode 100644
index 0000000..9ce4648
--- /dev/null
+++ b/libcacard/vcardt.c
@@ -0,0 +1,40 @@
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include "libcacard/vcardt.h"
+
+#include "libcacard/vcardt_internal.h"
+
+/* create an ATR with appropriate historical bytes */
+#define ATR_TS_DIRECT_CONVENTION 0x3b
+#define ATR_TA_PRESENT 0x10
+#define ATR_TB_PRESENT 0x20
+#define ATR_TC_PRESENT 0x40
+#define ATR_TD_PRESENT 0x80
+
+unsigned char *vcard_alloc_atr(const char *postfix, int *atr_len)
+{
+ int postfix_len;
+ const char prefix[] = "VCARD_";
+ const char default_postfix[] = "DEFAULT";
+ const int prefix_len = sizeof(prefix) - 1;
+ int total_len;
+ unsigned char *atr;
+
+ if (postfix == NULL) {
+ postfix = default_postfix;
+ }
+ postfix_len = strlen(postfix);
+ total_len = 3 + prefix_len + postfix_len;
+ atr = g_malloc(total_len);
+ atr[0] = ATR_TS_DIRECT_CONVENTION;
+ atr[1] = ATR_TD_PRESENT + prefix_len + postfix_len;
+ atr[2] = 0x00;
+ memcpy(&atr[3], prefix, prefix_len);
+ memcpy(&atr[3 + prefix_len], postfix, postfix_len);
+ if (atr_len) {
+ *atr_len = total_len;
+ }
+ return atr;
+}
diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
index 3b9a619..795e265 100644
--- a/libcacard/vcardt.h
+++ b/libcacard/vcardt.h
@@ -25,19 +25,6 @@ typedef struct VCardEmulStruct VCardEmul;
#define MAX_CHANNEL 4
-/* create an ATR with appropriate historical bytes */
-#define TS_DIRECT_CONVENTION 0x3b
-#define TA_PRESENT 0x10
-#define TB_PRESENT 0x20
-#define TC_PRESENT 0x40
-#define TD_PRESENT 0x80
-
-#define VCARD_ATR_PREFIX(size) \
- TS_DIRECT_CONVENTION, \
- TD_PRESENT + (6 + size), \
- 0x00, \
- 'V', 'C', 'A', 'R', 'D', '_'
-
typedef enum {
VCARD_DONE,
VCARD_NEXT,
diff --git a/libcacard/vcardt_internal.h b/libcacard/vcardt_internal.h
new file mode 100644
index 0000000..e5c8d2d
--- /dev/null
+++ b/libcacard/vcardt_internal.h
@@ -0,0 +1,6 @@
+#ifndef VCARDT_INTERNAL_H
+#define VCARDT_INTERNAL_H
+
+unsigned char *vcard_alloc_atr(const char *postfix, int *atr_len);
+
+#endif
--
1.8.3.1

View File

@ -0,0 +1,34 @@
From 002714edb70b00c20de7d54980a528ac7232bb33 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Tue, 5 Mar 2013 17:31:10 +0200
Subject: [PATCH 238/241] dev-smartcard-reader: empty implementation for
Mechanical (fail correctly)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit 58aeda15abb963196faaa4a0f23c5af45840f1b0)
---
hw/usb/dev-smartcard-reader.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 4e08f9b..a473b87 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1051,6 +1051,10 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
ccid_reset_error_status(s);
ccid_write_parameters(s, ccid_header);
break;
+ case CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical:
+ ccid_report_error_failed(s, 0);
+ ccid_write_slot_status(s, ccid_header);
+ break;
default:
DPRINTF(s, 1,
"handle_data: ERROR: unhandled message type %Xh\n",
--
1.8.3.1

View File

@ -0,0 +1,209 @@
From 8527c47117c0ec6d12929b6c19206eed6ee90528 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Mon, 4 Mar 2013 21:43:36 +0200
Subject: [PATCH 239/241] libcacard/cac: change big switch functions to single
return point
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit 57f97834efe0c208ffadc9d2959f3d3d55580e52)
---
libcacard/cac.c | 73 ++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 52 insertions(+), 21 deletions(-)
diff --git a/libcacard/cac.c b/libcacard/cac.c
index 5864539..7a06b5a 100644
--- a/libcacard/cac.c
+++ b/libcacard/cac.c
@@ -40,41 +40,51 @@ static VCardStatus
cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
{
int ef;
+ VCardStatus ret = VCARD_FAIL;
switch (apdu->a_ins) {
case VCARD7816_INS_SELECT_FILE:
if (apdu->a_p1 != 0x02) {
/* let the 7816 code handle applet switches */
- return VCARD_NEXT;
+ ret = VCARD_NEXT;
+ break;
}
/* handle file id setting */
if (apdu->a_Lc != 2) {
*response = vcard_make_response(
VCARD7816_STATUS_ERROR_DATA_INVALID);
- return VCARD_DONE;
+ ret = VCARD_DONE;
+ break;
}
/* CAC 1.0 only supports ef = 0 */
ef = apdu->a_body[0] | (apdu->a_body[1] << 8);
if (ef != 0) {
*response = vcard_make_response(
VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
- return VCARD_DONE;
+ ret = VCARD_DONE;
+ break;
}
*response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
- return VCARD_DONE;
+ ret = VCARD_DONE;
+ break;
case VCARD7816_INS_GET_RESPONSE:
case VCARD7816_INS_VERIFY:
/* let the 7816 code handle these */
- return VCARD_NEXT;
+ ret = VCARD_NEXT;
+ break;
case CAC_GET_PROPERTIES:
case CAC_GET_ACR:
/* skip these for now, this will probably be needed */
*response = vcard_make_response(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
- return VCARD_DONE;
+ ret = VCARD_DONE;
+ break;
+ default:
+ *response = vcard_make_response(
+ VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+ ret = VCARD_DONE;
+ break;
}
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- return VCARD_DONE;
+ return ret;
}
/*
@@ -108,6 +118,7 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
int size, next;
unsigned char *sign_buffer;
vcard_7816_status_t status;
+ VCardStatus ret = VCARD_FAIL;
applet_private = vcard_get_current_applet_private(card, apdu->a_channel);
assert(applet_private);
@@ -117,7 +128,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
case CAC_UPDATE_BUFFER:
*response = vcard_make_response(
VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
- return VCARD_DONE;
+ ret = VCARD_DONE;
+ break;
case CAC_GET_CERTIFICATE:
if ((apdu->a_p2 != 0) || (apdu->a_p1 != 0)) {
*response = vcard_make_response(
@@ -147,7 +159,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
*response = vcard_make_response(
VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
}
- return VCARD_DONE;
+ ret = VCARD_DONE;
+ break;
case CAC_SIGN_DECRYPT:
if (apdu->a_p2 != 0) {
*response = vcard_make_response(
@@ -164,7 +177,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
pki_applet->sign_buffer_len = 0;
*response = vcard_make_response(
VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
- return VCARD_DONE;
+ ret = VCARD_DONE;
+ break;
}
memcpy(sign_buffer+pki_applet->sign_buffer_len, apdu->a_body, size);
size += pki_applet->sign_buffer_len;
@@ -175,7 +189,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
pki_applet->sign_buffer = sign_buffer;
pki_applet->sign_buffer_len = size;
*response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
- return VCARD_DONE;
+ ret = VCARD_DONE;
+ break;
case 0x00:
/* we now have the whole buffer, do the operation, result will be
* in the sign_buffer */
@@ -200,15 +215,20 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
g_free(sign_buffer);
pki_applet->sign_buffer = NULL;
pki_applet->sign_buffer_len = 0;
- return VCARD_DONE;
+ ret = VCARD_DONE;
+ break;
case CAC_READ_BUFFER:
/* new CAC call, go ahead and use the old version for now */
/* TODO: implement */
*response = vcard_make_response(
VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- return VCARD_DONE;
+ ret = VCARD_DONE;
+ break;
+ default:
+ ret = cac_common_process_apdu(card, apdu, response);
+ break;
}
- return cac_common_process_apdu(card, apdu, response);
+ return ret;
}
@@ -216,19 +236,26 @@ static VCardStatus
cac_applet_id_process_apdu(VCard *card, VCardAPDU *apdu,
VCardResponse **response)
{
+ VCardStatus ret = VCARD_FAIL;
+
switch (apdu->a_ins) {
case CAC_UPDATE_BUFFER:
*response = vcard_make_response(
VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
- return VCARD_DONE;
+ ret = VCARD_DONE;
+ break;
case CAC_READ_BUFFER:
/* new CAC call, go ahead and use the old version for now */
/* TODO: implement */
*response = vcard_make_response(
VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- return VCARD_DONE;
+ ret = VCARD_DONE;
+ break;
+ default:
+ ret = cac_common_process_apdu(card, apdu, response);
+ break;
}
- return cac_common_process_apdu(card, apdu, response);
+ return ret;
}
@@ -240,16 +267,20 @@ static VCardStatus
cac_applet_container_process_apdu(VCard *card, VCardAPDU *apdu,
VCardResponse **response)
{
+ VCardStatus ret = VCARD_FAIL;
+
switch (apdu->a_ins) {
case CAC_READ_BUFFER:
case CAC_UPDATE_BUFFER:
*response = vcard_make_response(
VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- return VCARD_DONE;
+ ret = VCARD_DONE;
+ break;
default:
+ ret = cac_common_process_apdu(card, apdu, response);
break;
}
- return cac_common_process_apdu(card, apdu, response);
+ return ret;
}
/*
--
1.8.3.1

View File

@ -0,0 +1,55 @@
From aae98aa5aa23dbddf3a6e8c8c0399948f0d43480 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Tue, 4 Jun 2013 16:23:37 -0400
Subject: [PATCH 240/241] libcacard/vscclient: fix leakage of socket on error
paths
Spotted by Coverity.
Signed-off-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit 581fe784c3adf85dc167a47a4a60fd1245a98217)
---
libcacard/vscclient.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
index ac23647..5180d29 100644
--- a/libcacard/vscclient.c
+++ b/libcacard/vscclient.c
@@ -618,18 +618,22 @@ connect_to_qemu(
if (ret != 0) {
/* Error */
fprintf(stderr, "getaddrinfo failed\n");
- return -1;
+ goto cleanup_socket;
}
if (connect(sock, server->ai_addr, server->ai_addrlen) < 0) {
/* Error */
fprintf(stderr, "Could not connect\n");
- return -1;
+ goto cleanup_socket;
}
if (verbose) {
printf("Connected (sizeof Header=%zd)!\n", sizeof(VSCMsgHeader));
}
return sock;
+
+cleanup_socket:
+ closesocket(sock);
+ return -1;
}
int
@@ -759,5 +763,6 @@ main(
g_io_channel_unref(channel_socket);
g_byte_array_unref(socket_to_send);
+ closesocket(sock);
return 0;
}
--
1.8.3.1

View File

@ -0,0 +1,89 @@
From 742e78d849a701e49f3c7d3c13eb9c4013f2cec3 Mon Sep 17 00:00:00 2001
From: Stefan Weil <sw@weilnetz.de>
Date: Sun, 16 Jun 2013 11:08:52 +0200
Subject: [PATCH 241/241] libcacard: Fix cppcheck warning and remove unneeded
code
The local function vcard_emul_alloc_arrays always returned PR_TRUE.
Therefore cppcheck complained about code which handled the
non-existent PR_FALSE case.
Remove the function's return value and the dead code.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit 48f0475f813dfa5ceb0e1f10c2ac3f28a8af583b)
---
libcacard/vcard_emul_nss.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)
diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 1a3e568..fb429b1 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -90,17 +90,13 @@ static int nss_emul_init;
/*
* allocate the set of arrays for certs, cert_len, key
*/
-static PRBool
+static void
vcard_emul_alloc_arrays(unsigned char ***certsp, int **cert_lenp,
VCardKey ***keysp, int cert_count)
{
- *certsp = NULL;
- *cert_lenp = NULL;
- *keysp = NULL;
*certsp = (unsigned char **)g_malloc(sizeof(unsigned char *)*cert_count);
*cert_lenp = (int *)g_malloc(sizeof(int)*cert_count);
*keysp = (VCardKey **)g_malloc(sizeof(VCardKey *)*cert_count);
- return PR_TRUE;
}
/*
@@ -601,7 +597,6 @@ vcard_emul_mirror_card(VReader *vreader)
int *cert_len;
VCardKey **keys;
PK11SlotInfo *slot;
- PRBool ret;
VCard *card;
slot = vcard_emul_reader_get_slot(vreader);
@@ -627,10 +622,7 @@ vcard_emul_mirror_card(VReader *vreader)
}
/* allocate the arrays */
- ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count);
- if (ret == PR_FALSE) {
- return NULL;
- }
+ vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count);
/* fill in the arrays */
cert_count = 0;
@@ -878,7 +870,7 @@ VCardEmulError
vcard_emul_init(const VCardEmulOptions *options)
{
SECStatus rv;
- PRBool ret, has_readers = PR_FALSE;
+ PRBool has_readers = PR_FALSE;
VReader *vreader;
VReaderEmul *vreader_emul;
SECMODListLock *module_lock;
@@ -944,11 +936,9 @@ vcard_emul_init(const VCardEmulOptions *options)
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;
- }
+ vcard_emul_alloc_arrays(&certs, &cert_len, &keys,
+ options->vreader[i].cert_count);
+
cert_count = 0;
for (j = 0; j < options->vreader[i].cert_count; j++) {
/* we should have a better way of identifying certs than by
--
1.8.3.1

View File

@ -131,7 +131,7 @@
Summary: QEMU is a FAST! processor emulator
Name: qemu
Version: 1.4.2
Release: 6%{?dist}
Release: 7%{?dist}
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
Epoch: 2
License: GPLv2+ and LGPLv2+ and BSD
@ -254,6 +254,39 @@ Patch0209: 0209-Fix-usage-of-USB_DEV_FLAG_IS_HOST-flag.patch
# Fix crash when adding spice vdagent channel in the guest (bz #969084)
Patch0210: 0210-qxl-Fix-QXLRam-initialisation.patch
# 917860 related libcacard and qemu/hw/ccid windows 7 smartcard support.
Patch0211: 0211-qemu-socket-Make-socket_optslist-public.patch
Patch0212: 0212-libcacard-correct-T0-historical-bytes-size.patch
Patch0213: 0213-ccid-card-emul-do-not-crash-if-backend-is-not-provid.patch
Patch0214: 0214-ccid-make-backend_enum_table-static-const-and-adjust.patch
Patch0215: 0215-ccid-declare-DEFAULT_ATR-table-to-be-static-const.patch
Patch0216: 0216-libcacard-use-system-config-directory-for-nss-db-on-.patch
Patch0217: 0217-util-move-socket_init-to-osdep.c.patch
Patch0218: 0218-build-sys-must-link-with-fstack-protector.patch
Patch0219: 0219-libcacard-fix-mingw64-cross-compilation.patch
Patch0220: 0220-libcacard-split-vscclient-main-from-socket-reading.patch
Patch0221: 0221-libcacard-vscclient-to-use-QemuThread-for-portabilit.patch
Patch0222: 0222-libcacard-teach-vscclient-to-use-GMainLoop-for-porta.patch
Patch0223: 0223-libcacard-remove-sql-prefix.patch
Patch0224: 0224-libcacard-remove-default-libcoolkey-loading.patch
Patch0225: 0225-dev-smartcard-reader-white-space-fixes.patch
Patch0226: 0226-dev-smartcard-reader-nicer-debug-messages.patch
Patch0227: 0227-dev-smartcard-reader-remove-aborts-never-triggered-b.patch
Patch0228: 0228-dev-smartcard-reader-support-windows-guest.patch
Patch0229: 0229-dev-smartcard-reader-reuse-usb.h-definitions.patch
Patch0230: 0230-libcacard-change-default-ATR.patch
Patch0231: 0231-ccid-card-passthru-add-atr-check.patch
Patch0232: 0232-ccid-card-passthru-dev-smartcard-reader-add-debug-en.patch
Patch0233: 0233-dev-smartcard-reader-define-structs-for-CCID_Paramet.patch
Patch0234: 0234-dev-smartcard-reader-change-default-protocol-to-T-0.patch
Patch0235: 0235-dev-smartcard-reader-copy-atr-protocol-to-ccid-param.patch
Patch0236: 0236-libcacard-vreader-add-debugging-messages-for-apdu.patch
Patch0237: 0237-libcacard-move-atr-setting-from-macro-to-function.patch
Patch0238: 0238-dev-smartcard-reader-empty-implementation-for-Mechan.patch
Patch0239: 0239-libcacard-cac-change-big-switch-functions-to-single-.patch
Patch0240: 0240-libcacard-vscclient-fix-leakage-of-socket-on-error-p.patch
Patch0241: 0241-libcacard-Fix-cppcheck-warning-and-remove-unneeded-c.patch
BuildRequires: SDL-devel
BuildRequires: zlib-devel
BuildRequires: which
@ -796,6 +829,39 @@ CAC emulation development files.
# Fix crash when adding spice vdagent channel in the guest (bz #969084)
%patch0210 -p1
# 917860 libcacard and qemu/hw/ccid windows 7 smartcard support.
%patch0211 -p1
%patch0212 -p1
%patch0213 -p1
%patch0214 -p1
%patch0215 -p1
%patch0216 -p1
%patch0217 -p1
%patch0218 -p1
%patch0219 -p1
%patch0220 -p1
%patch0221 -p1
%patch0222 -p1
%patch0223 -p1
%patch0224 -p1
%patch0225 -p1
%patch0226 -p1
%patch0227 -p1
%patch0228 -p1
%patch0229 -p1
%patch0230 -p1
%patch0231 -p1
%patch0232 -p1
%patch0233 -p1
%patch0234 -p1
%patch0235 -p1
%patch0236 -p1
%patch0237 -p1
%patch0238 -p1
%patch0239 -p1
%patch0240 -p1
%patch0241 -p1
%build
%if %{with kvmonly}
buildarch="%{kvm_target}-softmmu"
@ -1441,6 +1507,9 @@ getent passwd qemu >/dev/null || \
%endif
%changelog
* Sun Aug 18 2013 Alon Levy <alevy@redhat.com> - 2:1.4.2-7
- Support windows 7 smartcard using guests and clients - (bz #917860 rhel 6.5)
* Thu Aug 01 2013 Cole Robinson <crobinso@redhat.com> - 2:1.4.2-6
- Fix crash when adding spice vdagent channel in the guest (bz #969084)