/src/boringssl/crypto/x509/name_print.cc
Line | Count | Source |
1 | | // Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include <openssl/x509.h> |
16 | | |
17 | | #include <assert.h> |
18 | | #include <inttypes.h> |
19 | | #include <string.h> |
20 | | |
21 | | #include <openssl/asn1.h> |
22 | | #include <openssl/bio.h> |
23 | | #include <openssl/obj.h> |
24 | | |
25 | | |
26 | 1.04k | static int maybe_write(BIO *out, const void *buf, int len) { |
27 | | // If |out| is NULL, ignore the output but report the length. |
28 | 1.04k | return out == nullptr || BIO_write(out, buf, len) == len; |
29 | 1.04k | } |
30 | | |
31 | | // do_indent prints |indent| spaces to |out|. |
32 | 351 | static int do_indent(BIO *out, int indent) { |
33 | 351 | for (int i = 0; i < indent; i++) { |
34 | 0 | if (!maybe_write(out, " ", 1)) { |
35 | 0 | return 0; |
36 | 0 | } |
37 | 0 | } |
38 | 351 | return 1; |
39 | 351 | } |
40 | | |
41 | | #define FN_WIDTH_LN 25 |
42 | | #define FN_WIDTH_SN 10 |
43 | | |
44 | | static int do_name_ex(BIO *out, const X509_NAME *n, int indent, |
45 | 135 | unsigned long flags) { |
46 | 135 | int prev = -1, orflags; |
47 | 135 | char objtmp[80]; |
48 | 135 | const char *objbuf; |
49 | 135 | int outlen, len; |
50 | 135 | const char *sep_dn, *sep_mv, *sep_eq; |
51 | 135 | int sep_dn_len, sep_mv_len, sep_eq_len; |
52 | 135 | if (indent < 0) { |
53 | 0 | indent = 0; |
54 | 0 | } |
55 | 135 | outlen = indent; |
56 | 135 | if (!do_indent(out, indent)) { |
57 | 0 | return -1; |
58 | 0 | } |
59 | 135 | switch (flags & XN_FLAG_SEP_MASK) { |
60 | 0 | case XN_FLAG_SEP_MULTILINE: |
61 | 0 | sep_dn = "\n"; |
62 | 0 | sep_dn_len = 1; |
63 | 0 | sep_mv = " + "; |
64 | 0 | sep_mv_len = 3; |
65 | 0 | break; |
66 | | |
67 | 0 | case XN_FLAG_SEP_COMMA_PLUS: |
68 | 0 | sep_dn = ","; |
69 | 0 | sep_dn_len = 1; |
70 | 0 | sep_mv = "+"; |
71 | 0 | sep_mv_len = 1; |
72 | 0 | indent = 0; |
73 | 0 | break; |
74 | | |
75 | 135 | case XN_FLAG_SEP_CPLUS_SPC: |
76 | 135 | sep_dn = ", "; |
77 | 135 | sep_dn_len = 2; |
78 | 135 | sep_mv = " + "; |
79 | 135 | sep_mv_len = 3; |
80 | 135 | indent = 0; |
81 | 135 | break; |
82 | | |
83 | 0 | case XN_FLAG_SEP_SPLUS_SPC: |
84 | 0 | sep_dn = "; "; |
85 | 0 | sep_dn_len = 2; |
86 | 0 | sep_mv = " + "; |
87 | 0 | sep_mv_len = 3; |
88 | 0 | indent = 0; |
89 | 0 | break; |
90 | | |
91 | 0 | default: |
92 | 0 | return -1; |
93 | 135 | } |
94 | | |
95 | 135 | if (flags & XN_FLAG_SPC_EQ) { |
96 | 135 | sep_eq = " = "; |
97 | 135 | sep_eq_len = 3; |
98 | 135 | } else { |
99 | 0 | sep_eq = "="; |
100 | 0 | sep_eq_len = 1; |
101 | 0 | } |
102 | | |
103 | 135 | int cnt = X509_NAME_entry_count(n); |
104 | 525 | for (int i = 0; i < cnt; i++) { |
105 | 390 | const X509_NAME_ENTRY *ent; |
106 | 390 | if (flags & XN_FLAG_DN_REV) { |
107 | 0 | ent = X509_NAME_get_entry(n, cnt - i - 1); |
108 | 390 | } else { |
109 | 390 | ent = X509_NAME_get_entry(n, i); |
110 | 390 | } |
111 | 390 | if (prev != -1) { |
112 | 269 | if (prev == X509_NAME_ENTRY_set(ent)) { |
113 | 53 | if (!maybe_write(out, sep_mv, sep_mv_len)) { |
114 | 0 | return -1; |
115 | 0 | } |
116 | 53 | outlen += sep_mv_len; |
117 | 216 | } else { |
118 | 216 | if (!maybe_write(out, sep_dn, sep_dn_len)) { |
119 | 0 | return -1; |
120 | 0 | } |
121 | 216 | outlen += sep_dn_len; |
122 | 216 | if (!do_indent(out, indent)) { |
123 | 0 | return -1; |
124 | 0 | } |
125 | 216 | outlen += indent; |
126 | 216 | } |
127 | 269 | } |
128 | 390 | prev = X509_NAME_ENTRY_set(ent); |
129 | 390 | const ASN1_OBJECT *fn = X509_NAME_ENTRY_get_object(ent); |
130 | 390 | const ASN1_STRING *val = X509_NAME_ENTRY_get_data(ent); |
131 | 390 | assert((flags & XN_FLAG_FN_MASK) == XN_FLAG_FN_SN); |
132 | 390 | int fn_nid = OBJ_obj2nid(fn); |
133 | 390 | if (fn_nid == NID_undef) { |
134 | 257 | OBJ_obj2txt(objtmp, sizeof(objtmp), fn, 1); |
135 | 257 | objbuf = objtmp; |
136 | 257 | } else { |
137 | 133 | objbuf = OBJ_nid2sn(fn_nid); |
138 | 133 | } |
139 | 390 | int objlen = strlen(objbuf); |
140 | 390 | if (!maybe_write(out, objbuf, objlen) || |
141 | 390 | !maybe_write(out, sep_eq, sep_eq_len)) { |
142 | 0 | return -1; |
143 | 0 | } |
144 | 390 | outlen += objlen + sep_eq_len; |
145 | | // If the field name is unknown then fix up the DER dump flag. We |
146 | | // might want to limit this further so it will DER dump on anything |
147 | | // other than a few 'standard' fields. |
148 | 390 | if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) { |
149 | 0 | orflags = ASN1_STRFLGS_DUMP_ALL; |
150 | 390 | } else { |
151 | 390 | orflags = 0; |
152 | 390 | } |
153 | | |
154 | 390 | len = ASN1_STRING_print_ex(out, val, flags | orflags); |
155 | 390 | if (len < 0) { |
156 | 0 | return -1; |
157 | 0 | } |
158 | 390 | outlen += len; |
159 | 390 | } |
160 | 135 | return outlen; |
161 | 135 | } |
162 | | |
163 | | int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent, |
164 | 5.67k | unsigned long flags) { |
165 | 5.67k | if (flags == XN_FLAG_COMPAT) { |
166 | 5.54k | return X509_NAME_print(out, nm, indent); |
167 | 5.54k | } |
168 | 135 | return do_name_ex(out, nm, indent, flags); |
169 | 5.67k | } |
170 | | |
171 | | int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent, |
172 | 0 | unsigned long flags) { |
173 | 0 | BIO *bio = nullptr; |
174 | 0 | if (fp != nullptr) { |
175 | | // If |fp| is NULL, this function returns the number of bytes without |
176 | | // writing. |
177 | 0 | bio = BIO_new_fp(fp, BIO_NOCLOSE); |
178 | 0 | if (bio == nullptr) { |
179 | 0 | return -1; |
180 | 0 | } |
181 | 0 | } |
182 | 0 | int ret = X509_NAME_print_ex(bio, nm, indent, flags); |
183 | 0 | BIO_free(bio); |
184 | 0 | return ret; |
185 | 0 | } |