/src/boringssl/crypto/x509/v3_prn.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 1999-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 | | // X509 v3 extension utilities |
16 | | |
17 | | #include <stdio.h> |
18 | | |
19 | | #include <openssl/bio.h> |
20 | | #include <openssl/conf.h> |
21 | | #include <openssl/mem.h> |
22 | | #include <openssl/x509.h> |
23 | | |
24 | | // Extension printing routines |
25 | | |
26 | | static int unknown_ext_print(BIO *out, const X509_EXTENSION *ext, |
27 | | unsigned long flag, int indent, int supported); |
28 | | |
29 | | // Print out a name+value stack |
30 | | static void X509V3_EXT_val_prn(BIO *out, const STACK_OF(CONF_VALUE) *val, |
31 | 2.69k | int indent, int ml) { |
32 | 2.69k | if (!val) { |
33 | 0 | return; |
34 | 0 | } |
35 | 2.69k | if (!ml || !sk_CONF_VALUE_num(val)) { |
36 | 2.46k | BIO_printf(out, "%*s", indent, ""); |
37 | 2.46k | if (!sk_CONF_VALUE_num(val)) { |
38 | 260 | BIO_puts(out, "<EMPTY>\n"); |
39 | 260 | } |
40 | 2.46k | } |
41 | 19.4k | for (size_t i = 0; i < sk_CONF_VALUE_num(val); i++) { |
42 | 16.7k | if (ml) { |
43 | 399 | BIO_printf(out, "%*s", indent, ""); |
44 | 16.3k | } else if (i > 0) { |
45 | 14.1k | BIO_printf(out, ", "); |
46 | 14.1k | } |
47 | 16.7k | const CONF_VALUE *nval = sk_CONF_VALUE_value(val, i); |
48 | 16.7k | if (!nval->name) { |
49 | 700 | BIO_puts(out, nval->value); |
50 | 16.0k | } else if (!nval->value) { |
51 | 6.49k | BIO_puts(out, nval->name); |
52 | 9.50k | } else { |
53 | 9.50k | BIO_printf(out, "%s:%s", nval->name, nval->value); |
54 | 9.50k | } |
55 | 16.7k | if (ml) { |
56 | 399 | BIO_puts(out, "\n"); |
57 | 399 | } |
58 | 16.7k | } |
59 | 2.69k | } |
60 | | |
61 | | // Main routine: print out a general extension |
62 | | |
63 | | int X509V3_EXT_print(BIO *out, const X509_EXTENSION *ext, unsigned long flag, |
64 | 28.3k | int indent) { |
65 | 28.3k | const X509V3_EXT_METHOD *method = X509V3_EXT_get(ext); |
66 | 28.3k | if (method == NULL) { |
67 | 12.8k | return unknown_ext_print(out, ext, flag, indent, 0); |
68 | 12.8k | } |
69 | 15.5k | const ASN1_STRING *ext_data = X509_EXTENSION_get_data(ext); |
70 | 15.5k | const unsigned char *p = ASN1_STRING_get0_data(ext_data); |
71 | 15.5k | void *ext_str = ASN1_item_d2i(NULL, &p, ASN1_STRING_length(ext_data), |
72 | 15.5k | ASN1_ITEM_ptr(method->it)); |
73 | 15.5k | if (!ext_str) { |
74 | 8.36k | return unknown_ext_print(out, ext, flag, indent, 1); |
75 | 8.36k | } |
76 | | |
77 | 7.15k | char *value = NULL; |
78 | 7.15k | STACK_OF(CONF_VALUE) *nval = NULL; |
79 | 7.15k | int ok = 0; |
80 | 7.15k | if (method->i2s) { |
81 | 2.36k | if (!(value = method->i2s(method, ext_str))) { |
82 | 11 | goto err; |
83 | 11 | } |
84 | 2.35k | BIO_printf(out, "%*s%s", indent, "", value); |
85 | 4.79k | } else if (method->i2v) { |
86 | 3.39k | if (!(nval = method->i2v(method, ext_str, NULL))) { |
87 | 694 | goto err; |
88 | 694 | } |
89 | 2.69k | X509V3_EXT_val_prn(out, nval, indent, |
90 | 2.69k | method->ext_flags & X509V3_EXT_MULTILINE); |
91 | 2.69k | } else if (method->i2r) { |
92 | 1.40k | if (!method->i2r(method, ext_str, out, indent)) { |
93 | 0 | goto err; |
94 | 0 | } |
95 | 1.40k | } else { |
96 | 0 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED); |
97 | 0 | goto err; |
98 | 0 | } |
99 | | |
100 | 6.45k | ok = 1; |
101 | | |
102 | 7.15k | err: |
103 | 7.15k | sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); |
104 | 7.15k | OPENSSL_free(value); |
105 | 7.15k | ASN1_item_free(reinterpret_cast<ASN1_VALUE *>(ext_str), |
106 | 7.15k | ASN1_ITEM_ptr(method->it)); |
107 | 7.15k | return ok; |
108 | 6.45k | } |
109 | | |
110 | | int X509V3_extensions_print(BIO *bp, const char *title, |
111 | | const STACK_OF(X509_EXTENSION) *exts, |
112 | 2.81k | unsigned long flag, int indent) { |
113 | 2.81k | size_t i; |
114 | 2.81k | int j; |
115 | | |
116 | 2.81k | if (sk_X509_EXTENSION_num(exts) <= 0) { |
117 | 327 | return 1; |
118 | 327 | } |
119 | | |
120 | 2.48k | if (title) { |
121 | 2.48k | BIO_printf(bp, "%*s%s:\n", indent, "", title); |
122 | 2.48k | indent += 4; |
123 | 2.48k | } |
124 | | |
125 | 30.8k | for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { |
126 | 28.3k | const X509_EXTENSION *ex = sk_X509_EXTENSION_value(exts, i); |
127 | 28.3k | if (indent && BIO_printf(bp, "%*s", indent, "") <= 0) { |
128 | 0 | return 0; |
129 | 0 | } |
130 | 28.3k | const ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex); |
131 | 28.3k | i2a_ASN1_OBJECT(bp, obj); |
132 | 28.3k | j = X509_EXTENSION_get_critical(ex); |
133 | 28.3k | if (BIO_printf(bp, ": %s\n", j ? "critical" : "") <= 0) { |
134 | 0 | return 0; |
135 | 0 | } |
136 | 28.3k | if (!X509V3_EXT_print(bp, ex, flag, indent + 4)) { |
137 | 21.8k | BIO_printf(bp, "%*s", indent + 4, ""); |
138 | 21.8k | ASN1_STRING_print(bp, X509_EXTENSION_get_data(ex)); |
139 | 21.8k | } |
140 | 28.3k | if (BIO_write(bp, "\n", 1) <= 0) { |
141 | 0 | return 0; |
142 | 0 | } |
143 | 28.3k | } |
144 | 2.48k | return 1; |
145 | 2.48k | } |
146 | | |
147 | | static int unknown_ext_print(BIO *out, const X509_EXTENSION *ext, |
148 | 21.1k | unsigned long flag, int indent, int supported) { |
149 | 21.1k | switch (flag & X509V3_EXT_UNKNOWN_MASK) { |
150 | 21.1k | case X509V3_EXT_DEFAULT: |
151 | 21.1k | return 0; |
152 | | |
153 | 0 | case X509V3_EXT_ERROR_UNKNOWN: |
154 | 0 | if (supported) { |
155 | 0 | BIO_printf(out, "%*s<Parse Error>", indent, ""); |
156 | 0 | } else { |
157 | 0 | BIO_printf(out, "%*s<Not Supported>", indent, ""); |
158 | 0 | } |
159 | 0 | return 1; |
160 | | |
161 | 0 | case X509V3_EXT_PARSE_UNKNOWN: |
162 | 0 | case X509V3_EXT_DUMP_UNKNOWN: { |
163 | 0 | const ASN1_STRING *data = X509_EXTENSION_get_data(ext); |
164 | 0 | return BIO_hexdump(out, ASN1_STRING_get0_data(data), |
165 | 0 | ASN1_STRING_length(data), indent); |
166 | 0 | } |
167 | | |
168 | 0 | default: |
169 | 0 | return 1; |
170 | 21.1k | } |
171 | 21.1k | } |
172 | | |
173 | | int X509V3_EXT_print_fp(FILE *fp, const X509_EXTENSION *ext, int flag, |
174 | 0 | int indent) { |
175 | 0 | BIO *bio_tmp; |
176 | 0 | int ret; |
177 | 0 | if (!(bio_tmp = BIO_new_fp(fp, BIO_NOCLOSE))) { |
178 | 0 | return 0; |
179 | 0 | } |
180 | 0 | ret = X509V3_EXT_print(bio_tmp, ext, flag, indent); |
181 | 0 | BIO_free(bio_tmp); |
182 | 0 | return ret; |
183 | 0 | } |