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