added option parsing and more error checking

git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@353 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
frankmorgner
2010-11-10 20:14:19 +00:00
parent daf88aafa7
commit 44dc9f6c7d
7 changed files with 151 additions and 81 deletions

View File

@@ -3,8 +3,8 @@ EXTRA_DIST = picc.py
bin_PROGRAMS = pcsc-relay bin_PROGRAMS = pcsc-relay
bin_SCRIPTS = picc.py bin_SCRIPTS = picc.py
pcsc_relay_SOURCES = pcsc-relay.c pcscutil.c opicc.c lnfc.c pcsc_relay_SOURCES = pcsc-relay.c pcscutil.c opicc.c lnfc.c binutil.c
pcsc_relay_LDADD = $(PCSC_LIBS) $(LIBNFC_LIBS) pcsc_relay_LDADD = $(PCSC_LIBS) $(LIBNFC_LIBS)
pcsc_relay_CFLAGS = $(PCSC_CFLAGS) $(LIBNFC_CFLAGS) pcsc_relay_CFLAGS = $(PCSC_CFLAGS) $(LIBNFC_CFLAGS)
noinst_HEADERS = pcscutil.h pcsc-relay.h noinst_HEADERS = pcscutil.h pcsc-relay.h binutil.h

1
pcsc-relay/src/binutil.c Symbolic link
View File

@@ -0,0 +1 @@
../../ccid/src/binutil.c

1
pcsc-relay/src/binutil.h Symbolic link
View File

@@ -0,0 +1 @@
../../ccid/src/binutil.h

View File

@@ -127,22 +127,18 @@ static int lnfc_connect(void **driver_data)
// Try to open the NFC emulator device // Try to open the NFC emulator device
data->pndTarget = nfc_connect (NULL); data->pndTarget = nfc_connect (NULL);
if (data->pndTarget == NULL) { if (data->pndTarget == NULL) {
if (verbose || debug) ERROR("Error connecting NFC emulator device\n");
fprintf (stderr, "Error connecting NFC emulator device\n");
return 0; return 0;
} }
if (verbose) INFO("Connected to the NFC emulator device: %s\n", data->pndTarget->acName);
printf ("Connected to the NFC emulator device: %s\n", data->pndTarget->acName);
if (!nfc_target_init (data->pndTarget, &ntEmulatedTarget, data->abtCapdu, &data->szCapduLen)) { if (!nfc_target_init (data->pndTarget, &ntEmulatedTarget, data->abtCapdu, &data->szCapduLen)) {
if (verbose || debug) ERROR("Initialization of NFC emulator failed");
fprintf (stderr, "%s", "Initialization of NFC emulator failed");
nfc_disconnect (data->pndTarget); nfc_disconnect (data->pndTarget);
return 0; return 0;
} }
if (debug) DEBUG("%s\n", "Done, relaying frames now!");
printf ("%s\n", "Done, relaying frames now!");
return 1; return 1;
@@ -170,7 +166,7 @@ static int lnfc_receive_capdu(void *driver_data,
// Receive external reader command through target // Receive external reader command through target
if (!nfc_target_receive_bytes(data->pndTarget, data->abtCapdu, &data->szCapduLen)) { if (!nfc_target_receive_bytes(data->pndTarget, data->abtCapdu, &data->szCapduLen)) {
if (verbose || debug) if (verbose >= 0)
nfc_perror (data->pndTarget, "nfc_target_receive_bytes"); nfc_perror (data->pndTarget, "nfc_target_receive_bytes");
return 0; return 0;
} }
@@ -189,7 +185,8 @@ static int lnfc_send_rapdu(void *driver_data,
if (!nfc_target_send_bytes(data->pndTarget, rapdu, len)) { if (!nfc_target_send_bytes(data->pndTarget, rapdu, len)) {
nfc_perror (data->pndTarget, "nfc_target_send_bytes"); if (verbose >= 0)
nfc_perror (data->pndTarget, "nfc_target_send_bytes");
return 0; return 0;
} }

View File

@@ -28,25 +28,27 @@ struct picc_data {
size_t buflen; size_t buflen;
FILE *fd; FILE *fd;
}; };
static size_t picc_encode_rapdu(const unsigned char *inbuf, size_t inlen, char **outbuf); static int picc_encode_rapdu(const unsigned char *inbuf, size_t inlen,
static size_t picc_decode_apdu(const char *inbuf, size_t inlen, unsigned char **outbuf); char **outbuf, size_t *outlen);
static int picc_decode_apdu(const char *inbuf, size_t inlen,
unsigned char **outbuf, size_t *outlen);
size_t picc_encode_rapdu(const unsigned char *inbuf, size_t inlen, char **outbuf) int picc_encode_rapdu(const unsigned char *inbuf, size_t inlen,
char **outbuf, size_t *outlen)
{ {
char *p; char *p;
const unsigned char *next; const unsigned char *next;
size_t length; size_t length;
if (!inbuf || inlen > 0xffff || !outbuf) if (!inbuf || inlen > 0xffff || !outbuf)
goto err; return 0;
length = 5+inlen*3+1; length = 5+inlen*3+1;
p = realloc(*outbuf, length); p = realloc(*outbuf, length);
if (!p) { if (!p) {
if (debug || verbose) ERROR("Error allocating memory for encoded R-APDU\n");
fprintf(stderr, "Error allocating memory for encoded R-APDU\n"); return 0;
goto err;
} }
*outbuf = p; *outbuf = p;
@@ -61,35 +63,38 @@ size_t picc_encode_rapdu(const unsigned char *inbuf, size_t inlen, char **outbuf
p += 3; p += 3;
} }
return length; *outlen = length;
return 1;
err:
return 0;
} }
size_t picc_decode_apdu(const char *inbuf, size_t inlen, unsigned char **outbuf) int picc_decode_apdu(const char *inbuf, size_t inlen,
unsigned char **outbuf, size_t *outlen)
{ {
size_t pos, length; size_t pos, length;
char *end, *p; char *end, *p;
unsigned long int b; unsigned long int b;
if (!outbuf || inbuf == NULL || inlen == 0 || inbuf[0] == '\0') { if (!outbuf || !outlen) {
/* Ignore invalid parameters, empty and 'RESET' lines */ /* Invalid parameters */
goto noapdu; return 0;
}
if (inbuf == NULL || inlen == 0 || inbuf[0] == '\0') {
/* Ignore empty and 'RESET' lines */
*outlen = 0;
return 1;
} }
length = strtoul(inbuf, &end, 16); length = strtoul(inbuf, &end, 16);
/* check for ':' right behind the length */ /* check for ':' right behind the length */
if (inbuf+inlen < end+1 || end[0] != ':') if (inbuf+inlen < end+1 || end[0] != ':')
goto noapdu; return 0;
end++; end++;
p = realloc(*outbuf, length); p = realloc(*outbuf, length);
if (!p) { if (!p) {
if (debug || verbose) ERROR("Error allocating memory for decoded C-APDU\n");
fprintf(stderr, "Error allocating memory for decoded C-APDU\n"); return 0;
goto noapdu;
} }
*outbuf = p; *outbuf = p;
@@ -97,18 +102,16 @@ size_t picc_decode_apdu(const char *inbuf, size_t inlen, unsigned char **outbuf)
while(inbuf+inlen > end && length > pos) { while(inbuf+inlen > end && length > pos) {
b = strtoul(end, &end, 16); b = strtoul(end, &end, 16);
if (b > 0xff) { if (b > 0xff) {
if (debug || verbose) ERROR( "%s:%u Error decoding C-APDU\n", __FILE__, __LINE__);
fprintf(stderr, "%s:%u Error decoding C-APDU\n", __FILE__, __LINE__); return 0;
goto noapdu;
} }
(*outbuf)[pos++] = b; (*outbuf)[pos++] = b;
} }
return length; *outlen = length;
noapdu: return 1;
return 0;
} }
@@ -127,8 +130,7 @@ static int picc_connect(void **driver_data)
data->fd = fopen(PICCDEV, "a+"); /*O_NOCTTY ?*/ data->fd = fopen(PICCDEV, "a+"); /*O_NOCTTY ?*/
if (!data->fd) { if (!data->fd) {
if (debug || verbose) ERROR("Error opening %s\n", PICCDEV);
fprintf(stderr,"Error opening %s\n", PICCDEV);
return 0; return 0;
} }
@@ -136,8 +138,7 @@ static int picc_connect(void **driver_data)
data->buflen = 0; data->buflen = 0;
if (debug || verbose) INFO("Connected to %s\n", PICCDEV);
printf("Connected to %s\n", PICCDEV);
return 1; return 1;
} }
@@ -176,8 +177,7 @@ static int picc_receive_capdu(void *driver_data,
linelen = getline(&buf, &buflen, data->fd); linelen = getline(&buf, &buflen, data->fd);
if (linelen < 0) { if (linelen < 0) {
if (linelen < 0) { if (linelen < 0) {
if (debug || verbose) ERROR("Error reading from %s\n", PICCDEV);
fprintf(stderr,"Error reading from %s\n", PICCDEV);
return 0; return 0;
} }
} }
@@ -187,12 +187,13 @@ static int picc_receive_capdu(void *driver_data,
} }
fflush(data->fd); fflush(data->fd);
if (debug) DEBUG("%s\n", buf);
printf("%s\n", buf);
/* decode C-APDU */ /* decode C-APDU */
*len = picc_decode_apdu(buf, linelen, capdu); if (!picc_decode_apdu(buf, linelen, capdu, len))
return 0;
return 1; return 1;
} }
@@ -200,28 +201,29 @@ static int picc_receive_capdu(void *driver_data,
static int picc_send_rapdu(void *driver_data, static int picc_send_rapdu(void *driver_data,
const unsigned char *rapdu, size_t len) const unsigned char *rapdu, size_t len)
{ {
size_t buflen;
struct picc_data *data = driver_data; struct picc_data *data = driver_data;
size_t buflen;
if (!data || !rapdu) if (!data || !rapdu)
return 0; return 0;
/* encode R-APDU */ /* encode R-APDU */
buflen = picc_encode_rapdu(rapdu, len, &data->buf); if (!picc_encode_rapdu(rapdu, len, &data->buf, &buflen))
if (buflen > data->buflen) return 0;
if (data->buflen < buflen)
data->buflen = buflen; data->buflen = buflen;
/* write R-APDU */ /* write R-APDU */
if (debug) DEBUG("INF: Writing R-APDU\n\n%s\n\n", data->buf);
printf("INF: Writing R-APDU\n\n%s\n\n", data->buf);
if (fprintf(data->fd,"%s\r\n", (char *) data->buf) < 0 if (fprintf(data->fd,"%s\r\n", (char *) data->buf) < 0
|| fflush(data->fd) != 0) { || fflush(data->fd) != 0) {
return 0; return 0;
} }
return 1; return 1;
} }

View File

@@ -29,17 +29,41 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include "binutil.h"
#include "config.h" #include "config.h"
#include "pcsc-relay.h" #include "pcsc-relay.h"
#include "pcscutil.h" #include "pcscutil.h"
struct rf_driver *driver = &driver_libnfc; #define OPT_HELP 'h'
#define OPT_READER 'r'
#define OPT_VERBOSE 'v'
#define OPT_FOREGROUND 'f'
#define OPT_EMULATOR 'e'
static const struct option options[] = {
{ "help", no_argument, NULL, OPT_HELP },
{ "reader", required_argument, NULL, OPT_READER },
{ "foreground", no_argument, NULL, OPT_FOREGROUND },
{ "emulator", required_argument, NULL, OPT_EMULATOR },
{ "verbose", no_argument, NULL, OPT_VERBOSE },
{ NULL, 0, NULL, 0 }
};
static const char *option_help[] = {
"Print help and exit",
"Number of reader to use (default: 0)",
"Stay in foreground",
"Emulation backend (openpicc [default], libnfc)",
"Use (several times) to be more verbose",
};
static int doinfo = 0;
static int dodaemon = 1;
int verbose = 0;
static unsigned int readernum = 0;
static struct rf_driver *driver = &driver_openpicc;
static LPSTR readers = NULL; static LPSTR readers = NULL;
static SCARDCONTEXT hContext = 0; static SCARDCONTEXT hContext = 0;
static SCARDHANDLE hCard = 0; static SCARDHANDLE hCard = 0;
int verbose = 0, debug = 0;
/* Forward declaration */ /* Forward declaration */
static void daemonize(); static void daemonize();
@@ -93,8 +117,9 @@ void cleanup(void) {
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
/*printf("%s:%d\n", __FILE__, __LINE__);*/ /*printf("%s:%d\n", __FILE__, __LINE__);*/
void *buf = NULL; unsigned char *buf = NULL;
size_t buflen; size_t buflen;
int i, oindex;
BYTE outputBuffer[MAX_BUFFER_SIZE]; BYTE outputBuffer[MAX_BUFFER_SIZE];
DWORD outputLength; DWORD outputLength;
@@ -102,34 +127,63 @@ int main (int argc, char **argv)
LONG r = SCARD_S_SUCCESS; LONG r = SCARD_S_SUCCESS;
DWORD ctl, protocol; DWORD ctl, protocol;
char *read = NULL;
size_t readlen = 0;
unsigned int readernum = 0;
struct sigaction new_sig, old_sig; struct sigaction new_sig, old_sig;
if (argc > 1) { while (1) {
readernum = strtoul(argv[1], NULL, 10); i = getopt_long(argc, argv, "hr:fe:v", options, &oindex);
if (argc > 2) { if (i == -1)
if (0 == strcmp(argv[2], "verbose")) break;
switch (i) {
case OPT_HELP:
print_usage(argv[0] , options, option_help);
exit(0);
break;
case OPT_READER:
if (sscanf(optarg, "%u", &readernum) != 1) {
parse_error(argv[0], options, option_help, optarg, oindex);
exit(2);
}
break;
case OPT_VERBOSE:
verbose++; verbose++;
else if (0 == strcmp(argv[2], "debug")) dodaemon = 0;
debug++; break;
else case OPT_FOREGROUND:
goto parse_err; dodaemon = 0;
if (argc > 3) { break;
parse_err: case OPT_EMULATOR:
fprintf(stderr, "Usage: " if (strncmp(optarg, "openpicc", strlen("openpicc")) == 0)
"%s [reader number] [verbose | debug]\n", argv[0]); driver = &driver_openpicc;
exit(2); else
} if (strncmp(optarg, "libnfc", strlen("libnfc")) == 0)
driver = &driver_libnfc;
else {
parse_error(argv[0], options, option_help, optarg, oindex);
exit(2);
}
break;
case '?':
/* fall through */
default:
exit(1);
break;
} }
} }
if (!verbose && !debug)
if (doinfo) {
fprintf(stderr, "%s written by Frank Morgner.\n" ,
PACKAGE_STRING);
return 0;
}
if (dodaemon) {
verbose = -1;
daemonize(); daemonize();
}
/* Register signal handlers */ /* Register signal handlers */
new_sig.sa_handler = cleanup_exit; new_sig.sa_handler = cleanup_exit;
@@ -144,6 +198,7 @@ parse_err:
if (!driver->connect(&driver->data)) if (!driver->connect(&driver->data))
goto err; goto err;
/* connect to reader and card */ /* connect to reader and card */
r = pcsc_connect(readernum, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_ANY, r = pcsc_connect(readernum, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_ANY,
&hContext, &readers, &hCard, &protocol); &hContext, &readers, &hCard, &protocol);
@@ -152,13 +207,14 @@ parse_err:
while(1) { while(1) {
if (!driver->receive_capdu(driver->data, (unsigned char **) &buf, &buflen)) /* get C-APDU */
if (!driver->receive_capdu(driver->data, &buf, &buflen))
goto err; goto err;
if (!buflen) if (!buflen || !buf)
continue; continue;
if (!verbose) if (verbose >= 0)
printb("C-APDU: ===================================================\n", buf, buflen); printb("C-APDU:\n", buf, buflen);
/* transmit APDU to card */ /* transmit APDU to card */
@@ -167,9 +223,10 @@ parse_err:
if (r != SCARD_S_SUCCESS) if (r != SCARD_S_SUCCESS)
goto err; goto err;
if (!verbose)
printb("R-APDU:\n", outputBuffer, outputLength);
/* send R-APDU */
if (verbose >= 0)
printb("R-APDU:\n", outputBuffer, outputLength);
if (!driver->send_rapdu(driver->data, outputBuffer, outputLength)) if (!driver->send_rapdu(driver->data, outputBuffer, outputLength))
goto err; goto err;

View File

@@ -37,11 +37,23 @@ struct rf_driver {
const unsigned char *rapdu, size_t len); const unsigned char *rapdu, size_t len);
}; };
extern int verbose, debug; extern int verbose;
extern struct rf_driver driver_openpicc; extern struct rf_driver driver_openpicc;
extern struct rf_driver driver_libnfc; extern struct rf_driver driver_libnfc;
#define LEVEL_INFO 1
#define LEVEL_DEBUG 2
#define DEBUG(...) \
{if (verbose >= LEVEL_DEBUG) \
printf (__VA_ARGS__);}
#define INFO(...) \
{if (verbose >= LEVEL_INFO) \
printf (__VA_ARGS__);}
#define ERROR(...) \
{if (verbose >= 0) \
fprintf (stderr, __VA_ARGS__);}
#ifdef __cplusplus #ifdef __cplusplus
} }