1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * All rights reserved.
3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This package is an SSL implementation written
5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * by Eric Young (eay@cryptsoft.com).
6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The implementation was written so as to conform with Netscapes SSL.
7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This library is free for commercial and non-commercial use as long as
9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the following conditions are aheared to.  The following conditions
10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * apply to all code found in this distribution, be it the RC4, RSA,
11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * included with this distribution is covered by the same copyright terms
13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright remains Eric Young's, and as such any Copyright notices in
16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the code are not to be removed.
17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * If this package is used in a product, Eric Young should be given attribution
18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * as the author of the parts of the library used.
19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This can be in the form of a textual message at program startup or
20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * in documentation (online or textual) provided with the package.
21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without
23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions
24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met:
25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the copyright
26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer.
27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright
28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer in the
29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    documentation and/or other materials provided with the distribution.
30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this software
31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    must display the following acknowledgement:
32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes cryptographic software written by
33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *     Eric Young (eay@cryptsoft.com)"
34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    The word 'cryptographic' can be left out if the rouines from the library
35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    being used are not cryptographic related :-).
36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. If you include any Windows specific code (or a derivative thereof) from
37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    the apps directory (application code) you must include an acknowledgement:
38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SUCH DAMAGE.
51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The licence and distribution terms for any publically available version or
53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * derivative of this code cannot be changed.  i.e. this code cannot simply be
54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copied and put under another distribution licence
55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * [including the GNU Public Licence.] */
56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/x509.h>
58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h>
60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/asn1.h>
62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h>
63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/obj.h>
64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "charmap.h"
66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* ASN1_STRING_print_ex() and X509_NAME_print_ex().
69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Enhanced string and name printing routines handling
70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * multibyte characters, RFC2253 and a host of other
71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * options.
72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define CHARTYPE_BS_ESC		(ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253)
76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \
78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		  ASN1_STRFLGS_ESC_QUOTE | \
79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		  ASN1_STRFLGS_ESC_CTRL | \
80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		  ASN1_STRFLGS_ESC_MSB)
81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
83d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int send_bio_chars(void *arg, const void *buf, int len)
84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(!arg) return 1;
86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(BIO_write(arg, buf, len) != len) return 0;
87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return 1;
88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
90d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int send_fp_chars(void *arg, const void *buf, int len)
91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(!arg) return 1;
93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(fwrite(buf, 1, len, arg) != (unsigned int)len) return 0;
94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return 1;
95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
97d9e397b599b13d642138480a28c14db7a136bf0Adam Langleytypedef int char_io(void *arg, const void *buf, int len);
98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* This function handles display of
100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * strings, one character at a time.
101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * It is passed an unsigned long for each
102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * character because it could come from 2 or even
103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4 byte forms.
104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define HEX_SIZE(type) (sizeof(type)*2)
107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
108d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes, char_io *io_ch, void *arg)
109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	unsigned char chflgs, chtmp;
111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	char tmphex[HEX_SIZE(long)+3];
112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(c > 0xffffffffL)
114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return -1;
115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(c > 0xffff) {
116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		BIO_snprintf(tmphex, sizeof tmphex, "\\W%08lX", c);
117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(!io_ch(arg, tmphex, 10)) return -1;
118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return 10;
119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(c > 0xff) {
121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		BIO_snprintf(tmphex, sizeof tmphex, "\\U%04lX", c);
122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(!io_ch(arg, tmphex, 6)) return -1;
123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return 6;
124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
125d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	chtmp = (unsigned char)c;
126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(chtmp > 0x7f) chflgs = flags & ASN1_STRFLGS_ESC_MSB;
127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	else chflgs = char_type[chtmp] & flags;
128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(chflgs & CHARTYPE_BS_ESC) {
129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		/* If we don't escape with quotes, signal we need quotes */
130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(chflgs & ASN1_STRFLGS_ESC_QUOTE) {
131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			if(do_quotes) *do_quotes = 1;
132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			if(!io_ch(arg, &chtmp, 1)) return -1;
133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			return 1;
134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		}
135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(!io_ch(arg, "\\", 1)) return -1;
136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(!io_ch(arg, &chtmp, 1)) return -1;
137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return 2;
138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(chflgs & (ASN1_STRFLGS_ESC_CTRL|ASN1_STRFLGS_ESC_MSB)) {
140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		BIO_snprintf(tmphex, 11, "\\%02X", chtmp);
141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(!io_ch(arg, tmphex, 3)) return -1;
142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return 3;
143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	/* If we get this far and do any escaping at all must escape
145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	 * the escape character itself: backslash.
146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	 */
147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if (chtmp == '\\' && flags & ESC_FLAGS) {
148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(!io_ch(arg, "\\\\", 2)) return -1;
149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return 2;
150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(!io_ch(arg, &chtmp, 1)) return -1;
152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return 1;
153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define BUF_TYPE_WIDTH_MASK	0x7
156d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define BUF_TYPE_CONVUTF8	0x8
157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* This function sends each character in a buffer to
159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * do_esc_char(). It interprets the content formats
160d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * and converts to or from UTF8 as appropriate.
161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
163d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int do_buf(unsigned char *buf, int buflen,
164d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			int type, unsigned char flags, char *quotes, char_io *io_ch, void *arg)
165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
166d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int i, outlen, len;
167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	unsigned char orflags, *p, *q;
168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	unsigned long c;
169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	p = buf;
170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	q = buf + buflen;
171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	outlen = 0;
172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	while(p != q) {
173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(p == buf && flags & ASN1_STRFLGS_ESC_2253) orflags = CHARTYPE_FIRST_ESC_2253;
174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		else orflags = 0;
175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		switch(type & BUF_TYPE_WIDTH_MASK) {
176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			case 4:
177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			c = ((unsigned long)*p++) << 24;
178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			c |= ((unsigned long)*p++) << 16;
179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			c |= ((unsigned long)*p++) << 8;
180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			c |= *p++;
181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			break;
182d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			case 2:
184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			c = ((unsigned long)*p++) << 8;
185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			c |= *p++;
186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			break;
187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			case 1:
189d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			c = *p++;
190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			break;
191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			case 0:
193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			i = UTF8_getc(p, buflen, &c);
194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			if(i < 0) return -1;	/* Invalid UTF8String */
195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			p += i;
196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			break;
197d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			default:
198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			return -1;	/* invalid width */
199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		}
200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if (p == q && flags & ASN1_STRFLGS_ESC_2253) orflags = CHARTYPE_LAST_ESC_2253;
201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(type & BUF_TYPE_CONVUTF8) {
202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			unsigned char utfbuf[6];
203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			int utflen;
204d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			utflen = UTF8_putc(utfbuf, sizeof utfbuf, c);
205d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			for(i = 0; i < utflen; i++) {
206d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				/* We don't need to worry about setting orflags correctly
207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				 * because if utflen==1 its value will be correct anyway
208d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				 * otherwise each character will be > 0x7f and so the
209d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				 * character will never be escaped on first and last.
210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				 */
211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				len = do_esc_char(utfbuf[i], (unsigned char)(flags | orflags), quotes, io_ch, arg);
212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				if(len < 0) return -1;
213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				outlen += len;
214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			}
215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		} else {
216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			len = do_esc_char(c, (unsigned char)(flags | orflags), quotes, io_ch, arg);
217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			if(len < 0) return -1;
218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			outlen += len;
219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		}
220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return outlen;
222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* This function hex dumps a buffer of characters */
225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
226d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf, int buflen)
227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	static const char hexdig[] = "0123456789ABCDEF";
229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	unsigned char *p, *q;
230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	char hextmp[2];
231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(arg) {
232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		p = buf;
233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		q = buf + buflen;
234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		while(p != q) {
235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			hextmp[0] = hexdig[*p >> 4];
236d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			hextmp[1] = hexdig[*p & 0xf];
237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			if(!io_ch(arg, hextmp, 2)) return -1;
238d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			p++;
239d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		}
240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
241d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return buflen << 1;
242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
243d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* "dump" a string. This is done when the type is unknown,
245d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * or the flags request it. We can either dump the content
246d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * octets or the entire DER encoding. This uses the RFC2253
247d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * #01234 format.
248d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
250d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int do_dump(unsigned long lflags, char_io *io_ch, void *arg, ASN1_STRING *str)
251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
252d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	/* Placing the ASN1_STRING in a temp ASN1_TYPE allows
253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	 * the DER encoding to readily obtained
254d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	 */
255d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	ASN1_TYPE t;
256d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	unsigned char *der_buf, *p;
257d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int outlen, der_len;
258d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
259d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(!io_ch(arg, "#", 1)) return -1;
260d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	/* If we don't dump DER encoding just dump content octets */
261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(!(lflags & ASN1_STRFLGS_DUMP_DER)) {
262d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		outlen = do_hex_dump(io_ch, arg, str->data, str->length);
263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(outlen < 0) return -1;
264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return outlen + 1;
265d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
266d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	t.type = str->type;
267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	t.value.ptr = (char *)str;
268d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	der_len = i2d_ASN1_TYPE(&t, NULL);
269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	der_buf = OPENSSL_malloc(der_len);
270d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(!der_buf) return -1;
271d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	p = der_buf;
272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	i2d_ASN1_TYPE(&t, &p);
273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	outlen = do_hex_dump(io_ch, arg, der_buf, der_len);
274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	OPENSSL_free(der_buf);
275d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(outlen < 0) return -1;
276d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return outlen + 1;
277d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
278d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
279d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Lookup table to convert tags to character widths,
280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 0 = UTF8 encoded, -1 is used for non string types
281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * otherwise it is the number of bytes per character
282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
284d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const signed char tag2nbyte[] = {
285d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	-1, -1, -1, -1, -1,	/* 0-4 */
286d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	-1, -1, -1, -1, -1,	/* 5-9 */
287d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	-1, -1, 0, -1,		/* 10-13 */
288d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	-1, -1, -1, -1,		/* 15-17 */
289d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	-1, 1, 1,		/* 18-20 */
290d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	-1, 1, 1, 1,		/* 21-24 */
291d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	-1, 1, -1,		/* 25-27 */
292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	4, -1, 2		/* 28-30 */
293d9e397b599b13d642138480a28c14db7a136bf0Adam Langley};
294d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* This is the main function, print out an
296d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ASN1_STRING taking note of various escape
297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * and display options. Returns number of
298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * characters written or -1 if an error
299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * occurred.
300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
302d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags, ASN1_STRING *str)
303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
304d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int outlen, len;
305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int type;
306d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	char quotes;
307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	unsigned char flags;
308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	quotes = 0;
309d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	/* Keep a copy of escape flags */
310d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	flags = (unsigned char)(lflags & ESC_FLAGS);
311d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	type = str->type;
313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
314d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	outlen = 0;
315d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(lflags & ASN1_STRFLGS_SHOW_TYPE) {
318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		const char *tagname;
319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		tagname = ASN1_tag2str(type);
320d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		outlen += strlen(tagname);
321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1)) return -1;
322d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		outlen++;
323d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
325d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	/* Decide what to do with type, either dump content or display it */
326d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
327d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	/* Dump everything */
328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(lflags & ASN1_STRFLGS_DUMP_ALL) type = -1;
329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	/* Ignore the string type */
330d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	else if(lflags & ASN1_STRFLGS_IGNORE_TYPE) type = 1;
331d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	else {
332d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		/* Else determine width based on type */
333d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if((type > 0) && (type < 31)) type = tag2nbyte[type];
334d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		else type = -1;
335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN)) type = 1;
336d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
337d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
338d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(type == -1) {
339d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		len = do_dump(lflags, io_ch, arg, str);
340d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(len < 0) return -1;
341d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		outlen += len;
342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return outlen;
343d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
344d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
345d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(lflags & ASN1_STRFLGS_UTF8_CONVERT) {
346d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		/* Note: if string is UTF8 and we want
347d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		 * to convert to UTF8 then we just interpret
348d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		 * it as 1 byte per character to avoid converting
349d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		 * twice.
350d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		 */
351d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(!type) type = 1;
352d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		else type |= BUF_TYPE_CONVUTF8;
353d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
354d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	len = do_buf(str->data, str->length, type, flags, &quotes, io_ch, NULL);
356d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(len < 0) return -1;
357d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	outlen += len;
358d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(quotes) outlen += 2;
359d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(!arg) return outlen;
360d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(quotes && !io_ch(arg, "\"", 1)) return -1;
361d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0)
362d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return -1;
363d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(quotes && !io_ch(arg, "\"", 1)) return -1;
364d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return outlen;
365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
366d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Used for line indenting: print 'indent' spaces */
368d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
369d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int do_indent(char_io *io_ch, void *arg, int indent)
370d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int i;
372d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	for(i = 0; i < indent; i++)
373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			if(!io_ch(arg, " ", 1)) return 0;
374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return 1;
375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
376d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
377d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define FN_WIDTH_LN	25
378d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define FN_WIDTH_SN	10
379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
380d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n,
381d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				int indent, unsigned long flags)
382d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
383d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int i, prev = -1, orflags, cnt;
384d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int fn_opt, fn_nid;
385d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	ASN1_OBJECT *fn;
386d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	ASN1_STRING *val;
387d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	X509_NAME_ENTRY *ent;
388d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	char objtmp[80];
389d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	const char *objbuf;
390d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int outlen, len;
391d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	const char *sep_dn, *sep_mv, *sep_eq;
392d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int sep_dn_len, sep_mv_len, sep_eq_len;
393d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(indent < 0) indent = 0;
394d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	outlen = indent;
395d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(!do_indent(io_ch, arg, indent)) return -1;
396d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	switch (flags & XN_FLAG_SEP_MASK)
397d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	{
398d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		case XN_FLAG_SEP_MULTILINE:
399d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_dn = "\n";
400d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_dn_len = 1;
401d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_mv = " + ";
402d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_mv_len = 3;
403d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		break;
404d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
405d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		case XN_FLAG_SEP_COMMA_PLUS:
406d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_dn = ",";
407d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_dn_len = 1;
408d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_mv = "+";
409d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_mv_len = 1;
410d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		indent = 0;
411d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		break;
412d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
413d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		case XN_FLAG_SEP_CPLUS_SPC:
414d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_dn = ", ";
415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_dn_len = 2;
416d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_mv = " + ";
417d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_mv_len = 3;
418d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		indent = 0;
419d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		break;
420d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
421d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		case XN_FLAG_SEP_SPLUS_SPC:
422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_dn = "; ";
423d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_dn_len = 2;
424d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_mv = " + ";
425d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_mv_len = 3;
426d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		indent = 0;
427d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		break;
428d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
429d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		default:
430d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return -1;
431d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
433d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(flags & XN_FLAG_SPC_EQ) {
434d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_eq = " = ";
435d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_eq_len = 3;
436d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	} else {
437d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_eq = "=";
438d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		sep_eq_len = 1;
439d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
440d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
441d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	fn_opt = flags & XN_FLAG_FN_MASK;
442d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
443d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	cnt = X509_NAME_entry_count(n);
444d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	for(i = 0; i < cnt; i++) {
445d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(flags & XN_FLAG_DN_REV)
446d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				ent = X509_NAME_get_entry(n, cnt - i - 1);
447d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		else ent = X509_NAME_get_entry(n, i);
448d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(prev != -1) {
449d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			if(prev == ent->set) {
450d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				if(!io_ch(arg, sep_mv, sep_mv_len)) return -1;
451d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				outlen += sep_mv_len;
452d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			} else {
453d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				if(!io_ch(arg, sep_dn, sep_dn_len)) return -1;
454d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				outlen += sep_dn_len;
455d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				if(!do_indent(io_ch, arg, indent)) return -1;
456d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				outlen += indent;
457d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			}
458d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		}
459d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		prev = ent->set;
460d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		fn = X509_NAME_ENTRY_get_object(ent);
461d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		val = X509_NAME_ENTRY_get_data(ent);
462d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		fn_nid = OBJ_obj2nid(fn);
463d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(fn_opt != XN_FLAG_FN_NONE) {
464d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			int objlen, fld_len;
465d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			if((fn_opt == XN_FLAG_FN_OID) || (fn_nid==NID_undef) ) {
466d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1);
467d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				fld_len = 0; /* XXX: what should this be? */
468d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				objbuf = objtmp;
469d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			} else {
470d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				if(fn_opt == XN_FLAG_FN_SN) {
471d9e397b599b13d642138480a28c14db7a136bf0Adam Langley					fld_len = FN_WIDTH_SN;
472d9e397b599b13d642138480a28c14db7a136bf0Adam Langley					objbuf = OBJ_nid2sn(fn_nid);
473d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				} else if(fn_opt == XN_FLAG_FN_LN) {
474d9e397b599b13d642138480a28c14db7a136bf0Adam Langley					fld_len = FN_WIDTH_LN;
475d9e397b599b13d642138480a28c14db7a136bf0Adam Langley					objbuf = OBJ_nid2ln(fn_nid);
476d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				} else {
477d9e397b599b13d642138480a28c14db7a136bf0Adam Langley					fld_len = 0; /* XXX: what should this be? */
478d9e397b599b13d642138480a28c14db7a136bf0Adam Langley					objbuf = "";
479d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				}
480d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			}
481d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			objlen = strlen(objbuf);
482d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			if(!io_ch(arg, objbuf, objlen)) return -1;
483d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
484d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				if (!do_indent(io_ch, arg, fld_len - objlen)) return -1;
485d9e397b599b13d642138480a28c14db7a136bf0Adam Langley				outlen += fld_len - objlen;
486d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			}
487d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			if(!io_ch(arg, sep_eq, sep_eq_len)) return -1;
488d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			outlen += objlen + sep_eq_len;
489d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		}
490d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		/* If the field name is unknown then fix up the DER dump
491d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		 * flag. We might want to limit this further so it will
492d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 		 * DER dump on anything other than a few 'standard' fields.
493d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		 */
494d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS))
495d9e397b599b13d642138480a28c14db7a136bf0Adam Langley					orflags = ASN1_STRFLGS_DUMP_ALL;
496d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		else orflags = 0;
497d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
498d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		len = do_print_ex(io_ch, arg, flags | orflags, val);
499d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(len < 0) return -1;
500d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		outlen += len;
501d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
502d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return outlen;
503d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
504d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
505d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Wrappers round the main functions */
506d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
507d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags)
508d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
509d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(flags == XN_FLAG_COMPAT)
510d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return X509_NAME_print(out, nm, indent);
511d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return do_name_ex(send_bio_chars, out, nm, indent, flags);
512d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
513d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
514d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#ifndef OPENSSL_NO_FP_API
515d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, unsigned long flags)
516d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
517d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(flags == XN_FLAG_COMPAT)
518d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		{
519d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		BIO *btmp;
520d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		int ret;
521d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		btmp = BIO_new_fp(fp, BIO_NOCLOSE);
522d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(!btmp) return -1;
523d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		ret = X509_NAME_print(btmp, nm, indent);
524d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		BIO_free(btmp);
525d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return ret;
526d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		}
527d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return do_name_ex(send_fp_chars, fp, nm, indent, flags);
528d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
529d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#endif
530d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
531d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags)
532d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
533d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return do_print_ex(send_bio_chars, out, flags, str);
534d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
535d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
536d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#ifndef OPENSSL_NO_FP_API
537d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags)
538d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
539d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return do_print_ex(send_fp_chars, fp, flags, str);
540d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
541d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#endif
542d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
543d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Utility function: convert any string type to UTF8, returns number of bytes
544d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * in output string or a negative error code
545d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
546d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
547d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in)
548d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
549d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	ASN1_STRING stmp, *str = &stmp;
550d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int mbflag, type, ret;
551d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(!in) return -1;
552d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	type = in->type;
553d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if((type < 0) || (type > 30)) return -1;
554d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	mbflag = tag2nbyte[type];
555d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(mbflag == -1) return -1;
556d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	mbflag |= MBSTRING_FLAG;
557d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	stmp.data = NULL;
558d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	stmp.length = 0;
559d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	stmp.flags = 0;
560d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, B_ASN1_UTF8STRING);
561d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(ret < 0) return ret;
562d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	*out = stmp.data;
563d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return stmp.length;
564d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
565