opensc-explorer: extend do_asn1() to decode records
Have do_asn1() accept an optional parameter indicating a record number. If this is given and the file is a record-oriented file, then ASN.1-decode the record requested.
This commit is contained in:
parent
d345c65a5d
commit
45e7039940
|
@ -166,11 +166,16 @@
|
|||
<term>
|
||||
<command>asn1</command>
|
||||
<replaceable>file-id</replaceable>
|
||||
<arg choice="opt"><replaceable>rec-no</replaceable></arg>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Parse and print the ASN.1 encoded content of the working EF
|
||||
specified by <replaceable>file-id</replaceable>.
|
||||
If the optional parameter
|
||||
<replaceable>rec-no</replaceable> is given and the file is
|
||||
a record-oriented EF, parse and print only the record
|
||||
indicated by this parameter.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "libopensc/cardctl.h"
|
||||
#include "libopensc/cards.h"
|
||||
#include "libopensc/log.h"
|
||||
#include "libopensc/internal.h"
|
||||
#include "common/compat_strlcpy.h"
|
||||
#include <getopt.h>
|
||||
#include "util.h"
|
||||
|
@ -205,8 +206,8 @@ static struct command cmds[] = {
|
|||
"apdu", "<data> ...",
|
||||
"send a custom apdu command" },
|
||||
{ do_asn1,
|
||||
"asn1", "[<file-id>]",
|
||||
"decode an ASN.1 file" },
|
||||
"asn1", "[<file-id> [<rec-no>]]",
|
||||
"decode an ASN.1 file or record" },
|
||||
{ do_sm,
|
||||
"sm", "{open|close}",
|
||||
"call SM 'open' or 'close' handlers, if available"},
|
||||
|
@ -2064,10 +2065,9 @@ static int do_asn1(int argc, char **argv)
|
|||
sc_path_t path;
|
||||
sc_file_t *file = NULL;
|
||||
int not_current = 1;
|
||||
size_t len;
|
||||
unsigned char *buf = NULL;
|
||||
u8 buf[SC_MAX_EXT_APDU_DATA_SIZE];
|
||||
|
||||
if (argc > 1)
|
||||
if (argc > 2)
|
||||
return usage(do_asn1);
|
||||
|
||||
/* select file */
|
||||
|
@ -2081,7 +2081,7 @@ static int do_asn1(int argc, char **argv)
|
|||
r = sc_select_file(card, &path, &file);
|
||||
sc_unlock(card);
|
||||
if (r) {
|
||||
check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file);
|
||||
check_ret(r, SC_AC_OP_SELECT, "Unable to select file", current_file);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
|
@ -2090,34 +2090,59 @@ static int do_asn1(int argc, char **argv)
|
|||
not_current = 0;
|
||||
}
|
||||
if (file->type != SC_FILE_TYPE_WORKING_EF) {
|
||||
fprintf(stderr, "only working EFs may be read\n");
|
||||
fprintf(stderr, "Only working EFs may be read\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* read */
|
||||
if (file->ef_structure != SC_FILE_EF_TRANSPARENT) {
|
||||
fprintf(stderr, "only transparent file type is supported at the moment\n");
|
||||
goto err;
|
||||
if (file->ef_structure == SC_FILE_EF_TRANSPARENT) {
|
||||
size_t size = (file->size > 0) ? file->size : sizeof(buf);
|
||||
|
||||
if (argc > 1) {
|
||||
fprintf(stderr, "Transparent EFs do not support records\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = sc_lock(card);
|
||||
if (r == SC_SUCCESS)
|
||||
r = sc_read_binary(card, 0, buf, MIN(size, sizeof(buf)), 0);
|
||||
sc_unlock(card);
|
||||
if (r < 0) {
|
||||
check_ret(r, SC_AC_OP_READ, "read failed", file);
|
||||
goto err;
|
||||
}
|
||||
if ((size_t) r != file->size) {
|
||||
fprintf(stderr, "WARNING: expecting %"SC_FORMAT_LEN_SIZE_T"u, got %d bytes.\n",
|
||||
file->size, r);
|
||||
/* some cards return a bogus value for file length. As
|
||||
* long as the actual length is not higher than the expected
|
||||
* length, continue */
|
||||
if ((size_t) r > file->size)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
len = file->size;
|
||||
buf = calloc(1, len);
|
||||
if (!buf) {
|
||||
goto err;
|
||||
}
|
||||
r = sc_lock(card);
|
||||
if (r == SC_SUCCESS)
|
||||
r = sc_read_binary(card, 0, buf, len, 0);
|
||||
sc_unlock(card);
|
||||
if (r < 0) {
|
||||
check_ret(r, SC_AC_OP_READ, "read failed", file);
|
||||
goto err;
|
||||
}
|
||||
if ((size_t)r != len) {
|
||||
printf("WARNING: expecting %lu, got %d bytes.\n", (unsigned long) len, r);
|
||||
/* some cards return a bogus value for file length. As
|
||||
* long as the actual length is not higher than the expected
|
||||
* length, continue */
|
||||
if(r > (signed)len) {
|
||||
else { /* record-oriented file */
|
||||
unsigned int rec = 0;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Record-oriented EFs require parameter record number.\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
rec = (unsigned int) strtoul(argv[1], NULL, 10);
|
||||
if (rec < 1 || rec > file->record_count) {
|
||||
fprintf(stderr, "Invalid record number %u.\n", rec);
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = sc_lock(card);
|
||||
if (r == SC_SUCCESS)
|
||||
r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR);
|
||||
else
|
||||
r = SC_ERROR_READER_LOCKED;
|
||||
sc_unlock(card);
|
||||
if (r < 0) {
|
||||
check_ret(r, SC_AC_OP_READ, "Read failed", file);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
@ -2127,8 +2152,6 @@ static int do_asn1(int argc, char **argv)
|
|||
|
||||
err = 0;
|
||||
err:
|
||||
if (buf)
|
||||
free(buf);
|
||||
if (not_current) {
|
||||
sc_file_free(file);
|
||||
select_current_path_or_die();
|
||||
|
|
Loading…
Reference in New Issue