1 1.1.1.2 christos /* 2 1.1.1.2 christos * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * 4 1.1.1.2 christos * Licensed under the OpenSSL license (the "License"). You may not use 5 1.1.1.2 christos * this file except in compliance with the License. You can obtain a copy 6 1.1.1.2 christos * in the file LICENSE in the source distribution or at 7 1.1.1.2 christos * https://www.openssl.org/source/license.html 8 1.1 christos */ 9 1.1 christos 10 1.1 christos #include <stdio.h> 11 1.1 christos #include <stdlib.h> 12 1.1 christos #include <string.h> 13 1.1 christos #include "apps.h" 14 1.1.1.2 christos #include "progs.h" 15 1.1 christos #include <openssl/bio.h> 16 1.1 christos #include <openssl/err.h> 17 1.1 christos #include <openssl/x509.h> 18 1.1 christos #include <openssl/x509v3.h> 19 1.1 christos #include <openssl/pem.h> 20 1.1 christos 21 1.1.1.2 christos static int cb(int ok, X509_STORE_CTX *ctx); 22 1.1.1.2 christos static int check(X509_STORE *ctx, const char *file, 23 1.1 christos STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, 24 1.1.1.2 christos STACK_OF(X509_CRL) *crls, int show_chain); 25 1.1 christos static int v_verbose = 0, vflags = 0; 26 1.1 christos 27 1.1.1.2 christos typedef enum OPTION_choice { 28 1.1.1.2 christos OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, 29 1.1.1.2 christos OPT_ENGINE, OPT_CAPATH, OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, 30 1.1.1.2 christos OPT_UNTRUSTED, OPT_TRUSTED, OPT_CRLFILE, OPT_CRL_DOWNLOAD, OPT_SHOW_CHAIN, 31 1.1.1.2 christos OPT_V_ENUM, OPT_NAMEOPT, 32 1.1.1.2 christos OPT_VERBOSE 33 1.1.1.2 christos } OPTION_CHOICE; 34 1.1.1.2 christos 35 1.1.1.2 christos const OPTIONS verify_options[] = { 36 1.1.1.2 christos {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"}, 37 1.1.1.2 christos {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, 38 1.1.1.2 christos {"help", OPT_HELP, '-', "Display this summary"}, 39 1.1.1.2 christos {"verbose", OPT_VERBOSE, '-', 40 1.1.1.2 christos "Print extra information about the operations being performed."}, 41 1.1.1.2 christos {"CApath", OPT_CAPATH, '/', "A directory of trusted certificates"}, 42 1.1.1.2 christos {"CAfile", OPT_CAFILE, '<', "A file of trusted certificates"}, 43 1.1.1.2 christos {"no-CAfile", OPT_NOCAFILE, '-', 44 1.1.1.2 christos "Do not load the default certificates file"}, 45 1.1.1.2 christos {"no-CApath", OPT_NOCAPATH, '-', 46 1.1.1.2 christos "Do not load certificates from the default certificates directory"}, 47 1.1.1.2 christos {"untrusted", OPT_UNTRUSTED, '<', "A file of untrusted certificates"}, 48 1.1.1.2 christos {"trusted", OPT_TRUSTED, '<', "A file of trusted certificates"}, 49 1.1.1.2 christos {"CRLfile", OPT_CRLFILE, '<', 50 1.1.1.2 christos "File containing one or more CRL's (in PEM format) to load"}, 51 1.1.1.2 christos {"crl_download", OPT_CRL_DOWNLOAD, '-', 52 1.1.1.2 christos "Attempt to download CRL information for this certificate"}, 53 1.1.1.2 christos {"show_chain", OPT_SHOW_CHAIN, '-', 54 1.1.1.2 christos "Display information about the certificate chain"}, 55 1.1.1.2 christos {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, 56 1.1.1.2 christos OPT_V_OPTIONS, 57 1.1.1.2 christos #ifndef OPENSSL_NO_ENGINE 58 1.1.1.2 christos {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 59 1.1.1.2 christos #endif 60 1.1.1.2 christos {NULL} 61 1.1.1.2 christos }; 62 1.1 christos 63 1.1.1.2 christos int verify_main(int argc, char **argv) 64 1.1 christos { 65 1.1 christos ENGINE *e = NULL; 66 1.1 christos STACK_OF(X509) *untrusted = NULL, *trusted = NULL; 67 1.1 christos STACK_OF(X509_CRL) *crls = NULL; 68 1.1.1.2 christos X509_STORE *store = NULL; 69 1.1 christos X509_VERIFY_PARAM *vpm = NULL; 70 1.1.1.2 christos const char *prog, *CApath = NULL, *CAfile = NULL; 71 1.1.1.2 christos int noCApath = 0, noCAfile = 0; 72 1.1.1.2 christos int vpmtouched = 0, crl_download = 0, show_chain = 0, i = 0, ret = 1; 73 1.1.1.2 christos OPTION_CHOICE o; 74 1.1 christos 75 1.1.1.2 christos if ((vpm = X509_VERIFY_PARAM_new()) == NULL) 76 1.1 christos goto end; 77 1.1 christos 78 1.1.1.2 christos prog = opt_init(argc, argv, verify_options); 79 1.1.1.2 christos while ((o = opt_next()) != OPT_EOF) { 80 1.1.1.2 christos switch (o) { 81 1.1.1.2 christos case OPT_EOF: 82 1.1.1.2 christos case OPT_ERR: 83 1.1.1.2 christos BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 84 1.1.1.2 christos goto end; 85 1.1.1.2 christos case OPT_HELP: 86 1.1.1.2 christos opt_help(verify_options); 87 1.1.1.2 christos BIO_printf(bio_err, "Recognized usages:\n"); 88 1.1.1.2 christos for (i = 0; i < X509_PURPOSE_get_count(); i++) { 89 1.1.1.2 christos X509_PURPOSE *ptmp; 90 1.1.1.2 christos ptmp = X509_PURPOSE_get0(i); 91 1.1.1.2 christos BIO_printf(bio_err, "\t%-10s\t%s\n", 92 1.1.1.2 christos X509_PURPOSE_get0_sname(ptmp), 93 1.1.1.2 christos X509_PURPOSE_get0_name(ptmp)); 94 1.1.1.2 christos } 95 1.1 christos 96 1.1.1.2 christos BIO_printf(bio_err, "Recognized verify names:\n"); 97 1.1.1.2 christos for (i = 0; i < X509_VERIFY_PARAM_get_count(); i++) { 98 1.1.1.2 christos const X509_VERIFY_PARAM *vptmp; 99 1.1.1.2 christos vptmp = X509_VERIFY_PARAM_get0(i); 100 1.1.1.2 christos BIO_printf(bio_err, "\t%-10s\n", 101 1.1.1.2 christos X509_VERIFY_PARAM_get0_name(vptmp)); 102 1.1 christos } 103 1.1.1.2 christos ret = 0; 104 1.1.1.2 christos goto end; 105 1.1.1.2 christos case OPT_V_CASES: 106 1.1.1.2 christos if (!opt_verify(o, vpm)) 107 1.1.1.2 christos goto end; 108 1.1.1.2 christos vpmtouched++; 109 1.1.1.2 christos break; 110 1.1.1.2 christos case OPT_CAPATH: 111 1.1.1.2 christos CApath = opt_arg(); 112 1.1.1.2 christos break; 113 1.1.1.2 christos case OPT_CAFILE: 114 1.1.1.2 christos CAfile = opt_arg(); 115 1.1 christos break; 116 1.1.1.2 christos case OPT_NOCAPATH: 117 1.1.1.2 christos noCApath = 1; 118 1.1.1.2 christos break; 119 1.1.1.2 christos case OPT_NOCAFILE: 120 1.1.1.2 christos noCAfile = 1; 121 1.1.1.2 christos break; 122 1.1.1.2 christos case OPT_UNTRUSTED: 123 1.1.1.2 christos /* Zero or more times */ 124 1.1.1.2 christos if (!load_certs(opt_arg(), &untrusted, FORMAT_PEM, NULL, 125 1.1.1.2 christos "untrusted certificates")) 126 1.1.1.2 christos goto end; 127 1.1.1.2 christos break; 128 1.1.1.2 christos case OPT_TRUSTED: 129 1.1.1.2 christos /* Zero or more times */ 130 1.1.1.2 christos noCAfile = 1; 131 1.1.1.2 christos noCApath = 1; 132 1.1.1.2 christos if (!load_certs(opt_arg(), &trusted, FORMAT_PEM, NULL, 133 1.1.1.2 christos "trusted certificates")) 134 1.1.1.2 christos goto end; 135 1.1.1.2 christos break; 136 1.1.1.2 christos case OPT_CRLFILE: 137 1.1.1.2 christos /* Zero or more times */ 138 1.1.1.2 christos if (!load_crls(opt_arg(), &crls, FORMAT_PEM, NULL, 139 1.1.1.2 christos "other CRLs")) 140 1.1.1.2 christos goto end; 141 1.1.1.2 christos break; 142 1.1.1.2 christos case OPT_CRL_DOWNLOAD: 143 1.1.1.2 christos crl_download = 1; 144 1.1.1.2 christos break; 145 1.1.1.2 christos case OPT_ENGINE: 146 1.1.1.2 christos if ((e = setup_engine(opt_arg(), 0)) == NULL) { 147 1.1.1.2 christos /* Failure message already displayed */ 148 1.1.1.2 christos goto end; 149 1.1.1.2 christos } 150 1.1.1.2 christos break; 151 1.1.1.2 christos case OPT_SHOW_CHAIN: 152 1.1.1.2 christos show_chain = 1; 153 1.1.1.2 christos break; 154 1.1.1.2 christos case OPT_NAMEOPT: 155 1.1.1.2 christos if (!set_nameopt(opt_arg())) 156 1.1.1.2 christos goto end; 157 1.1.1.2 christos break; 158 1.1.1.2 christos case OPT_VERBOSE: 159 1.1.1.2 christos v_verbose = 1; 160 1.1.1.2 christos break; 161 1.1.1.2 christos } 162 1.1.1.2 christos } 163 1.1.1.2 christos argc = opt_num_rest(); 164 1.1.1.2 christos argv = opt_rest(); 165 1.1.1.2 christos if (trusted != NULL && (CAfile || CApath)) { 166 1.1.1.2 christos BIO_printf(bio_err, 167 1.1.1.2 christos "%s: Cannot use -trusted with -CAfile or -CApath\n", 168 1.1.1.2 christos prog); 169 1.1.1.2 christos goto end; 170 1.1 christos } 171 1.1 christos 172 1.1.1.2 christos if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) 173 1.1.1.2 christos goto end; 174 1.1.1.2 christos X509_STORE_set_verify_cb(store, cb); 175 1.1 christos 176 1.1.1.2 christos if (vpmtouched) 177 1.1.1.2 christos X509_STORE_set1_param(store, vpm); 178 1.1 christos 179 1.1 christos ERR_clear_error(); 180 1.1 christos 181 1.1.1.2 christos if (crl_download) 182 1.1.1.2 christos store_setup_crl_download(store); 183 1.1 christos 184 1.1 christos ret = 0; 185 1.1 christos if (argc < 1) { 186 1.1.1.2 christos if (check(store, NULL, untrusted, trusted, crls, show_chain) != 1) 187 1.1 christos ret = -1; 188 1.1 christos } else { 189 1.1 christos for (i = 0; i < argc; i++) 190 1.1.1.2 christos if (check(store, argv[i], untrusted, trusted, crls, 191 1.1.1.2 christos show_chain) != 1) 192 1.1 christos ret = -1; 193 1.1 christos } 194 1.1 christos 195 1.1 christos end: 196 1.1.1.2 christos X509_VERIFY_PARAM_free(vpm); 197 1.1.1.2 christos X509_STORE_free(store); 198 1.1 christos sk_X509_pop_free(untrusted, X509_free); 199 1.1 christos sk_X509_pop_free(trusted, X509_free); 200 1.1 christos sk_X509_CRL_pop_free(crls, X509_CRL_free); 201 1.1 christos release_engine(e); 202 1.1.1.2 christos return (ret < 0 ? 2 : ret); 203 1.1 christos } 204 1.1 christos 205 1.1.1.2 christos static int check(X509_STORE *ctx, const char *file, 206 1.1 christos STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, 207 1.1.1.2 christos STACK_OF(X509_CRL) *crls, int show_chain) 208 1.1 christos { 209 1.1 christos X509 *x = NULL; 210 1.1 christos int i = 0, ret = 0; 211 1.1 christos X509_STORE_CTX *csc; 212 1.1.1.2 christos STACK_OF(X509) *chain = NULL; 213 1.1.1.2 christos int num_untrusted; 214 1.1 christos 215 1.1.1.2 christos x = load_cert(file, FORMAT_PEM, "certificate file"); 216 1.1 christos if (x == NULL) 217 1.1 christos goto end; 218 1.1 christos 219 1.1 christos csc = X509_STORE_CTX_new(); 220 1.1 christos if (csc == NULL) { 221 1.1.1.2 christos printf("error %s: X.509 store context allocation failed\n", 222 1.1.1.2 christos (file == NULL) ? "stdin" : file); 223 1.1 christos goto end; 224 1.1 christos } 225 1.1.1.2 christos 226 1.1 christos X509_STORE_set_flags(ctx, vflags); 227 1.1 christos if (!X509_STORE_CTX_init(csc, ctx, x, uchain)) { 228 1.1.1.2 christos X509_STORE_CTX_free(csc); 229 1.1.1.2 christos printf("error %s: X.509 store context initialization failed\n", 230 1.1.1.2 christos (file == NULL) ? "stdin" : file); 231 1.1 christos goto end; 232 1.1 christos } 233 1.1.1.2 christos if (tchain != NULL) 234 1.1.1.2 christos X509_STORE_CTX_set0_trusted_stack(csc, tchain); 235 1.1.1.2 christos if (crls != NULL) 236 1.1 christos X509_STORE_CTX_set0_crls(csc, crls); 237 1.1 christos i = X509_verify_cert(csc); 238 1.1.1.2 christos if (i > 0 && X509_STORE_CTX_get_error(csc) == X509_V_OK) { 239 1.1.1.2 christos printf("%s: OK\n", (file == NULL) ? "stdin" : file); 240 1.1.1.2 christos ret = 1; 241 1.1.1.2 christos if (show_chain) { 242 1.1.1.2 christos int j; 243 1.1.1.2 christos 244 1.1.1.2 christos chain = X509_STORE_CTX_get1_chain(csc); 245 1.1.1.2 christos num_untrusted = X509_STORE_CTX_get_num_untrusted(csc); 246 1.1.1.2 christos printf("Chain:\n"); 247 1.1.1.2 christos for (j = 0; j < sk_X509_num(chain); j++) { 248 1.1.1.2 christos X509 *cert = sk_X509_value(chain, j); 249 1.1.1.2 christos printf("depth=%d: ", j); 250 1.1.1.2 christos X509_NAME_print_ex_fp(stdout, 251 1.1.1.2 christos X509_get_subject_name(cert), 252 1.1.1.2 christos 0, get_nameopt()); 253 1.1.1.2 christos if (j < num_untrusted) 254 1.1.1.2 christos printf(" (untrusted)"); 255 1.1.1.2 christos printf("\n"); 256 1.1.1.2 christos } 257 1.1.1.2 christos sk_X509_pop_free(chain, X509_free); 258 1.1.1.2 christos } 259 1.1.1.2 christos } else { 260 1.1.1.2 christos printf("error %s: verification failed\n", (file == NULL) ? "stdin" : file); 261 1.1.1.2 christos } 262 1.1 christos X509_STORE_CTX_free(csc); 263 1.1 christos 264 1.1 christos end: 265 1.1.1.2 christos if (i <= 0) 266 1.1 christos ERR_print_errors(bio_err); 267 1.1.1.2 christos X509_free(x); 268 1.1 christos 269 1.1.1.2 christos return ret; 270 1.1 christos } 271 1.1 christos 272 1.1.1.2 christos static int cb(int ok, X509_STORE_CTX *ctx) 273 1.1 christos { 274 1.1 christos int cert_error = X509_STORE_CTX_get_error(ctx); 275 1.1 christos X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx); 276 1.1 christos 277 1.1 christos if (!ok) { 278 1.1.1.2 christos if (current_cert != NULL) { 279 1.1.1.2 christos X509_NAME_print_ex(bio_err, 280 1.1.1.2 christos X509_get_subject_name(current_cert), 281 1.1.1.2 christos 0, get_nameopt()); 282 1.1.1.2 christos BIO_printf(bio_err, "\n"); 283 1.1 christos } 284 1.1.1.2 christos BIO_printf(bio_err, "%serror %d at %d depth lookup: %s\n", 285 1.1.1.2 christos X509_STORE_CTX_get0_parent_ctx(ctx) ? "[CRL path] " : "", 286 1.1 christos cert_error, 287 1.1 christos X509_STORE_CTX_get_error_depth(ctx), 288 1.1 christos X509_verify_cert_error_string(cert_error)); 289 1.1.1.2 christos 290 1.1.1.2 christos /* 291 1.1.1.2 christos * Pretend that some errors are ok, so they don't stop further 292 1.1.1.2 christos * processing of the certificate chain. Setting ok = 1 does this. 293 1.1.1.2 christos * After X509_verify_cert() is done, we verify that there were 294 1.1.1.2 christos * no actual errors, even if the returned value was positive. 295 1.1.1.2 christos */ 296 1.1 christos switch (cert_error) { 297 1.1 christos case X509_V_ERR_NO_EXPLICIT_POLICY: 298 1.1.1.2 christos policies_print(ctx); 299 1.1.1.2 christos /* fall thru */ 300 1.1 christos case X509_V_ERR_CERT_HAS_EXPIRED: 301 1.1.1.2 christos /* Continue even if the leaf is a self signed cert */ 302 1.1 christos case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: 303 1.1 christos /* Continue after extension errors too */ 304 1.1 christos case X509_V_ERR_INVALID_CA: 305 1.1 christos case X509_V_ERR_INVALID_NON_CA: 306 1.1 christos case X509_V_ERR_PATH_LENGTH_EXCEEDED: 307 1.1 christos case X509_V_ERR_INVALID_PURPOSE: 308 1.1 christos case X509_V_ERR_CRL_HAS_EXPIRED: 309 1.1 christos case X509_V_ERR_CRL_NOT_YET_VALID: 310 1.1 christos case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: 311 1.1 christos ok = 1; 312 1.1 christos } 313 1.1 christos 314 1.1 christos return ok; 315 1.1 christos 316 1.1 christos } 317 1.1 christos if (cert_error == X509_V_OK && ok == 2) 318 1.1.1.2 christos policies_print(ctx); 319 1.1 christos if (!v_verbose) 320 1.1 christos ERR_clear_error(); 321 1.1.1.2 christos return ok; 322 1.1 christos } 323