168651Skris/* a_strex.c */ 2194206Ssimon/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 368651Skris * project 2000. 468651Skris */ 568651Skris/* ==================================================================== 6160814Ssimon * Copyright (c) 2000 The OpenSSL Project. All rights reserved. 768651Skris * 868651Skris * Redistribution and use in source and binary forms, with or without 968651Skris * modification, are permitted provided that the following conditions 1068651Skris * are met: 1168651Skris * 1268651Skris * 1. Redistributions of source code must retain the above copyright 1368651Skris * notice, this list of conditions and the following disclaimer. 1468651Skris * 1568651Skris * 2. Redistributions in binary form must reproduce the above copyright 1668651Skris * notice, this list of conditions and the following disclaimer in 1768651Skris * the documentation and/or other materials provided with the 1868651Skris * distribution. 1968651Skris * 2068651Skris * 3. All advertising materials mentioning features or use of this 2168651Skris * software must display the following acknowledgment: 2268651Skris * "This product includes software developed by the OpenSSL Project 2368651Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2468651Skris * 2568651Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2668651Skris * endorse or promote products derived from this software without 2768651Skris * prior written permission. For written permission, please contact 2868651Skris * licensing@OpenSSL.org. 2968651Skris * 3068651Skris * 5. Products derived from this software may not be called "OpenSSL" 3168651Skris * nor may "OpenSSL" appear in their names without prior written 3268651Skris * permission of the OpenSSL Project. 3368651Skris * 3468651Skris * 6. Redistributions of any form whatsoever must retain the following 3568651Skris * acknowledgment: 3668651Skris * "This product includes software developed by the OpenSSL Project 3768651Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3868651Skris * 3968651Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4068651Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4168651Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4268651Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4368651Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4468651Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4568651Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4668651Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4768651Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4868651Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4968651Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5068651Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 5168651Skris * ==================================================================== 5268651Skris * 5368651Skris * This product includes cryptographic software written by Eric Young 5468651Skris * (eay@cryptsoft.com). This product includes software written by Tim 5568651Skris * Hudson (tjh@cryptsoft.com). 5668651Skris * 5768651Skris */ 5868651Skris 5968651Skris#include <stdio.h> 6068651Skris#include <string.h> 61160814Ssimon#include "cryptlib.h" 6268651Skris#include <openssl/crypto.h> 6368651Skris#include <openssl/x509.h> 6468651Skris#include <openssl/asn1.h> 6568651Skris 6668651Skris#include "charmap.h" 6768651Skris 6868651Skris/* ASN1_STRING_print_ex() and X509_NAME_print_ex(). 6968651Skris * Enhanced string and name printing routines handling 7068651Skris * multibyte characters, RFC2253 and a host of other 7168651Skris * options. 7268651Skris */ 7368651Skris 7468651Skris 7568651Skris#define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253) 7668651Skris 77237657Sjkim#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \ 78237657Sjkim ASN1_STRFLGS_ESC_QUOTE | \ 79237657Sjkim ASN1_STRFLGS_ESC_CTRL | \ 80237657Sjkim ASN1_STRFLGS_ESC_MSB) 8168651Skris 82237657Sjkim 8368651Skris/* Three IO functions for sending data to memory, a BIO and 8468651Skris * and a FILE pointer. 8568651Skris */ 86109998Smarkm#if 0 /* never used */ 87109998Smarkmstatic int send_mem_chars(void *arg, const void *buf, int len) 8868651Skris{ 8968651Skris unsigned char **out = arg; 9068651Skris if(!out) return 1; 9168651Skris memcpy(*out, buf, len); 9268651Skris *out += len; 9368651Skris return 1; 9468651Skris} 95109998Smarkm#endif 9668651Skris 97109998Smarkmstatic int send_bio_chars(void *arg, const void *buf, int len) 9868651Skris{ 9968651Skris if(!arg) return 1; 10068651Skris if(BIO_write(arg, buf, len) != len) return 0; 10168651Skris return 1; 10268651Skris} 10368651Skris 104109998Smarkmstatic int send_fp_chars(void *arg, const void *buf, int len) 10568651Skris{ 10668651Skris if(!arg) return 1; 10768651Skris if(fwrite(buf, 1, len, arg) != (unsigned int)len) return 0; 10868651Skris return 1; 10968651Skris} 11068651Skris 11168651Skristypedef int char_io(void *arg, const void *buf, int len); 11268651Skris 11368651Skris/* This function handles display of 11468651Skris * strings, one character at a time. 11568651Skris * It is passed an unsigned long for each 11668651Skris * character because it could come from 2 or even 11768651Skris * 4 byte forms. 11868651Skris */ 11968651Skris 12068651Skrisstatic int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes, char_io *io_ch, void *arg) 12168651Skris{ 12268651Skris unsigned char chflgs, chtmp; 123109998Smarkm char tmphex[HEX_SIZE(long)+3]; 124109998Smarkm 125109998Smarkm if(c > 0xffffffffL) 126109998Smarkm return -1; 12768651Skris if(c > 0xffff) { 128109998Smarkm BIO_snprintf(tmphex, sizeof tmphex, "\\W%08lX", c); 12968651Skris if(!io_ch(arg, tmphex, 10)) return -1; 13068651Skris return 10; 13168651Skris } 13268651Skris if(c > 0xff) { 133109998Smarkm BIO_snprintf(tmphex, sizeof tmphex, "\\U%04lX", c); 13468651Skris if(!io_ch(arg, tmphex, 6)) return -1; 13568651Skris return 6; 13668651Skris } 13768651Skris chtmp = (unsigned char)c; 13868651Skris if(chtmp > 0x7f) chflgs = flags & ASN1_STRFLGS_ESC_MSB; 13968651Skris else chflgs = char_type[chtmp] & flags; 14068651Skris if(chflgs & CHARTYPE_BS_ESC) { 14168651Skris /* If we don't escape with quotes, signal we need quotes */ 14268651Skris if(chflgs & ASN1_STRFLGS_ESC_QUOTE) { 14368651Skris if(do_quotes) *do_quotes = 1; 14468651Skris if(!io_ch(arg, &chtmp, 1)) return -1; 14568651Skris return 1; 14668651Skris } 14768651Skris if(!io_ch(arg, "\\", 1)) return -1; 14868651Skris if(!io_ch(arg, &chtmp, 1)) return -1; 14968651Skris return 2; 15068651Skris } 15168651Skris if(chflgs & (ASN1_STRFLGS_ESC_CTRL|ASN1_STRFLGS_ESC_MSB)) { 15268651Skris BIO_snprintf(tmphex, 11, "\\%02X", chtmp); 15368651Skris if(!io_ch(arg, tmphex, 3)) return -1; 15468651Skris return 3; 15568651Skris } 156237657Sjkim /* If we get this far and do any escaping at all must escape 157237657Sjkim * the escape character itself: backslash. 158237657Sjkim */ 159237657Sjkim if (chtmp == '\\' && flags & ESC_FLAGS) { 160237657Sjkim if(!io_ch(arg, "\\\\", 2)) return -1; 161237657Sjkim return 2; 162237657Sjkim } 16368651Skris if(!io_ch(arg, &chtmp, 1)) return -1; 16468651Skris return 1; 16568651Skris} 16668651Skris 16768651Skris#define BUF_TYPE_WIDTH_MASK 0x7 16868651Skris#define BUF_TYPE_CONVUTF8 0x8 16968651Skris 17068651Skris/* This function sends each character in a buffer to 17168651Skris * do_esc_char(). It interprets the content formats 17268651Skris * and converts to or from UTF8 as appropriate. 17368651Skris */ 17468651Skris 17568651Skrisstatic int do_buf(unsigned char *buf, int buflen, 17668651Skris int type, unsigned char flags, char *quotes, char_io *io_ch, void *arg) 17768651Skris{ 17868651Skris int i, outlen, len; 17968651Skris unsigned char orflags, *p, *q; 18068651Skris unsigned long c; 18168651Skris p = buf; 18268651Skris q = buf + buflen; 18368651Skris outlen = 0; 18468651Skris while(p != q) { 185167612Ssimon if(p == buf && flags & ASN1_STRFLGS_ESC_2253) orflags = CHARTYPE_FIRST_ESC_2253; 18668651Skris else orflags = 0; 18768651Skris switch(type & BUF_TYPE_WIDTH_MASK) { 18868651Skris case 4: 18968651Skris c = ((unsigned long)*p++) << 24; 19068651Skris c |= ((unsigned long)*p++) << 16; 19168651Skris c |= ((unsigned long)*p++) << 8; 19268651Skris c |= *p++; 19368651Skris break; 19468651Skris 19568651Skris case 2: 19668651Skris c = ((unsigned long)*p++) << 8; 19768651Skris c |= *p++; 19868651Skris break; 19968651Skris 20068651Skris case 1: 20168651Skris c = *p++; 20268651Skris break; 20368651Skris 20468651Skris case 0: 20568651Skris i = UTF8_getc(p, buflen, &c); 20668651Skris if(i < 0) return -1; /* Invalid UTF8String */ 20768651Skris p += i; 20868651Skris break; 209160814Ssimon default: 210160814Ssimon return -1; /* invalid width */ 21168651Skris } 212167612Ssimon if (p == q && flags & ASN1_STRFLGS_ESC_2253) orflags = CHARTYPE_LAST_ESC_2253; 21368651Skris if(type & BUF_TYPE_CONVUTF8) { 21468651Skris unsigned char utfbuf[6]; 21568651Skris int utflen; 216109998Smarkm utflen = UTF8_putc(utfbuf, sizeof utfbuf, c); 21768651Skris for(i = 0; i < utflen; i++) { 21868651Skris /* We don't need to worry about setting orflags correctly 21968651Skris * because if utflen==1 its value will be correct anyway 22068651Skris * otherwise each character will be > 0x7f and so the 22168651Skris * character will never be escaped on first and last. 22268651Skris */ 22368651Skris len = do_esc_char(utfbuf[i], (unsigned char)(flags | orflags), quotes, io_ch, arg); 22468651Skris if(len < 0) return -1; 22568651Skris outlen += len; 22668651Skris } 22768651Skris } else { 22868651Skris len = do_esc_char(c, (unsigned char)(flags | orflags), quotes, io_ch, arg); 22968651Skris if(len < 0) return -1; 23068651Skris outlen += len; 23168651Skris } 23268651Skris } 23368651Skris return outlen; 23468651Skris} 23568651Skris 23668651Skris/* This function hex dumps a buffer of characters */ 23768651Skris 23868651Skrisstatic int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf, int buflen) 23968651Skris{ 240160814Ssimon static const char hexdig[] = "0123456789ABCDEF"; 24168651Skris unsigned char *p, *q; 24268651Skris char hextmp[2]; 24368651Skris if(arg) { 24468651Skris p = buf; 24568651Skris q = buf + buflen; 24668651Skris while(p != q) { 24768651Skris hextmp[0] = hexdig[*p >> 4]; 24868651Skris hextmp[1] = hexdig[*p & 0xf]; 24968651Skris if(!io_ch(arg, hextmp, 2)) return -1; 25068651Skris p++; 25168651Skris } 25268651Skris } 25368651Skris return buflen << 1; 25468651Skris} 25568651Skris 25668651Skris/* "dump" a string. This is done when the type is unknown, 25768651Skris * or the flags request it. We can either dump the content 25868651Skris * octets or the entire DER encoding. This uses the RFC2253 25968651Skris * #01234 format. 26068651Skris */ 26168651Skris 262109998Smarkmstatic int do_dump(unsigned long lflags, char_io *io_ch, void *arg, ASN1_STRING *str) 26368651Skris{ 26468651Skris /* Placing the ASN1_STRING in a temp ASN1_TYPE allows 26568651Skris * the DER encoding to readily obtained 26668651Skris */ 26768651Skris ASN1_TYPE t; 26868651Skris unsigned char *der_buf, *p; 26968651Skris int outlen, der_len; 27068651Skris 27168651Skris if(!io_ch(arg, "#", 1)) return -1; 27268651Skris /* If we don't dump DER encoding just dump content octets */ 27368651Skris if(!(lflags & ASN1_STRFLGS_DUMP_DER)) { 27468651Skris outlen = do_hex_dump(io_ch, arg, str->data, str->length); 27568651Skris if(outlen < 0) return -1; 27668651Skris return outlen + 1; 27768651Skris } 27868651Skris t.type = str->type; 27968651Skris t.value.ptr = (char *)str; 28068651Skris der_len = i2d_ASN1_TYPE(&t, NULL); 28168651Skris der_buf = OPENSSL_malloc(der_len); 28268651Skris if(!der_buf) return -1; 28368651Skris p = der_buf; 28468651Skris i2d_ASN1_TYPE(&t, &p); 28568651Skris outlen = do_hex_dump(io_ch, arg, der_buf, der_len); 28668651Skris OPENSSL_free(der_buf); 28768651Skris if(outlen < 0) return -1; 28868651Skris return outlen + 1; 28968651Skris} 29068651Skris 29168651Skris/* Lookup table to convert tags to character widths, 29268651Skris * 0 = UTF8 encoded, -1 is used for non string types 29368651Skris * otherwise it is the number of bytes per character 29468651Skris */ 29568651Skris 296160814Ssimonstatic const signed char tag2nbyte[] = { 29768651Skris -1, -1, -1, -1, -1, /* 0-4 */ 29868651Skris -1, -1, -1, -1, -1, /* 5-9 */ 29968651Skris -1, -1, 0, -1, /* 10-13 */ 30068651Skris -1, -1, -1, -1, /* 15-17 */ 30168651Skris -1, 1, 1, /* 18-20 */ 302127128Snectar -1, 1, 1, 1, /* 21-24 */ 30368651Skris -1, 1, -1, /* 25-27 */ 30468651Skris 4, -1, 2 /* 28-30 */ 30568651Skris}; 30668651Skris 30768651Skris/* This is the main function, print out an 30868651Skris * ASN1_STRING taking note of various escape 30968651Skris * and display options. Returns number of 31068651Skris * characters written or -1 if an error 31168651Skris * occurred. 31268651Skris */ 31368651Skris 31468651Skrisstatic int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags, ASN1_STRING *str) 31568651Skris{ 31668651Skris int outlen, len; 31768651Skris int type; 31868651Skris char quotes; 31968651Skris unsigned char flags; 32068651Skris quotes = 0; 32168651Skris /* Keep a copy of escape flags */ 32268651Skris flags = (unsigned char)(lflags & ESC_FLAGS); 32368651Skris 32468651Skris type = str->type; 32568651Skris 32668651Skris outlen = 0; 32768651Skris 32868651Skris 32968651Skris if(lflags & ASN1_STRFLGS_SHOW_TYPE) { 33068651Skris const char *tagname; 33168651Skris tagname = ASN1_tag2str(type); 33268651Skris outlen += strlen(tagname); 33368651Skris if(!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1)) return -1; 33468651Skris outlen++; 33568651Skris } 33668651Skris 33768651Skris /* Decide what to do with type, either dump content or display it */ 33868651Skris 33968651Skris /* Dump everything */ 34068651Skris if(lflags & ASN1_STRFLGS_DUMP_ALL) type = -1; 34168651Skris /* Ignore the string type */ 34268651Skris else if(lflags & ASN1_STRFLGS_IGNORE_TYPE) type = 1; 34368651Skris else { 34468651Skris /* Else determine width based on type */ 34568651Skris if((type > 0) && (type < 31)) type = tag2nbyte[type]; 34668651Skris else type = -1; 34768651Skris if((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN)) type = 1; 34868651Skris } 34968651Skris 35068651Skris if(type == -1) { 35168651Skris len = do_dump(lflags, io_ch, arg, str); 35268651Skris if(len < 0) return -1; 35368651Skris outlen += len; 35468651Skris return outlen; 35568651Skris } 35668651Skris 35768651Skris if(lflags & ASN1_STRFLGS_UTF8_CONVERT) { 35868651Skris /* Note: if string is UTF8 and we want 35968651Skris * to convert to UTF8 then we just interpret 36068651Skris * it as 1 byte per character to avoid converting 36168651Skris * twice. 36268651Skris */ 36368651Skris if(!type) type = 1; 36468651Skris else type |= BUF_TYPE_CONVUTF8; 36568651Skris } 36668651Skris 36768651Skris len = do_buf(str->data, str->length, type, flags, "es, io_ch, NULL); 368160814Ssimon if(len < 0) return -1; 36968651Skris outlen += len; 37068651Skris if(quotes) outlen += 2; 37168651Skris if(!arg) return outlen; 37268651Skris if(quotes && !io_ch(arg, "\"", 1)) return -1; 373160814Ssimon if(do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0) 374160814Ssimon return -1; 37568651Skris if(quotes && !io_ch(arg, "\"", 1)) return -1; 37668651Skris return outlen; 37768651Skris} 37868651Skris 37968651Skris/* Used for line indenting: print 'indent' spaces */ 38068651Skris 38168651Skrisstatic int do_indent(char_io *io_ch, void *arg, int indent) 38268651Skris{ 38368651Skris int i; 38468651Skris for(i = 0; i < indent; i++) 38568651Skris if(!io_ch(arg, " ", 1)) return 0; 38668651Skris return 1; 38768651Skris} 38868651Skris 389109998Smarkm#define FN_WIDTH_LN 25 390109998Smarkm#define FN_WIDTH_SN 10 39168651Skris 39268651Skrisstatic int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n, 39368651Skris int indent, unsigned long flags) 39468651Skris{ 39568651Skris int i, prev = -1, orflags, cnt; 39668651Skris int fn_opt, fn_nid; 39768651Skris ASN1_OBJECT *fn; 39868651Skris ASN1_STRING *val; 39968651Skris X509_NAME_ENTRY *ent; 40068651Skris char objtmp[80]; 40168651Skris const char *objbuf; 40268651Skris int outlen, len; 40368651Skris char *sep_dn, *sep_mv, *sep_eq; 40468651Skris int sep_dn_len, sep_mv_len, sep_eq_len; 40568651Skris if(indent < 0) indent = 0; 40668651Skris outlen = indent; 40768651Skris if(!do_indent(io_ch, arg, indent)) return -1; 40868651Skris switch (flags & XN_FLAG_SEP_MASK) 40968651Skris { 41068651Skris case XN_FLAG_SEP_MULTILINE: 41168651Skris sep_dn = "\n"; 41268651Skris sep_dn_len = 1; 41368651Skris sep_mv = " + "; 41468651Skris sep_mv_len = 3; 41568651Skris break; 41668651Skris 41768651Skris case XN_FLAG_SEP_COMMA_PLUS: 41868651Skris sep_dn = ","; 41968651Skris sep_dn_len = 1; 42068651Skris sep_mv = "+"; 42168651Skris sep_mv_len = 1; 42268651Skris indent = 0; 42368651Skris break; 42468651Skris 42568651Skris case XN_FLAG_SEP_CPLUS_SPC: 42668651Skris sep_dn = ", "; 42768651Skris sep_dn_len = 2; 42868651Skris sep_mv = " + "; 42968651Skris sep_mv_len = 3; 43068651Skris indent = 0; 43168651Skris break; 43268651Skris 43368651Skris case XN_FLAG_SEP_SPLUS_SPC: 43468651Skris sep_dn = "; "; 43568651Skris sep_dn_len = 2; 43668651Skris sep_mv = " + "; 43768651Skris sep_mv_len = 3; 43868651Skris indent = 0; 43968651Skris break; 44068651Skris 44168651Skris default: 44268651Skris return -1; 44368651Skris } 44468651Skris 44568651Skris if(flags & XN_FLAG_SPC_EQ) { 44668651Skris sep_eq = " = "; 44768651Skris sep_eq_len = 3; 44868651Skris } else { 44968651Skris sep_eq = "="; 45068651Skris sep_eq_len = 1; 45168651Skris } 45268651Skris 45368651Skris fn_opt = flags & XN_FLAG_FN_MASK; 45468651Skris 45568651Skris cnt = X509_NAME_entry_count(n); 45668651Skris for(i = 0; i < cnt; i++) { 45768651Skris if(flags & XN_FLAG_DN_REV) 45868651Skris ent = X509_NAME_get_entry(n, cnt - i - 1); 45968651Skris else ent = X509_NAME_get_entry(n, i); 46068651Skris if(prev != -1) { 46168651Skris if(prev == ent->set) { 46268651Skris if(!io_ch(arg, sep_mv, sep_mv_len)) return -1; 46368651Skris outlen += sep_mv_len; 46468651Skris } else { 46568651Skris if(!io_ch(arg, sep_dn, sep_dn_len)) return -1; 46668651Skris outlen += sep_dn_len; 46768651Skris if(!do_indent(io_ch, arg, indent)) return -1; 46868651Skris outlen += indent; 46968651Skris } 47068651Skris } 47168651Skris prev = ent->set; 47268651Skris fn = X509_NAME_ENTRY_get_object(ent); 47368651Skris val = X509_NAME_ENTRY_get_data(ent); 47468651Skris fn_nid = OBJ_obj2nid(fn); 47568651Skris if(fn_opt != XN_FLAG_FN_NONE) { 476109998Smarkm int objlen, fld_len; 47768651Skris if((fn_opt == XN_FLAG_FN_OID) || (fn_nid==NID_undef) ) { 478109998Smarkm OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1); 479109998Smarkm fld_len = 0; /* XXX: what should this be? */ 48068651Skris objbuf = objtmp; 48168651Skris } else { 482109998Smarkm if(fn_opt == XN_FLAG_FN_SN) { 483109998Smarkm fld_len = FN_WIDTH_SN; 48468651Skris objbuf = OBJ_nid2sn(fn_nid); 485109998Smarkm } else if(fn_opt == XN_FLAG_FN_LN) { 486109998Smarkm fld_len = FN_WIDTH_LN; 48768651Skris objbuf = OBJ_nid2ln(fn_nid); 488109998Smarkm } else { 489109998Smarkm fld_len = 0; /* XXX: what should this be? */ 490109998Smarkm objbuf = ""; 491109998Smarkm } 49268651Skris } 49368651Skris objlen = strlen(objbuf); 49468651Skris if(!io_ch(arg, objbuf, objlen)) return -1; 495109998Smarkm if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) { 496109998Smarkm if (!do_indent(io_ch, arg, fld_len - objlen)) return -1; 497109998Smarkm outlen += fld_len - objlen; 498109998Smarkm } 49968651Skris if(!io_ch(arg, sep_eq, sep_eq_len)) return -1; 50068651Skris outlen += objlen + sep_eq_len; 50168651Skris } 50268651Skris /* If the field name is unknown then fix up the DER dump 50368651Skris * flag. We might want to limit this further so it will 50468651Skris * DER dump on anything other than a few 'standard' fields. 50568651Skris */ 50668651Skris if((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) 50768651Skris orflags = ASN1_STRFLGS_DUMP_ALL; 50868651Skris else orflags = 0; 50968651Skris 51068651Skris len = do_print_ex(io_ch, arg, flags | orflags, val); 51168651Skris if(len < 0) return -1; 51268651Skris outlen += len; 51368651Skris } 51468651Skris return outlen; 51568651Skris} 51668651Skris 51768651Skris/* Wrappers round the main functions */ 51868651Skris 51968651Skrisint X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags) 52068651Skris{ 521109998Smarkm if(flags == XN_FLAG_COMPAT) 522109998Smarkm return X509_NAME_print(out, nm, indent); 52368651Skris return do_name_ex(send_bio_chars, out, nm, indent, flags); 52468651Skris} 52568651Skris 526160814Ssimon#ifndef OPENSSL_NO_FP_API 52768651Skrisint X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, unsigned long flags) 52868651Skris{ 529109998Smarkm if(flags == XN_FLAG_COMPAT) 530109998Smarkm { 531109998Smarkm BIO *btmp; 532109998Smarkm int ret; 533109998Smarkm btmp = BIO_new_fp(fp, BIO_NOCLOSE); 534109998Smarkm if(!btmp) return -1; 535109998Smarkm ret = X509_NAME_print(btmp, nm, indent); 536109998Smarkm BIO_free(btmp); 537109998Smarkm return ret; 538109998Smarkm } 53968651Skris return do_name_ex(send_fp_chars, fp, nm, indent, flags); 54068651Skris} 541160814Ssimon#endif 54268651Skris 54368651Skrisint ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags) 54468651Skris{ 54568651Skris return do_print_ex(send_bio_chars, out, flags, str); 54668651Skris} 54768651Skris 548160814Ssimon#ifndef OPENSSL_NO_FP_API 54968651Skrisint ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags) 55068651Skris{ 55168651Skris return do_print_ex(send_fp_chars, fp, flags, str); 55268651Skris} 553160814Ssimon#endif 55468651Skris 55568651Skris/* Utility function: convert any string type to UTF8, returns number of bytes 55668651Skris * in output string or a negative error code 55768651Skris */ 55868651Skris 55968651Skrisint ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in) 56068651Skris{ 56168651Skris ASN1_STRING stmp, *str = &stmp; 56268651Skris int mbflag, type, ret; 563109998Smarkm if(!in) return -1; 56468651Skris type = in->type; 56568651Skris if((type < 0) || (type > 30)) return -1; 56668651Skris mbflag = tag2nbyte[type]; 56768651Skris if(mbflag == -1) return -1; 568160814Ssimon mbflag |= MBSTRING_FLAG; 56968651Skris stmp.data = NULL; 570246772Sjkim stmp.length = 0; 571279264Sdelphij stmp.flags = 0; 57268651Skris ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, B_ASN1_UTF8STRING); 57368651Skris if(ret < 0) return ret; 574109998Smarkm *out = stmp.data; 57568651Skris return stmp.length; 57668651Skris} 577