1 /* 2 * Copyright (c) 1997 - 2005 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include "der_locl.h" 35 #include <com_err.h> 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <getarg.h> 39 #include <err.h> 40 #include <der.h> 41 42 RCSID("$Id: asn1_print.c 19539 2006-12-28 17:15:05Z lha $"); 43 44 static int indent_flag = 1; 45 46 static unsigned long indefinite_form_loop; 47 static unsigned long indefinite_form_loop_max = 10000; 48 49 static size_t 50 loop (unsigned char *buf, size_t len, int indent) 51 { 52 unsigned char *start_buf = buf; 53 54 while (len > 0) { 55 int ret; 56 Der_class class; 57 Der_type type; 58 unsigned int tag; 59 size_t sz; 60 size_t length; 61 size_t loop_length = 0; 62 int end_tag = 0; 63 const char *tagname; 64 65 ret = der_get_tag (buf, len, &class, &type, &tag, &sz); 66 if (ret) 67 errx (1, "der_get_tag: %s", error_message (ret)); 68 if (sz > len) 69 errx (1, "unreasonable length (%u) > %u", 70 (unsigned)sz, (unsigned)len); 71 buf += sz; 72 len -= sz; 73 if (indent_flag) { 74 int i; 75 for (i = 0; i < indent; ++i) 76 printf (" "); 77 } 78 printf ("%s %s ", der_get_class_name(class), der_get_type_name(type)); 79 tagname = der_get_tag_name(tag); 80 if (class == ASN1_C_UNIV && tagname != NULL) 81 printf ("%s = ", tagname); 82 else 83 printf ("tag %d = ", tag); 84 ret = der_get_length (buf, len, &length, &sz); 85 if (ret) 86 errx (1, "der_get_tag: %s", error_message (ret)); 87 if (sz > len) 88 errx (1, "unreasonable tag length (%u) > %u", 89 (unsigned)sz, (unsigned)len); 90 buf += sz; 91 len -= sz; 92 if (length == ASN1_INDEFINITE) { 93 if ((class == ASN1_C_UNIV && type == PRIM && tag == UT_OctetString) || 94 (class == ASN1_C_CONTEXT && type == CONS) || 95 (class == ASN1_C_UNIV && type == CONS && tag == UT_Sequence) || 96 (class == ASN1_C_UNIV && type == CONS && tag == UT_Set)) { 97 printf("*INDEFINITE FORM*"); 98 } else { 99 fflush(stdout); 100 errx(1, "indef form used on unsupported object"); 101 } 102 end_tag = 1; 103 if (indefinite_form_loop > indefinite_form_loop_max) 104 errx(1, "indefinite form used recursively more then %lu " 105 "times, aborting", indefinite_form_loop_max); 106 indefinite_form_loop++; 107 length = len; 108 } else if (length > len) { 109 printf("\n"); 110 fflush(stdout); 111 errx (1, "unreasonable inner length (%u) > %u", 112 (unsigned)length, (unsigned)len); 113 } 114 if (class == ASN1_C_CONTEXT || class == ASN1_C_APPL) { 115 printf ("%lu bytes [%u]", (unsigned long)length, tag); 116 if (type == CONS) { 117 printf("\n"); 118 loop_length = loop (buf, length, indent + 2); 119 } else { 120 printf(" IMPLICIT content\n"); 121 } 122 } else if (class == ASN1_C_UNIV) { 123 switch (tag) { 124 case UT_EndOfContent: 125 printf (" INDEFINITE length was %lu\n", 126 (unsigned long)(buf - start_buf)); 127 break; 128 case UT_Set : 129 case UT_Sequence : 130 printf ("%lu bytes {\n", (unsigned long)length); 131 loop_length = loop (buf, length, indent + 2); 132 if (indent_flag) { 133 int i; 134 for (i = 0; i < indent; ++i) 135 printf (" "); 136 printf ("}\n"); 137 } else 138 printf ("} indent = %d\n", indent / 2); 139 break; 140 case UT_Integer : { 141 int val; 142 143 if (length <= sizeof(val)) { 144 ret = der_get_integer (buf, length, &val, NULL); 145 if (ret) 146 errx (1, "der_get_integer: %s", error_message (ret)); 147 printf ("integer %d\n", val); 148 } else { 149 heim_integer vali; 150 char *p; 151 152 ret = der_get_heim_integer(buf, length, &vali, NULL); 153 if (ret) 154 errx (1, "der_get_heim_integer: %s", 155 error_message (ret)); 156 ret = der_print_hex_heim_integer(&vali, &p); 157 if (ret) 158 errx (1, "der_print_hex_heim_integer: %s", 159 error_message (ret)); 160 printf ("BIG NUM integer: length %lu %s\n", 161 (unsigned long)length, p); 162 free(p); 163 } 164 break; 165 } 166 case UT_OctetString : { 167 heim_octet_string str; 168 int i; 169 unsigned char *uc; 170 171 ret = der_get_octet_string (buf, length, &str, NULL); 172 if (ret) 173 errx (1, "der_get_octet_string: %s", error_message (ret)); 174 printf ("(length %lu), ", (unsigned long)length); 175 uc = (unsigned char *)str.data; 176 for (i = 0; i < min(16,length); ++i) 177 printf ("%02x", uc[i]); 178 printf ("\n"); 179 free (str.data); 180 break; 181 } 182 case UT_GeneralizedTime : 183 case UT_GeneralString : 184 case UT_PrintableString : 185 case UT_VisibleString : { 186 heim_general_string str; 187 188 ret = der_get_general_string (buf, length, &str, NULL); 189 if (ret) 190 errx (1, "der_get_general_string: %s", 191 error_message (ret)); 192 printf ("\"%s\"\n", str); 193 free (str); 194 break; 195 } 196 case UT_OID: { 197 heim_oid o; 198 char *p; 199 200 ret = der_get_oid(buf, length, &o, NULL); 201 if (ret) 202 errx (1, "der_get_oid: %s", error_message (ret)); 203 ret = der_print_heim_oid(&o, '.', &p); 204 der_free_oid(&o); 205 if (ret) 206 errx (1, "der_print_heim_oid: %s", error_message (ret)); 207 printf("%s\n", p); 208 free(p); 209 210 break; 211 } 212 case UT_Enumerated: { 213 int num; 214 215 ret = der_get_integer (buf, length, &num, NULL); 216 if (ret) 217 errx (1, "der_get_enum: %s", error_message (ret)); 218 219 printf("%u\n", num); 220 break; 221 } 222 default : 223 printf ("%lu bytes\n", (unsigned long)length); 224 break; 225 } 226 } 227 if (end_tag) { 228 if (loop_length == 0) 229 errx(1, "zero length INDEFINITE data ? indent = %d\n", 230 indent / 2); 231 if (loop_length < length) 232 length = loop_length; 233 if (indefinite_form_loop == 0) 234 errx(1, "internal error in indefinite form loop detection"); 235 indefinite_form_loop--; 236 } else if (loop_length) 237 errx(1, "internal error for INDEFINITE form"); 238 buf += length; 239 len -= length; 240 } 241 return 0; 242 } 243 244 static int 245 doit (const char *filename) 246 { 247 int fd = open (filename, O_RDONLY); 248 struct stat sb; 249 unsigned char *buf; 250 size_t len; 251 int ret; 252 253 if(fd < 0) 254 err (1, "opening %s for read", filename); 255 if (fstat (fd, &sb) < 0) 256 err (1, "stat %s", filename); 257 len = sb.st_size; 258 buf = emalloc (len); 259 if (read (fd, buf, len) != len) 260 errx (1, "read failed"); 261 close (fd); 262 ret = loop (buf, len, 0); 263 free (buf); 264 return 0; 265 } 266 267 268 static int version_flag; 269 static int help_flag; 270 struct getargs args[] = { 271 { "indent", 0, arg_negative_flag, &indent_flag }, 272 { "version", 0, arg_flag, &version_flag }, 273 { "help", 0, arg_flag, &help_flag } 274 }; 275 int num_args = sizeof(args) / sizeof(args[0]); 276 277 static void 278 usage(int code) 279 { 280 arg_printusage(args, num_args, NULL, "dump-file"); 281 exit(code); 282 } 283 284 int 285 main(int argc, char **argv) 286 { 287 int optidx = 0; 288 289 setprogname (argv[0]); 290 initialize_asn1_error_table (); 291 if(getarg(args, num_args, argc, argv, &optidx)) 292 usage(1); 293 if(help_flag) 294 usage(0); 295 if(version_flag) { 296 print_version(NULL); 297 exit(0); 298 } 299 argv += optidx; 300 argc -= optidx; 301 if (argc != 1) 302 usage (1); 303 return doit (argv[0]); 304 } 305