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

View File

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

View File

@@ -29,17 +29,41 @@
#include <string.h>
#include <errno.h>
#include "binutil.h"
#include "config.h"
#include "pcsc-relay.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 SCARDCONTEXT hContext = 0;
static SCARDHANDLE hCard = 0;
int verbose = 0, debug = 0;
/* Forward declaration */
static void daemonize();
@@ -93,8 +117,9 @@ void cleanup(void) {
int main (int argc, char **argv)
{
/*printf("%s:%d\n", __FILE__, __LINE__);*/
void *buf = NULL;
unsigned char *buf = NULL;
size_t buflen;
int i, oindex;
BYTE outputBuffer[MAX_BUFFER_SIZE];
DWORD outputLength;
@@ -102,34 +127,63 @@ int main (int argc, char **argv)
LONG r = SCARD_S_SUCCESS;
DWORD ctl, protocol;
char *read = NULL;
size_t readlen = 0;
unsigned int readernum = 0;
struct sigaction new_sig, old_sig;
if (argc > 1) {
readernum = strtoul(argv[1], NULL, 10);
if (argc > 2) {
if (0 == strcmp(argv[2], "verbose"))
while (1) {
i = getopt_long(argc, argv, "hr:fe:v", options, &oindex);
if (i == -1)
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++;
else if (0 == strcmp(argv[2], "debug"))
debug++;
else
goto parse_err;
if (argc > 3) {
parse_err:
fprintf(stderr, "Usage: "
"%s [reader number] [verbose | debug]\n", argv[0]);
exit(2);
}
dodaemon = 0;
break;
case OPT_FOREGROUND:
dodaemon = 0;
break;
case OPT_EMULATOR:
if (strncmp(optarg, "openpicc", strlen("openpicc")) == 0)
driver = &driver_openpicc;
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();
}
/* Register signal handlers */
new_sig.sa_handler = cleanup_exit;
@@ -144,6 +198,7 @@ parse_err:
if (!driver->connect(&driver->data))
goto err;
/* connect to reader and card */
r = pcsc_connect(readernum, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_ANY,
&hContext, &readers, &hCard, &protocol);
@@ -152,13 +207,14 @@ parse_err:
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;
if (!buflen)
if (!buflen || !buf)
continue;
if (!verbose)
printb("C-APDU: ===================================================\n", buf, buflen);
if (verbose >= 0)
printb("C-APDU:\n", buf, buflen);
/* transmit APDU to card */
@@ -167,9 +223,10 @@ parse_err:
if (r != SCARD_S_SUCCESS)
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))
goto err;

View File

@@ -37,11 +37,23 @@ struct rf_driver {
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_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
}