OpenPGP: extend openpgp-tool
This commit is contained in:
parent
c58e94810b
commit
8238239852
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue