1 | /*
|
---|
2 | * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License 2.0 (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 "crypto/asn1.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 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 short 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, charwidth;
|
---|
143 | unsigned short orflags;
|
---|
144 | unsigned char *p, *q;
|
---|
145 | unsigned long c;
|
---|
146 |
|
---|
147 | p = buf;
|
---|
148 | q = buf + buflen;
|
---|
149 | outlen = 0;
|
---|
150 | charwidth = type & BUF_TYPE_WIDTH_MASK;
|
---|
151 |
|
---|
152 | switch (charwidth) {
|
---|
153 | case 4:
|
---|
154 | if (buflen & 3) {
|
---|
155 | ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
|
---|
156 | return -1;
|
---|
157 | }
|
---|
158 | break;
|
---|
159 | case 2:
|
---|
160 | if (buflen & 1) {
|
---|
161 | ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
|
---|
162 | return -1;
|
---|
163 | }
|
---|
164 | break;
|
---|
165 | default:
|
---|
166 | break;
|
---|
167 | }
|
---|
168 |
|
---|
169 | while (p != q) {
|
---|
170 | if (p == buf && flags & ASN1_STRFLGS_ESC_2253)
|
---|
171 | orflags = CHARTYPE_FIRST_ESC_2253;
|
---|
172 | else
|
---|
173 | orflags = 0;
|
---|
174 |
|
---|
175 | switch (charwidth) {
|
---|
176 | case 4:
|
---|
177 | c = ((unsigned long)*p++) << 24;
|
---|
178 | c |= ((unsigned long)*p++) << 16;
|
---|
179 | c |= ((unsigned long)*p++) << 8;
|
---|
180 | c |= *p++;
|
---|
181 | break;
|
---|
182 |
|
---|
183 | case 2:
|
---|
184 | c = ((unsigned long)*p++) << 8;
|
---|
185 | c |= *p++;
|
---|
186 | break;
|
---|
187 |
|
---|
188 | case 1:
|
---|
189 | c = *p++;
|
---|
190 | break;
|
---|
191 |
|
---|
192 | case 0:
|
---|
193 | i = UTF8_getc(p, buflen, &c);
|
---|
194 | if (i < 0)
|
---|
195 | return -1; /* Invalid UTF8String */
|
---|
196 | buflen -= i;
|
---|
197 | p += i;
|
---|
198 | break;
|
---|
199 | default:
|
---|
200 | return -1; /* invalid width */
|
---|
201 | }
|
---|
202 | if (p == q && flags & ASN1_STRFLGS_ESC_2253)
|
---|
203 | orflags = CHARTYPE_LAST_ESC_2253;
|
---|
204 | if (type & BUF_TYPE_CONVUTF8) {
|
---|
205 | unsigned char utfbuf[6];
|
---|
206 | int utflen;
|
---|
207 | utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c);
|
---|
208 | for (i = 0; i < utflen; i++) {
|
---|
209 | /*
|
---|
210 | * We don't need to worry about setting orflags correctly
|
---|
211 | * because if utflen==1 its value will be correct anyway
|
---|
212 | * otherwise each character will be > 0x7f and so the
|
---|
213 | * character will never be escaped on first and last.
|
---|
214 | */
|
---|
215 | len = do_esc_char(utfbuf[i], flags | orflags, quotes,
|
---|
216 | io_ch, arg);
|
---|
217 | if (len < 0)
|
---|
218 | return -1;
|
---|
219 | outlen += len;
|
---|
220 | }
|
---|
221 | } else {
|
---|
222 | len = do_esc_char(c, flags | orflags, quotes,
|
---|
223 | io_ch, arg);
|
---|
224 | if (len < 0)
|
---|
225 | return -1;
|
---|
226 | outlen += len;
|
---|
227 | }
|
---|
228 | }
|
---|
229 | return outlen;
|
---|
230 | }
|
---|
231 |
|
---|
232 | /* This function hex dumps a buffer of characters */
|
---|
233 |
|
---|
234 | static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf,
|
---|
235 | int buflen)
|
---|
236 | {
|
---|
237 | static const char hexdig[] = "0123456789ABCDEF";
|
---|
238 | unsigned char *p, *q;
|
---|
239 | char hextmp[2];
|
---|
240 | if (arg) {
|
---|
241 | p = buf;
|
---|
242 | q = buf + buflen;
|
---|
243 | while (p != q) {
|
---|
244 | hextmp[0] = hexdig[*p >> 4];
|
---|
245 | hextmp[1] = hexdig[*p & 0xf];
|
---|
246 | if (!io_ch(arg, hextmp, 2))
|
---|
247 | return -1;
|
---|
248 | p++;
|
---|
249 | }
|
---|
250 | }
|
---|
251 | return buflen << 1;
|
---|
252 | }
|
---|
253 |
|
---|
254 | /*
|
---|
255 | * "dump" a string. This is done when the type is unknown, or the flags
|
---|
256 | * request it. We can either dump the content octets or the entire DER
|
---|
257 | * encoding. This uses the RFC2253 #01234 format.
|
---|
258 | */
|
---|
259 |
|
---|
260 | static int do_dump(unsigned long lflags, char_io *io_ch, void *arg,
|
---|
261 | const ASN1_STRING *str)
|
---|
262 | {
|
---|
263 | /*
|
---|
264 | * Placing the ASN1_STRING in a temp ASN1_TYPE allows the DER encoding to
|
---|
265 | * readily obtained
|
---|
266 | */
|
---|
267 | ASN1_TYPE t;
|
---|
268 | unsigned char *der_buf, *p;
|
---|
269 | int outlen, der_len;
|
---|
270 |
|
---|
271 | if (!io_ch(arg, "#", 1))
|
---|
272 | return -1;
|
---|
273 | /* If we don't dump DER encoding just dump content octets */
|
---|
274 | if (!(lflags & ASN1_STRFLGS_DUMP_DER)) {
|
---|
275 | outlen = do_hex_dump(io_ch, arg, str->data, str->length);
|
---|
276 | if (outlen < 0)
|
---|
277 | return -1;
|
---|
278 | return outlen + 1;
|
---|
279 | }
|
---|
280 | t.type = str->type;
|
---|
281 | t.value.ptr = (char *)str;
|
---|
282 | der_len = i2d_ASN1_TYPE(&t, NULL);
|
---|
283 | if (der_len <= 0)
|
---|
284 | return -1;
|
---|
285 | if ((der_buf = OPENSSL_malloc(der_len)) == NULL) {
|
---|
286 | ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
|
---|
287 | return -1;
|
---|
288 | }
|
---|
289 | p = der_buf;
|
---|
290 | i2d_ASN1_TYPE(&t, &p);
|
---|
291 | outlen = do_hex_dump(io_ch, arg, der_buf, der_len);
|
---|
292 | OPENSSL_free(der_buf);
|
---|
293 | if (outlen < 0)
|
---|
294 | return -1;
|
---|
295 | return outlen + 1;
|
---|
296 | }
|
---|
297 |
|
---|
298 | /*
|
---|
299 | * Lookup table to convert tags to character widths, 0 = UTF8 encoded, -1 is
|
---|
300 | * used for non string types otherwise it is the number of bytes per
|
---|
301 | * character
|
---|
302 | */
|
---|
303 |
|
---|
304 | static const signed char tag2nbyte[] = {
|
---|
305 | -1, -1, -1, -1, -1, /* 0-4 */
|
---|
306 | -1, -1, -1, -1, -1, /* 5-9 */
|
---|
307 | -1, -1, /* 10-11 */
|
---|
308 | 0, /* 12 V_ASN1_UTF8STRING */
|
---|
309 | -1, -1, -1, -1, -1, /* 13-17 */
|
---|
310 | 1, /* 18 V_ASN1_NUMERICSTRING */
|
---|
311 | 1, /* 19 V_ASN1_PRINTABLESTRING */
|
---|
312 | 1, /* 20 V_ASN1_T61STRING */
|
---|
313 | -1, /* 21 */
|
---|
314 | 1, /* 22 V_ASN1_IA5STRING */
|
---|
315 | 1, /* 23 V_ASN1_UTCTIME */
|
---|
316 | 1, /* 24 V_ASN1_GENERALIZEDTIME */
|
---|
317 | -1, /* 25 */
|
---|
318 | 1, /* 26 V_ASN1_ISO64STRING */
|
---|
319 | -1, /* 27 */
|
---|
320 | 4, /* 28 V_ASN1_UNIVERSALSTRING */
|
---|
321 | -1, /* 29 */
|
---|
322 | 2 /* 30 V_ASN1_BMPSTRING */
|
---|
323 | };
|
---|
324 |
|
---|
325 | /*
|
---|
326 | * This is the main function, print out an ASN1_STRING taking note of various
|
---|
327 | * escape and display options. Returns number of characters written or -1 if
|
---|
328 | * an error occurred.
|
---|
329 | */
|
---|
330 |
|
---|
331 | static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags,
|
---|
332 | const ASN1_STRING *str)
|
---|
333 | {
|
---|
334 | int outlen, len;
|
---|
335 | int type;
|
---|
336 | char quotes;
|
---|
337 | unsigned short flags;
|
---|
338 | quotes = 0;
|
---|
339 | /* Keep a copy of escape flags */
|
---|
340 | flags = (unsigned short)(lflags & ESC_FLAGS);
|
---|
341 |
|
---|
342 | type = str->type;
|
---|
343 |
|
---|
344 | outlen = 0;
|
---|
345 |
|
---|
346 | if (lflags & ASN1_STRFLGS_SHOW_TYPE) {
|
---|
347 | const char *tagname;
|
---|
348 | tagname = ASN1_tag2str(type);
|
---|
349 | outlen += strlen(tagname);
|
---|
350 | if (!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1))
|
---|
351 | return -1;
|
---|
352 | outlen++;
|
---|
353 | }
|
---|
354 |
|
---|
355 | /* Decide what to do with type, either dump content or display it */
|
---|
356 |
|
---|
357 | /* Dump everything */
|
---|
358 | if (lflags & ASN1_STRFLGS_DUMP_ALL)
|
---|
359 | type = -1;
|
---|
360 | /* Ignore the string type */
|
---|
361 | else if (lflags & ASN1_STRFLGS_IGNORE_TYPE)
|
---|
362 | type = 1;
|
---|
363 | else {
|
---|
364 | /* Else determine width based on type */
|
---|
365 | if ((type > 0) && (type < 31))
|
---|
366 | type = tag2nbyte[type];
|
---|
367 | else
|
---|
368 | type = -1;
|
---|
369 | if ((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN))
|
---|
370 | type = 1;
|
---|
371 | }
|
---|
372 |
|
---|
373 | if (type == -1) {
|
---|
374 | len = do_dump(lflags, io_ch, arg, str);
|
---|
375 | if (len < 0)
|
---|
376 | return -1;
|
---|
377 | outlen += len;
|
---|
378 | return outlen;
|
---|
379 | }
|
---|
380 |
|
---|
381 | if (lflags & ASN1_STRFLGS_UTF8_CONVERT) {
|
---|
382 | /*
|
---|
383 | * Note: if string is UTF8 and we want to convert to UTF8 then we
|
---|
384 | * just interpret it as 1 byte per character to avoid converting
|
---|
385 | * twice.
|
---|
386 | */
|
---|
387 | if (!type)
|
---|
388 | type = 1;
|
---|
389 | else
|
---|
390 | type |= BUF_TYPE_CONVUTF8;
|
---|
391 | }
|
---|
392 |
|
---|
393 | len = do_buf(str->data, str->length, type, flags, "es, io_ch, NULL);
|
---|
394 | if (len < 0)
|
---|
395 | return -1;
|
---|
396 | outlen += len;
|
---|
397 | if (quotes)
|
---|
398 | outlen += 2;
|
---|
399 | if (!arg)
|
---|
400 | return outlen;
|
---|
401 | if (quotes && !io_ch(arg, "\"", 1))
|
---|
402 | return -1;
|
---|
403 | if (do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0)
|
---|
404 | return -1;
|
---|
405 | if (quotes && !io_ch(arg, "\"", 1))
|
---|
406 | return -1;
|
---|
407 | return outlen;
|
---|
408 | }
|
---|
409 |
|
---|
410 | /* Used for line indenting: print 'indent' spaces */
|
---|
411 |
|
---|
412 | static int do_indent(char_io *io_ch, void *arg, int indent)
|
---|
413 | {
|
---|
414 | int i;
|
---|
415 | for (i = 0; i < indent; i++)
|
---|
416 | if (!io_ch(arg, " ", 1))
|
---|
417 | return 0;
|
---|
418 | return 1;
|
---|
419 | }
|
---|
420 |
|
---|
421 | #define FN_WIDTH_LN 25
|
---|
422 | #define FN_WIDTH_SN 10
|
---|
423 |
|
---|
424 | static int do_name_ex(char_io *io_ch, void *arg, const X509_NAME *n,
|
---|
425 | int indent, unsigned long flags)
|
---|
426 | {
|
---|
427 | int i, prev = -1, orflags, cnt;
|
---|
428 | int fn_opt, fn_nid;
|
---|
429 | ASN1_OBJECT *fn;
|
---|
430 | const ASN1_STRING *val;
|
---|
431 | const X509_NAME_ENTRY *ent;
|
---|
432 | char objtmp[80];
|
---|
433 | const char *objbuf;
|
---|
434 | int outlen, len;
|
---|
435 | char *sep_dn, *sep_mv, *sep_eq;
|
---|
436 | int sep_dn_len, sep_mv_len, sep_eq_len;
|
---|
437 | if (indent < 0)
|
---|
438 | indent = 0;
|
---|
439 | outlen = indent;
|
---|
440 | if (!do_indent(io_ch, arg, indent))
|
---|
441 | return -1;
|
---|
442 | switch (flags & XN_FLAG_SEP_MASK) {
|
---|
443 | case XN_FLAG_SEP_MULTILINE:
|
---|
444 | sep_dn = "\n";
|
---|
445 | sep_dn_len = 1;
|
---|
446 | sep_mv = " + ";
|
---|
447 | sep_mv_len = 3;
|
---|
448 | break;
|
---|
449 |
|
---|
450 | case XN_FLAG_SEP_COMMA_PLUS:
|
---|
451 | sep_dn = ",";
|
---|
452 | sep_dn_len = 1;
|
---|
453 | sep_mv = "+";
|
---|
454 | sep_mv_len = 1;
|
---|
455 | indent = 0;
|
---|
456 | break;
|
---|
457 |
|
---|
458 | case XN_FLAG_SEP_CPLUS_SPC:
|
---|
459 | sep_dn = ", ";
|
---|
460 | sep_dn_len = 2;
|
---|
461 | sep_mv = " + ";
|
---|
462 | sep_mv_len = 3;
|
---|
463 | indent = 0;
|
---|
464 | break;
|
---|
465 |
|
---|
466 | case XN_FLAG_SEP_SPLUS_SPC:
|
---|
467 | sep_dn = "; ";
|
---|
468 | sep_dn_len = 2;
|
---|
469 | sep_mv = " + ";
|
---|
470 | sep_mv_len = 3;
|
---|
471 | indent = 0;
|
---|
472 | break;
|
---|
473 |
|
---|
474 | default:
|
---|
475 | return -1;
|
---|
476 | }
|
---|
477 |
|
---|
478 | if (flags & XN_FLAG_SPC_EQ) {
|
---|
479 | sep_eq = " = ";
|
---|
480 | sep_eq_len = 3;
|
---|
481 | } else {
|
---|
482 | sep_eq = "=";
|
---|
483 | sep_eq_len = 1;
|
---|
484 | }
|
---|
485 |
|
---|
486 | fn_opt = flags & XN_FLAG_FN_MASK;
|
---|
487 |
|
---|
488 | cnt = X509_NAME_entry_count(n);
|
---|
489 | for (i = 0; i < cnt; i++) {
|
---|
490 | if (flags & XN_FLAG_DN_REV)
|
---|
491 | ent = X509_NAME_get_entry(n, cnt - i - 1);
|
---|
492 | else
|
---|
493 | ent = X509_NAME_get_entry(n, i);
|
---|
494 | if (prev != -1) {
|
---|
495 | if (prev == X509_NAME_ENTRY_set(ent)) {
|
---|
496 | if (!io_ch(arg, sep_mv, sep_mv_len))
|
---|
497 | return -1;
|
---|
498 | outlen += sep_mv_len;
|
---|
499 | } else {
|
---|
500 | if (!io_ch(arg, sep_dn, sep_dn_len))
|
---|
501 | return -1;
|
---|
502 | outlen += sep_dn_len;
|
---|
503 | if (!do_indent(io_ch, arg, indent))
|
---|
504 | return -1;
|
---|
505 | outlen += indent;
|
---|
506 | }
|
---|
507 | }
|
---|
508 | prev = X509_NAME_ENTRY_set(ent);
|
---|
509 | fn = X509_NAME_ENTRY_get_object(ent);
|
---|
510 | val = X509_NAME_ENTRY_get_data(ent);
|
---|
511 | fn_nid = OBJ_obj2nid(fn);
|
---|
512 | if (fn_opt != XN_FLAG_FN_NONE) {
|
---|
513 | int objlen, fld_len;
|
---|
514 | if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) {
|
---|
515 | OBJ_obj2txt(objtmp, sizeof(objtmp), fn, 1);
|
---|
516 | fld_len = 0; /* XXX: what should this be? */
|
---|
517 | objbuf = objtmp;
|
---|
518 | } else {
|
---|
519 | if (fn_opt == XN_FLAG_FN_SN) {
|
---|
520 | fld_len = FN_WIDTH_SN;
|
---|
521 | objbuf = OBJ_nid2sn(fn_nid);
|
---|
522 | } else if (fn_opt == XN_FLAG_FN_LN) {
|
---|
523 | fld_len = FN_WIDTH_LN;
|
---|
524 | objbuf = OBJ_nid2ln(fn_nid);
|
---|
525 | } else {
|
---|
526 | fld_len = 0; /* XXX: what should this be? */
|
---|
527 | objbuf = "";
|
---|
528 | }
|
---|
529 | }
|
---|
530 | objlen = strlen(objbuf);
|
---|
531 | if (!io_ch(arg, objbuf, objlen))
|
---|
532 | return -1;
|
---|
533 | if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
|
---|
534 | if (!do_indent(io_ch, arg, fld_len - objlen))
|
---|
535 | return -1;
|
---|
536 | outlen += fld_len - objlen;
|
---|
537 | }
|
---|
538 | if (!io_ch(arg, sep_eq, sep_eq_len))
|
---|
539 | return -1;
|
---|
540 | outlen += objlen + sep_eq_len;
|
---|
541 | }
|
---|
542 | /*
|
---|
543 | * If the field name is unknown then fix up the DER dump flag. We
|
---|
544 | * might want to limit this further so it will DER dump on anything
|
---|
545 | * other than a few 'standard' fields.
|
---|
546 | */
|
---|
547 | if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS))
|
---|
548 | orflags = ASN1_STRFLGS_DUMP_ALL;
|
---|
549 | else
|
---|
550 | orflags = 0;
|
---|
551 |
|
---|
552 | len = do_print_ex(io_ch, arg, flags | orflags, val);
|
---|
553 | if (len < 0)
|
---|
554 | return -1;
|
---|
555 | outlen += len;
|
---|
556 | }
|
---|
557 | return outlen;
|
---|
558 | }
|
---|
559 |
|
---|
560 | /* Wrappers round the main functions */
|
---|
561 |
|
---|
562 | int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent,
|
---|
563 | unsigned long flags)
|
---|
564 | {
|
---|
565 | if (flags == XN_FLAG_COMPAT)
|
---|
566 | return X509_NAME_print(out, nm, indent);
|
---|
567 | return do_name_ex(send_bio_chars, out, nm, indent, flags);
|
---|
568 | }
|
---|
569 |
|
---|
570 | #ifndef OPENSSL_NO_STDIO
|
---|
571 | int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent,
|
---|
572 | unsigned long flags)
|
---|
573 | {
|
---|
574 | if (flags == XN_FLAG_COMPAT) {
|
---|
575 | BIO *btmp;
|
---|
576 | int ret;
|
---|
577 | btmp = BIO_new_fp(fp, BIO_NOCLOSE);
|
---|
578 | if (!btmp)
|
---|
579 | return -1;
|
---|
580 | ret = X509_NAME_print(btmp, nm, indent);
|
---|
581 | BIO_free(btmp);
|
---|
582 | return ret;
|
---|
583 | }
|
---|
584 | return do_name_ex(send_fp_chars, fp, nm, indent, flags);
|
---|
585 | }
|
---|
586 | #endif
|
---|
587 |
|
---|
588 | int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags)
|
---|
589 | {
|
---|
590 | return do_print_ex(send_bio_chars, out, flags, str);
|
---|
591 | }
|
---|
592 |
|
---|
593 | #ifndef OPENSSL_NO_STDIO
|
---|
594 | int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags)
|
---|
595 | {
|
---|
596 | return do_print_ex(send_fp_chars, fp, flags, str);
|
---|
597 | }
|
---|
598 | #endif
|
---|
599 |
|
---|
600 | /*
|
---|
601 | * Utility function: convert any string type to UTF8, returns number of bytes
|
---|
602 | * in output string or a negative error code
|
---|
603 | */
|
---|
604 |
|
---|
605 | int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in)
|
---|
606 | {
|
---|
607 | ASN1_STRING stmp, *str = &stmp;
|
---|
608 | int mbflag, type, ret;
|
---|
609 | if (!in)
|
---|
610 | return -1;
|
---|
611 | type = in->type;
|
---|
612 | if ((type < 0) || (type > 30))
|
---|
613 | return -1;
|
---|
614 | mbflag = tag2nbyte[type];
|
---|
615 | if (mbflag == -1)
|
---|
616 | return -1;
|
---|
617 | mbflag |= MBSTRING_FLAG;
|
---|
618 | stmp.data = NULL;
|
---|
619 | stmp.length = 0;
|
---|
620 | stmp.flags = 0;
|
---|
621 | ret =
|
---|
622 | ASN1_mbstring_copy(&str, in->data, in->length, mbflag,
|
---|
623 | B_ASN1_UTF8STRING);
|
---|
624 | if (ret < 0)
|
---|
625 | return ret;
|
---|
626 | *out = stmp.data;
|
---|
627 | return stmp.length;
|
---|
628 | }
|
---|