diff options
Diffstat (limited to 'crypto/heimdal/lib/asn1/asn1_print.c')
-rw-r--r-- | crypto/heimdal/lib/asn1/asn1_print.c | 217 |
1 files changed, 133 insertions, 84 deletions
diff --git a/crypto/heimdal/lib/asn1/asn1_print.c b/crypto/heimdal/lib/asn1/asn1_print.c index d3199e8..e00bf10 100644 --- a/crypto/heimdal/lib/asn1/asn1_print.c +++ b/crypto/heimdal/lib/asn1/asn1_print.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -37,63 +37,30 @@ #include <sys/stat.h> #include <getarg.h> #include <err.h> +#include <der.h> -RCSID("$Id: asn1_print.c,v 1.11 2002/08/29 20:45:35 assar Exp $"); +RCSID("$Id: asn1_print.c 19539 2006-12-28 17:15:05Z lha $"); -const char *class_names[] = { - "UNIV", /* 0 */ - "APPL", /* 1 */ - "CONTEXT", /* 2 */ - "PRIVATE" /* 3 */ -}; - -const char *type_names[] = { - "PRIM", /* 0 */ - "CONS" /* 1 */ -}; +static int indent_flag = 1; -const char *tag_names[] = { - NULL, /* 0 */ - NULL, /* 1 */ - "Integer", /* 2 */ - "BitString", /* 3 */ - "OctetString", /* 4 */ - "Null", /* 5 */ - "ObjectID", /* 6 */ - NULL, /* 7 */ - NULL, /* 8 */ - NULL, /* 9 */ - NULL, /* 10 */ - NULL, /* 11 */ - NULL, /* 12 */ - NULL, /* 13 */ - NULL, /* 14 */ - NULL, /* 15 */ - "Sequence", /* 16 */ - "Set", /* 17 */ - NULL, /* 18 */ - "PrintableString", /* 19 */ - NULL, /* 20 */ - NULL, /* 21 */ - "IA5String", /* 22 */ - "UTCTime", /* 23 */ - "GeneralizedTime", /* 24 */ - NULL, /* 25 */ - "VisibleString", /* 26 */ - "GeneralString" /* 27 */ -}; +static unsigned long indefinite_form_loop; +static unsigned long indefinite_form_loop_max = 10000; -static int +static size_t loop (unsigned char *buf, size_t len, int indent) { + unsigned char *start_buf = buf; + while (len > 0) { int ret; Der_class class; Der_type type; - int tag; + unsigned int tag; size_t sz; size_t length; - int i; + size_t loop_length = 0; + int end_tag = 0; + const char *tagname; ret = der_get_tag (buf, len, &class, &type, &tag, &sz); if (ret) @@ -103,42 +70,101 @@ loop (unsigned char *buf, size_t len, int indent) (unsigned)sz, (unsigned)len); buf += sz; len -= sz; - for (i = 0; i < indent; ++i) - printf (" "); - printf ("%s %s ", class_names[class], type_names[type]); - if (tag_names[tag]) - printf ("%s = ", tag_names[tag]); + if (indent_flag) { + int i; + for (i = 0; i < indent; ++i) + printf (" "); + } + printf ("%s %s ", der_get_class_name(class), der_get_type_name(type)); + tagname = der_get_tag_name(tag); + if (class == ASN1_C_UNIV && tagname != NULL) + printf ("%s = ", tagname); else printf ("tag %d = ", tag); ret = der_get_length (buf, len, &length, &sz); if (ret) errx (1, "der_get_tag: %s", error_message (ret)); + if (sz > len) + errx (1, "unreasonable tag length (%u) > %u", + (unsigned)sz, (unsigned)len); buf += sz; len -= sz; - - if (class == CONTEXT) { - printf ("[%d]\n", tag); - loop (buf, length, indent); - } else if (class == UNIV) { + if (length == ASN1_INDEFINITE) { + if ((class == ASN1_C_UNIV && type == PRIM && tag == UT_OctetString) || + (class == ASN1_C_CONTEXT && type == CONS) || + (class == ASN1_C_UNIV && type == CONS && tag == UT_Sequence) || + (class == ASN1_C_UNIV && type == CONS && tag == UT_Set)) { + printf("*INDEFINITE FORM*"); + } else { + fflush(stdout); + errx(1, "indef form used on unsupported object"); + } + end_tag = 1; + if (indefinite_form_loop > indefinite_form_loop_max) + errx(1, "indefinite form used recursively more then %lu " + "times, aborting", indefinite_form_loop_max); + indefinite_form_loop++; + length = len; + } else if (length > len) { + printf("\n"); + fflush(stdout); + errx (1, "unreasonable inner length (%u) > %u", + (unsigned)length, (unsigned)len); + } + if (class == ASN1_C_CONTEXT || class == ASN1_C_APPL) { + printf ("%lu bytes [%u]", (unsigned long)length, tag); + if (type == CONS) { + printf("\n"); + loop_length = loop (buf, length, indent + 2); + } else { + printf(" IMPLICIT content\n"); + } + } else if (class == ASN1_C_UNIV) { switch (tag) { + case UT_EndOfContent: + printf (" INDEFINITE length was %lu\n", + (unsigned long)(buf - start_buf)); + break; + case UT_Set : case UT_Sequence : - printf ("{\n"); - loop (buf, length, indent + 2); - for (i = 0; i < indent; ++i) - printf (" "); - printf ("}\n"); + printf ("%lu bytes {\n", (unsigned long)length); + loop_length = loop (buf, length, indent + 2); + if (indent_flag) { + int i; + for (i = 0; i < indent; ++i) + printf (" "); + printf ("}\n"); + } else + printf ("} indent = %d\n", indent / 2); break; case UT_Integer : { int val; - ret = der_get_int (buf, length, &val, NULL); - if (ret) - errx (1, "der_get_int: %s", error_message (ret)); - printf ("integer %d\n", val); + if (length <= sizeof(val)) { + ret = der_get_integer (buf, length, &val, NULL); + if (ret) + errx (1, "der_get_integer: %s", error_message (ret)); + printf ("integer %d\n", val); + } else { + heim_integer vali; + char *p; + + ret = der_get_heim_integer(buf, length, &vali, NULL); + if (ret) + errx (1, "der_get_heim_integer: %s", + error_message (ret)); + ret = der_print_hex_heim_integer(&vali, &p); + if (ret) + errx (1, "der_print_hex_heim_integer: %s", + error_message (ret)); + printf ("BIG NUM integer: length %lu %s\n", + (unsigned long)length, p); + free(p); + } break; } case UT_OctetString : { - octet_string str; + heim_octet_string str; int i; unsigned char *uc; @@ -147,15 +173,17 @@ loop (unsigned char *buf, size_t len, int indent) errx (1, "der_get_octet_string: %s", error_message (ret)); printf ("(length %lu), ", (unsigned long)length); uc = (unsigned char *)str.data; - for (i = 0; i < 16; ++i) + for (i = 0; i < min(16,length); ++i) printf ("%02x", uc[i]); printf ("\n"); free (str.data); break; } case UT_GeneralizedTime : - case UT_GeneralString : { - general_string str; + case UT_GeneralString : + case UT_PrintableString : + case UT_VisibleString : { + heim_general_string str; ret = der_get_general_string (buf, length, &str, NULL); if (ret) @@ -166,18 +194,29 @@ loop (unsigned char *buf, size_t len, int indent) break; } case UT_OID: { - oid o; - int i; + heim_oid o; + char *p; ret = der_get_oid(buf, length, &o, NULL); if (ret) errx (1, "der_get_oid: %s", error_message (ret)); + ret = der_print_heim_oid(&o, '.', &p); + der_free_oid(&o); + if (ret) + errx (1, "der_print_heim_oid: %s", error_message (ret)); + printf("%s\n", p); + free(p); + + break; + } + case UT_Enumerated: { + int num; + + ret = der_get_integer (buf, length, &num, NULL); + if (ret) + errx (1, "der_get_enum: %s", error_message (ret)); - for (i = 0; i < o.length ; i++) - printf("%d%s", o.components[i], - i < o.length - 1 ? "." : ""); - printf("\n"); - free_oid(&o); + printf("%u\n", num); break; } default : @@ -185,6 +224,17 @@ loop (unsigned char *buf, size_t len, int indent) break; } } + if (end_tag) { + if (loop_length == 0) + errx(1, "zero length INDEFINITE data ? indent = %d\n", + indent / 2); + if (loop_length < length) + length = loop_length; + if (indefinite_form_loop == 0) + errx(1, "internal error in indefinite form loop detection"); + indefinite_form_loop--; + } else if (loop_length) + errx(1, "internal error for INDEFINITE form"); buf += length; len -= length; } @@ -205,21 +255,20 @@ doit (const char *filename) if (fstat (fd, &sb) < 0) err (1, "stat %s", filename); len = sb.st_size; - buf = malloc (len); - if (buf == NULL) - err (1, "malloc %u", (unsigned)len); + buf = emalloc (len); if (read (fd, buf, len) != len) errx (1, "read failed"); close (fd); ret = loop (buf, len, 0); free (buf); - return ret; + return 0; } static int version_flag; static int help_flag; struct getargs args[] = { + { "indent", 0, arg_negative_flag, &indent_flag }, { "version", 0, arg_flag, &version_flag }, { "help", 0, arg_flag, &help_flag } }; @@ -235,11 +284,11 @@ usage(int code) int main(int argc, char **argv) { - int optind = 0; + int optidx = 0; setprogname (argv[0]); initialize_asn1_error_table (); - if(getarg(args, num_args, argc, argv, &optind)) + if(getarg(args, num_args, argc, argv, &optidx)) usage(1); if(help_flag) usage(0); @@ -247,8 +296,8 @@ main(int argc, char **argv) print_version(NULL); exit(0); } - argv += optind; - argc -= optind; + argv += optidx; + argc -= optidx; if (argc != 1) usage (1); return doit (argv[0]); |