Initial import from FreeBSD RELENG_4:
[dragonfly.git] / crypto / heimdal / lib / asn1 / asn1_print.c
1 /*
2  * Copyright (c) 1997 - 2002 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
41 RCSID("$Id: asn1_print.c,v 1.11 2002/08/29 20:45:35 assar Exp $");
42
43 const char *class_names[] = {
44     "UNIV",                     /* 0 */
45     "APPL",                     /* 1 */
46     "CONTEXT",                  /* 2 */
47     "PRIVATE"                   /* 3 */
48 };
49
50 const char *type_names[] = {
51     "PRIM",                     /* 0 */
52     "CONS"                      /* 1 */
53 };
54
55 const char *tag_names[] = {
56     NULL,                       /* 0 */
57     NULL,                       /* 1 */
58     "Integer",                  /* 2 */
59     "BitString",                /* 3 */
60     "OctetString",              /* 4 */
61     "Null",                     /* 5 */
62     "ObjectID",                 /* 6 */
63     NULL,                       /* 7 */
64     NULL,                       /* 8 */
65     NULL,                       /* 9 */
66     NULL,                       /* 10 */
67     NULL,                       /* 11 */
68     NULL,                       /* 12 */
69     NULL,                       /* 13 */
70     NULL,                       /* 14 */
71     NULL,                       /* 15 */
72     "Sequence",                 /* 16 */
73     "Set",                      /* 17 */
74     NULL,                       /* 18 */
75     "PrintableString",          /* 19 */
76     NULL,                       /* 20 */
77     NULL,                       /* 21 */
78     "IA5String",                /* 22 */
79     "UTCTime",                  /* 23 */
80     "GeneralizedTime",          /* 24 */
81     NULL,                       /* 25 */
82     "VisibleString",            /* 26 */
83     "GeneralString"             /* 27 */
84 };
85
86 static int
87 loop (unsigned char *buf, size_t len, int indent)
88 {
89     while (len > 0) {
90         int ret;
91         Der_class class;
92         Der_type type;
93         int tag;
94         size_t sz;
95         size_t length;
96         int i;
97
98         ret = der_get_tag (buf, len, &class, &type, &tag, &sz);
99         if (ret)
100             errx (1, "der_get_tag: %s", error_message (ret));
101         if (sz > len)
102             errx (1, "unreasonable length (%u) > %u",
103                   (unsigned)sz, (unsigned)len);
104         buf += sz;
105         len -= sz;
106         for (i = 0; i < indent; ++i)
107             printf (" ");
108         printf ("%s %s ", class_names[class], type_names[type]);
109         if (tag_names[tag])
110             printf ("%s = ", tag_names[tag]);
111         else
112             printf ("tag %d = ", tag);
113         ret = der_get_length (buf, len, &length, &sz);
114         if (ret)
115             errx (1, "der_get_tag: %s", error_message (ret));
116         buf += sz;
117         len -= sz;
118
119         if (class == CONTEXT) {
120             printf ("[%d]\n", tag);
121             loop (buf, length, indent);
122         } else if (class == UNIV) {
123             switch (tag) {
124             case UT_Sequence :
125                 printf ("{\n");
126                 loop (buf, length, indent + 2);
127                 for (i = 0; i < indent; ++i)
128                     printf (" ");
129                 printf ("}\n");
130                 break;
131             case UT_Integer : {
132                 int val;
133
134                 ret = der_get_int (buf, length, &val, NULL);
135                 if (ret)
136                     errx (1, "der_get_int: %s", error_message (ret));
137                 printf ("integer %d\n", val);
138                 break;
139             }
140             case UT_OctetString : {
141                 octet_string str;
142                 int i;
143                 unsigned char *uc;
144
145                 ret = der_get_octet_string (buf, length, &str, NULL);
146                 if (ret)
147                     errx (1, "der_get_octet_string: %s", error_message (ret));
148                 printf ("(length %lu), ", (unsigned long)length);
149                 uc = (unsigned char *)str.data;
150                 for (i = 0; i < 16; ++i)
151                     printf ("%02x", uc[i]);
152                 printf ("\n");
153                 free (str.data);
154                 break;
155             }
156             case UT_GeneralizedTime :
157             case UT_GeneralString : {
158                 general_string str;
159
160                 ret = der_get_general_string (buf, length, &str, NULL);
161                 if (ret)
162                     errx (1, "der_get_general_string: %s",
163                           error_message (ret));
164                 printf ("\"%s\"\n", str);
165                 free (str);
166                 break;
167             }
168             case UT_OID: {
169                 oid o;
170                 int i;
171
172                 ret = der_get_oid(buf, length, &o, NULL);
173                 if (ret)
174                     errx (1, "der_get_oid: %s", error_message (ret));
175                 
176                 for (i = 0; i < o.length ; i++)
177                     printf("%d%s", o.components[i],
178                            i < o.length - 1 ? "." : "");
179                 printf("\n");
180                 free_oid(&o);
181                 break;
182             }
183             default :
184                 printf ("%lu bytes\n", (unsigned long)length);
185                 break;
186             }
187         }
188         buf += length;
189         len -= length;
190     }
191     return 0;
192 }
193
194 static int
195 doit (const char *filename)
196 {
197     int fd = open (filename, O_RDONLY);
198     struct stat sb;
199     unsigned char *buf;
200     size_t len;
201     int ret;
202
203     if(fd < 0)
204         err (1, "opening %s for read", filename);
205     if (fstat (fd, &sb) < 0)
206         err (1, "stat %s", filename);
207     len = sb.st_size;
208     buf = malloc (len);
209     if (buf == NULL)
210         err (1, "malloc %u", (unsigned)len);
211     if (read (fd, buf, len) != len)
212         errx (1, "read failed");
213     close (fd);
214     ret = loop (buf, len, 0);
215     free (buf);
216     return ret;
217 }
218
219
220 static int version_flag;
221 static int help_flag;
222 struct getargs args[] = {
223     { "version", 0, arg_flag, &version_flag },
224     { "help", 0, arg_flag, &help_flag }
225 };
226 int num_args = sizeof(args) / sizeof(args[0]);
227
228 static void
229 usage(int code)
230 {
231     arg_printusage(args, num_args, NULL, "dump-file");
232     exit(code);
233 }
234
235 int
236 main(int argc, char **argv)
237 {
238     int optind = 0;
239
240     setprogname (argv[0]);
241     initialize_asn1_error_table ();
242     if(getarg(args, num_args, argc, argv, &optind))
243         usage(1);
244     if(help_flag)
245         usage(0);
246     if(version_flag) {
247         print_version(NULL);
248         exit(0);
249     }
250     argv += optind;
251     argc -= optind;
252     if (argc != 1)
253         usage (1);
254     return doit (argv[0]);
255 }