Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/asn1/asn1_print.c
34878 views
1
/*
2
* Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
3
* (Royal Institute of Technology, Stockholm, Sweden).
4
* All rights reserved.
5
*
6
* Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
*
12
* 1. Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
14
*
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.
18
*
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.
22
*
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.
34
*/
35
36
#include "der_locl.h"
37
#include <com_err.h>
38
#include <sys/types.h>
39
#include <sys/stat.h>
40
#include <getarg.h>
41
#include <err.h>
42
#include <der.h>
43
44
static int indent_flag = 1;
45
static int inner_flag = 0;
46
47
static unsigned long indefinite_form_loop;
48
static unsigned long indefinite_form_loop_max = 10000;
49
50
static size_t
51
loop (unsigned char *buf, size_t len, int indent)
52
{
53
unsigned char *start_buf = buf;
54
55
while (len > 0) {
56
int ret;
57
Der_class class;
58
Der_type type;
59
unsigned int tag;
60
size_t sz;
61
size_t length;
62
size_t loop_length = 0;
63
int end_tag = 0;
64
const char *tagname;
65
66
ret = der_get_tag (buf, len, &class, &type, &tag, &sz);
67
if (ret)
68
errx (1, "der_get_tag: %s", error_message (ret));
69
if (sz > len)
70
errx (1, "unreasonable length (%u) > %u",
71
(unsigned)sz, (unsigned)len);
72
buf += sz;
73
len -= sz;
74
if (indent_flag) {
75
int i;
76
for (i = 0; i < indent; ++i)
77
printf (" ");
78
}
79
printf ("%s %s ", der_get_class_name(class), der_get_type_name(type));
80
tagname = der_get_tag_name(tag);
81
if (class == ASN1_C_UNIV && tagname != NULL)
82
printf ("%s = ", tagname);
83
else
84
printf ("tag %d = ", tag);
85
ret = der_get_length (buf, len, &length, &sz);
86
if (ret)
87
errx (1, "der_get_tag: %s", error_message (ret));
88
if (sz > len)
89
errx (1, "unreasonable tag length (%u) > %u",
90
(unsigned)sz, (unsigned)len);
91
buf += sz;
92
len -= sz;
93
if (length == ASN1_INDEFINITE) {
94
if ((class == ASN1_C_UNIV && type == PRIM && tag == UT_OctetString) ||
95
(class == ASN1_C_CONTEXT && type == CONS) ||
96
(class == ASN1_C_UNIV && type == CONS && tag == UT_Sequence) ||
97
(class == ASN1_C_UNIV && type == CONS && tag == UT_Set)) {
98
printf("*INDEFINITE FORM*");
99
} else {
100
fflush(stdout);
101
errx(1, "indef form used on unsupported object");
102
}
103
end_tag = 1;
104
if (indefinite_form_loop > indefinite_form_loop_max)
105
errx(1, "indefinite form used recursively more then %lu "
106
"times, aborting", indefinite_form_loop_max);
107
indefinite_form_loop++;
108
length = len;
109
} else if (length > len) {
110
printf("\n");
111
fflush(stdout);
112
errx (1, "unreasonable inner length (%u) > %u",
113
(unsigned)length, (unsigned)len);
114
}
115
if (class == ASN1_C_CONTEXT || class == ASN1_C_APPL) {
116
printf ("%lu bytes [%u]", (unsigned long)length, tag);
117
if (type == CONS) {
118
printf("\n");
119
loop_length = loop (buf, length, indent + 2);
120
} else {
121
printf(" IMPLICIT content\n");
122
}
123
} else if (class == ASN1_C_UNIV) {
124
switch (tag) {
125
case UT_EndOfContent:
126
printf (" INDEFINITE length was %lu\n",
127
(unsigned long)(buf - start_buf));
128
break;
129
case UT_Set :
130
case UT_Sequence :
131
printf ("%lu bytes {\n", (unsigned long)length);
132
loop_length = loop (buf, length, indent + 2);
133
if (indent_flag) {
134
int i;
135
for (i = 0; i < indent; ++i)
136
printf (" ");
137
printf ("}\n");
138
} else
139
printf ("} indent = %d\n", indent / 2);
140
break;
141
case UT_Integer : {
142
int val;
143
144
if (length <= sizeof(val)) {
145
ret = der_get_integer (buf, length, &val, NULL);
146
if (ret)
147
errx (1, "der_get_integer: %s", error_message (ret));
148
printf ("integer %d\n", val);
149
} else {
150
heim_integer vali;
151
char *p;
152
153
ret = der_get_heim_integer(buf, length, &vali, NULL);
154
if (ret)
155
errx (1, "der_get_heim_integer: %s",
156
error_message (ret));
157
ret = der_print_hex_heim_integer(&vali, &p);
158
if (ret)
159
errx (1, "der_print_hex_heim_integer: %s",
160
error_message (ret));
161
printf ("BIG NUM integer: length %lu %s\n",
162
(unsigned long)length, p);
163
free(p);
164
}
165
break;
166
}
167
case UT_OctetString : {
168
heim_octet_string str;
169
size_t i;
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
176
if (inner_flag) {
177
Der_class class;
178
Der_type type;
179
unsigned int tag;
180
181
ret = der_get_tag(str.data, str.length,
182
&class, &type, &tag, &sz);
183
if (ret || sz > str.length ||
184
type != CONS || tag != UT_Sequence)
185
goto just_an_octet_string;
186
187
printf("{\n");
188
loop (str.data, str.length, indent + 2);
189
for (i = 0; i < indent; ++i)
190
printf (" ");
191
printf ("}\n");
192
193
} else {
194
unsigned char *uc;
195
196
just_an_octet_string:
197
uc = (unsigned char *)str.data;
198
for (i = 0; i < min(16,length); ++i)
199
printf ("%02x", uc[i]);
200
printf ("\n");
201
}
202
free (str.data);
203
break;
204
}
205
case UT_IA5String :
206
case UT_PrintableString : {
207
heim_printable_string str;
208
unsigned char *s;
209
size_t n;
210
211
memset(&str, 0, sizeof(str));
212
213
ret = der_get_printable_string (buf, length, &str, NULL);
214
if (ret)
215
errx (1, "der_get_general_string: %s",
216
error_message (ret));
217
s = str.data;
218
printf("\"");
219
for (n = 0; n < str.length; n++) {
220
if (isprint((int)s[n]))
221
printf ("%c", s[n]);
222
else
223
printf ("#%02x", s[n]);
224
}
225
printf("\"\n");
226
der_free_printable_string(&str);
227
break;
228
}
229
case UT_GeneralizedTime :
230
case UT_GeneralString :
231
case UT_VisibleString :
232
case UT_UTF8String : {
233
heim_general_string str;
234
235
ret = der_get_general_string (buf, length, &str, NULL);
236
if (ret)
237
errx (1, "der_get_general_string: %s",
238
error_message (ret));
239
printf ("\"%s\"\n", str);
240
free (str);
241
break;
242
}
243
case UT_OID: {
244
heim_oid o;
245
char *p;
246
247
ret = der_get_oid(buf, length, &o, NULL);
248
if (ret)
249
errx (1, "der_get_oid: %s", error_message (ret));
250
ret = der_print_heim_oid(&o, '.', &p);
251
der_free_oid(&o);
252
if (ret)
253
errx (1, "der_print_heim_oid: %s", error_message (ret));
254
printf("%s\n", p);
255
free(p);
256
257
break;
258
}
259
case UT_Enumerated: {
260
int num;
261
262
ret = der_get_integer (buf, length, &num, NULL);
263
if (ret)
264
errx (1, "der_get_enum: %s", error_message (ret));
265
266
printf("%u\n", num);
267
break;
268
}
269
default :
270
printf ("%lu bytes\n", (unsigned long)length);
271
break;
272
}
273
}
274
if (end_tag) {
275
if (loop_length == 0)
276
errx(1, "zero length INDEFINITE data ? indent = %d\n",
277
indent / 2);
278
if (loop_length < length)
279
length = loop_length;
280
if (indefinite_form_loop == 0)
281
errx(1, "internal error in indefinite form loop detection");
282
indefinite_form_loop--;
283
} else if (loop_length)
284
errx(1, "internal error for INDEFINITE form");
285
buf += length;
286
len -= length;
287
}
288
return 0;
289
}
290
291
static int
292
doit (const char *filename)
293
{
294
int fd = open (filename, O_RDONLY);
295
struct stat sb;
296
unsigned char *buf;
297
size_t len;
298
int ret;
299
300
if(fd < 0)
301
err (1, "opening %s for read", filename);
302
if (fstat (fd, &sb) < 0)
303
err (1, "stat %s", filename);
304
len = sb.st_size;
305
buf = emalloc (len);
306
if (read (fd, buf, len) != len)
307
errx (1, "read failed");
308
close (fd);
309
ret = loop (buf, len, 0);
310
free (buf);
311
return ret;
312
}
313
314
315
static int version_flag;
316
static int help_flag;
317
struct getargs args[] = {
318
{ "indent", 0, arg_negative_flag, &indent_flag },
319
{ "inner", 0, arg_flag, &inner_flag, "try to parse inner structures of OCTET STRING" },
320
{ "version", 0, arg_flag, &version_flag },
321
{ "help", 0, arg_flag, &help_flag }
322
};
323
int num_args = sizeof(args) / sizeof(args[0]);
324
325
static void
326
usage(int code)
327
{
328
arg_printusage(args, num_args, NULL, "dump-file");
329
exit(code);
330
}
331
332
int
333
main(int argc, char **argv)
334
{
335
int optidx = 0;
336
337
setprogname (argv[0]);
338
initialize_asn1_error_table ();
339
if(getarg(args, num_args, argc, argv, &optidx))
340
usage(1);
341
if(help_flag)
342
usage(0);
343
if(version_flag) {
344
print_version(NULL);
345
exit(0);
346
}
347
argv += optidx;
348
argc -= optidx;
349
if (argc != 1)
350
usage (1);
351
return doit (argv[0]);
352
}
353
354