/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.27k | 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.27k | return out == nullptr || BIO_write(out, buf, len) == len; |
29 | 1.27k | } |
30 | | |
31 | | // do_indent prints `indent` spaces to `out`. |
32 | 417 | static int do_indent(BIO *out, int indent) { |
33 | 417 | for (int i = 0; i < indent; i++) { |
34 | 0 | if (!maybe_write(out, " ", 1)) { |
35 | 0 | return 0; |
36 | 0 | } |
37 | 0 | } |
38 | 417 | return 1; |
39 | 417 | } |
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 | 161 | unsigned long flags) { |
46 | 161 | int prev = -1, orflags; |
47 | 161 | int outlen, len; |
48 | 161 | const char *sep_dn, *sep_mv, *sep_eq; |
49 | 161 | int sep_dn_len, sep_mv_len, sep_eq_len; |
50 | 161 | if (indent < 0) { |
51 | 0 | indent = 0; |
52 | 0 | } |
53 | 161 | outlen = indent; |
54 | 161 | if (!do_indent(out, indent)) { |
55 | 0 | return -1; |
56 | 0 | } |
57 | 161 | switch (flags & XN_FLAG_SEP_MASK) { |
58 | 0 | case XN_FLAG_SEP_MULTILINE: |
59 | 0 | sep_dn = "\n"; |
60 | 0 | sep_dn_len = 1; |
61 | 0 | sep_mv = " + "; |
62 | 0 | sep_mv_len = 3; |
63 | 0 | break; |
64 | | |
65 | 0 | case XN_FLAG_SEP_COMMA_PLUS: |
66 | 0 | sep_dn = ","; |
67 | 0 | sep_dn_len = 1; |
68 | 0 | sep_mv = "+"; |
69 | 0 | sep_mv_len = 1; |
70 | 0 | indent = 0; |
71 | 0 | break; |
72 | | |
73 | 161 | case XN_FLAG_SEP_CPLUS_SPC: |
74 | 161 | sep_dn = ", "; |
75 | 161 | sep_dn_len = 2; |
76 | 161 | sep_mv = " + "; |
77 | 161 | sep_mv_len = 3; |
78 | 161 | indent = 0; |
79 | 161 | break; |
80 | | |
81 | 0 | case XN_FLAG_SEP_SPLUS_SPC: |
82 | 0 | sep_dn = "; "; |
83 | 0 | sep_dn_len = 2; |
84 | 0 | sep_mv = " + "; |
85 | 0 | sep_mv_len = 3; |
86 | 0 | indent = 0; |
87 | 0 | break; |
88 | | |
89 | 0 | default: |
90 | 0 | return -1; |
91 | 161 | } |
92 | | |
93 | 161 | if (flags & XN_FLAG_SPC_EQ) { |
94 | 161 | sep_eq = " = "; |
95 | 161 | sep_eq_len = 3; |
96 | 161 | } else { |
97 | 0 | sep_eq = "="; |
98 | 0 | sep_eq_len = 1; |
99 | 0 | } |
100 | | |
101 | 161 | int cnt = X509_NAME_entry_count(n); |
102 | 637 | for (int i = 0; i < cnt; i++) { |
103 | 476 | const X509_NAME_ENTRY *ent; |
104 | 476 | if (flags & XN_FLAG_DN_REV) { |
105 | 0 | ent = X509_NAME_get_entry(n, cnt - i - 1); |
106 | 476 | } else { |
107 | 476 | ent = X509_NAME_get_entry(n, i); |
108 | 476 | } |
109 | 476 | if (prev != -1) { |
110 | 325 | if (prev == X509_NAME_ENTRY_set(ent)) { |
111 | 69 | if (!maybe_write(out, sep_mv, sep_mv_len)) { |
112 | 0 | return -1; |
113 | 0 | } |
114 | 69 | outlen += sep_mv_len; |
115 | 256 | } else { |
116 | 256 | if (!maybe_write(out, sep_dn, sep_dn_len)) { |
117 | 0 | return -1; |
118 | 0 | } |
119 | 256 | outlen += sep_dn_len; |
120 | 256 | if (!do_indent(out, indent)) { |
121 | 0 | return -1; |
122 | 0 | } |
123 | 256 | outlen += indent; |
124 | 256 | } |
125 | 325 | } |
126 | 476 | prev = X509_NAME_ENTRY_set(ent); |
127 | 476 | const ASN1_OBJECT *fn = X509_NAME_ENTRY_get_object(ent); |
128 | 476 | const ASN1_STRING *val = X509_NAME_ENTRY_get_data(ent); |
129 | 476 | assert((flags & XN_FLAG_FN_MASK) == XN_FLAG_FN_SN); |
130 | | // Print the short name if available, otherwise serialize the OID. |
131 | 476 | char objtmp[80]; |
132 | 476 | const char *objbuf = nullptr; |
133 | 476 | int fn_nid = OBJ_obj2nid(fn); |
134 | 476 | if (fn_nid != NID_undef) { |
135 | 112 | objbuf = OBJ_nid2sn(fn_nid); |
136 | 112 | } |
137 | 476 | if (objbuf == nullptr) { |
138 | 364 | OBJ_obj2txt(objtmp, sizeof(objtmp), fn, /*always_return_oid=*/1); |
139 | 364 | objbuf = objtmp; |
140 | 364 | } |
141 | 476 | int objlen = strlen(objbuf); |
142 | 476 | if (!maybe_write(out, objbuf, objlen) || |
143 | 476 | !maybe_write(out, sep_eq, sep_eq_len)) { |
144 | 0 | return -1; |
145 | 0 | } |
146 | 476 | outlen += objlen + sep_eq_len; |
147 | | // If the field name is unknown then fix up the DER dump flag. We |
148 | | // might want to limit this further so it will DER dump on anything |
149 | | // other than a few 'standard' fields. |
150 | 476 | if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) { |
151 | 0 | orflags = ASN1_STRFLGS_DUMP_ALL; |
152 | 476 | } else { |
153 | 476 | orflags = 0; |
154 | 476 | } |
155 | | |
156 | 476 | len = ASN1_STRING_print_ex(out, val, flags | orflags); |
157 | 476 | if (len < 0) { |
158 | 0 | return -1; |
159 | 0 | } |
160 | 476 | outlen += len; |
161 | 476 | } |
162 | 161 | return outlen; |
163 | 161 | } |
164 | | |
165 | | int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent, |
166 | 5.88k | unsigned long flags) { |
167 | 5.88k | if (flags == XN_FLAG_COMPAT) { |
168 | 5.72k | return X509_NAME_print(out, nm, indent); |
169 | 5.72k | } |
170 | 161 | return do_name_ex(out, nm, indent, flags); |
171 | 5.88k | } |
172 | | |
173 | | int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent, |
174 | 0 | unsigned long flags) { |
175 | 0 | BIO *bio = nullptr; |
176 | 0 | if (fp != nullptr) { |
177 | | // If `fp` is NULL, this function returns the number of bytes without |
178 | | // writing. |
179 | 0 | bio = BIO_new_fp(fp, BIO_NOCLOSE); |
180 | 0 | if (bio == nullptr) { |
181 | 0 | return -1; |
182 | 0 | } |
183 | 0 | } |
184 | 0 | int ret = X509_NAME_print_ex(bio, nm, indent, flags); |
185 | 0 | BIO_free(bio); |
186 | 0 | return ret; |
187 | 0 | } |