5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2007 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 #include "silcruntime.h"
21 #include "silccrypto.h"
23 SilcBool hexdump = FALSE;
24 SilcBool dec_base64 = FALSE;
25 SilcBool parse_all = FALSE;
26 SilcBool ignore_header = FALSE;
28 const char *asn1_tag_name(SilcAsn1Tag tag)
31 case SILC_ASN1_TAG_CHOICE:
33 case SILC_ASN1_TAG_ANY:
35 case SILC_ASN1_TAG_ANY_PRIMITIVE:
36 return "any primitive";
37 case SILC_ASN1_TAG_SEQUENCE_OF:
39 case SILC_ASN1_TAG_SEQUENCE:
41 case SILC_ASN1_TAG_SET:
43 case SILC_ASN1_TAG_INTEGER:
45 case SILC_ASN1_TAG_SHORT_INTEGER:
46 return "short integer";
47 case SILC_ASN1_TAG_OID:
49 case SILC_ASN1_TAG_BOOLEAN:
51 case SILC_ASN1_TAG_OCTET_STRING:
52 return "octet-string";
53 case SILC_ASN1_TAG_BIT_STRING:
55 case SILC_ASN1_TAG_NULL:
57 case SILC_ASN1_TAG_ENUM:
59 case SILC_ASN1_TAG_UTC_TIME:
61 case SILC_ASN1_TAG_GENERALIZED_TIME:
62 return "generalized-time";
63 case SILC_ASN1_TAG_UTF8_STRING:
65 case SILC_ASN1_TAG_NUMERIC_STRING:
66 return "numeric-string";
67 case SILC_ASN1_TAG_PRINTABLE_STRING:
68 return "printable-string";
69 case SILC_ASN1_TAG_IA5_STRING:
71 case SILC_ASN1_TAG_VISIBLE_STRING:
72 return "visible-string";
73 case SILC_ASN1_TAG_UNIVERSAL_STRING:
74 return "universal-string";
75 case SILC_ASN1_TAG_UNRESTRICTED_STRING:
76 return "unrestricted-string";
77 case SILC_ASN1_TAG_BMP_STRING:
79 case SILC_ASN1_TAG_ODE:
81 case SILC_ASN1_TAG_ETI:
83 case SILC_ASN1_TAG_REAL:
85 case SILC_ASN1_TAG_EMBEDDED:
87 case SILC_ASN1_TAG_ROI:
89 case SILC_ASN1_TAG_TELETEX_STRING:
90 return "teletex-string";
91 case SILC_ASN1_TAG_VIDEOTEX_STRING:
92 return "videotex-string";
93 case SILC_ASN1_TAG_GRAPHIC_STRING:
94 return "graphic-string";
95 case SILC_ASN1_TAG_GENERAL_STRING:
96 return "general-string";
103 int asn1_dump(SilcAsn1 asn1, SilcBuffer src, int depth)
105 SilcBool ret = FALSE;
106 SilcBerEncoding renc;
108 const unsigned char *rdata;
109 SilcBufferStruct buf;
111 SilcUInt32 rdata_len, len = 0;
115 memset(indent, 0, sizeof(indent));
117 while (silc_buffer_len(src)) {
118 /* Decode the BER block */
119 ret = silc_ber_decode(src, &rclass, &renc, &rtag, &rdata,
120 &rdata_len, &rindef, &len);
122 fprintf(stderr, "Error: Cannot parse BER block, malformed ASN.1 data\n");
126 /* If class is 0, encoding 0, tag 0 and data length 0 ignore them
127 as they are zero bytes, unless user wants to see them */
128 if (rclass == 0 && renc == 0 && rtag == 0 && rdata_len == 0 &&
130 if (len && silc_buffer_len(src) >= len)
131 silc_buffer_pull(src, len);
136 memset(indent, 32, depth);
138 fprintf(stdout, "%04d: %s%s [%d] %s %s %s", depth, indent,
139 asn1_tag_name(rtag), (int)rtag,
140 rclass == SILC_BER_CLASS_UNIVERSAL ? "univ" :
141 rclass == SILC_BER_CLASS_APPLICATION ? "appl" :
142 rclass == SILC_BER_CLASS_CONTEXT ? "cont" : "priv",
143 renc == SILC_BER_ENC_PRIMITIVE ? "primit" : "constr",
144 rindef ? "indef" : "defin");
146 if (rtag != SILC_ASN1_TAG_SEQUENCE &&
147 rtag != SILC_ASN1_TAG_SET &&
148 rtag != SILC_ASN1_TAG_SEQUENCE_OF) {
150 fprintf(stdout, " [len %lu]\n", rdata_len);
151 silc_hexdump(rdata, rdata_len, stdout);
153 fprintf(stdout, "\n");
156 fprintf(stdout, "\n");
159 if (renc == SILC_BER_ENC_PRIMITIVE)
160 len = len + rdata_len;
164 if (len && silc_buffer_len(src) >= len)
165 silc_buffer_pull(src, len);
167 /* Decode sequences and sets recursively */
168 if ((rtag == SILC_ASN1_TAG_SEQUENCE ||
169 rtag == SILC_ASN1_TAG_SET ||
170 rtag == SILC_ASN1_TAG_SEQUENCE_OF) &&
171 depth + 1 < sizeof(indent) - 1) {
172 silc_buffer_set(&buf, (unsigned char *)rdata, rdata_len);
173 if (silc_buffer_len(src) >= rdata_len)
174 silc_buffer_pull(src, rdata_len);
175 if (asn1_dump(asn1, &buf, depth + 1) < 0)
177 if (silc_buffer_len(src) == 0)
188 "Usage: asn1dump [OPTIONS] FILE\n"
191 " -h Print this help, then exit\n"
192 " -x HEX dump ASN.1 data\n"
193 " -b Remove Base64 encoding before parsing\n"
194 " -i Remove file header/footer that has at least four '-' characters\n"
195 " -a Parse all data, including possible trailing zeroes\n"
199 " appl Application\n"
203 "ASN.1 length types:\n"
204 " defin Definitive\n"
205 " indef Indefinitive\n"
207 "ASN.1 encoding types:\n"
208 " primit Primitive\n"
209 " constr Constructed\n"
214 int main(int argc, char **argv)
218 SilcBufferStruct buf;
219 unsigned char *data, *tmp;
227 while ((opt = getopt(argc, argv, "hxbai")) != EOF) {
243 ignore_header = TRUE;
256 data = tmp = silc_file_readfile(argv[argc - 1], &data_len, NULL);
258 fprintf(stderr, "Error: Cannot read file '%s': %s\n", argv[argc - 1],
259 silc_errno_string(silc_errno));
263 silc_buffer_set(&buf, data, data_len);
266 SilcBool header = FALSE;
267 for (i = 0; i < data_len; i++) {
268 if (data_len > i + 4 &&
269 data[i ] == '-' && data[i + 1] == '-' &&
270 data[i + 2] == '-' && data[i + 3] == '-') {
272 if (data_len > i + 5 && (data[i + 4] == '\r' ||
273 tmp[i + 4] == '\n')) {
274 /* End of line, header */
275 if (data_len > i + 6 && data[i + 4] == '\r' &&
279 silc_buffer_pull(&buf, i);
281 } else if (i > 0 && data_len > i + 5 && data[i + 4] != '-' &&
283 /* Start of line, footer */
284 silc_buffer_push_tail(&buf, silc_buffer_truelen(&buf) - i);
292 data = silc_base64_decode(NULL, silc_buffer_data(&buf),
293 silc_buffer_len(&buf), &data_len);
295 fprintf(stderr, "Error: Cannot decode Base64 encoding\n");
298 silc_buffer_set(&buf, data, data_len);
302 asn1 = silc_asn1_alloc(NULL);
304 ret = asn1_dump(asn1, &buf, 0);
306 silc_asn1_free(asn1);