vpcd: added real thread safety
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
110
virtualsmartcard/src/vpcd/lock.c
Normal file
110
virtualsmartcard/src/vpcd/lock.c
Normal 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
|
||||
33
virtualsmartcard/src/vpcd/lock.h
Normal file
33
virtualsmartcard/src/vpcd/lock.h
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ struct vicc_ctx {
|
||||
int client_sock;
|
||||
char *hostname;
|
||||
unsigned short port;
|
||||
void *io_lock;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user