diff --git a/pcsc-relay/Makefile.am b/pcsc-relay/Makefile.am index 3920780..cf53b16 100644 --- a/pcsc-relay/Makefile.am +++ b/pcsc-relay/Makefile.am @@ -1 +1,43 @@ -SUBDIRS = src doc +SUBDIRS=src doc + + +LIBUSB_WIN32_BIN_VERSION=1.2.6.0 +LIBUSB_WIN32_BIN_DIR=libusb-win32-bin-$(LIBUSB_WIN32_BIN_VERSION) +LIBUSB_DLL=$(abs_builddir)/$(LIBUSB_WIN32_BIN_DIR)/bin/x86/libusb0_x86.dll +LIBUSB_WIN32_BIN_ARCHIVE=$(LIBUSB_WIN32_BIN_DIR).zip +$(LIBUSB_WIN32_BIN_ARCHIVE): + wget http://freefr.dl.sourceforge.net/project/libusb-win32/libusb-win32-releases/$(LIBUSB_WIN32_BIN_VERSION)/$(LIBUSB_WIN32_BIN_ARCHIVE) +$(LIBUSB_DLL): $(LIBUSB_WIN32_BIN_ARCHIVE) + unzip $< + + +LIBNFC_DIR=$(abs_builddir)/libnfc +LIBNFC_DLL=$(LIBNFC_DIR)/libnfc.dll +$(LIBNFC_DIR): + svn co http://libnfc.googlecode.com/svn/trunk $@ +$(LIBNFC_DLL): $(LIBNFC_DIR) $(LIBUSB_DLL) + cd $< && wget http://www2.informatik.hu-berlin.de/~morgner/libnfc.dll + + +MINGW=i686-w64-mingw32 +MINGW_DIR=/usr/$(MINGW) +PCSC_RELAY_EXE=$(abs_builddir)/src/pcsc-relay.exe +$(PCSC_RELAY_EXE): $(LIBNFC_DIR) $(LIBNFC_DLL) + ./configure --target=$(MINGW) --host=$(MINGW) \ + PKG_CONFIG_LIBDIR=$(MINGW_DIR)/lib/pkgconfig \ + CFLAGS=-I$(MINGW_DIR)/include \ + LDFLAGS=-L$(MINGW_DIR)/lib \ + PCSC_LIBS="-lwinscard" \ + LIBNFC_CFLAGS="-I$(LIBNFC_DIR)/include" \ + LIBNFC_LIBS="$(LIBNFC_DLL)" + make + + +WIN32_DIR=$(PACKAGE_TARNAME)-$(PACKAGE_VERSION)_win32 +win: src/pcsc-relay.exe + mkdir -p $(WIN32_DIR) + for i in \ + $(LIBNFC_DLL) \ + $(PCSC_RELAY_EXE) \ + ; do cp $${i} $(WIN32_DIR); done + cp $(LIBUSB_DLL) $(WIN32_DIR)/libusb0.dll diff --git a/pcsc-relay/configure.ac b/pcsc-relay/configure.ac index 074252f..c8ada04 100644 --- a/pcsc-relay/configure.ac +++ b/pcsc-relay/configure.ac @@ -29,22 +29,22 @@ PKG_CHECK_EXISTS([libnfc >= 1.6], saved_CPPFLAGS="$CPPFLAGS" -saved_LIBS="$LIBS" CPPFLAGS="$CPPFLAGS $PCSC_CFLAGS $LIBNFC_CFLAGS" -LIBS="$LDFLAGS $PCSC_LIBS $LIBNFC_LIBS" AC_CHECK_HEADERS(winscard.h, [], [ AC_MSG_ERROR([winscard.h not found, install PC/SC Lite or similar or use ./configure PCSC_CFLAGS=...]) ]) AC_CHECK_HEADERS(reader.h, [AC_DEFINE(HAVE_READER_H, 1, [use reader.h from PC/SC Lite])], []) AC_CHECK_HEADERS(pcsclite.h, [AC_DEFINE(HAVE_PCSCLITE_H, 1, [use pcsclite.h from PC/SC Lite])], []) -AC_MSG_CHECKING([for SCardEstablishContext]) -AC_TRY_LINK_FUNC(SCardEstablishContext, [ AC_MSG_RESULT([yes]) ], - [ AC_MSG_ERROR([libpcsclite not found, use ./configure PCSC_LIBS=...]) ]) AC_CHECK_HEADERS(nfc/nfc.h,, [ AC_MSG_ERROR([nfc/nfc.h not found, install libnfc >= 5.1.9 or use ./configure LIBNFC_CFLAGS=...]) ]) AC_MSG_CHECKING([for nfc_initiator_select_passive_target]) -AC_TRY_LINK_FUNC(nfc_initiator_select_passive_target, [ AC_MSG_RESULT([yes]) ], - [ AC_MSG_ERROR([libnfc >= 1.6 not found, use ./configure LIBNFC_LIBS=...]) ]) CPPFLAGS="$saved_CPPFLAGS" -LIBS="$saved_LIBS" +#saved_LIBS="$LIBS" +#LIBS="$LIBS $PCSC_LIBS $LIBNFC_LIBS" +#AC_MSG_CHECKING([for SCardEstablishContext]) +#AC_TRY_LINK_FUNC(SCardEstablishContext, [ AC_MSG_RESULT([yes]) ], + #[ AC_MSG_ERROR([libpcsclite not found, use ./configure PCSC_LIBS=...]) ]) +#AC_TRY_LINK_FUNC(nfc_initiator_select_passive_target, [ AC_MSG_RESULT([yes]) ], + #[ AC_MSG_ERROR([libnfc >= 1.6 not found, use ./configure LIBNFC_LIBS=...]) ]) +#LIBS="$saved_LIBS" # --enable-piccdev=DEV @@ -60,6 +60,8 @@ AC_CHECK_HEADERS([fcntl.h stdint.h stdlib.h string.h unistd.h]) AC_TYPE_SIZE_T # Checks for library functions. +AC_CHECK_FUNCS([sigaction tcgetattr]) +AC_FUNC_FORK AC_FUNC_MALLOC diff --git a/pcsc-relay/src/lnfc.c b/pcsc-relay/src/lnfc.c index d66bf9d..58d8097 100644 --- a/pcsc-relay/src/lnfc.c +++ b/pcsc-relay/src/lnfc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Frank Morgner + * Copyright (C) 2010-2012 Frank Morgner . * * This file is part of pcsc-relay. * @@ -142,7 +142,7 @@ static int lnfc_connect(driver_data_t **driver_data) data->pndTarget = nfc_open(NULL, NULL); if (data->pndTarget == NULL) { - ERROR("Error connecting to NFC emulator device\n"); + RELAY_ERROR("Error connecting to NFC emulator device\n"); return 0; } @@ -152,7 +152,7 @@ static int lnfc_connect(driver_data_t **driver_data) DEBUG("Waiting for a command that is not part of the anti-collision...\n"); data->iCapduLen = nfc_target_init(data->pndTarget, &ntEmulatedTarget, data->abtCapdu, sizeof data->abtCapdu, 0); if (data->iCapduLen < 0) { - ERROR("nfc_target_init: %s\n", nfc_strerror(data->pndTarget)); + RELAY_ERROR("nfc_target_init: %s\n", nfc_strerror(data->pndTarget)); nfc_close (data->pndTarget); return 0; } @@ -189,14 +189,14 @@ static int lnfc_receive_capdu(driver_data_t *driver_data, // Receive external reader command through target data->iCapduLen = nfc_target_receive_bytes(data->pndTarget, data->abtCapdu, sizeof data->abtCapdu, TRANSMIT_TIMEOUT); if (data->iCapduLen < 0) { - ERROR ("nfc_target_receive_bytes: %s\n", nfc_strerror(data->pndTarget)); + RELAY_ERROR ("nfc_target_receive_bytes: %s\n", nfc_strerror(data->pndTarget)); return 0; } p = realloc(*capdu, data->iCapduLen); if (!p) { - ERROR("Error allocating memory for C-APDU\n"); + RELAY_ERROR("Error allocating memory for C-APDU\n"); return 0; } memcpy(p, data->abtCapdu, data->iCapduLen); @@ -219,7 +219,7 @@ static int lnfc_send_rapdu(driver_data_t *driver_data, r = nfc_target_send_bytes(data->pndTarget, rapdu, len, TRANSMIT_TIMEOUT); if (r < 0) { - ERROR ("nfc_target_send_bytes: %s\n", nfc_strerror(data->pndTarget)); + RELAY_ERROR ("nfc_target_send_bytes: %s\n", nfc_strerror(data->pndTarget)); return 0; } if (r < len) diff --git a/pcsc-relay/src/opicc.c b/pcsc-relay/src/opicc.c index dc8373c..8a3da56 100644 --- a/pcsc-relay/src/opicc.c +++ b/pcsc-relay/src/opicc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Frank Morgner + * Copyright (C) 2010-2012 Frank Morgner . * * This file is part of pcsc-relay. * @@ -16,15 +16,16 @@ * You should have received a copy of the GNU General Public License along with * pcsc-relay. If not, see . */ -#include +#include "config.h" +#include "pcsc-relay.h" #include + +#if HAVE_TCGETATTR +#include #include #include #include -#include "config.h" -#include "pcsc-relay.h" - struct picc_data { char *e_rapdu; @@ -53,7 +54,7 @@ int picc_encode_rapdu(const unsigned char *inbuf, size_t inlen, length = 5+inlen*3+1; p = realloc(*outbuf, length); if (!p) { - ERROR("Error allocating memory for encoded R-APDU\n"); + RELAY_ERROR("Error allocating memory for encoded R-APDU\n"); return 0; } *outbuf = p; @@ -102,7 +103,7 @@ int picc_decode_apdu(const char *inbuf, size_t inlen, p = realloc(*outbuf, length); if (!p) { - ERROR("Error allocating memory for decoded C-APDU\n"); + RELAY_ERROR("Error allocating memory for decoded C-APDU\n"); return 0; } *outbuf = p; @@ -111,7 +112,7 @@ int picc_decode_apdu(const char *inbuf, size_t inlen, while(inbuf+inlen > end && length > pos) { b = strtoul(end, &end, 16); if (b > 0xff) { - ERROR("Error decoding C-APDU\n"); + RELAY_ERROR("Error decoding C-APDU\n"); return 0; } @@ -141,7 +142,7 @@ void un_braindead_ify_device(int fd) cfsetospeed (&options, B115200); if (tcsetattr (fd, TCSANOW, &options)) - ERROR("Can't set device attributes"); + RELAY_ERROR("Can't set device attributes"); } @@ -164,7 +165,7 @@ static int picc_connect(driver_data_t **driver_data) data->fd = fopen(PICCDEV, "a+"); /*O_NOCTTY ?*/ if (!data->fd) { - ERROR("Error opening %s: %s\n", PICCDEV, strerror(errno)); + RELAY_ERROR("Error opening %s: %s\n", PICCDEV, strerror(errno)); return 0; } un_braindead_ify_device(fileno(data->fd)); @@ -207,7 +208,7 @@ static int picc_receive_capdu(driver_data_t *driver_data, linelen = getline(&data->line, &data->linemax, data->fd); if (linelen <= 0) { if (linelen < 0) { - ERROR("Error reading from %s: %s\n", PICCDEV, strerror(errno)); + RELAY_ERROR("Error reading from %s: %s\n", PICCDEV, strerror(errno)); return 0; } if (linelen == 0) { @@ -216,7 +217,7 @@ static int picc_receive_capdu(driver_data_t *driver_data, } } if (fflush(data->fd) != 0) - ERROR("Warning, fflush failed: %s\n", strerror(errno)); + RELAY_ERROR("Warning, fflush failed: %s\n", strerror(errno)); DEBUG(data->line); @@ -244,17 +245,34 @@ static int picc_send_rapdu(driver_data_t *driver_data, DEBUG("INF: Writing R-APDU\r\n%s\r\n", data->e_rapdu); if (fprintf(data->fd,"%s\r\n", data->e_rapdu) < 0) { - ERROR("Error writing to %s: %s\n", PICCDEV, strerror(errno)); + RELAY_ERROR("Error writing to %s: %s\n", PICCDEV, strerror(errno)); return 0; } if (fflush(data->fd) != 0) - ERROR("Warning, fflush failed: %s\n", strerror(errno)); + RELAY_ERROR("Warning, fflush failed: %s\n", strerror(errno)); return 1; } +#else +/* If tcgetattr() is not available, OpenPICC backend will not be supported. I + * don't want to hassle with any workarounds. */ +#define OPICCERR RELAY_ERROR("OpenPICC backend currently not supported on your system.\n") +static int picc_send_rapdu(driver_data_t *driver_data, + const unsigned char *rapdu, size_t len) +{ OPICCERR; return 0; } +static int picc_receive_capdu(driver_data_t *driver_data, + unsigned char **capdu, size_t *len) +{ OPICCERR; return 0; } +static int picc_disconnect(driver_data_t *driver_data) +{ OPICCERR; return 0; } +static int picc_connect(driver_data_t **driver_data) +{ OPICCERR; return 0; } + + +#endif struct rf_driver driver_openpicc = { .connect = picc_connect, .disconnect = picc_disconnect, diff --git a/pcsc-relay/src/pcsc-relay.c b/pcsc-relay/src/pcsc-relay.c index 75073be..09b533d 100644 --- a/pcsc-relay/src/pcsc-relay.c +++ b/pcsc-relay/src/pcsc-relay.c @@ -34,6 +34,10 @@ #include "pcsc-relay.h" #include "pcscutil.h" +#ifndef MAX_BUFFER_SIZE +#define MAX_BUFFER_SIZE 264 /**< Maximum Tx/Rx Buffer for short APDU */ +#endif + static int doinfo = 0; static int dodaemon = 1; int verbose = 0; @@ -51,13 +55,14 @@ static void cleanup_exit(int signo); static void cleanup(void); +#if HAVE_WORKING_FORK void daemonize(void) { pid_t pid, sid; /* Fork and continue as child process */ pid = fork(); if (pid < 0) { - ERROR("fork: %s\n", strerror(errno)); + RELAY_ERROR("fork: %s\n", strerror(errno)); goto err; } if (pid > 0) /* Exit the parent */ @@ -68,14 +73,14 @@ void daemonize(void) { /* Create new session and set the process group ID */ sid = setsid(); if (sid < 0) { - ERROR("setsid: %s\n", strerror(errno)); + RELAY_ERROR("setsid: %s\n", strerror(errno)); goto err; } /* Change the current working directory. This prevents the current * directory from being locked; hence not being able to remove it. */ if (chdir("/") < 0) { - ERROR("chdir: %s\n", strerror(errno)); + RELAY_ERROR("chdir: %s\n", strerror(errno)); goto err; } @@ -91,6 +96,15 @@ err: exit(1); } + +#else +/* If fork() is not available, daemon mode will not be supported. I don't want + * to hassle with any workarounds. */ +void daemonize(void) +{ RELAY_ERROR("Daemon mode currently not supported on your system.\n"); exit(1); } +#endif + + void cleanup_exit(int signo){ cleanup(); exit(0); @@ -115,7 +129,6 @@ int main (int argc, char **argv) LONG r = SCARD_S_SUCCESS; DWORD ctl, protocol; - struct sigaction new_sig, old_sig; struct gengetopt_args_info args_info; @@ -134,15 +147,19 @@ int main (int argc, char **argv) } +#if HAVE_SIGACTION + struct sigaction new_sig, old_sig; + /* Register signal handlers */ new_sig.sa_handler = cleanup_exit; sigemptyset(&new_sig.sa_mask); new_sig.sa_flags = SA_RESTART; if ((sigaction(SIGINT, &new_sig, &old_sig) < 0) || (sigaction(SIGTERM, &new_sig, &old_sig) < 0)) { - ERROR("sigaction: %s\n", strerror(errno)); + RELAY_ERROR("sigaction: %s\n", strerror(errno)); goto err; } +#endif /* Open the device */ @@ -195,7 +212,7 @@ err: cleanup(); if (r != SCARD_S_SUCCESS) { - ERROR(pcsc_stringify_error(r)); + RELAY_ERROR(stringify_error(r)); exit(1); } diff --git a/pcsc-relay/src/pcsc-relay.ggo.in b/pcsc-relay/src/pcsc-relay.ggo.in index 433570a..39bc171 100644 --- a/pcsc-relay/src/pcsc-relay.ggo.in +++ b/pcsc-relay/src/pcsc-relay.ggo.in @@ -7,7 +7,7 @@ option "reader" r optional option "emulator" e "Contact-less emulator backend" - values="openpicc","libnfc" default="openpicc" + values="libnfc","openpicc" default="libnfc" enum optional option "foreground" f diff --git a/pcsc-relay/src/pcsc-relay.h b/pcsc-relay/src/pcsc-relay.h index 2ce58d0..a550734 100644 --- a/pcsc-relay/src/pcsc-relay.h +++ b/pcsc-relay/src/pcsc-relay.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Frank Morgner + * Copyright (C) 2010-2012 Frank Morgner . * * This file is part of pcsc-relay. * @@ -23,6 +23,9 @@ #define _PCSC_RELAY_H +#include + + #ifdef __cplusplus extern "C" { #endif @@ -50,7 +53,7 @@ extern struct rf_driver driver_libnfc; #define INFO(...) \ {if (verbose >= LEVEL_INFO) \ printf (__VA_ARGS__);} -#define ERROR(...) \ +#define RELAY_ERROR(...) \ { \ if (verbose >= LEVEL_DEBUG) fprintf (stderr, "%s:%u\t", __FILE__, __LINE__); \ if (verbose >= 0) fprintf (stderr, __VA_ARGS__); \