Fix safestack issues in x509.h
[openssl.git] / crypto / x509 / v3_prn.c
1 /*
2  * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 /* X509 v3 extension utilities */
11
12 #include <stdio.h>
13 #include "internal/cryptlib.h"
14 #include <openssl/conf.h>
15 #include <openssl/x509v3.h>
16
17 DEFINE_STACK_OF(CONF_VALUE)
18
19 /* Extension printing routines */
20
21 static int unknown_ext_print(BIO *out, const unsigned char *ext, int extlen,
22                              unsigned long flag, int indent, int supported);
23
24 /* Print out a name+value stack */
25
26 void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
27                         int ml)
28 {
29     int i;
30     CONF_VALUE *nval;
31     if (!val)
32         return;
33     if (!ml || !sk_CONF_VALUE_num(val)) {
34         BIO_printf(out, "%*s", indent, "");
35         if (!sk_CONF_VALUE_num(val))
36             BIO_puts(out, "<EMPTY>\n");
37     }
38     for (i = 0; i < sk_CONF_VALUE_num(val); i++) {
39         if (ml) {
40             if (i > 0)
41                 BIO_printf(out, "\n");
42             BIO_printf(out, "%*s", indent, "");
43         }
44         else if (i > 0)
45             BIO_printf(out, ", ");
46         nval = sk_CONF_VALUE_value(val, i);
47         if (!nval->name)
48             BIO_puts(out, nval->value);
49         else if (!nval->value)
50             BIO_puts(out, nval->name);
51 #ifndef CHARSET_EBCDIC
52         else
53             BIO_printf(out, "%s:%s", nval->name, nval->value);
54 #else
55         else {
56             int len;
57             char *tmp;
58             len = strlen(nval->value) + 1;
59             tmp = OPENSSL_malloc(len);
60             if (tmp != NULL) {
61                 ascii2ebcdic(tmp, nval->value, len);
62                 BIO_printf(out, "%s:%s", nval->name, tmp);
63                 OPENSSL_free(tmp);
64             }
65         }
66 #endif
67     }
68 }
69
70 /* Main routine: print out a general extension */
71
72 int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag,
73                      int indent)
74 {
75     void *ext_str = NULL;
76     char *value = NULL;
77     ASN1_OCTET_STRING *extoct;
78     const unsigned char *p;
79     int extlen;
80     const X509V3_EXT_METHOD *method;
81     STACK_OF(CONF_VALUE) *nval = NULL;
82     int ok = 1;
83
84     extoct = X509_EXTENSION_get_data(ext);
85     p = ASN1_STRING_get0_data(extoct);
86     extlen = ASN1_STRING_length(extoct);
87
88     if ((method = X509V3_EXT_get(ext)) == NULL)
89         return unknown_ext_print(out, p, extlen, flag, indent, 0);
90     if (method->it)
91         ext_str = ASN1_item_d2i(NULL, &p, extlen, ASN1_ITEM_ptr(method->it));
92     else
93         ext_str = method->d2i(NULL, &p, extlen);
94
95     if (!ext_str)
96         return unknown_ext_print(out, p, extlen, flag, indent, 1);
97
98     if (method->i2s) {
99         if ((value = method->i2s(method, ext_str)) == NULL) {
100             ok = 0;
101             goto err;
102         }
103 #ifndef CHARSET_EBCDIC
104         BIO_printf(out, "%*s%s", indent, "", value);
105 #else
106         {
107             int len;
108             char *tmp;
109             len = strlen(value) + 1;
110             tmp = OPENSSL_malloc(len);
111             if (tmp != NULL) {
112                 ascii2ebcdic(tmp, value, len);
113                 BIO_printf(out, "%*s%s", indent, "", tmp);
114                 OPENSSL_free(tmp);
115             }
116         }
117 #endif
118     } else if (method->i2v) {
119         if ((nval = method->i2v(method, ext_str, NULL)) == NULL) {
120             ok = 0;
121             goto err;
122         }
123         X509V3_EXT_val_prn(out, nval, indent,
124                            method->ext_flags & X509V3_EXT_MULTILINE);
125     } else if (method->i2r) {
126         if (!method->i2r(method, ext_str, out, indent))
127             ok = 0;
128     } else
129         ok = 0;
130
131  err:
132     sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
133     OPENSSL_free(value);
134     if (method->it)
135         ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it));
136     else
137         method->ext_free(ext_str);
138     return ok;
139 }
140
141 int X509V3_extensions_print(BIO *bp, const char *title,
142                             const STACK_OF(X509_EXTENSION) *exts,
143                             unsigned long flag, int indent)
144 {
145     int i, j;
146
147     if (sk_X509_EXTENSION_num(exts) <= 0)
148         return 1;
149
150     if (title) {
151         BIO_printf(bp, "%*s%s:\n", indent, "", title);
152         indent += 4;
153     }
154
155     for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
156         ASN1_OBJECT *obj;
157         X509_EXTENSION *ex;
158
159         ex = sk_X509_EXTENSION_value(exts, i);
160         obj = X509_EXTENSION_get_object(ex);
161         if ((flag & X509_FLAG_EXTENSIONS_ONLY_KID) != 0
162                 && OBJ_obj2nid(obj) != NID_subject_key_identifier
163                 && OBJ_obj2nid(obj) != NID_authority_key_identifier)
164             continue;
165         if (indent && BIO_printf(bp, "%*s", indent, "") <= 0)
166             return 0;
167         i2a_ASN1_OBJECT(bp, obj);
168         j = X509_EXTENSION_get_critical(ex);
169         if (BIO_printf(bp, ": %s\n", j ? "critical" : "") <= 0)
170             return 0;
171         if (!X509V3_EXT_print(bp, ex, flag, indent + 4)) {
172             BIO_printf(bp, "%*s", indent + 4, "");
173             ASN1_STRING_print(bp, X509_EXTENSION_get_data(ex));
174         }
175         if (BIO_write(bp, "\n", 1) <= 0)
176             return 0;
177     }
178     return 1;
179 }
180
181 static int unknown_ext_print(BIO *out, const unsigned char *ext, int extlen,
182                              unsigned long flag, int indent, int supported)
183 {
184     switch (flag & X509V3_EXT_UNKNOWN_MASK) {
185
186     case X509V3_EXT_DEFAULT:
187         return 0;
188
189     case X509V3_EXT_ERROR_UNKNOWN:
190         if (supported)
191             BIO_printf(out, "%*s<Parse Error>", indent, "");
192         else
193             BIO_printf(out, "%*s<Not Supported>", indent, "");
194         return 1;
195
196     case X509V3_EXT_PARSE_UNKNOWN:
197         return ASN1_parse_dump(out, ext, extlen, indent, -1);
198     case X509V3_EXT_DUMP_UNKNOWN:
199         return BIO_dump_indent(out, (const char *)ext, extlen, indent);
200
201     default:
202         return 1;
203     }
204 }
205
206 #ifndef OPENSSL_NO_STDIO
207 int X509V3_EXT_print_fp(FILE *fp, X509_EXTENSION *ext, int flag, int indent)
208 {
209     BIO *bio_tmp;
210     int ret;
211
212     if ((bio_tmp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL)
213         return 0;
214     ret = X509V3_EXT_print(bio_tmp, ext, flag, indent);
215     BIO_free(bio_tmp);
216     return ret;
217 }
218 #endif