1 | /*
|
---|
2 | * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | *
|
---|
4 | * Licensed under the OpenSSL license (the "License"). You may not use
|
---|
5 | * this file except in compliance with the License. You can obtain a copy
|
---|
6 | * in the file LICENSE in the source distribution or at
|
---|
7 | * https://www.openssl.org/source/license.html
|
---|
8 | */
|
---|
9 |
|
---|
10 | #include <stdio.h>
|
---|
11 | #include <string.h>
|
---|
12 | #include "internal/cryptlib.h"
|
---|
13 | #include "internal/asn1_int.h"
|
---|
14 | #include <openssl/crypto.h>
|
---|
15 | #include <openssl/x509.h>
|
---|
16 | #include <openssl/asn1.h>
|
---|
17 |
|
---|
18 | #include "charmap.h"
|
---|
19 |
|
---|
20 | /*
|
---|
21 | * ASN1_STRING_print_ex() and X509_NAME_print_ex(). Enhanced string and name
|
---|
22 | * printing routines handling multibyte characters, RFC2253 and a host of
|
---|
23 | * other options.
|
---|
24 | */
|
---|
25 |
|
---|
26 | #define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253)
|
---|
27 |
|
---|
28 | #define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \
|
---|
29 | ASN1_STRFLGS_ESC_2254 | \
|
---|
30 | ASN1_STRFLGS_ESC_QUOTE | \
|
---|
31 | ASN1_STRFLGS_ESC_CTRL | \
|
---|
32 | ASN1_STRFLGS_ESC_MSB)
|
---|
33 |
|
---|
34 | /*
|
---|
35 | * Three IO functions for sending data to memory, a BIO and and a FILE
|
---|
36 | * pointer.
|
---|
37 | */
|
---|
38 | static int send_bio_chars(void *arg, const void *buf, int len)
|
---|
39 | {
|
---|
40 | if (!arg)
|
---|
41 | return 1;
|
---|
42 | if (BIO_write(arg, buf, len) != len)
|
---|
43 | return 0;
|
---|
44 | return 1;
|
---|
45 | }
|
---|
46 |
|
---|
47 | #ifndef OPENSSL_NO_STDIO
|
---|
48 | static int send_fp_chars(void *arg, const void *buf, int len)
|
---|
49 | {
|
---|
50 | if (!arg)
|
---|
51 | return 1;
|
---|
52 | if (fwrite(buf, 1, len, arg) != (unsigned int)len)
|
---|
53 | return 0;
|
---|
54 | return 1;
|
---|
55 | }
|
---|
56 | #endif
|
---|
57 |
|
---|
58 | typedef int char_io (void *arg, const void *buf, int len);
|
---|
59 |
|
---|
60 | /*
|
---|
61 | * This function handles display of strings, one character at a time. It is
|
---|
62 | * passed an unsigned long for each character because it could come from 2 or
|
---|
63 | * even 4 byte forms.
|
---|
64 | */
|
---|
65 |
|
---|
66 | static int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes,
|
---|
67 | char_io *io_ch, void *arg)
|
---|
68 | {
|
---|
69 | unsigned short chflgs;
|
---|
70 | unsigned char chtmp;
|
---|
71 | char tmphex[HEX_SIZE(long) + 3];
|
---|
72 |
|
---|
73 | if (c > 0xffffffffL)
|
---|
74 | return -1;
|
---|
75 | if (c > 0xffff) {
|
---|
76 | BIO_snprintf(tmphex, sizeof tmphex, "\\W%08lX", c);
|
---|
77 | if (!io_ch(arg, tmphex, 10))
|
---|
78 | return -1;
|
---|
79 | return 10;
|
---|
80 | }
|
---|
81 | if (c > 0xff) {
|
---|
82 | BIO_snprintf(tmphex, sizeof tmphex, "\\U%04lX", c);
|
---|
83 | if (!io_ch(arg, tmphex, 6))
|
---|
84 | return -1;
|
---|
85 | return 6;
|
---|
86 | }
|
---|
87 | chtmp = (unsigned char)c;
|
---|
88 | if (chtmp > 0x7f)
|
---|
89 | chflgs = flags & ASN1_STRFLGS_ESC_MSB;
|
---|
90 | else
|
---|
91 | chflgs = char_type[chtmp] & flags;
|
---|
92 | if (chflgs & CHARTYPE_BS_ESC) {
|
---|
93 | /* If we don't escape with quotes, signal we need quotes */
|
---|
94 | if (chflgs & ASN1_STRFLGS_ESC_QUOTE) {
|
---|
95 | if (do_quotes)
|
---|
96 | *do_quotes = 1;
|
---|
97 | if (!io_ch(arg, &chtmp, 1))
|
---|
98 | return -1;
|
---|
99 | return 1;
|
---|
100 | }
|
---|
101 | if (!io_ch(arg, "\\", 1))
|
---|
102 | return -1;
|
---|
103 | if (!io_ch(arg, &chtmp, 1))
|
---|
104 | return -1;
|
---|
105 | return 2;
|
---|
106 | }
|
---|
107 | if (chflgs & (ASN1_STRFLGS_ESC_CTRL
|
---|
108 | | ASN1_STRFLGS_ESC_MSB
|
---|
109 | | ASN1_STRFLGS_ESC_2254)) {
|
---|
110 | BIO_snprintf(tmphex, 11, "\\%02X", chtmp);
|
---|
111 | if (!io_ch(arg, tmphex, 3))
|
---|
112 | return -1;
|
---|
113 | return 3;
|
---|
114 | }
|
---|
115 | /*
|
---|
116 | * If we get this far and do any escaping at all must escape the escape
|
---|
117 | * character itself: backslash.
|
---|
118 | */
|
---|
119 | if (chtmp == '\\' && flags & ESC_FLAGS) {
|
---|
120 | if (!io_ch(arg, "\\\\", 2))
|
---|
121 | return -1;
|
---|
122 | return 2;
|
---|
123 | }
|
---|
124 | if (!io_ch(arg, &chtmp, 1))
|
---|
125 | return -1;
|
---|
126 | return 1;
|
---|
127 | }
|
---|
128 |
|
---|
129 | #define BUF_TYPE_WIDTH_MASK 0x7
|
---|
130 | #define BUF_TYPE_CONVUTF8 0x8
|
---|
131 |
|
---|
132 | /*
|
---|
133 | * This function sends each character in a buffer to do_esc_char(). It
|
---|
134 | * interprets the content formats and converts to or from UTF8 as
|
---|
135 | * appropriate.
|
---|
136 | */
|
---|
137 |
|
---|
138 | static int do_buf(unsigned char *buf, int buflen,
|
---|
139 | int type, unsigned short flags, char *quotes, char_io *io_ch,
|
---|
140 | void *arg)
|
---|
141 | {
|
---|
142 | int i, outlen, len;
|
---|
143 | unsigned short orflags;
|
---|
144 | unsigned char *p, *q;
|
---|
145 | unsigned long c;
|
---|
146 | p = buf;
|
---|
147 | q = buf + buflen;
|
---|
148 | outlen = 0;
|
---|
149 | while (p != q) {
|
---|
150 | if (p == buf && flags & ASN1_STRFLGS_ESC_2253)
|
---|
151 | orflags = CHARTYPE_FIRST_ESC_2253;
|
---|
152 | else
|
---|
153 | orflags = 0;
|
---|
154 | switch (type & BUF_TYPE_WIDTH_MASK) {
|
---|
155 | case 4:
|
---|
156 | c = ((unsigned long)*p++) << 24;
|
---|
157 | c |= ((unsigned long)*p++) << 16;
|
---|
158 | c |= ((unsigned long)*p++) << 8;
|
---|
159 | c |= *p++;
|
---|
160 | break;
|
---|
161 |
|
---|
162 | case 2:
|
---|
163 | c = ((unsigned long)*p++) << 8;
|
---|
164 | c |= *p++;
|
---|
165 | break;
|
---|
166 |
|
---|
167 | case 1:
|
---|
168 | c = *p++;
|
---|
169 | break;
|
---|
170 |
|
---|
171 | case 0:
|
---|
172 | i = UTF8_getc(p, buflen, &c);
|
---|
173 | if (i < 0)
|
---|
174 | return -1; /* Invalid UTF8String */
|
---|
175 | p += i;
|
---|
176 | break;
|
---|
177 | default:
|
---|
178 | return -1; /* invalid width */
|
---|
179 | }
|
---|
180 | if (p == q && flags & ASN1_STRFLGS_ESC_2253)
|
---|
181 | orflags = CHARTYPE_LAST_ESC_2253;
|
---|
182 | if (type & BUF_TYPE_CONVUTF8) {
|
---|
183 | unsigned char utfbuf[6];
|
---|
184 | int utflen;
|
---|
185 | utflen = UTF8_putc(utfbuf, sizeof utfbuf, c);
|
---|
186 | for (i = 0; i < utflen; i++) {
|
---|
187 | /*
|
---|
188 | * We don't need to worry about setting orflags correctly
|
---|
189 | * because if utflen==1 its value will be correct anyway
|
---|
190 | * otherwise each character will be > 0x7f and so the
|
---|
191 | * character will never be escaped on first and last.
|
---|
192 | */
|
---|
193 | len =
|
---|
194 | do_esc_char(utfbuf[i], (unsigned short)(flags | orflags),
|
---|
195 | quotes, io_ch, arg);
|
---|
196 | if (len < 0)
|
---|
197 | return -1;
|
---|
198 | outlen += len;
|
---|
199 | }
|
---|
200 | } else {
|
---|
201 | len =
|
---|
202 | do_esc_char(c, (unsigned short)(flags | orflags), quotes,
|
---|
203 | io_ch, arg);
|
---|
204 | if (len < 0)
|
---|
205 | return -1;
|
---|
206 | outlen += len;
|
---|
207 | }
|
---|
208 | }
|
---|
209 | return outlen;
|
---|
210 | }
|
---|
211 |
|
---|
212 | /* This function hex dumps a buffer of characters */
|
---|
213 |
|
---|
214 | static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf,
|
---|
215 | int buflen)
|
---|
216 | {
|
---|
217 | static const char hexdig[] = "0123456789ABCDEF";
|
---|
218 | unsigned char *p, *q;
|
---|
219 | char hextmp[2];
|
---|
220 | if (arg) {
|
---|
221 | p = buf;
|
---|
222 | q = buf + buflen;
|
---|
223 | while (p != q) {
|
---|
224 | hextmp[0] = hexdig[*p >> 4];
|
---|
225 | hextmp[1] = hexdig[*p & 0xf];
|
---|
226 | if (!io_ch(arg, hextmp, 2))
|
---|
227 | return -1;
|
---|
228 | p++;
|
---|
229 | }
|
---|
230 | }
|
---|
231 | return buflen << 1;
|
---|
232 | }
|
---|
233 |
|
---|
234 | /*
|
---|
235 | * "dump" a string. This is done when the type is unknown, or the flags
|
---|
236 | * request it. We can either dump the content octets or the entire DER
|
---|
237 | * encoding. This uses the RFC2253 #01234 format.
|
---|
238 | */
|
---|
239 |
|
---|
240 | static int do_dump(unsigned long lflags, char_io *io_ch, void *arg,
|
---|
241 | const ASN1_STRING *str)
|
---|
242 | {
|
---|
243 | /*
|
---|
244 | * Placing the ASN1_STRING in a temp ASN1_TYPE allows the DER encoding to
|
---|
245 | * readily obtained
|
---|
246 | */
|
---|
247 | ASN1_TYPE t;
|
---|
248 | unsigned char *der_buf, *p;
|
---|
249 | int outlen, der_len;
|
---|
250 |
|
---|
251 | if (!io_ch(arg, "#", 1))
|
---|
252 | return -1;
|
---|
253 | /* If we don't dump DER encoding just dump content octets */
|
---|
254 | if (!(lflags & ASN1_STRFLGS_DUMP_DER)) {
|
---|
255 | outlen = do_hex_dump(io_ch, arg, str->data, str->length);
|
---|
256 | if (outlen < 0)
|
---|
257 | return -1;
|
---|
258 | return outlen + 1;
|
---|
259 | }
|
---|
260 | t.type = str->type;
|
---|
261 | t.value.ptr = (char *)str;
|
---|
262 | der_len = i2d_ASN1_TYPE(&t, NULL);
|
---|
263 | der_buf = OPENSSL_malloc(der_len);
|
---|
264 | if (der_buf == NULL)
|
---|
265 | return -1;
|
---|
266 | p = der_buf;
|
---|
267 | i2d_ASN1_TYPE(&t, &p);
|
---|
268 | outlen = do_hex_dump(io_ch, arg, der_buf, der_len);
|
---|
269 | OPENSSL_free(der_buf);
|
---|
270 | if (outlen < 0)
|
---|
271 | return -1;
|
---|
272 | return outlen + 1;
|
---|
273 | }
|
---|
274 |
|
---|
275 | /*
|
---|
276 | * Lookup table to convert tags to character widths, 0 = UTF8 encoded, -1 is
|
---|
277 | * used for non string types otherwise it is the number of bytes per
|
---|
278 | * character
|
---|
279 | */
|
---|
280 |
|
---|
281 | static const signed char tag2nbyte[] = {
|
---|
282 | -1, -1, -1, -1, -1, /* 0-4 */
|
---|
283 | -1, -1, -1, -1, -1, /* 5-9 */
|
---|
284 | -1, -1, 0, -1, /* 10-13 */
|
---|
285 | -1, -1, -1, -1, /* 15-17 */
|
---|
286 | 1, 1, 1, /* 18-20 */
|
---|
287 | -1, 1, 1, 1, /* 21-24 */
|
---|
288 | -1, 1, -1, /* 25-27 */
|
---|
289 | 4, -1, 2 /* 28-30 */
|
---|
290 | };
|
---|
291 |
|
---|
292 | /*
|
---|
293 | * This is the main function, print out an ASN1_STRING taking note of various
|
---|
294 | * escape and display options. Returns number of characters written or -1 if
|
---|
295 | * an error occurred.
|
---|
296 | */
|
---|
297 |
|
---|
298 | static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags,
|
---|
299 | const ASN1_STRING *str)
|
---|
300 | {
|
---|
301 | int outlen, len;
|
---|
302 | int type;
|
---|
303 | char quotes;
|
---|
304 | unsigned short flags;
|
---|
305 | quotes = 0;
|
---|
306 | /* Keep a copy of escape flags */
|
---|
307 | flags = (unsigned short)(lflags & ESC_FLAGS);
|
---|
308 |
|
---|
309 | type = str->type;
|
---|
310 |
|
---|
311 | outlen = 0;
|
---|
312 |
|
---|
313 | if (lflags & ASN1_STRFLGS_SHOW_TYPE) {
|
---|
314 | const char *tagname;
|
---|
315 | tagname = ASN1_tag2str(type);
|
---|
316 | outlen += strlen(tagname);
|
---|
317 | if (!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1))
|
---|
318 | return -1;
|
---|
319 | outlen++;
|
---|
320 | }
|
---|
321 |
|
---|
322 | /* Decide what to do with type, either dump content or display it */
|
---|
323 |
|
---|
324 | /* Dump everything */
|
---|
325 | if (lflags & ASN1_STRFLGS_DUMP_ALL)
|
---|
326 | type = -1;
|
---|
327 | /* Ignore the string type */
|
---|
328 | else if (lflags & ASN1_STRFLGS_IGNORE_TYPE)
|
---|
329 | type = 1;
|
---|
330 | else {
|
---|
331 | /* Else determine width based on type */
|
---|
332 | if ((type > 0) && (type < 31))
|
---|
333 | type = tag2nbyte[type];
|
---|
334 | else
|
---|
335 | type = -1;
|
---|
336 | if ((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN))
|
---|
337 | type = 1;
|
---|
338 | }
|
---|
339 |
|
---|
340 | if (type == -1) {
|
---|
341 | len = do_dump(lflags, io_ch, arg, str);
|
---|
342 | if (len < 0)
|
---|
343 | return -1;
|
---|
344 | outlen += len;
|
---|
345 | return outlen;
|
---|
346 | }
|
---|
347 |
|
---|
348 | if (lflags & ASN1_STRFLGS_UTF8_CONVERT) {
|
---|
349 | /*
|
---|
350 | * Note: if string is UTF8 and we want to convert to UTF8 then we
|
---|
351 | * just interpret it as 1 byte per character to avoid converting
|
---|
352 | * twice.
|
---|
353 | */
|
---|
354 | if (!type)
|
---|
355 | type = 1;
|
---|
356 | else
|
---|
357 | type |= BUF_TYPE_CONVUTF8;
|
---|
358 | }
|
---|
359 |
|
---|
360 | len = do_buf(str->data, str->length, type, flags, "es, io_ch, NULL);
|
---|
361 | if (len < 0)
|
---|
362 | return -1;
|
---|
363 | outlen += len;
|
---|
364 | if (quotes)
|
---|
365 | outlen += 2;
|
---|
366 | if (!arg)
|
---|
367 | return outlen;
|
---|
368 | if (quotes && !io_ch(arg, "\"", 1))
|
---|
369 | return -1;
|
---|
370 | if (do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0)
|
---|
371 | return -1;
|
---|
372 | if (quotes && !io_ch(arg, "\"", 1))
|
---|
373 | return -1;
|
---|
374 | return outlen;
|
---|
375 | }
|
---|
376 |
|
---|
377 | /* Used for line indenting: print 'indent' spaces */
|
---|
378 |
|
---|
379 | static int do_indent(char_io *io_ch, void *arg, int indent)
|
---|
380 | {
|
---|
381 | int i;
|
---|
382 | for (i = 0; i < indent; i++)
|
---|
383 | if (!io_ch(arg, " ", 1))
|
---|
384 | return 0;
|
---|
385 | return 1;
|
---|
386 | }
|
---|
387 |
|
---|
388 | #define FN_WIDTH_LN 25
|
---|
389 | #define FN_WIDTH_SN 10
|
---|
390 |
|
---|
391 | static int do_name_ex(char_io *io_ch, void *arg, const X509_NAME *n,
|
---|
392 | int indent, unsigned long flags)
|
---|
393 | {
|
---|
394 | int i, prev = -1, orflags, cnt;
|
---|
395 | int fn_opt, fn_nid;
|
---|
396 | ASN1_OBJECT *fn;
|
---|
397 | const ASN1_STRING *val;
|
---|
398 | const X509_NAME_ENTRY *ent;
|
---|
399 | char objtmp[80];
|
---|
400 | const char *objbuf;
|
---|
401 | int outlen, len;
|
---|
402 | char *sep_dn, *sep_mv, *sep_eq;
|
---|
403 | int sep_dn_len, sep_mv_len, sep_eq_len;
|
---|
404 | if (indent < 0)
|
---|
405 | indent = 0;
|
---|
406 | outlen = indent;
|
---|
407 | if (!do_indent(io_ch, arg, indent))
|
---|
408 | return -1;
|
---|
409 | switch (flags & XN_FLAG_SEP_MASK) {
|
---|
410 | case XN_FLAG_SEP_MULTILINE:
|
---|
411 | sep_dn = "\n";
|
---|
412 | sep_dn_len = 1;
|
---|
413 | sep_mv = " + ";
|
---|
414 | sep_mv_len = 3;
|
---|
415 | break;
|
---|
416 |
|
---|
417 | case XN_FLAG_SEP_COMMA_PLUS:
|
---|
418 | sep_dn = ",";
|
---|
419 | sep_dn_len = 1;
|
---|
420 | sep_mv = "+";
|
---|
421 | sep_mv_len = 1;
|
---|
422 | indent = 0;
|
---|
423 | break;
|
---|
424 |
|
---|
425 | case XN_FLAG_SEP_CPLUS_SPC:
|
---|
426 | sep_dn = ", ";
|
---|
427 | sep_dn_len = 2;
|
---|
428 | sep_mv = " + ";
|
---|
429 | sep_mv_len = 3;
|
---|
430 | indent = 0;
|
---|
431 | break;
|
---|
432 |
|
---|
433 | case XN_FLAG_SEP_SPLUS_SPC:
|
---|
434 | sep_dn = "; ";
|
---|
435 | sep_dn_len = 2;
|
---|
436 | sep_mv = " + ";
|
---|
437 | sep_mv_len = 3;
|
---|
438 | indent = 0;
|
---|
439 | break;
|
---|
440 |
|
---|
441 | default:
|
---|
442 | return -1;
|
---|
443 | }
|
---|
444 |
|
---|
445 | if (flags & XN_FLAG_SPC_EQ) {
|
---|
446 | sep_eq = " = ";
|
---|
447 | sep_eq_len = 3;
|
---|
448 | } else {
|
---|
449 | sep_eq = "=";
|
---|
450 | sep_eq_len = 1;
|
---|
451 | }
|
---|
452 |
|
---|
453 | fn_opt = flags & XN_FLAG_FN_MASK;
|
---|
454 |
|
---|
455 | cnt = X509_NAME_entry_count(n);
|
---|
456 | for (i = 0; i < cnt; i++) {
|
---|
457 | if (flags & XN_FLAG_DN_REV)
|
---|
458 | ent = X509_NAME_get_entry(n, cnt - i - 1);
|
---|
459 | else
|
---|
460 | ent = X509_NAME_get_entry(n, i);
|
---|
461 | if (prev != -1) {
|
---|
462 | if (prev == X509_NAME_ENTRY_set(ent)) {
|
---|
463 | if (!io_ch(arg, sep_mv, sep_mv_len))
|
---|
464 | return -1;
|
---|
465 | outlen += sep_mv_len;
|
---|
466 | } else {
|
---|
467 | if (!io_ch(arg, sep_dn, sep_dn_len))
|
---|
468 | return -1;
|
---|
469 | outlen += sep_dn_len;
|
---|
470 | if (!do_indent(io_ch, arg, indent))
|
---|
471 | return -1;
|
---|
472 | outlen += indent;
|
---|
473 | }
|
---|
474 | }
|
---|
475 | prev = X509_NAME_ENTRY_set(ent);
|
---|
476 | fn = X509_NAME_ENTRY_get_object(ent);
|
---|
477 | val = X509_NAME_ENTRY_get_data(ent);
|
---|
478 | fn_nid = OBJ_obj2nid(fn);
|
---|
479 | if (fn_opt != XN_FLAG_FN_NONE) {
|
---|
480 | int objlen, fld_len;
|
---|
481 | if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) {
|
---|
482 | OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1);
|
---|
483 | fld_len = 0; /* XXX: what should this be? */
|
---|
484 | objbuf = objtmp;
|
---|
485 | } else {
|
---|
486 | if (fn_opt == XN_FLAG_FN_SN) {
|
---|
487 | fld_len = FN_WIDTH_SN;
|
---|
488 | objbuf = OBJ_nid2sn(fn_nid);
|
---|
489 | } else if (fn_opt == XN_FLAG_FN_LN) {
|
---|
490 | fld_len = FN_WIDTH_LN;
|
---|
491 | objbuf = OBJ_nid2ln(fn_nid);
|
---|
492 | } else {
|
---|
493 | fld_len = 0; /* XXX: what should this be? */
|
---|
494 | objbuf = "";
|
---|
495 | }
|
---|
496 | }
|
---|
497 | objlen = strlen(objbuf);
|
---|
498 | if (!io_ch(arg, objbuf, objlen))
|
---|
499 | return -1;
|
---|
500 | if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
|
---|
501 | if (!do_indent(io_ch, arg, fld_len - objlen))
|
---|
502 | return -1;
|
---|
503 | outlen += fld_len - objlen;
|
---|
504 | }
|
---|
505 | if (!io_ch(arg, sep_eq, sep_eq_len))
|
---|
506 | return -1;
|
---|
507 | outlen += objlen + sep_eq_len;
|
---|
508 | }
|
---|
509 | /*
|
---|
510 | * If the field name is unknown then fix up the DER dump flag. We
|
---|
511 | * might want to limit this further so it will DER dump on anything
|
---|
512 | * other than a few 'standard' fields.
|
---|
513 | */
|
---|
514 | if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS))
|
---|
515 | orflags = ASN1_STRFLGS_DUMP_ALL;
|
---|
516 | else
|
---|
517 | orflags = 0;
|
---|
518 |
|
---|
519 | len = do_print_ex(io_ch, arg, flags | orflags, val);
|
---|
520 | if (len < 0)
|
---|
521 | return -1;
|
---|
522 | outlen += len;
|
---|
523 | }
|
---|
524 | return outlen;
|
---|
525 | }
|
---|
526 |
|
---|
527 | /* Wrappers round the main functions */
|
---|
528 |
|
---|
529 | int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent,
|
---|
530 | unsigned long flags)
|
---|
531 | {
|
---|
532 | if (flags == XN_FLAG_COMPAT)
|
---|
533 | return X509_NAME_print(out, nm, indent);
|
---|
534 | return do_name_ex(send_bio_chars, out, nm, indent, flags);
|
---|
535 | }
|
---|
536 |
|
---|
537 | #ifndef OPENSSL_NO_STDIO
|
---|
538 | int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent,
|
---|
539 | unsigned long flags)
|
---|
540 | {
|
---|
541 | if (flags == XN_FLAG_COMPAT) {
|
---|
542 | BIO *btmp;
|
---|
543 | int ret;
|
---|
544 | btmp = BIO_new_fp(fp, BIO_NOCLOSE);
|
---|
545 | if (!btmp)
|
---|
546 | return -1;
|
---|
547 | ret = X509_NAME_print(btmp, nm, indent);
|
---|
548 | BIO_free(btmp);
|
---|
549 | return ret;
|
---|
550 | }
|
---|
551 | return do_name_ex(send_fp_chars, fp, nm, indent, flags);
|
---|
552 | }
|
---|
553 | #endif
|
---|
554 |
|
---|
555 | int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags)
|
---|
556 | {
|
---|
557 | return do_print_ex(send_bio_chars, out, flags, str);
|
---|
558 | }
|
---|
559 |
|
---|
560 | #ifndef OPENSSL_NO_STDIO
|
---|
561 | int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags)
|
---|
562 | {
|
---|
563 | return do_print_ex(send_fp_chars, fp, flags, str);
|
---|
564 | }
|
---|
565 | #endif
|
---|
566 |
|
---|
567 | /*
|
---|
568 | * Utility function: convert any string type to UTF8, returns number of bytes
|
---|
569 | * in output string or a negative error code
|
---|
570 | */
|
---|
571 |
|
---|
572 | int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in)
|
---|
573 | {
|
---|
574 | ASN1_STRING stmp, *str = &stmp;
|
---|
575 | int mbflag, type, ret;
|
---|
576 | if (!in)
|
---|
577 | return -1;
|
---|
578 | type = in->type;
|
---|
579 | if ((type < 0) || (type > 30))
|
---|
580 | return -1;
|
---|
581 | mbflag = tag2nbyte[type];
|
---|
582 | if (mbflag == -1)
|
---|
583 | return -1;
|
---|
584 | mbflag |= MBSTRING_FLAG;
|
---|
585 | stmp.data = NULL;
|
---|
586 | stmp.length = 0;
|
---|
587 | stmp.flags = 0;
|
---|
588 | ret =
|
---|
589 | ASN1_mbstring_copy(&str, in->data, in->length, mbflag,
|
---|
590 | B_ASN1_UTF8STRING);
|
---|
591 | if (ret < 0)
|
---|
592 | return ret;
|
---|
593 | *out = stmp.data;
|
---|
594 | return stmp.length;
|
---|
595 | }
|
---|
596 |
|
---|
597 | /* Return 1 if host is a valid hostname and 0 otherwise */
|
---|
598 | int asn1_valid_host(const ASN1_STRING *host)
|
---|
599 | {
|
---|
600 | int hostlen = host->length;
|
---|
601 | const unsigned char *hostptr = host->data;
|
---|
602 | int type = host->type;
|
---|
603 | int i;
|
---|
604 | char width = -1;
|
---|
605 | unsigned short chflags = 0, prevchflags;
|
---|
606 |
|
---|
607 | if (type > 0 && type < 31)
|
---|
608 | width = tag2nbyte[type];
|
---|
609 | if (width == -1 || hostlen == 0)
|
---|
610 | return 0;
|
---|
611 | /* Treat UTF8String as width 1 as any MSB set is invalid */
|
---|
612 | if (width == 0)
|
---|
613 | width = 1;
|
---|
614 | for (i = 0 ; i < hostlen; i+= width) {
|
---|
615 | prevchflags = chflags;
|
---|
616 | /* Value must be <= 0x7F: check upper bytes are all zeroes */
|
---|
617 | if (width == 4) {
|
---|
618 | if (*hostptr++ != 0 || *hostptr++ != 0 || *hostptr++ != 0)
|
---|
619 | return 0;
|
---|
620 | } else if (width == 2) {
|
---|
621 | if (*hostptr++ != 0)
|
---|
622 | return 0;
|
---|
623 | }
|
---|
624 | if (*hostptr > 0x7f)
|
---|
625 | return 0;
|
---|
626 | chflags = char_type[*hostptr++];
|
---|
627 | if (!(chflags & (CHARTYPE_HOST_ANY | CHARTYPE_HOST_WILD))) {
|
---|
628 | /* Nothing else allowed at start or end of string */
|
---|
629 | if (i == 0 || i == hostlen - 1)
|
---|
630 | return 0;
|
---|
631 | /* Otherwise invalid if not dot or hyphen */
|
---|
632 | if (!(chflags & (CHARTYPE_HOST_DOT | CHARTYPE_HOST_HYPHEN)))
|
---|
633 | return 0;
|
---|
634 | /*
|
---|
635 | * If previous is dot or hyphen then illegal unless both
|
---|
636 | * are hyphens: as .- -. .. are all illegal
|
---|
637 | */
|
---|
638 | if (prevchflags & (CHARTYPE_HOST_DOT | CHARTYPE_HOST_HYPHEN)
|
---|
639 | && ((prevchflags & CHARTYPE_HOST_DOT)
|
---|
640 | || (chflags & CHARTYPE_HOST_DOT)))
|
---|
641 | return 0;
|
---|
642 | }
|
---|
643 | }
|
---|
644 | return 1;
|
---|
645 | }
|
---|