summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/usr.bin/openssl/asn1pars.c343
1 files changed, 206 insertions, 137 deletions
diff --git a/src/usr.bin/openssl/asn1pars.c b/src/usr.bin/openssl/asn1pars.c
index e6d5339f66..62af4f164e 100644
--- a/src/usr.bin/openssl/asn1pars.c
+++ b/src/usr.bin/openssl/asn1pars.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: asn1pars.c,v 1.2 2014/08/28 14:23:52 jsing Exp $ */ 1/* $OpenBSD: asn1pars.c,v 1.3 2015/01/08 11:00:12 doug Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -72,126 +72,191 @@
72#include <openssl/pem.h> 72#include <openssl/pem.h>
73#include <openssl/x509.h> 73#include <openssl/x509.h>
74 74
75/* -inform arg - input format - default PEM (DER or PEM) 75static struct {
76 * -in arg - input file - default stdin 76 char *derfile;
77 * -i - indent the details by depth 77 int dump;
78 * -offset - where in the file to start 78 char *genconf;
79 * -length - how many bytes to use 79 char *genstr;
80 * -oid file - extra oid description file 80 int indent;
81 */ 81 char *infile;
82 int informat;
83 unsigned int length;
84 int noout;
85 int offset;
86 char *oidfile;
87 STACK_OF(OPENSSL_STRING) *osk;
88} asn1pars_config;
89
90static int
91asn1pars_opt_dlimit(char *arg)
92{
93 const char *errstr;
94
95 asn1pars_config.dump = strtonum(arg, 1, INT_MAX, &errstr);
96 if (errstr) {
97 fprintf(stderr, "-dlimit must be from 1 to INT_MAX: %s\n",
98 errstr);
99 return (-1);
100 }
101 return (0);
102}
103
104static int
105asn1pars_opt_length(char *arg)
106{
107 const char *errstr;
108
109 asn1pars_config.length = strtonum(arg, 1, UINT_MAX, &errstr);
110 if (errstr) {
111 fprintf(stderr, "-length must be from 1 to UINT_MAX: %s\n",
112 errstr);
113 return (-1);
114 }
115 return (0);
116}
117
118static int
119asn1pars_opt_strparse(char *arg)
120{
121 if (sk_OPENSSL_STRING_push(asn1pars_config.osk, arg) == 0) {
122 fprintf(stderr, "-strparse cannot add argument\n");
123 return (-1);
124 }
125 return (0);
126}
82 127
83int asn1parse_main(int, char **); 128static struct option asn1pars_options[] = {
129 {
130 .name = "dump",
131 .desc = "Dump unknown data in hex form",
132 .type = OPTION_VALUE,
133 .value = -1,
134 .opt.value = &asn1pars_config.dump,
135 },
136 {
137 .name = "dlimit",
138 .argname = "num",
139 .desc = "Dump the first num bytes of unknown data in hex form",
140 .type = OPTION_ARG_FUNC,
141 .opt.argfunc = asn1pars_opt_dlimit,
142 },
143 {
144 .name = "genconf",
145 .argname = "file",
146 .desc = "File to generate ASN.1 structure from",
147 .type = OPTION_ARG,
148 .opt.arg = &asn1pars_config.genconf,
149 },
150 {
151 .name = "genstr",
152 .argname = "string",
153 .desc = "String to generate ASN.1 structure from",
154 .type = OPTION_ARG,
155 .opt.arg = &asn1pars_config.genstr,
156 },
157 {
158 .name = "i",
159 .desc = "Indent output according to depth of structures",
160 .type = OPTION_FLAG,
161 .opt.flag = &asn1pars_config.indent,
162 },
163 {
164 .name = "in",
165 .argname = "file",
166 .desc = "The input file (default stdin)",
167 .type = OPTION_ARG,
168 .opt.arg = &asn1pars_config.infile,
169 },
170 {
171 .name = "inform",
172 .argname = "fmt",
173 .desc = "Input format (DER, TXT or PEM (default))",
174 .type = OPTION_ARG_FORMAT,
175 .opt.value = &asn1pars_config.informat,
176 },
177 {
178 .name = "length",
179 .argname = "num",
180 .desc = "Number of bytes to parse (default until EOF)",
181 .type = OPTION_ARG_FUNC,
182 .opt.argfunc = asn1pars_opt_length,
183 },
184 {
185 .name = "noout",
186 .desc = "Do not produce any output",
187 .type = OPTION_FLAG,
188 .opt.flag = &asn1pars_config.noout,
189 },
190 {
191 .name = "offset",
192 .argname = "num",
193 .desc = "Offset to begin parsing",
194 .type = OPTION_ARG_INT,
195 .opt.value = &asn1pars_config.offset,
196 },
197 {
198 .name = "oid",
199 .argname = "file",
200 .desc = "File containing additional object identifiers (OIDs)",
201 .type = OPTION_ARG,
202 .opt.arg = &asn1pars_config.oidfile,
203 },
204 {
205 .name = "out",
206 .argname = "file",
207 .desc = "Output file in DER format",
208 .type = OPTION_ARG,
209 .opt.arg = &asn1pars_config.derfile,
210 },
211 {
212 .name = "strparse",
213 .argname = "offset",
214 .desc = "Parse the content octets of ASN.1 object starting at"
215 " offset",
216 .type = OPTION_ARG_FUNC,
217 .opt.argfunc = asn1pars_opt_strparse,
218 },
219 { NULL },
220};
221
222static void
223asn1pars_usage()
224{
225 fprintf(stderr,
226 "usage: asn1parse [-i] [-dlimit num] [-dump] [-genconf file] "
227 "[-genstr string]\n"
228 " [-in file] [-inform fmt] [-length num] [-noout] [-offset num] "
229 "[-oid file]\n"
230 " [-out file] [-strparse offset]\n\n");
231 options_usage(asn1pars_options);
232}
84 233
85static int do_generate(BIO * bio, char *genstr, char *genconf, BUF_MEM * buf); 234static int do_generate(BIO *bio, char *genstr, char *genconf, BUF_MEM *buf);
86 235
87int 236int
88asn1parse_main(int argc, char **argv) 237asn1parse_main(int argc, char **argv)
89{ 238{
90 int i, badops = 0, offset = 0, ret = 1, j; 239 int i, j, ret = 1;
91 unsigned int length = 0;
92 long num, tmplen; 240 long num, tmplen;
93 BIO *in = NULL, *out = NULL, *b64 = NULL, *derout = NULL; 241 BIO *in = NULL, *out = NULL, *b64 = NULL, *derout = NULL;
94 int informat, indent = 0, noout = 0, dump = 0; 242 char *str = NULL;
95 char *infile = NULL, *str = NULL, *prog, *oidfile = NULL, *derfile = NULL;
96 char *genstr = NULL, *genconf = NULL;
97 const char *errstr = NULL; 243 const char *errstr = NULL;
98 unsigned char *tmpbuf; 244 unsigned char *tmpbuf;
99 const unsigned char *ctmpbuf; 245 const unsigned char *ctmpbuf;
100 BUF_MEM *buf = NULL; 246 BUF_MEM *buf = NULL;
101 STACK_OF(OPENSSL_STRING) * osk = NULL;
102 ASN1_TYPE *at = NULL; 247 ASN1_TYPE *at = NULL;
103 248
104 informat = FORMAT_PEM; 249 memset(&asn1pars_config, 0, sizeof(asn1pars_config));
105 250
106 prog = argv[0]; 251 asn1pars_config.informat = FORMAT_PEM;
107 argc--; 252 if ((asn1pars_config.osk = sk_OPENSSL_STRING_new_null()) == NULL) {
108 argv++;
109 if ((osk = sk_OPENSSL_STRING_new_null()) == NULL) {
110 BIO_printf(bio_err, "Memory allocation failure\n"); 253 BIO_printf(bio_err, "Memory allocation failure\n");
111 goto end; 254 goto end;
112 } 255 }
113 while (argc >= 1) {
114 if (strcmp(*argv, "-inform") == 0) {
115 if (--argc < 1)
116 goto bad;
117 informat = str2fmt(*(++argv));
118 } else if (strcmp(*argv, "-in") == 0) {
119 if (--argc < 1)
120 goto bad;
121 infile = *(++argv);
122 } else if (strcmp(*argv, "-out") == 0) {
123 if (--argc < 1)
124 goto bad;
125 derfile = *(++argv);
126 } else if (strcmp(*argv, "-i") == 0) {
127 indent = 1;
128 } else if (strcmp(*argv, "-noout") == 0)
129 noout = 1;
130 else if (strcmp(*argv, "-oid") == 0) {
131 if (--argc < 1)
132 goto bad;
133 oidfile = *(++argv);
134 } else if (strcmp(*argv, "-offset") == 0) {
135 if (--argc < 1)
136 goto bad;
137 offset = strtonum(*(++argv), 0, INT_MAX, &errstr);
138 if (errstr)
139 goto bad;
140 } else if (strcmp(*argv, "-length") == 0) {
141 if (--argc < 1)
142 goto bad;
143 length = strtonum(*(++argv), 1, UINT_MAX, &errstr);
144 if (errstr)
145 goto bad;
146 } else if (strcmp(*argv, "-dump") == 0) {
147 dump = -1;
148 } else if (strcmp(*argv, "-dlimit") == 0) {
149 if (--argc < 1)
150 goto bad;
151 dump = strtonum(*(++argv), 1, INT_MAX, &errstr);
152 if (errstr)
153 goto bad;
154 } else if (strcmp(*argv, "-strparse") == 0) {
155 if (--argc < 1)
156 goto bad;
157 sk_OPENSSL_STRING_push(osk, *(++argv));
158 } else if (strcmp(*argv, "-genstr") == 0) {
159 if (--argc < 1)
160 goto bad;
161 genstr = *(++argv);
162 } else if (strcmp(*argv, "-genconf") == 0) {
163 if (--argc < 1)
164 goto bad;
165 genconf = *(++argv);
166 } else {
167 BIO_printf(bio_err, "unknown option %s\n", *argv);
168 badops = 1;
169 break;
170 }
171 argc--;
172 argv++;
173 }
174 256
175 if (badops) { 257 if (options_parse(argc, argv, asn1pars_options, NULL, NULL) != 0) {
176bad: 258 asn1pars_usage();
177 BIO_printf(bio_err, "%s [options] <infile\n", prog); 259 return (1);
178 BIO_printf(bio_err, "where options are\n");
179 BIO_printf(bio_err, " -inform arg input format - one of DER PEM\n");
180 BIO_printf(bio_err, " -in arg input file\n");
181 BIO_printf(bio_err, " -out arg output file (output format is always DER\n");
182 BIO_printf(bio_err, " -noout arg don't produce any output\n");
183 BIO_printf(bio_err, " -offset arg offset into file\n");
184 BIO_printf(bio_err, " -length arg length of section in file\n");
185 BIO_printf(bio_err, " -i indent entries\n");
186 BIO_printf(bio_err, " -dump dump unknown data in hex form\n");
187 BIO_printf(bio_err, " -dlimit arg dump the first arg bytes of unknown data in hex form\n");
188 BIO_printf(bio_err, " -oid file file of extra oid definitions\n");
189 BIO_printf(bio_err, " -strparse offset\n");
190 BIO_printf(bio_err, " a series of these can be used to 'dig' into multiple\n");
191 BIO_printf(bio_err, " ASN1 blob wrappings\n");
192 BIO_printf(bio_err, " -genstr str string to generate ASN1 structure from\n");
193 BIO_printf(bio_err, " -genconf file file to generate ASN1 structure from\n");
194 goto end;
195 } 260 }
196 261
197 in = BIO_new(BIO_s_file()); 262 in = BIO_new(BIO_s_file());
@@ -202,26 +267,28 @@ bad:
202 } 267 }
203 BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); 268 BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
204 269
205 if (oidfile != NULL) { 270 if (asn1pars_config.oidfile != NULL) {
206 if (BIO_read_filename(in, oidfile) <= 0) { 271 if (BIO_read_filename(in, asn1pars_config.oidfile) <= 0) {
207 BIO_printf(bio_err, "problems opening %s\n", oidfile); 272 BIO_printf(bio_err, "problems opening %s\n",
273 asn1pars_config.oidfile);
208 ERR_print_errors(bio_err); 274 ERR_print_errors(bio_err);
209 goto end; 275 goto end;
210 } 276 }
211 OBJ_create_objects(in); 277 OBJ_create_objects(in);
212 } 278 }
213 if (infile == NULL) 279 if (asn1pars_config.infile == NULL)
214 BIO_set_fp(in, stdin, BIO_NOCLOSE); 280 BIO_set_fp(in, stdin, BIO_NOCLOSE);
215 else { 281 else {
216 if (BIO_read_filename(in, infile) <= 0) { 282 if (BIO_read_filename(in, asn1pars_config.infile) <= 0) {
217 perror(infile); 283 perror(asn1pars_config.infile);
218 goto end; 284 goto end;
219 } 285 }
220 } 286 }
221 287
222 if (derfile) { 288 if (asn1pars_config.derfile) {
223 if (!(derout = BIO_new_file(derfile, "wb"))) { 289 if (!(derout = BIO_new_file(asn1pars_config.derfile, "wb"))) {
224 BIO_printf(bio_err, "problems opening %s\n", derfile); 290 BIO_printf(bio_err, "problems opening %s\n",
291 asn1pars_config.derfile);
225 ERR_print_errors(bio_err); 292 ERR_print_errors(bio_err);
226 goto end; 293 goto end;
227 } 294 }
@@ -231,15 +298,16 @@ bad:
231 if (!BUF_MEM_grow(buf, BUFSIZ * 8)) 298 if (!BUF_MEM_grow(buf, BUFSIZ * 8))
232 goto end; /* Pre-allocate :-) */ 299 goto end; /* Pre-allocate :-) */
233 300
234 if (genstr || genconf) { 301 if (asn1pars_config.genstr || asn1pars_config.genconf) {
235 num = do_generate(bio_err, genstr, genconf, buf); 302 num = do_generate(bio_err, asn1pars_config.genstr,
303 asn1pars_config.genconf, buf);
236 if (num < 0) { 304 if (num < 0) {
237 ERR_print_errors(bio_err); 305 ERR_print_errors(bio_err);
238 goto end; 306 goto end;
239 } 307 }
240 } else { 308 } else {
241 309
242 if (informat == FORMAT_PEM) { 310 if (asn1pars_config.informat == FORMAT_PEM) {
243 BIO *tmp; 311 BIO *tmp;
244 312
245 if ((b64 = BIO_new(BIO_f_base64())) == NULL) 313 if ((b64 = BIO_new(BIO_f_base64())) == NULL)
@@ -263,18 +331,21 @@ bad:
263 331
264 /* If any structs to parse go through in sequence */ 332 /* If any structs to parse go through in sequence */
265 333
266 if (sk_OPENSSL_STRING_num(osk)) { 334 if (sk_OPENSSL_STRING_num(asn1pars_config.osk)) {
267 tmpbuf = (unsigned char *) str; 335 tmpbuf = (unsigned char *) str;
268 tmplen = num; 336 tmplen = num;
269 for (i = 0; i < sk_OPENSSL_STRING_num(osk); i++) { 337 for (i = 0; i < sk_OPENSSL_STRING_num(asn1pars_config.osk);
338 i++) {
270 ASN1_TYPE *atmp; 339 ASN1_TYPE *atmp;
271 int typ; 340 int typ;
272 j = strtonum(sk_OPENSSL_STRING_value(osk, i), 341 j = strtonum(
342 sk_OPENSSL_STRING_value(asn1pars_config.osk, i),
273 1, INT_MAX, &errstr); 343 1, INT_MAX, &errstr);
274 if (errstr) { 344 if (errstr) {
275 BIO_printf(bio_err, 345 BIO_printf(bio_err,
276 "'%s' is an invalid number: %s\n", 346 "'%s' is an invalid number: %s\n",
277 sk_OPENSSL_STRING_value(osk, i), errstr); 347 sk_OPENSSL_STRING_value(asn1pars_config.osk,
348 i), errstr);
278 continue; 349 continue;
279 } 350 }
280 tmpbuf += j; 351 tmpbuf += j;
@@ -303,44 +374,43 @@ bad:
303 str = (char *) tmpbuf; 374 str = (char *) tmpbuf;
304 num = tmplen; 375 num = tmplen;
305 } 376 }
306 if (offset >= num) { 377 if (asn1pars_config.offset >= num) {
307 BIO_printf(bio_err, "Error: offset too large\n"); 378 BIO_printf(bio_err, "Error: offset too large\n");
308 goto end; 379 goto end;
309 } 380 }
310 num -= offset; 381 num -= asn1pars_config.offset;
311 382
312 if ((length == 0) || ((long) length > num)) 383 if ((asn1pars_config.length == 0) ||
313 length = (unsigned int) num; 384 ((long)asn1pars_config.length > num))
385 asn1pars_config.length = (unsigned int) num;
314 if (derout) { 386 if (derout) {
315 if (BIO_write(derout, str + offset, length) != (int) length) { 387 if (BIO_write(derout, str + asn1pars_config.offset,
388 asn1pars_config.length) != (int)asn1pars_config.length) {
316 BIO_printf(bio_err, "Error writing output\n"); 389 BIO_printf(bio_err, "Error writing output\n");
317 ERR_print_errors(bio_err); 390 ERR_print_errors(bio_err);
318 goto end; 391 goto end;
319 } 392 }
320 } 393 }
321 if (!noout && 394 if (!asn1pars_config.noout &&
322 !ASN1_parse_dump(out, (unsigned char *) &(str[offset]), length, 395 !ASN1_parse_dump(out,
323 indent, dump)) { 396 (unsigned char *)&(str[asn1pars_config.offset]),
397 asn1pars_config.length, asn1pars_config.indent,
398 asn1pars_config.dump)) {
324 ERR_print_errors(bio_err); 399 ERR_print_errors(bio_err);
325 goto end; 400 goto end;
326 } 401 }
327 ret = 0; 402 ret = 0;
328end: 403end:
329 BIO_free(derout); 404 BIO_free(derout);
330 if (in != NULL) 405 BIO_free(in);
331 BIO_free(in); 406 BIO_free_all(out);
332 if (out != NULL) 407 BIO_free(b64);
333 BIO_free_all(out);
334 if (b64 != NULL)
335 BIO_free(b64);
336 if (ret != 0) 408 if (ret != 0)
337 ERR_print_errors(bio_err); 409 ERR_print_errors(bio_err);
338 if (buf != NULL) 410 BUF_MEM_free(buf);
339 BUF_MEM_free(buf);
340 if (at != NULL) 411 if (at != NULL)
341 ASN1_TYPE_free(at); 412 ASN1_TYPE_free(at);
342 if (osk != NULL) 413 sk_OPENSSL_STRING_free(asn1pars_config.osk);
343 sk_OPENSSL_STRING_free(osk);
344 OBJ_cleanup(); 414 OBJ_cleanup();
345 415
346 return (ret); 416 return (ret);
@@ -374,7 +444,6 @@ do_generate(BIO * bio, char *genstr, char *genconf, BUF_MEM * buf)
374 return -1; 444 return -1;
375 445
376 len = i2d_ASN1_TYPE(atyp, NULL); 446 len = i2d_ASN1_TYPE(atyp, NULL);
377
378 if (len <= 0) 447 if (len <= 0)
379 goto err; 448 goto err;
380 449