opensc/src/tools/dnie-tool.c

232 lines
6.0 KiB
C

/*
* dnie-tool.c: DNIe tool
*
* Copyright (C) 2011 Juan Antonio Martinez <jonsito@terra.es>
*
* Based on file rutoken-tool.c from Pavel Mironchik <rutoken@rutoken.ru>
* and Eugene Hermann <rutoken@rutoken.ru>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include "libopensc/opensc.h"
#include "libopensc/errors.h"
#include "libopensc/cardctl.h"
#include "libopensc/cards.h"
#include "libopensc/pkcs15.h"
#include "util.h"
/* win32 needs this in open(2) */
#ifndef O_BINARY
#define O_BINARY 0
#endif
static const char *app_name = "dnie-tool";
#define OP_NONE 0 /* no operation requested */
#define OP_GET_DATA 1 /* retrieve DNIe number, apellidos, nombre */
#define OP_GET_IDESP 2 /* retrieve IDESP */
#define OP_GET_VERSION 4 /* retrieve DNIe version number */
#define OP_GET_SERIALNR 8 /* Get SerialNumber */
static const struct option options[] = {
{"reader", 1, NULL, 'r'},
{"wait", 0, NULL, 'w'},
{"pin", 1, NULL, 'p'},
{"idesp", 0, NULL, 'i'},
{"version", 0, NULL, 'V'},
{"data", 0, NULL, 'd'},
{"serial", 0, NULL, 's'},
{"all", 0, NULL, 'a'},
{"verbose", 0, NULL, 'v'},
{NULL, 0, NULL, 0 }
};
static const char *option_help[] = {
"Uses reader number <arg> [0]",
"Wait for a card to be inserted",
"Specify PIN",
"Retrieve IDESP",
"Gets DNIe software version",
"Show DNIe number, Name, and SurName",
"Show DNIe serial number",
"Display all the information available",
"Verbose operation. Use several times to enable debug output."
};
/* Get DNIe device extra information */
int main(int argc, char* argv[])
{
int opt_wait = 0;
const char *opt_pin = NULL;
const char *opt_reader = NULL;
int opt_operation = OP_NONE;
int verbose = 0;
int err = 0;
sc_context_t *ctx = NULL;
sc_context_param_t ctx_param;
sc_card_t *card = NULL;
int c, r;
char *data[] = { NULL, NULL, NULL, NULL, NULL };
sc_serial_number_t serial;
while ((c = getopt_long(argc, argv, "r:wp:iVdsav", options, (int *) 0)) != -1) {
switch (c) {
case 'r':
opt_reader = optarg;
break;
case 'w':
opt_wait = 1;
break;
case 'p':
util_get_pin(optarg, &opt_pin);
break;
case 'i':
opt_operation |= OP_GET_IDESP;
break;
case 'V':
opt_operation |= OP_GET_VERSION;
break;
case 'd':
opt_operation |= OP_GET_DATA;
break;
case 's':
opt_operation |= OP_GET_SERIALNR;
break;
case 'a':
opt_operation = OP_GET_IDESP | OP_GET_VERSION | OP_GET_DATA | OP_GET_SERIALNR;
break;
case 'v':
verbose++;
break;
default:
util_print_usage_and_die(app_name, options, option_help, NULL);
}
}
memset(&ctx_param, 0, sizeof(ctx_param));
ctx_param.app_name = app_name;
r = sc_context_create(&ctx, &ctx_param);
if (r) {
fprintf(stderr, "Error: Failed to establish context: %s\n",
sc_strerror(r));
err = -1;
goto dnie_tool_end;
}
/* force DNIe card driver */
err = sc_set_card_driver(ctx, "dnie");
if (err) {
fprintf(stderr, "DNIe card driver not found!\n");
err = -1;
goto dnie_tool_end;
}
if (util_connect_card(ctx, &card, opt_reader, opt_wait, verbose) ) {
fprintf(stderr, "Error: Cannot connect with card\n");
err = -1;
goto dnie_tool_end;
}
/* fail if card is not a DNIe card */
if (card->type < SC_CARD_TYPE_DNIE_BASE || card->type >= SC_CARD_TYPE_DNIE_BASE+1000) {
fprintf(stderr, "Card type %X: not a DNIe card\n", card->type);
err = -1;
goto dnie_tool_end;
}
if ( opt_pin ) {
int tries_left;
/* verify */
r = sc_verify(card, SC_AC_CHV, 0,
(u8*)opt_pin, strlen(opt_pin), &tries_left);
if (r) {
fprintf(stderr, "Error: PIN verification failed: %s",
sc_strerror(r));
if (r == SC_ERROR_PIN_CODE_INCORRECT)
fprintf(stderr, " (tries left %d)", tries_left);
putc('\n', stderr);
err=-1;
goto dnie_tool_end;
}
}
if (opt_operation & (OP_GET_DATA | OP_GET_IDESP | OP_GET_VERSION | OP_GET_SERIALNR)) {
r = sc_card_ctl(card, SC_CARDCTL_DNIE_GET_INFO, data);
if ( r != SC_SUCCESS ) {
fprintf(stderr, "Error: Get info failed: %s\n", sc_strerror(r));
err = -1;
goto dnie_tool_end;
}
if (opt_operation & OP_GET_DATA) {
printf("DNIe Number: %s\n",data[0]);
printf("Surname: %s\n",data[1]);
printf("Name: %s\n",data[2]);
}
if (opt_operation & OP_GET_IDESP) {
if (data[3]==NULL)
printf("IDESP: (Not available)\n");
else printf("IDESP: %s\n",data[3]);
}
if (opt_operation & OP_GET_VERSION) {
if (data[4]==NULL)
printf("DNIe Version: (Not available)\n");
else printf("DNIe Version: %s\n",data[4]);
}
if (opt_operation & OP_GET_SERIALNR) {
r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
if ( r != SC_SUCCESS ) {
fprintf(stderr,"Error: Get serial failed: %s\n",sc_strerror(r));
err = -1;
goto dnie_tool_end;
}
printf("Serial number: ");
util_hex_dump(stdout, serial.value, serial.len, NULL);
putchar('\n');
}
}
else {
fprintf(stderr,"Error: No operation specified");
err = -1;
}
dnie_tool_end:
if (card) {
/* sc_lock and sc_connect_card in util_connect_card */
sc_unlock(card);
sc_disconnect_card(card);
}
sc_release_context(ctx);
return err;
}