2010-03-04 08:14:36 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
2001-12-29 12:03:18 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2002-02-21 18:53:23 +00:00
|
|
|
#include <stdarg.h>
|
2010-04-18 07:47:16 +00:00
|
|
|
#ifndef _WIN32
|
|
|
|
#include <termios.h>
|
2010-04-28 09:20:18 +00:00
|
|
|
#else
|
|
|
|
#include <conio.h>
|
2010-04-18 07:47:16 +00:00
|
|
|
#endif
|
2001-12-29 12:03:18 +00:00
|
|
|
#include <ctype.h>
|
|
|
|
#include "util.h"
|
|
|
|
|
2008-03-06 16:06:59 +00:00
|
|
|
int util_connect_card(sc_context_t *ctx, sc_card_t **cardp,
|
2010-03-29 08:23:07 +00:00
|
|
|
const char *reader_id, int do_wait, int verbose)
|
2003-01-03 16:57:46 +00:00
|
|
|
{
|
2010-01-24 15:29:47 +00:00
|
|
|
sc_reader_t *reader, *found;
|
2003-12-29 13:06:28 +00:00
|
|
|
sc_card_t *card;
|
2010-01-24 15:29:47 +00:00
|
|
|
int r, tmp_reader_num;
|
2003-01-03 16:57:46 +00:00
|
|
|
|
2010-03-29 08:23:07 +00:00
|
|
|
if (do_wait) {
|
2003-01-03 16:57:46 +00:00
|
|
|
unsigned int event;
|
|
|
|
|
2010-02-03 09:58:37 +00:00
|
|
|
if (sc_ctx_get_reader_count(ctx) == 0) {
|
|
|
|
fprintf(stderr, "Waiting for a reader to be attached...\n");
|
|
|
|
r = sc_wait_for_event(ctx, SC_EVENT_READER_ATTACHED, &found, &event, -1);
|
|
|
|
if (r < 0) {
|
|
|
|
fprintf(stderr, "Error while waiting for a reader: %s\n", sc_strerror(r));
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
r = sc_ctx_detect_readers(ctx);
|
|
|
|
if (r < 0) {
|
|
|
|
fprintf(stderr, "Error while refreshing readers: %s\n", sc_strerror(r));
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fprintf(stderr, "Waiting for a card to be inserted...\n");
|
2010-01-24 15:29:47 +00:00
|
|
|
r = sc_wait_for_event(ctx, SC_EVENT_CARD_INSERTED, &found, &event, -1);
|
2003-01-03 16:57:46 +00:00
|
|
|
if (r < 0) {
|
2010-02-03 09:58:37 +00:00
|
|
|
fprintf(stderr, "Error while waiting for a card: %s\n", sc_strerror(r));
|
2003-01-03 16:57:46 +00:00
|
|
|
return 3;
|
|
|
|
}
|
2010-01-24 15:29:47 +00:00
|
|
|
reader = found;
|
2003-01-03 16:57:46 +00:00
|
|
|
} else {
|
2006-02-15 17:29:40 +00:00
|
|
|
if (sc_ctx_get_reader_count(ctx) == 0) {
|
2003-01-03 16:57:46 +00:00
|
|
|
fprintf(stderr,
|
2008-12-06 11:41:00 +00:00
|
|
|
"No smart card readers found.\n");
|
2003-01-03 16:57:46 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2010-01-24 15:29:47 +00:00
|
|
|
if (!reader_id) {
|
2009-10-06 07:36:51 +00:00
|
|
|
unsigned int i;
|
2008-12-05 15:48:49 +00:00
|
|
|
/* Automatically try to skip to a reader with a card if reader not specified */
|
|
|
|
for (i = 0; i < sc_ctx_get_reader_count(ctx); i++) {
|
|
|
|
reader = sc_ctx_get_reader(ctx, i);
|
2010-01-24 15:29:47 +00:00
|
|
|
if (sc_detect_card_presence(reader) & SC_READER_CARD_PRESENT) {
|
2008-12-05 15:48:49 +00:00
|
|
|
fprintf(stderr, "Using reader with a card: %s\n", reader->name);
|
|
|
|
goto autofound;
|
|
|
|
}
|
|
|
|
}
|
2010-01-24 15:29:47 +00:00
|
|
|
/* If no reader had a card, default to the first reader */
|
|
|
|
reader = sc_ctx_get_reader(ctx, 0);
|
|
|
|
} else {
|
|
|
|
/* Get the reader by name if possible */
|
|
|
|
if (!sscanf(reader_id, "%d", &tmp_reader_num)) {
|
|
|
|
reader = sc_ctx_get_reader_by_name(ctx, reader_id);
|
|
|
|
} else {
|
|
|
|
reader = sc_ctx_get_reader(ctx, tmp_reader_num);
|
|
|
|
}
|
2008-12-05 15:48:49 +00:00
|
|
|
}
|
|
|
|
autofound:
|
2010-01-24 15:29:47 +00:00
|
|
|
if (!reader) {
|
2003-01-03 16:57:46 +00:00
|
|
|
fprintf(stderr,
|
2010-01-24 15:29:47 +00:00
|
|
|
"Reader \"%s\" not found (%d reader(s) detected)\n", reader_id, sc_ctx_get_reader_count(ctx));
|
2003-01-03 16:57:46 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-01-24 15:29:47 +00:00
|
|
|
if (sc_detect_card_presence(reader) <= 0) {
|
2003-01-03 16:57:46 +00:00
|
|
|
fprintf(stderr, "Card not present.\n");
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-06-13 20:13:12 +00:00
|
|
|
if (verbose)
|
2003-12-29 13:06:28 +00:00
|
|
|
printf("Connecting to card in reader %s...\n", reader->name);
|
2010-01-24 15:29:47 +00:00
|
|
|
if ((r = sc_connect_card(reader, &card)) < 0) {
|
2003-01-03 16:57:46 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"Failed to connect to card: %s\n",
|
|
|
|
sc_strerror(r));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2004-06-13 20:13:12 +00:00
|
|
|
if (verbose)
|
2003-12-29 13:06:28 +00:00
|
|
|
printf("Using card driver %s.\n", card->driver->name);
|
|
|
|
|
|
|
|
if ((r = sc_lock(card)) < 0) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Failed to lock card: %s\n",
|
|
|
|
sc_strerror(r));
|
2010-01-24 15:29:47 +00:00
|
|
|
sc_disconnect_card(card);
|
2003-12-29 13:06:28 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
*cardp = card;
|
2003-01-03 16:57:46 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-03-06 16:06:59 +00:00
|
|
|
void util_print_binary(FILE *f, const u8 *buf, int count)
|
2001-12-29 12:03:18 +00:00
|
|
|
{
|
|
|
|
int i;
|
2010-02-03 09:58:37 +00:00
|
|
|
|
2001-12-29 12:03:18 +00:00
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
unsigned char c = buf[i];
|
|
|
|
const char *format;
|
2008-01-04 13:13:53 +00:00
|
|
|
if (!isprint(c))
|
2001-12-29 12:03:18 +00:00
|
|
|
format = "\\x%02X";
|
|
|
|
else
|
|
|
|
format = "%c";
|
|
|
|
fprintf(f, format, c);
|
|
|
|
}
|
|
|
|
(void) fflush(f);
|
|
|
|
}
|
|
|
|
|
2008-03-06 16:06:59 +00:00
|
|
|
void util_hex_dump(FILE *f, const u8 *in, int len, const char *sep)
|
2001-12-29 12:03:18 +00:00
|
|
|
{
|
|
|
|
int i;
|
2010-02-03 09:58:37 +00:00
|
|
|
|
2002-01-24 16:02:54 +00:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
if (sep != NULL && i)
|
|
|
|
fprintf(f, "%s", sep);
|
|
|
|
fprintf(f, "%02X", in[i]);
|
|
|
|
}
|
2001-12-29 12:03:18 +00:00
|
|
|
}
|
|
|
|
|
2008-03-06 16:06:59 +00:00
|
|
|
void util_hex_dump_asc(FILE *f, const u8 *in, size_t count, int addr)
|
2001-12-29 12:03:18 +00:00
|
|
|
{
|
|
|
|
int lines = 0;
|
|
|
|
|
|
|
|
while (count) {
|
|
|
|
char ascbuf[17];
|
2006-02-14 22:04:47 +00:00
|
|
|
size_t i;
|
2010-02-03 09:58:37 +00:00
|
|
|
|
2002-01-09 01:03:10 +00:00
|
|
|
if (addr >= 0) {
|
|
|
|
fprintf(f, "%08X: ", addr);
|
|
|
|
addr += 16;
|
|
|
|
}
|
2001-12-29 12:03:18 +00:00
|
|
|
for (i = 0; i < count && i < 16; i++) {
|
|
|
|
fprintf(f, "%02X ", *in);
|
|
|
|
if (isprint(*in))
|
|
|
|
ascbuf[i] = *in;
|
|
|
|
else
|
|
|
|
ascbuf[i] = '.';
|
|
|
|
in++;
|
|
|
|
}
|
|
|
|
count -= i;
|
|
|
|
ascbuf[i] = 0;
|
|
|
|
for (; i < 16 && lines; i++)
|
|
|
|
fprintf(f, " ");
|
|
|
|
fprintf(f, "%s\n", ascbuf);
|
|
|
|
lines++;
|
|
|
|
}
|
|
|
|
}
|
2002-01-08 13:56:50 +00:00
|
|
|
|
2008-03-06 16:06:59 +00:00
|
|
|
void util_print_usage_and_die(const char *app_name, const struct option options[],
|
2007-06-21 13:46:08 +00:00
|
|
|
const char *option_help[])
|
2002-01-08 13:56:50 +00:00
|
|
|
{
|
|
|
|
int i = 0;
|
2002-03-24 14:12:38 +00:00
|
|
|
printf("Usage: %s [OPTIONS]\nOptions:\n", app_name);
|
2002-01-08 13:56:50 +00:00
|
|
|
|
|
|
|
while (options[i].name) {
|
|
|
|
char buf[40], tmp[5];
|
|
|
|
const char *arg_str;
|
2010-02-03 09:58:37 +00:00
|
|
|
|
2003-05-16 16:41:53 +00:00
|
|
|
/* Skip "hidden" options */
|
2003-05-16 19:11:38 +00:00
|
|
|
if (option_help[i] == NULL) {
|
|
|
|
i++;
|
2003-05-16 16:41:53 +00:00
|
|
|
continue;
|
2003-05-16 19:11:38 +00:00
|
|
|
}
|
2003-05-16 16:41:53 +00:00
|
|
|
|
2002-01-08 13:56:50 +00:00
|
|
|
if (options[i].val > 0 && options[i].val < 128)
|
|
|
|
sprintf(tmp, ", -%c", options[i].val);
|
|
|
|
else
|
|
|
|
tmp[0] = 0;
|
|
|
|
switch (options[i].has_arg) {
|
|
|
|
case 1:
|
|
|
|
arg_str = " <arg>";
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
arg_str = " [arg]";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
arg_str = "";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
sprintf(buf, "--%s%s%s", options[i].name, tmp, arg_str);
|
2003-01-09 09:09:01 +00:00
|
|
|
if (strlen(buf) > 29) {
|
|
|
|
printf(" %s\n", buf);
|
|
|
|
buf[0] = '\0';
|
|
|
|
}
|
|
|
|
printf(" %-29s %s\n", buf, option_help[i]);
|
2002-01-08 13:56:50 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
|
2008-03-06 16:06:59 +00:00
|
|
|
const char * util_acl_to_str(const sc_acl_entry_t *e)
|
2002-01-09 01:03:10 +00:00
|
|
|
{
|
2002-02-20 09:56:47 +00:00
|
|
|
static char line[80], buf[10];
|
|
|
|
unsigned int acl;
|
2010-02-03 09:58:37 +00:00
|
|
|
|
2002-02-20 09:56:47 +00:00
|
|
|
if (e == NULL)
|
2002-01-13 23:56:13 +00:00
|
|
|
return "N/A";
|
2002-01-09 01:03:10 +00:00
|
|
|
line[0] = 0;
|
2002-02-20 09:56:47 +00:00
|
|
|
while (e != NULL) {
|
|
|
|
acl = e->method;
|
|
|
|
|
|
|
|
switch (acl) {
|
|
|
|
case SC_AC_UNKNOWN:
|
|
|
|
return "N/A";
|
|
|
|
case SC_AC_NEVER:
|
|
|
|
return "NEVR";
|
|
|
|
case SC_AC_NONE:
|
|
|
|
return "NONE";
|
|
|
|
case SC_AC_CHV:
|
|
|
|
strcpy(buf, "CHV");
|
|
|
|
if (e->key_ref != SC_AC_KEY_REF_NONE)
|
|
|
|
sprintf(buf + 3, "%d", e->key_ref);
|
|
|
|
break;
|
|
|
|
case SC_AC_TERM:
|
|
|
|
strcpy(buf, "TERM");
|
|
|
|
break;
|
|
|
|
case SC_AC_PRO:
|
|
|
|
strcpy(buf, "PROT");
|
|
|
|
break;
|
|
|
|
case SC_AC_AUT:
|
|
|
|
strcpy(buf, "AUTH");
|
|
|
|
if (e->key_ref != SC_AC_KEY_REF_NONE)
|
|
|
|
sprintf(buf + 4, "%d", e->key_ref);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
strcpy(buf, "????");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
strcat(line, buf);
|
|
|
|
strcat(line, " ");
|
|
|
|
e = e->next;
|
|
|
|
}
|
2002-01-09 01:03:10 +00:00
|
|
|
line[strlen(line)-1] = 0; /* get rid of trailing space */
|
|
|
|
return line;
|
|
|
|
}
|
2002-02-21 18:53:23 +00:00
|
|
|
|
|
|
|
void
|
2008-03-06 16:06:59 +00:00
|
|
|
util_fatal(const char *fmt, ...)
|
2002-02-21 18:53:23 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
fprintf(stderr, "error: ");
|
|
|
|
vfprintf(stderr, fmt, ap);
|
|
|
|
fprintf(stderr, "\nAborting.\n");
|
|
|
|
va_end(ap);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-03-06 16:06:59 +00:00
|
|
|
util_error(const char *fmt, ...)
|
2002-02-21 18:53:23 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
fprintf(stderr, "error: ");
|
|
|
|
vfprintf(stderr, fmt, ap);
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-03-06 16:06:59 +00:00
|
|
|
util_warn(const char *fmt, ...)
|
2002-02-21 18:53:23 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
fprintf(stderr, "warning: ");
|
|
|
|
vfprintf(stderr, fmt, ap);
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
va_end(ap);
|
|
|
|
}
|
2004-07-26 18:47:23 +00:00
|
|
|
|
2010-04-28 09:20:18 +00:00
|
|
|
int
|
|
|
|
util_getpass (char **lineptr, size_t *len, FILE *stream)
|
2010-04-18 07:47:16 +00:00
|
|
|
{
|
|
|
|
#define MAX_PASS_SIZE 128
|
|
|
|
char *buf;
|
|
|
|
int i;
|
2010-04-28 09:20:18 +00:00
|
|
|
#ifndef _WIN32
|
|
|
|
struct termios old, new;
|
|
|
|
|
|
|
|
fflush(stdout);
|
|
|
|
if (tcgetattr (fileno (stdout), &old) != 0)
|
|
|
|
return -1;
|
|
|
|
new = old;
|
|
|
|
new.c_lflag &= ~ECHO;
|
|
|
|
if (tcsetattr (fileno (stdout), TCSAFLUSH, &new) != 0)
|
|
|
|
return -1;
|
|
|
|
#endif
|
2010-04-18 07:47:16 +00:00
|
|
|
|
|
|
|
buf = calloc(1, MAX_PASS_SIZE);
|
|
|
|
if (!buf)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_PASS_SIZE - 1; i++) {
|
2010-04-28 09:20:18 +00:00
|
|
|
#ifndef _WIN32
|
|
|
|
buf[i] = getchar();
|
|
|
|
#else
|
2010-04-27 07:30:38 +00:00
|
|
|
buf[i] = _getch();
|
2010-04-28 09:20:18 +00:00
|
|
|
#endif
|
2010-04-18 07:47:16 +00:00
|
|
|
if (buf[i] == 0 || buf[i] == 3)
|
2010-04-28 09:20:18 +00:00
|
|
|
break;
|
2010-04-18 07:47:16 +00:00
|
|
|
if (buf[i] == '\n' || buf[i] == '\r')
|
|
|
|
break;
|
|
|
|
}
|
2010-04-28 09:20:18 +00:00
|
|
|
#ifndef _WIN32
|
|
|
|
tcsetattr (fileno (stdout), TCSAFLUSH, &old);
|
|
|
|
fputs("\n", stdout);
|
|
|
|
#endif
|
|
|
|
if (buf[i] == 0 || buf[i] == 3) {
|
|
|
|
free(buf);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-04-18 07:47:16 +00:00
|
|
|
buf[i] = 0;
|
|
|
|
|
2010-04-28 09:20:18 +00:00
|
|
|
if (*lineptr && (!len || *len < i+1)) {
|
|
|
|
free(*lineptr);
|
|
|
|
*lineptr = NULL;
|
|
|
|
}
|
|
|
|
|
2010-04-18 07:47:16 +00:00
|
|
|
if (*lineptr) {
|
2010-04-28 09:20:18 +00:00
|
|
|
memcpy(*lineptr,buf,i+1);
|
|
|
|
memset(buf, 0, MAX_PASS_SIZE);
|
|
|
|
free(buf);
|
2010-04-18 07:47:16 +00:00
|
|
|
} else {
|
|
|
|
*lineptr = buf;
|
|
|
|
if (len)
|
|
|
|
*len = MAX_PASS_SIZE;
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|