Don't attempt to parse nested ASN1 strings by default.
[oweals/openssl.git] / crypto / asn1 / a_strex.c
index ef225be06a8c517e09f73373397a5c6d31cd4beb..bde666a6ff1553328edb70ec66b04aa67790a518 100644 (file)
  */
 
 #include <stdio.h>
+#include <string.h>
 #include <openssl/crypto.h>
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
 
 #include "charmap.h"
+#include "cryptlib.h"
 
 /* ASN1_STRING_print_ex() and X509_NAME_print_ex().
  * Enhanced string and name printing routines handling
@@ -76,8 +78,8 @@
 /* Three IO functions for sending data to memory, a BIO and
  * and a FILE pointer.
  */
-
-int send_mem_chars(void *arg, const void *buf, int len)
+#if 0                          /* never used */
+static int send_mem_chars(void *arg, const void *buf, int len)
 {
        unsigned char **out = arg;
        if(!out) return 1;
@@ -85,18 +87,19 @@ int send_mem_chars(void *arg, const void *buf, int len)
        *out += len;
        return 1;
 }
+#endif
 
-int send_bio_chars(void *arg, const void *buf, int len)
+static int send_bio_chars(void *arg, const void *buf, int len)
 {
        if(!arg) return 1;
        if(BIO_write(arg, buf, len) != len) return 0;
        return 1;
 }
 
-int send_fp_chars(void *arg, const void *buf, int len)
+static int send_fp_chars(void *arg, const void *buf, int len)
 {
        if(!arg) return 1;
-       if(fwrite(buf, 1, len, arg) != len) return 0;
+       if(fwrite(buf, 1, len, arg) != (unsigned int)len) return 0;
        return 1;
 }
 
@@ -112,18 +115,21 @@ typedef int char_io(void *arg, const void *buf, int len);
 static int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes, char_io *io_ch, void *arg)
 {
        unsigned char chflgs, chtmp;
-       char tmphex[11];
+       char tmphex[HEX_SIZE(long)+3];
+
+       if(c > 0xffffffffL)
+               return -1;
        if(c > 0xffff) {
-               BIO_snprintf(tmphex, 11, "\\W%08lX", c);
+               BIO_snprintf(tmphex, sizeof tmphex, "\\W%08lX", c);
                if(!io_ch(arg, tmphex, 10)) return -1;
                return 10;
        }
        if(c > 0xff) {
-               BIO_snprintf(tmphex, 11, "\\U%04lX", c);
+               BIO_snprintf(tmphex, sizeof tmphex, "\\U%04lX", c);
                if(!io_ch(arg, tmphex, 6)) return -1;
                return 6;
        }
-       chtmp = c;
+       chtmp = (unsigned char)c;
        if(chtmp > 0x7f) chflgs = flags & ASN1_STRFLGS_ESC_MSB;
        else chflgs = char_type[chtmp] & flags;
        if(chflgs & CHARTYPE_BS_ESC) {
@@ -193,19 +199,19 @@ static int do_buf(unsigned char *buf, int buflen,
                if(type & BUF_TYPE_CONVUTF8) {
                        unsigned char utfbuf[6];
                        int utflen;
-                       utflen = UTF8_putc(utfbuf, 6, c);
+                       utflen = UTF8_putc(utfbuf, sizeof utfbuf, c);
                        for(i = 0; i < utflen; i++) {
                                /* We don't need to worry about setting orflags correctly
                                 * because if utflen==1 its value will be correct anyway 
                                 * otherwise each character will be > 0x7f and so the 
                                 * character will never be escaped on first and last.
                                 */
-                               len = do_esc_char(utfbuf[i], flags | orflags, quotes, io_ch, arg);
+                               len = do_esc_char(utfbuf[i], (unsigned char)(flags | orflags), quotes, io_ch, arg);
                                if(len < 0) return -1;
                                outlen += len;
                        }
                } else {
-                       len = do_esc_char(c, flags | orflags, quotes, io_ch, arg);
+                       len = do_esc_char(c, (unsigned char)(flags | orflags), quotes, io_ch, arg);
                        if(len < 0) return -1;
                        outlen += len;
                }
@@ -239,7 +245,7 @@ static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf, int buflen
  * #01234 format.
  */
 
-int do_dump(unsigned long lflags, char_io *io_ch, void *arg, ASN1_STRING *str)
+static int do_dump(unsigned long lflags, char_io *io_ch, void *arg, ASN1_STRING *str)
 {
        /* Placing the ASN1_STRING in a temp ASN1_TYPE allows
         * the DER encoding to readily obtained
@@ -273,13 +279,13 @@ int do_dump(unsigned long lflags, char_io *io_ch, void *arg, ASN1_STRING *str)
  * otherwise it is the number of bytes per character
  */
 
-const static char tag2nbyte[] = {
+const static signed char tag2nbyte[] = {
        -1, -1, -1, -1, -1,     /* 0-4 */
        -1, -1, -1, -1, -1,     /* 5-9 */
        -1, -1, 0, -1,          /* 10-13 */
        -1, -1, -1, -1,         /* 15-17 */
        -1, 1, 1,               /* 18-20 */
-       -1, 1, -1,-1,           /* 21-24 */
+       -1, 1, 1, 1,            /* 21-24 */
        -1, 1, -1,              /* 25-27 */
        4, -1, 2                /* 28-30 */
 };
@@ -304,14 +310,14 @@ static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags, ASN1_STR
        unsigned char flags;
        quotes = 0;
        /* Keep a copy of escape flags */
-       flags = lflags & ESC_FLAGS;
+       flags = (unsigned char)(lflags & ESC_FLAGS);
 
        type = str->type;
 
        outlen = 0;
 
 
-       if(lflags & ASN1_STRFLGS_SHOW_NAME) {
+       if(lflags & ASN1_STRFLGS_SHOW_TYPE) {
                const char *tagname;
                tagname = ASN1_tag2str(type);
                outlen += strlen(tagname);
@@ -370,6 +376,8 @@ static int do_indent(char_io *io_ch, void *arg, int indent)
        return 1;
 }
 
+#define FN_WIDTH_LN    25
+#define FN_WIDTH_SN    10
 
 static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n,
                                int indent, unsigned long flags)
@@ -392,8 +400,8 @@ static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n,
                case XN_FLAG_SEP_MULTILINE:
                sep_dn = "\n";
                sep_dn_len = 1;
-               sep_mv = "+";
-               sep_mv_len = 1;
+               sep_mv = " + ";
+               sep_mv_len = 3;
                break;
 
                case XN_FLAG_SEP_COMMA_PLUS:
@@ -446,28 +454,38 @@ static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n,
                        } else {
                                if(!io_ch(arg, sep_dn, sep_dn_len)) return -1;
                                outlen += sep_dn_len;
+                               if(!do_indent(io_ch, arg, indent)) return -1;
+                               outlen += indent;
                        }
-                       if(!do_indent(io_ch, arg, indent)) return -1;
-                       outlen += indent;
                }
                prev = ent->set;
                fn = X509_NAME_ENTRY_get_object(ent);
                val = X509_NAME_ENTRY_get_data(ent);
                fn_nid = OBJ_obj2nid(fn);
                if(fn_opt != XN_FLAG_FN_NONE) {
-                       int objlen;
+                       int objlen, fld_len;
                        if((fn_opt == XN_FLAG_FN_OID) || (fn_nid==NID_undef) ) {
-                               OBJ_obj2txt(objtmp, 80, fn, 1);
+                               OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1);
+                               fld_len = 0; /* XXX: what should this be? */
                                objbuf = objtmp;
                        } else {
-                               if(fn_opt == XN_FLAG_FN_SN) 
+                               if(fn_opt == XN_FLAG_FN_SN) {
+                                       fld_len = FN_WIDTH_SN;
                                        objbuf = OBJ_nid2sn(fn_nid);
-                               else if(fn_opt == XN_FLAG_FN_LN)
+                               } else if(fn_opt == XN_FLAG_FN_LN) {
+                                       fld_len = FN_WIDTH_LN;
                                        objbuf = OBJ_nid2ln(fn_nid);
-                               else objbuf = "";
+                               } else {
+                                       fld_len = 0; /* XXX: what should this be? */
+                                       objbuf = "";
+                               }
                        }
                        objlen = strlen(objbuf);
                        if(!io_ch(arg, objbuf, objlen)) return -1;
+                       if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
+                               if (!do_indent(io_ch, arg, fld_len - objlen)) return -1;
+                               outlen += fld_len - objlen;
+                       }
                        if(!io_ch(arg, sep_eq, sep_eq_len)) return -1;
                        outlen += objlen + sep_eq_len;
                }
@@ -490,12 +508,24 @@ static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n,
 
 int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags)
 {
+       if(flags == XN_FLAG_COMPAT)
+               return X509_NAME_print(out, nm, indent);
        return do_name_ex(send_bio_chars, out, nm, indent, flags);
 }
 
 
 int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, unsigned long flags)
 {
+       if(flags == XN_FLAG_COMPAT)
+               {
+               BIO *btmp;
+               int ret;
+               btmp = BIO_new_fp(fp, BIO_NOCLOSE);
+               if(!btmp) return -1;
+               ret = X509_NAME_print(btmp, nm, indent);
+               BIO_free(btmp);
+               return ret;
+               }
        return do_name_ex(send_fp_chars, fp, nm, indent, flags);
 }
 
@@ -509,3 +539,24 @@ int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags)
 {
        return do_print_ex(send_fp_chars, fp, flags, str);
 }
+
+/* Utility function: convert any string type to UTF8, returns number of bytes
+ * in output string or a negative error code
+ */
+
+int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in)
+{
+       ASN1_STRING stmp, *str = &stmp;
+       int mbflag, type, ret;
+       if(!in) return -1;
+       type = in->type;
+       if((type < 0) || (type > 30)) return -1;
+       mbflag = tag2nbyte[type];
+       if(mbflag == -1) return -1;
+       mbflag |= MBSTRING_FLAG;
+       stmp.data = NULL;
+       ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, B_ASN1_UTF8STRING);
+       if(ret < 0) return ret;
+       *out = stmp.data;
+       return stmp.length;
+}