• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.] */
56 
57 #include <openssl/x509.h>
58 
59 #include <inttypes.h>
60 #include <string.h>
61 
62 #include <openssl/asn1.h>
63 #include <openssl/bio.h>
64 #include <openssl/obj.h>
65 
66 
maybe_write(BIO * out,const void * buf,int len)67 static int maybe_write(BIO *out, const void *buf, int len)
68 {
69     /* If |out| is NULL, ignore the output but report the length. */
70     return out == NULL || BIO_write(out, buf, len) == len;
71 }
72 
73 /* do_indent prints |indent| spaces to |out|. */
do_indent(BIO * out,int indent)74 static int do_indent(BIO *out, int indent)
75 {
76     for (int i = 0; i < indent; i++) {
77         if (!maybe_write(out, " ", 1)) {
78             return 0;
79         }
80     }
81     return 1;
82 }
83 
84 #define FN_WIDTH_LN     25
85 #define FN_WIDTH_SN     10
86 
do_name_ex(BIO * out,const X509_NAME * n,int indent,unsigned long flags)87 static int do_name_ex(BIO *out, const X509_NAME *n, int indent,
88                       unsigned long flags)
89 {
90     int i, prev = -1, orflags, cnt;
91     int fn_opt, fn_nid;
92     ASN1_OBJECT *fn;
93     ASN1_STRING *val;
94     X509_NAME_ENTRY *ent;
95     char objtmp[80];
96     const char *objbuf;
97     int outlen, len;
98     const char *sep_dn, *sep_mv, *sep_eq;
99     int sep_dn_len, sep_mv_len, sep_eq_len;
100     if (indent < 0)
101         indent = 0;
102     outlen = indent;
103     if (!do_indent(out, indent))
104         return -1;
105     switch (flags & XN_FLAG_SEP_MASK) {
106     case XN_FLAG_SEP_MULTILINE:
107         sep_dn = "\n";
108         sep_dn_len = 1;
109         sep_mv = " + ";
110         sep_mv_len = 3;
111         break;
112 
113     case XN_FLAG_SEP_COMMA_PLUS:
114         sep_dn = ",";
115         sep_dn_len = 1;
116         sep_mv = "+";
117         sep_mv_len = 1;
118         indent = 0;
119         break;
120 
121     case XN_FLAG_SEP_CPLUS_SPC:
122         sep_dn = ", ";
123         sep_dn_len = 2;
124         sep_mv = " + ";
125         sep_mv_len = 3;
126         indent = 0;
127         break;
128 
129     case XN_FLAG_SEP_SPLUS_SPC:
130         sep_dn = "; ";
131         sep_dn_len = 2;
132         sep_mv = " + ";
133         sep_mv_len = 3;
134         indent = 0;
135         break;
136 
137     default:
138         return -1;
139     }
140 
141     if (flags & XN_FLAG_SPC_EQ) {
142         sep_eq = " = ";
143         sep_eq_len = 3;
144     } else {
145         sep_eq = "=";
146         sep_eq_len = 1;
147     }
148 
149     fn_opt = flags & XN_FLAG_FN_MASK;
150 
151     cnt = X509_NAME_entry_count(n);
152     for (i = 0; i < cnt; i++) {
153         if (flags & XN_FLAG_DN_REV)
154             ent = X509_NAME_get_entry(n, cnt - i - 1);
155         else
156             ent = X509_NAME_get_entry(n, i);
157         if (prev != -1) {
158             if (prev == X509_NAME_ENTRY_set(ent)) {
159                 if (!maybe_write(out, sep_mv, sep_mv_len))
160                     return -1;
161                 outlen += sep_mv_len;
162             } else {
163                 if (!maybe_write(out, sep_dn, sep_dn_len))
164                     return -1;
165                 outlen += sep_dn_len;
166                 if (!do_indent(out, indent))
167                     return -1;
168                 outlen += indent;
169             }
170         }
171         prev = X509_NAME_ENTRY_set(ent);
172         fn = X509_NAME_ENTRY_get_object(ent);
173         val = X509_NAME_ENTRY_get_data(ent);
174         fn_nid = OBJ_obj2nid(fn);
175         if (fn_opt != XN_FLAG_FN_NONE) {
176             int objlen, fld_len;
177             if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) {
178                 OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1);
179                 fld_len = 0;    /* XXX: what should this be? */
180                 objbuf = objtmp;
181             } else {
182                 if (fn_opt == XN_FLAG_FN_SN) {
183                     fld_len = FN_WIDTH_SN;
184                     objbuf = OBJ_nid2sn(fn_nid);
185                 } else if (fn_opt == XN_FLAG_FN_LN) {
186                     fld_len = FN_WIDTH_LN;
187                     objbuf = OBJ_nid2ln(fn_nid);
188                 } else {
189                     fld_len = 0; /* XXX: what should this be? */
190                     objbuf = "";
191                 }
192             }
193             objlen = strlen(objbuf);
194             if (!maybe_write(out, objbuf, objlen))
195                 return -1;
196             if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
197                 if (!do_indent(out, fld_len - objlen))
198                     return -1;
199                 outlen += fld_len - objlen;
200             }
201             if (!maybe_write(out, sep_eq, sep_eq_len))
202                 return -1;
203             outlen += objlen + sep_eq_len;
204         }
205         /*
206          * If the field name is unknown then fix up the DER dump flag. We
207          * might want to limit this further so it will DER dump on anything
208          * other than a few 'standard' fields.
209          */
210         if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS))
211             orflags = ASN1_STRFLGS_DUMP_ALL;
212         else
213             orflags = 0;
214 
215         len = ASN1_STRING_print_ex(out, val, flags | orflags);
216         if (len < 0)
217             return -1;
218         outlen += len;
219     }
220     return outlen;
221 }
222 
X509_NAME_print_ex(BIO * out,const X509_NAME * nm,int indent,unsigned long flags)223 int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent,
224                        unsigned long flags)
225 {
226     if (flags == XN_FLAG_COMPAT)
227         return X509_NAME_print(out, nm, indent);
228     return do_name_ex(out, nm, indent, flags);
229 }
230 
X509_NAME_print_ex_fp(FILE * fp,const X509_NAME * nm,int indent,unsigned long flags)231 int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent,
232                           unsigned long flags)
233 {
234     BIO *bio = NULL;
235     if (fp != NULL) {
236         /* If |fp| is NULL, this function returns the number of bytes without
237          * writing. */
238         bio = BIO_new_fp(fp, BIO_NOCLOSE);
239         if (bio == NULL) {
240             return -1;
241         }
242     }
243     int ret = X509_NAME_print_ex(bio, nm, indent, flags);
244     BIO_free(bio);
245     return ret;
246 }
247