vpcd: added real thread safety

This commit is contained in:
Frank Morgner
2014-03-28 07:08:31 +01:00
parent ac3b70f4d1
commit 0aec0e4d31
10 changed files with 531 additions and 47 deletions

View File

@@ -1,10 +1,10 @@
VPCD_LIB = $(LIB_PREFIX)vpcd.$(DYN_LIB_EXT)
libvpcd_la_SOURCES = ifd-vpcd.c vpcd.c
libvpcd_la_SOURCES = ifd-vpcd.c vpcd.c lock.c
libvpcd_la_LDFLAGS = -no-undefined
libvpcd_la_CFLAGS = $(PCSC_CFLAGS)
noinst_HEADERS = vpcd.h
noinst_HEADERS = vpcd.h lock.h
EXTRA_DIST = reader.conf.in

View File

@@ -0,0 +1,110 @@
/*
* Copyright (C) 2014 Frank Morgner
*
* This file is part of virtualsmartcard.
*
* virtualsmartcard is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* virtualsmartcard is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* virtualsmartcard. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
int lock(void *io_lock)
{
EnterCriticalSection(io_lock);
return 1;
}
int unlock(void *io_lock)
{
LeaveCriticalSection(io_lock);
return 1;
}
void *create_lock(void)
{
CRITICAL_SECTION *io_lock = malloc(sizeof *io_lock);
InitializeCriticalSection(io_lock);
/* FIXME error handling */
return io_lock;
}
void free_lock(void *io_lock)
{
DeleteCriticalSection(io_lock);
free(io_lock);
}
#else
#ifdef HAVE_PTHREAD
#include <pthread.h>
int lock(void *io_lock)
{
r = 0;
if (0 == pthread_mutex_lock(io_lock))
r = 1;
return r;
}
int unlock(void *io_lock)
{
r = 0;
if (0 == pthread_mutex_unlock(io_lock))
r = 1;
return r;
}
void *create_lock(void)
{
pthread_mutex_t *io_lock = malloc(sizeof *io_lock);
if (io_lock) {
*io_lock = PTHREAD_MUTEX_INITIALIZER;
}
return io_lock;
}
void free_lock(void *io_lock)
{
pthread_mutex_destroy(io_lock);
free(io_lock);
}
#else
int lock(void *io_lock)
{
return 1;
}
int unlock(void *io_lock)
{
return 1;
}
void *create_lock(void)
{
return (void *) 1;
}
void free_lock(void *io_lock)
{
}
#endif
#endif

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) 2014 Frank Morgner
*
* This file is part of virtualsmartcard.
*
* virtualsmartcard is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* virtualsmartcard is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* virtualsmartcard. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _LOCK_H_
#define _LOCK_H_
#ifdef __cplusplus
extern "C" {
#endif
int lock(void *io_lock);
int unlock(void *io_lock);
void *create_lock(void);
void free_lock(void *io_lock);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2013 Frank Morgner
* Copyright (C) 2009-2014 Frank Morgner
*
* This file is part of virtualsmartcard.
*
@@ -17,6 +17,7 @@
* virtualsmartcard. If not, see <http://www.gnu.org/licenses/>.
*/
#include "vpcd.h"
#include "lock.h"
#if HAVE_CONFIG_H
#include "config.h"
@@ -66,7 +67,6 @@ static ssize_t recvall(int sock, void *buffer, size_t size);
static int opensock(unsigned short port);
static int connectsock(const char *hostname, unsigned short port);
ssize_t sendall(int sock, const void *buffer, size_t size)
{
size_t sent;
@@ -249,46 +249,56 @@ int vicc_eject(struct vicc_ctx *ctx)
struct vicc_ctx * vicc_init(const char *hostname, unsigned short port)
{
struct vicc_ctx *r = NULL;
struct vicc_ctx *ctx = malloc(sizeof *ctx);
if (!ctx) {
return NULL;
goto err;
}
ctx->hostname = NULL;
ctx->io_lock = NULL;
ctx->server_sock = -1;
ctx->client_sock = -1;
ctx->port = port;
#ifdef _WIN32
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
ctx->io_lock = create_lock();
if (!ctx->io_lock) {
goto err;
}
if (hostname) {
ctx->hostname = strdup(hostname);
if (!ctx->hostname) {
free(ctx);
return NULL;
goto err;
}
ctx->server_sock = -1;
ctx->client_sock = connectsock(hostname, port);
} else {
ctx->hostname = NULL;
ctx->server_sock = opensock(port);
if (ctx->server_sock < 0) {
free(ctx);
return NULL;
goto err;
}
ctx->client_sock = -1;
}
ctx->port = port;
r = ctx;
return ctx;
err:
if (!r) {
vicc_exit(ctx);
}
return r;
}
int vicc_exit(struct vicc_ctx *ctx)
{
int r = vicc_eject(ctx);
if (ctx) {
free_lock(ctx->io_lock);
free(ctx->hostname);
if (ctx->server_sock > 0) {
ctx->server_sock = close(ctx->server_sock);
@@ -308,12 +318,16 @@ ssize_t vicc_transmit(struct vicc_ctx *ctx,
size_t apdu_len, const unsigned char *apdu,
unsigned char **rapdu)
{
ssize_t r;
ssize_t r = -1;
r = sendToVICC(ctx, apdu_len, apdu);
if (ctx && lock(ctx->io_lock)) {
r = sendToVICC(ctx, apdu_len, apdu);
if (r > 0)
r = recvFromVICC(ctx, rapdu);
if (r > 0)
r = recvFromVICC(ctx, rapdu);
unlock(ctx->io_lock);
}
if (r <= 0)
vicc_eject(ctx);
@@ -360,15 +374,36 @@ ssize_t vicc_getatr(struct vicc_ctx *ctx, unsigned char **atr) {
int vicc_poweron(struct vicc_ctx *ctx) {
unsigned char i = VPCD_CTRL_ON;
return sendToVICC(ctx, VPCD_CTRL_LEN, &i);
int r = 0;
if (ctx && lock(ctx->io_lock)) {
r = sendToVICC(ctx, VPCD_CTRL_LEN, &i);
unlock(ctx->io_lock);
}
return r;
}
int vicc_poweroff(struct vicc_ctx *ctx) {
unsigned char i = VPCD_CTRL_OFF;
return sendToVICC(ctx, VPCD_CTRL_LEN, &i);
int r = 0;
if (ctx && lock(ctx->io_lock)) {
r = sendToVICC(ctx, VPCD_CTRL_LEN, &i);
unlock(ctx->io_lock);
}
return r;
}
int vicc_reset(struct vicc_ctx *ctx) {
unsigned char i = VPCD_CTRL_RESET;
return sendToVICC(ctx, VPCD_CTRL_LEN, &i);
int r = 0;
if (ctx && lock(ctx->io_lock)) {
r = sendToVICC(ctx, VPCD_CTRL_LEN, &i);
unlock(ctx->io_lock);
}
return r;
}

View File

@@ -31,6 +31,7 @@ struct vicc_ctx {
int client_sock;
char *hostname;
unsigned short port;
void *io_lock;
};
#ifdef __cplusplus