lib/gssapi/spnego: _gss_negoex_init do not leak error message
[heimdal.git] / lib / asn1 / asn1_print.c
blob40c37fbbb9461c040f9cc43d2b17dcb23bb0a86a
1 /*
2 * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
36 #include "der_locl.h"
37 #include <com_err.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <dlfcn.h>
41 #include <getarg.h>
42 #include <err.h>
43 #include <der.h>
44 #include "cms_asn1.h"
45 #include "digest_asn1.h"
46 #include "krb5_asn1.h"
47 #include "kx509_asn1.h"
48 #include "ocsp_asn1.h"
49 #include "pkcs10_asn1.h"
50 #include "pkcs12_asn1.h"
51 #include "pkcs8_asn1.h"
52 #include "pkcs9_asn1.h"
53 #include "pkinit_asn1.h"
54 #include "rfc2459_asn1.h"
55 #include "rfc4108_asn1.h"
56 #ifdef ASN1_PRINT_SUPPORTED
57 #include "x690sample_template_asn1.h"
58 #else
59 #include "x690sample_asn1.h"
60 #endif
62 static int quiet_flag = 0;
63 static int print_flag = 1;
64 static int test_copy_flag;
65 static int test_encode_flag;
66 static int sequence_flag;
67 static int try_all_flag;
68 static int indent_flag = 1;
69 static int inner_flag;
71 static unsigned long indefinite_form_loop;
72 static unsigned long indefinite_form_loop_max = 10000;
74 typedef size_t (*lengther)(void *);
75 typedef int (*copyer)(const void *, void *);
76 typedef int (*encoder)(unsigned char *, size_t, void *, size_t *);
77 typedef int (*decoder)(const unsigned char *, size_t, void *, size_t *);
78 typedef char *(*printer)(const void *, int);
79 typedef void (*releaser)(void *);
80 const struct types {
81 const char *name;
82 size_t sz;
83 copyer cpy;
84 lengther len;
85 decoder decode;
86 encoder encode;
87 printer print;
88 releaser release;
89 } types[] = {
90 #define ASN1_SYM_INTVAL(n, gn, gns, i)
91 #define ASN1_SYM_OID(n, gn, gns)
92 #ifdef ASN1_PRINT_SUPPORTED
93 #define ASN1_SYM_TYPE(n, gn, gns) \
94 { \
95 n, \
96 sizeof(gns), \
97 (copyer)copy_ ## gns, \
98 (lengther)length_ ## gns, \
99 (decoder)decode_ ## gns, \
100 (encoder)encode_ ## gns, \
101 (printer)print_ ## gns, \
102 (releaser)free_ ## gns, \
104 #else
105 #define ASN1_SYM_TYPE(n, gn, gns) \
107 n, \
108 sizeof(gns), \
109 (copyer)copy_ ## gns, \
110 (lengther)length_ ## gns, \
111 (decoder)decode_ ## gns, \
112 (encoder)encode_ ## gns, \
113 0, \
114 (releaser)free_ ## gns, \
116 #endif
117 #include "cms_asn1_syms.c"
118 #include "digest_asn1_syms.c"
119 #include "krb5_asn1_syms.c"
120 #include "kx509_asn1_syms.c"
121 #include "ocsp_asn1_syms.c"
122 #include "pkcs10_asn1_syms.c"
123 #include "pkcs12_asn1_syms.c"
124 #include "pkcs8_asn1_syms.c"
125 #include "pkcs9_asn1_syms.c"
126 #include "pkinit_asn1_syms.c"
127 #include "rfc2459_asn1_syms.c"
128 #include "rfc4108_asn1_syms.c"
129 #ifdef ASN1_PRINT_SUPPORTED
130 #include "x690sample_template_asn1_syms.c"
131 #else
132 #include "x690sample_asn1_syms.c"
133 #endif
136 struct types sorted_types[sizeof(types)/sizeof(types[0])];
138 static size_t
139 loop (unsigned char *buf, size_t len, int indent)
141 unsigned char *start_buf = buf;
143 while (len > 0) {
144 int ret;
145 Der_class class;
146 Der_type type;
147 unsigned int tag;
148 size_t sz;
149 size_t length;
150 size_t loop_length = 0;
151 int end_tag = 0;
152 const char *tagname;
154 ret = der_get_tag (buf, len, &class, &type, &tag, &sz);
155 if (ret)
156 errx (1, "der_get_tag: %s", error_message (ret));
157 if (sz > len)
158 errx (1, "unreasonable length (%u) > %u",
159 (unsigned)sz, (unsigned)len);
160 buf += sz;
161 len -= sz;
162 if (indent_flag) {
163 int i;
164 for (i = 0; i < indent; ++i)
165 printf (" ");
167 printf ("%s %s ", der_get_class_name(class), der_get_type_name(type));
168 tagname = der_get_tag_name(tag);
169 if (class == ASN1_C_UNIV && tagname != NULL)
170 printf ("%s = ", tagname);
171 else
172 printf ("tag %d = ", tag);
173 ret = der_get_length (buf, len, &length, &sz);
174 if (ret)
175 errx (1, "der_get_tag: %s", error_message (ret));
176 if (sz > len)
177 errx (1, "unreasonable tag length (%u) > %u",
178 (unsigned)sz, (unsigned)len);
179 buf += sz;
180 len -= sz;
181 if (length == ASN1_INDEFINITE) {
182 if ((class == ASN1_C_UNIV && type == PRIM && tag == UT_OctetString) ||
183 (class == ASN1_C_CONTEXT && type == CONS) ||
184 (class == ASN1_C_UNIV && type == CONS && tag == UT_Sequence) ||
185 (class == ASN1_C_UNIV && type == CONS && tag == UT_Set)) {
186 printf("*INDEFINITE FORM*");
187 } else {
188 fflush(stdout);
189 errx(1, "indef form used on unsupported object");
191 end_tag = 1;
192 if (indefinite_form_loop > indefinite_form_loop_max)
193 errx(1, "indefinite form used recursively more then %lu "
194 "times, aborting", indefinite_form_loop_max);
195 indefinite_form_loop++;
196 length = len;
197 } else if (length > len) {
198 printf("\n");
199 fflush(stdout);
200 errx (1, "unreasonable inner length (%u) > %u",
201 (unsigned)length, (unsigned)len);
203 if (class == ASN1_C_CONTEXT || class == ASN1_C_APPL) {
204 printf ("%lu bytes [%u]", (unsigned long)length, tag);
205 if (type == CONS) {
206 printf("\n");
207 loop_length = loop (buf, length, indent + 2);
208 } else {
209 printf(" IMPLICIT content\n");
211 } else if (class == ASN1_C_UNIV) {
212 switch (tag) {
213 case UT_EndOfContent:
214 printf (" INDEFINITE length was %lu\n",
215 (unsigned long)(buf - start_buf));
216 break;
217 case UT_Set :
218 case UT_Sequence :
219 printf ("%lu bytes {\n", (unsigned long)length);
220 loop_length = loop (buf, length, indent + 2);
221 if (indent_flag) {
222 int i;
223 for (i = 0; i < indent; ++i)
224 printf (" ");
225 printf ("}\n");
226 } else
227 printf ("} indent = %d\n", indent / 2);
228 break;
229 case UT_Integer : {
230 int val;
232 if (length <= sizeof(val)) {
233 ret = der_get_integer (buf, length, &val, NULL);
234 if (ret)
235 errx (1, "der_get_integer: %s", error_message (ret));
236 printf ("integer %d\n", val);
237 } else {
238 heim_integer vali;
239 char *p;
241 ret = der_get_heim_integer(buf, length, &vali, NULL);
242 if (ret)
243 errx (1, "der_get_heim_integer: %s",
244 error_message (ret));
245 ret = der_print_hex_heim_integer(&vali, &p);
246 if (ret)
247 errx (1, "der_print_hex_heim_integer: %s",
248 error_message (ret));
249 printf ("BIG NUM integer: length %lu %s\n",
250 (unsigned long)length, p);
251 free(p);
253 break;
255 case UT_OctetString : {
256 heim_octet_string str;
257 size_t i;
259 ret = der_get_octet_string (buf, length, &str, NULL);
260 if (ret)
261 errx (1, "der_get_octet_string: %s", error_message (ret));
262 printf ("(length %lu), ", (unsigned long)length);
264 if (inner_flag) {
265 Der_class class2;
266 Der_type type2;
267 unsigned int tag2;
269 ret = der_get_tag(str.data, str.length,
270 &class2, &type2, &tag2, &sz);
271 if (ret || sz > str.length ||
272 type2 != CONS || tag2 != UT_Sequence)
273 goto just_an_octet_string;
275 printf("{\n");
276 loop (str.data, str.length, indent + 2);
277 for (i = 0; i < indent; ++i)
278 printf (" ");
279 printf ("}\n");
281 } else {
282 unsigned char *uc;
284 just_an_octet_string:
285 uc = (unsigned char *)str.data;
286 for (i = 0; i < min(16,length); ++i)
287 printf ("%02x", uc[i]);
288 printf ("\n");
290 free (str.data);
291 break;
293 case UT_IA5String :
294 case UT_PrintableString : {
295 heim_printable_string str;
296 unsigned char *s;
297 size_t n;
299 memset(&str, 0, sizeof(str));
301 ret = der_get_printable_string (buf, length, &str, NULL);
302 if (ret)
303 errx (1, "der_get_general_string: %s",
304 error_message (ret));
305 s = str.data;
306 printf("\"");
307 for (n = 0; n < str.length; n++) {
308 if (isprint((int)s[n]))
309 printf ("%c", s[n]);
310 else
311 printf ("#%02x", s[n]);
313 printf("\"\n");
314 der_free_printable_string(&str);
315 break;
317 case UT_GeneralizedTime :
318 case UT_GeneralString :
319 case UT_VisibleString :
320 case UT_UTF8String : {
321 heim_general_string str;
323 ret = der_get_general_string (buf, length, &str, NULL);
324 if (ret)
325 errx (1, "der_get_general_string: %s",
326 error_message (ret));
327 printf ("\"%s\"\n", str);
328 free (str);
329 break;
331 case UT_OID: {
332 heim_oid o;
333 char *p;
335 ret = der_get_oid(buf, length, &o, NULL);
336 if (ret)
337 errx (1, "der_get_oid: %s", error_message (ret));
338 ret = der_print_heim_oid_sym(&o, '.', &p);
339 der_free_oid(&o);
340 if (ret)
341 errx (1, "der_print_heim_oid_sym: %s", error_message (ret));
342 printf("%s\n", p);
343 free(p);
345 break;
347 case UT_Enumerated: {
348 int num;
350 ret = der_get_integer (buf, length, &num, NULL);
351 if (ret)
352 errx (1, "der_get_enum: %s", error_message (ret));
354 printf("%u\n", num);
355 break;
357 default :
358 printf ("%lu bytes\n", (unsigned long)length);
359 break;
362 if (end_tag) {
363 if (loop_length == 0)
364 errx(1, "zero length INDEFINITE data ? indent = %d\n",
365 indent / 2);
366 if (loop_length < length)
367 length = loop_length;
368 if (indefinite_form_loop == 0)
369 errx(1, "internal error in indefinite form loop detection");
370 indefinite_form_loop--;
371 } else if (loop_length)
372 errx(1, "internal error for INDEFINITE form");
373 buf += length;
374 len -= length;
376 return 0;
379 static int
380 type_cmp(const void *va, const void *vb)
382 const struct types *ta = (const struct types *)va;
383 const struct types *tb = (const struct types *)vb;
385 return strcmp(ta->name, tb->name);
388 static int
389 dotype(unsigned char *buf, size_t len, char **argv, size_t *size)
391 const char *typename = "";
392 size_t matches = 0;
393 size_t sz;
394 size_t tried = 0;
395 size_t i = 0;
396 void *v;
397 int ret = 0;
399 *size = len;
401 memcpy(sorted_types, types, sizeof(types));
402 qsort(sorted_types,
403 sizeof(types)/sizeof(types[0]),
404 sizeof(types[0]),
405 type_cmp);
407 while ((try_all_flag && i < sizeof(types)/sizeof(types[0])) ||
408 (typename = (argv++)[0])) {
410 if (try_all_flag) {
411 typename = sorted_types[i].name;
412 } else {
413 size_t right = sizeof(types)/sizeof(types[0]) - 1;
414 size_t left = 0;
415 size_t mid = (left + right) >> 1;
416 int c = -1;
418 while (left <= right) {
419 mid = (left + right) >> 1;
420 c = strcmp(sorted_types[mid].name, typename);
421 if (c < 0)
422 left = mid + 1;
423 else if (c > 0)
424 right = mid - 1;
425 else
426 break;
428 if (c != 0)
429 errx(1, "Type %s not found", typename);
430 i = mid;
432 v = ecalloc(1, sorted_types[i].sz);
433 ret = sorted_types[i].decode(buf, len, v, &sz);
434 if (ret == 0) {
435 matches++;
436 if (!quiet_flag && sz == len) {
437 fprintf(stderr, "Match: %s\n", typename);
438 } else if (sequence_flag) {
439 *size = sz;
440 } else if (!quiet_flag) {
441 fprintf(stderr, "Prefix match: %s\n", typename);
443 if (print_flag) {
444 static int warned = 0;
446 if (!sorted_types[i].print) {
447 if (!warned)
448 warnx("Missing print support; try enabling / not "
449 "disabling ASN.1 templating in build "
450 "configuration");
451 warned = 1;
452 } else {
453 char *s;
455 s = sorted_types[i].print(v, indent_flag ? ASN1_PRINT_INDENT : 0);
456 if (!s)
457 err(1, "Could not print %s\n", typename);
458 if (!quiet_flag)
459 printf("%s\n", s);
460 free(s);
463 if (test_encode_flag) {
464 unsigned char *der = emalloc(sz);
465 size_t wants = sorted_types[i].len(v);
467 if (wants != sz)
468 errx(1, "Encoding will not round trip");
469 ret = sorted_types[i].encode(der + (sz - 1), sz, v, &sz);
470 if (ret != 0)
471 errx(1, "Encoding failed");
472 if (memcmp(buf, der, sz) != 0)
473 errx(1, "Encoding did not round trip");
474 free(der);
476 if (test_copy_flag) {
477 void *vcpy = ecalloc(1, sorted_types[i].sz);
479 ret = sorted_types[i].cpy(v, vcpy);
480 if (ret != 0)
481 errx(1, "Copy function failed");
482 if (test_encode_flag) {
483 unsigned char *der = emalloc(sz);
484 size_t wants = sorted_types[i].len(vcpy);
486 if (wants != sz)
487 errx(1, "Encoding of copy will not round trip");
488 ret = sorted_types[i].encode(der + (sz - 1), sz, vcpy, &sz);
489 if (ret != 0)
490 errx(1, "Encoding of copy failed");
491 if (memcmp(buf, der, sz) != 0)
492 errx(1, "Encoding of copy did not round trip");
493 free(der);
495 sorted_types[i].release(vcpy);
496 free(vcpy);
499 sorted_types[i].release(v);
500 free(v);
501 tried++;
502 i++;
504 if (ret == 0 && !try_all_flag && !argv[0])
505 return 0;
507 if (!try_all_flag && argv[0])
508 continue;
510 if (try_all_flag) {
511 if (i < sizeof(types)/sizeof(types[0]))
512 continue;
513 if (matches)
514 break;
516 if (tried > 1)
517 errx(1, "No type matched the input value");
519 /* XXX Use com_err */
520 switch (ret) {
521 case ASN1_BAD_TIMEFORMAT:
522 errx(1, "Could not decode and print data as type %s: "
523 "Bad time format", typename);
524 case ASN1_MISSING_FIELD:
525 errx(1, "Could not decode and print data as type %s: "
526 "Missing required field", typename);
527 case ASN1_MISPLACED_FIELD:
528 errx(1, "Could not decode and print data as type %s: "
529 "Fields out of order", typename);
530 case ASN1_TYPE_MISMATCH:
531 errx(1, "Could not decode and print data as type %s: "
532 "Type mismatch", typename);
533 case ASN1_OVERFLOW:
534 errx(1, "Could not decode and print data as type %s: "
535 "DER value too large", typename);
536 case ASN1_OVERRUN:
537 errx(1, "Could not decode and print data as type %s: "
538 "DER value too short", typename);
539 case ASN1_BAD_ID:
540 errx(1, "Could not decode and print data as type %s: "
541 "DER tag is unexpected", typename);
542 case ASN1_BAD_LENGTH:
543 errx(1, "Could not decode and print data as type %s: "
544 "DER length does not match value", typename);
545 case ASN1_BAD_FORMAT:
546 case ASN1_PARSE_ERROR:
547 errx(1, "Could not decode and print data as type %s: "
548 "DER badly formatted", typename);
549 case ASN1_EXTRA_DATA:
550 errx(1, "Could not decode and print data as type %s: "
551 "Extra data past end of end structure", typename);
552 case ASN1_BAD_CHARACTER:
553 errx(1, "Could not decode and print data as type %s: "
554 "Invalid character encoding in string", typename);
555 case ASN1_MIN_CONSTRAINT:
556 errx(1, "Could not decode and print data as type %s: "
557 "Too few elements", typename);
558 case ASN1_MAX_CONSTRAINT:
559 errx(1, "Could not decode and print data as type %s: "
560 "Too many elements", typename);
561 case ASN1_EXACT_CONSTRAINT:
562 errx(1, "Could not decode and print data as type %s: "
563 "Wrong count of elements", typename);
564 case ASN1_INDEF_OVERRUN:
565 errx(1, "Could not decode and print data as type %s: "
566 "BER indefinte encoding overun", typename);
567 case ASN1_INDEF_UNDERRUN:
568 errx(1, "Could not decode and print data as type %s: "
569 "BER indefinte encoding underun", typename);
570 case ASN1_GOT_BER:
571 errx(1, "Could not decode and print data as type %s: "
572 "BER encoding when DER expected", typename);
573 case ASN1_INDEF_EXTRA_DATA:
574 errx(1, "Could not decode and print data as type %s: "
575 "End-of-contents tag contains data", typename);
576 default:
577 errx(1, "Could not decode and print data as type %s", typename);
580 return 0;
583 static int
584 doit(char **argv)
586 int fd = open(argv[0], O_RDONLY);
587 struct stat sb;
588 unsigned char *buf;
589 size_t len;
590 int ret;
592 if(fd < 0)
593 err(1, "opening %s for read", argv[0]);
594 if (fstat (fd, &sb) < 0)
595 err(1, "stat %s", argv[0]);
596 len = sb.st_size;
597 buf = emalloc(len);
598 if (read(fd, buf, len) != len)
599 errx(1, "read failed");
600 close(fd);
602 argv++;
603 if (argv[0] || try_all_flag) {
604 size_t off = 0;
605 size_t sz = 0;
607 do {
608 ret = dotype(buf + off, len - off, argv, &sz);
609 off += sz;
610 } while (ret == 0 && sequence_flag && off < len);
611 } else {
612 ret = loop(buf, len, 0);
614 free(buf);
615 return ret;
619 static int list_types_flag;
620 static int version_flag;
621 static int help_flag;
622 struct getargs args[] = {
623 { "indent", 'i', arg_negative_flag, &indent_flag,
624 "\tdo not indent dump", NULL },
625 { "inner", 'I', arg_flag, &inner_flag,
626 "\ttry to parse inner structures of OCTET STRING", NULL },
627 { "list-types", 'l', arg_flag, &list_types_flag,
628 "\tlist ASN.1 types known to this program", NULL },
629 { "try-all-types", 'A', arg_flag, &try_all_flag,
630 "\ttry all known types", NULL },
631 { "raw-sequence", 'S', arg_flag, &sequence_flag,
632 "\ttry parsing leftover data", NULL },
633 { "test-encode", 0, arg_flag, &test_encode_flag,
634 "\ttest encode round trip (for memory debugging and fuzzing)", NULL },
635 { "test-copy", 0, arg_flag, &test_copy_flag,
636 "\ttest copy operation (for memory debugging and fuzzing)", NULL },
637 { "print", 'n', arg_negative_flag, &print_flag,
638 "\ttest copy operation (for memory debugging and fuzzing)", NULL },
639 { "quiet", 'q', arg_flag, &quiet_flag,
640 "\tOutput nothing (exit status 0 means type matched)", NULL },
641 { "version", 'v', arg_flag, &version_flag, NULL, NULL },
642 { "help", 'h', arg_flag, &help_flag, NULL, NULL }
644 int num_args = sizeof(args) / sizeof(args[0]);
646 static void
647 usage(int code)
649 arg_printusage(args, num_args, NULL, "dump-file [TypeName [TypeName ...]]");
650 exit(code);
654 main(int argc, char **argv)
656 int optidx = 0;
658 setprogname(argv[0]);
659 initialize_asn1_error_table();
660 if (getarg(args, num_args, argc, argv, &optidx))
661 usage(1);
662 if (help_flag)
663 usage(0);
664 if (version_flag) {
665 print_version(NULL);
666 exit(0);
668 argv += optidx;
669 argc -= optidx;
671 if (sequence_flag && try_all_flag)
672 errx(1, "--raw-sequence and --try-all-types are mutually exclusive");
673 if (quiet_flag && !try_all_flag && argc < 2)
674 errx(1, "--quiet requires --try-all-types or that a TypeName be given");
675 if (!print_flag && !try_all_flag && argc < 2)
676 errx(1, "--no-print requires --try-all-types or that a TypeName be given");
678 if (list_types_flag) {
679 size_t i;
681 if (argc)
682 errx(1, "--list-types is exclusive of other options or arguments");
684 for (i = 0; i < sizeof(types)/sizeof(types[0]); i++)
685 printf("%s\n", types[i].name);
686 exit(0);
689 if (argc < 1)
690 usage(1);
691 return doit(argv);