OpenPGP: extend openpgp-tool

This commit is contained in:
Peter Marschall 2012-05-26 18:52:05 +02:00 committed by Viktor Tarasov
parent c58e94810b
commit 8238239852
1 changed files with 117 additions and 73 deletions

View File

@ -33,6 +33,9 @@
#include "libopensc/cards.h"
#include "util.h"
#define OPT_RAW 256
#define OPT_PRETTY 257
/* define structures */
struct ef_name_map {
const char *name;
@ -43,46 +46,64 @@ struct ef_name_map {
/* declare functions */
static void show_version(void);
static void show_help(void);
static char *prettify_name(char *str);
static char *prettify_language(char *str);
static char *prettify_gender(char *str);
static void display_data(const struct ef_name_map *mapping, char *value);
static int decode_options(int argc, char **argv);
static void do_openpgp(sc_card_t *card);
static int do_userinfo(sc_card_t *card);
static int read_transp(sc_card_t *card, const char *pathstring, unsigned char *buf, int buflen);
static void bintohex(char *buf, int len);
/* define global variables */
static int actions = 0;
static char *opt_reader = NULL;
static int stats = 0;
static int opt_wait = 0;
static int opt_raw = 0;
static int verbose = 0;
static int opt_userinfo = 0;
static int opt_cardinfo = 0;
static char *exec_program = NULL;
static int exit_status = EXIT_FAILURE;
static const char *app_name = "openpgp-tool";
static const struct option options[] = {
{ "reader", required_argument, NULL, 'r' },
{ "print", no_argument, NULL, 'p' },
{ "exec", required_argument, NULL, 'x' },
{ "stats", no_argument, NULL, 't' },
{ "help", no_argument, NULL, 'h' },
{ "wait", no_argument, NULL, 'w' },
{ "version", no_argument, NULL, 'V' },
{ "reader", required_argument, NULL, 'r' },
{ "wait", no_argument, NULL, 'w' },
{ "exec", required_argument, NULL, 'x' },
{ "raw", no_argument, NULL, OPT_RAW },
{ "pretty", no_argument, NULL, OPT_PRETTY },
{ "card-info", no_argument, NULL, 'C' },
{ "user-info", no_argument, NULL, 'U' },
{ "help", no_argument, NULL, 'h' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
/* Probably not used, but needed to build on Windows */
static const char *app_name = "openpgp-tool";
static const char *option_help[] = {
/* r */ "Use reader number <arg> [0]",
/* w */ "Wait for card insertion",
/* x */ "Execute program <arg> with data in env vars",
"Print values in raw format",
"Print values in pretty format",
/* C */ NULL,
/* U */ "Show card holder information",
/* h */ "Print this help message",
/* v */ "Verbose operation. Use several times to enable debug output.",
/* V */ "Show version number"
};
static const struct ef_name_map openpgp_data[] = {
{ "Account", "OPENGPG_ACCOUNT", "3F00:005E", NULL },
{ "URL", "OPENPGP_URL", "3F00:5F50", NULL },
{ "Name", "OPENPGP_NAME", "3F00:0065:005B", NULL },
{ "Account", "OPENGPG_ACCOUNT", "3F00:005E", NULL },
{ "URL", "OPENPGP_URL", "3F00:5F50", NULL },
{ "Name", "OPENPGP_NAME", "3F00:0065:005B", prettify_name },
{ "Language", "OPENPGP_LANG", "3F00:0065:5F2D", prettify_language },
{ "Gender", "OPENPGP_GENDER", "3F00:0065:5F35", prettify_gender },
{ "DO 0101", "OPENPGP_DO0101", "3F00:0101", NULL },
{ "DO 0102", "OPENPGP_DO0102", "3F00:0102", NULL },
// { "DO 0103", "OPENPGP_DO0103", "3F00:0103", NULL },
// { "DO 0104", "OPENPGP_DO0104", "3F00:0104", NULL },
{ "DO 0101", "OPENPGP_DO0101", "3F00:0101", NULL },
{ "DO 0102", "OPENPGP_DO0102", "3F00:0102", NULL },
// { "DO 0103", "OPENPGP_DO0103", "3F00:0103", NULL },
// { "DO 0104", "OPENPGP_DO0104", "3F00:0104", NULL },
{ NULL, NULL, NULL, NULL }
};
@ -97,17 +118,25 @@ static void show_version(void)
}
static void show_help(void)
/* prettify card holder's name */
static char *prettify_name(char *str)
{
show_version();
fprintf(stderr,
"-h --help - show this text and exit\n"
"-v --version - show version and exit\n"
"-r --reader - the reader to use\n"
"-w --wait - wait for a card to be inserted\n"
"-p --print - print the datafile\n"
"-t --stats - show usage counts of keys\n"
"-x --exec - execute a program with data in env vars.\n");
if (str != NULL) {
char *src = str;
char *dst = str;
while (*src != '\0') {
*dst = *src++;
if (*dst == '<') {
if (*src == '<')
src++;
*dst = ' ';
}
dst++;
}
*dst = '\0';
}
return str;
}
@ -122,7 +151,7 @@ static char *prettify_language(char *str)
case 6: memmove(str+5, str+4, 1+strlen(str+4));
str[4] = ',';
/* fall through */
case 4: memmove(str+3, str+2, 1+strlen(str+2));
case 4: memmove(str+3, str+2, 1+strlen(str+2));
str[2] = ',';
/* fall through */
case 2: return str;
@ -150,7 +179,7 @@ static char *prettify_gender(char *str)
static void display_data(const struct ef_name_map *mapping, char *value)
{
if (mapping != NULL && value != NULL) {
if (mapping->prettify_value != NULL)
if (mapping->prettify_value != NULL && !opt_raw)
value = mapping->prettify_value(value);
if (value != NULL) {
@ -179,43 +208,53 @@ static int decode_options(int argc, char **argv)
{
int c;
while ((c = getopt_long(argc, argv,"pwtr:x:hV", options, (int *) 0)) != EOF) {
while ((c = getopt_long(argc, argv,"r:x:CUhwvV", options, (int *) 0)) != EOF) {
switch (c) {
case 'r':
opt_reader = optarg;
break;
case 't':
stats = !stats;
break;
case 'x':
if (exec_program)
free(exec_program);
exec_program = strdup(optarg);
break;
case 'h':
show_help();
exit(EXIT_SUCCESS);
case OPT_RAW:
opt_raw = 1;
break;
case 'p':
case OPT_PRETTY:
opt_raw = 0;
break;
case 'C':
opt_cardinfo++;
actions++;;
break;
case 'U':
opt_userinfo++;
actions++;;
break;
case 'h':
util_print_usage_and_die(app_name, options, option_help);
break;
case 'w':
opt_wait = 1;
break;
case 'v':
verbose++;
break;
case 'V':
show_version();
exit(EXIT_SUCCESS);
break;
default:
show_help();
exit(EXIT_FAILURE);
util_print_usage_and_die(app_name, options, option_help);
}
}
return(optind);
return optind;
}
static void do_openpgp(sc_card_t *card)
static int do_userinfo(sc_card_t *card)
{
int i;
unsigned char buf[2048];
@ -233,7 +272,7 @@ static void do_openpgp(sc_card_t *card)
if (r) {
fprintf(stderr, "Failed to select EF %s: %s\n",
openpgp_data[i].ef, sc_strerror(r));
goto out;
return EXIT_FAILURE;
}
count = file->size;
@ -244,12 +283,12 @@ static void do_openpgp(sc_card_t *card)
if (r < 0) {
fprintf(stderr, "%s: read failed - %s\n",
openpgp_data[i].ef, sc_strerror(r));
goto out;
return EXIT_FAILURE;
}
if (r != c) {
fprintf(stderr, "%s: expecting %d, got only %d bytes\n",
openpgp_data[i].ef, c, r);
goto out;
return EXIT_FAILURE;
}
offset += r;
@ -263,10 +302,7 @@ static void do_openpgp(sc_card_t *card)
}
}
exit_status = EXIT_SUCCESS;
out:
return;
return EXIT_SUCCESS;
}
@ -311,9 +347,10 @@ int main(int argc, char **argv)
sc_context_param_t ctx_param;
sc_card_t *card = NULL;
int r;
int argind = 1;
int argind = 0;
int exit_status = EXIT_FAILURE;
/* get options */
/* decode options */
argind = decode_options(argc, argv);
/* connect to the card */
@ -323,35 +360,41 @@ int main(int argc, char **argv)
r = sc_context_create(&ctx, &ctx_param);
if (r) {
fprintf(stderr, "Failed to establish context: %s\n",
util_fatal("failed to establish context: %s\n",
sc_strerror(r));
return 1;
}
r = util_connect_card(ctx, &card, opt_reader, opt_wait, 0);
if (r) {
fprintf(stderr, "Failed to connect to card: %s\n",
sc_strerror(r));
return 1;
return EXIT_FAILURE;
}
/* Check card type */
if (verbose > 1) {
ctx->debug = verbose;
sc_ctx_log_to_file(ctx, "stderr");
}
r = util_connect_card(ctx, &card, opt_reader, opt_wait, verbose);
if (r) {
util_fatal("failed to connect to card: %s\n",
sc_strerror(r));
return EXIT_FAILURE;
}
/* check card type */
if ((card->type != SC_CARD_TYPE_OPENPGP_V1) &&
(card->type != SC_CARD_TYPE_OPENPGP_V2)) {
fprintf(stderr, "Not an OpenPGP card!\n");
util_error("not an OpenPGP card");
exit_status = EXIT_FAILURE;
goto out;
}
do_openpgp(card);
/* fail on too many arguments */
if (argind > argc)
show_help();
util_print_usage_and_die(app_name, options, option_help);
if (strcmp(argv[argind], "load") == 0) {
++argind;
}
else if (strcmp(argv[argind], "store") == 0) {
++argind;
}
/* set default action */
if (!actions)
opt_userinfo = 1;
if (opt_userinfo)
exit_status |= do_userinfo(card);
if (exec_program) {
char *const largv[] = {exec_program, NULL};
@ -361,12 +404,13 @@ int main(int argc, char **argv)
execv(exec_program, largv);
/* we should not get here */
perror("execv()");
exit(1);
exit(EXIT_FAILURE);
}
out:
sc_unlock(card);
sc_disconnect_card(card);
sc_release_context(ctx);
exit(exit_status);
}