174664626SKris Kennaway /* apps/verify.c */ 274664626SKris Kennaway /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 374664626SKris Kennaway * All rights reserved. 474664626SKris Kennaway * 574664626SKris Kennaway * This package is an SSL implementation written 674664626SKris Kennaway * by Eric Young (eay@cryptsoft.com). 774664626SKris Kennaway * The implementation was written so as to conform with Netscapes SSL. 874664626SKris Kennaway * 974664626SKris Kennaway * This library is free for commercial and non-commercial use as long as 1074664626SKris Kennaway * the following conditions are aheared to. The following conditions 1174664626SKris Kennaway * apply to all code found in this distribution, be it the RC4, RSA, 1274664626SKris Kennaway * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1374664626SKris Kennaway * included with this distribution is covered by the same copyright terms 1474664626SKris Kennaway * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1574664626SKris Kennaway * 1674664626SKris Kennaway * Copyright remains Eric Young's, and as such any Copyright notices in 1774664626SKris Kennaway * the code are not to be removed. 1874664626SKris Kennaway * If this package is used in a product, Eric Young should be given attribution 1974664626SKris Kennaway * as the author of the parts of the library used. 2074664626SKris Kennaway * This can be in the form of a textual message at program startup or 2174664626SKris Kennaway * in documentation (online or textual) provided with the package. 2274664626SKris Kennaway * 2374664626SKris Kennaway * Redistribution and use in source and binary forms, with or without 2474664626SKris Kennaway * modification, are permitted provided that the following conditions 2574664626SKris Kennaway * are met: 2674664626SKris Kennaway * 1. Redistributions of source code must retain the copyright 2774664626SKris Kennaway * notice, this list of conditions and the following disclaimer. 2874664626SKris Kennaway * 2. Redistributions in binary form must reproduce the above copyright 2974664626SKris Kennaway * notice, this list of conditions and the following disclaimer in the 3074664626SKris Kennaway * documentation and/or other materials provided with the distribution. 3174664626SKris Kennaway * 3. All advertising materials mentioning features or use of this software 3274664626SKris Kennaway * must display the following acknowledgement: 3374664626SKris Kennaway * "This product includes cryptographic software written by 3474664626SKris Kennaway * Eric Young (eay@cryptsoft.com)" 3574664626SKris Kennaway * The word 'cryptographic' can be left out if the rouines from the library 3674664626SKris Kennaway * being used are not cryptographic related :-). 3774664626SKris Kennaway * 4. If you include any Windows specific code (or a derivative thereof) from 3874664626SKris Kennaway * the apps directory (application code) you must include an acknowledgement: 3974664626SKris Kennaway * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4074664626SKris Kennaway * 4174664626SKris Kennaway * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4274664626SKris Kennaway * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4374664626SKris Kennaway * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4474664626SKris Kennaway * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4574664626SKris Kennaway * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4674664626SKris Kennaway * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4774664626SKris Kennaway * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4874664626SKris Kennaway * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4974664626SKris Kennaway * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5074664626SKris Kennaway * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5174664626SKris Kennaway * SUCH DAMAGE. 5274664626SKris Kennaway * 5374664626SKris Kennaway * The licence and distribution terms for any publically available version or 5474664626SKris Kennaway * derivative of this code cannot be changed. i.e. this code cannot simply be 5574664626SKris Kennaway * copied and put under another distribution licence 5674664626SKris Kennaway * [including the GNU Public Licence.] 5774664626SKris Kennaway */ 5874664626SKris Kennaway 5974664626SKris Kennaway #include <stdio.h> 6074664626SKris Kennaway #include <stdlib.h> 6174664626SKris Kennaway #include <string.h> 6274664626SKris Kennaway #include "apps.h" 6374664626SKris Kennaway #include <openssl/bio.h> 6474664626SKris Kennaway #include <openssl/err.h> 6574664626SKris Kennaway #include <openssl/x509.h> 66f579bf8eSKris Kennaway #include <openssl/x509v3.h> 6774664626SKris Kennaway #include <openssl/pem.h> 6874664626SKris Kennaway 6974664626SKris Kennaway #undef PROG 7074664626SKris Kennaway #define PROG verify_main 7174664626SKris Kennaway 7274664626SKris Kennaway static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx); 731f13597dSJung-uk Kim static int check(X509_STORE *ctx, char *file, 741f13597dSJung-uk Kim STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, 751f13597dSJung-uk Kim STACK_OF(X509_CRL) *crls, ENGINE *e); 765c87c606SMark Murray static int v_verbose = 0, vflags = 0; 7774664626SKris Kennaway 78f579bf8eSKris Kennaway int MAIN(int, char **); 79f579bf8eSKris Kennaway 8074664626SKris Kennaway int MAIN(int argc, char **argv) 8174664626SKris Kennaway { 825c87c606SMark Murray ENGINE *e = NULL; 833b4e3dcbSSimon L. B. Nielsen int i, ret = 1, badarg = 0; 8474664626SKris Kennaway char *CApath = NULL, *CAfile = NULL; 851f13597dSJung-uk Kim char *untfile = NULL, *trustfile = NULL, *crlfile = NULL; 86ddd58736SKris Kennaway STACK_OF(X509) *untrusted = NULL, *trusted = NULL; 871f13597dSJung-uk Kim STACK_OF(X509_CRL) *crls = NULL; 8874664626SKris Kennaway X509_STORE *cert_ctx = NULL; 8974664626SKris Kennaway X509_LOOKUP *lookup = NULL; 903b4e3dcbSSimon L. B. Nielsen X509_VERIFY_PARAM *vpm = NULL; 917bded2dbSJung-uk Kim int crl_download = 0; 92fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_ENGINE 935c87c606SMark Murray char *engine = NULL; 94fceca8a3SJacques Vidrine #endif 9574664626SKris Kennaway 9674664626SKris Kennaway cert_ctx = X509_STORE_new(); 976f9291ceSJung-uk Kim if (cert_ctx == NULL) 986f9291ceSJung-uk Kim goto end; 991f13597dSJung-uk Kim X509_STORE_set_verify_cb(cert_ctx, cb); 10074664626SKris Kennaway 10174664626SKris Kennaway ERR_load_crypto_strings(); 10274664626SKris Kennaway 10374664626SKris Kennaway apps_startup(); 10474664626SKris Kennaway 10574664626SKris Kennaway if (bio_err == NULL) 10674664626SKris Kennaway if ((bio_err = BIO_new(BIO_s_file())) != NULL) 10774664626SKris Kennaway BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); 10874664626SKris Kennaway 1095c87c606SMark Murray if (!load_config(bio_err, NULL)) 1105c87c606SMark Murray goto end; 1115c87c606SMark Murray 11274664626SKris Kennaway argc--; 11374664626SKris Kennaway argv++; 1146f9291ceSJung-uk Kim for (;;) { 1156f9291ceSJung-uk Kim if (argc >= 1) { 1166f9291ceSJung-uk Kim if (strcmp(*argv, "-CApath") == 0) { 1176f9291ceSJung-uk Kim if (argc-- < 1) 118*aeb5019cSJung-uk Kim goto usage; 11974664626SKris Kennaway CApath = *(++argv); 1206f9291ceSJung-uk Kim } else if (strcmp(*argv, "-CAfile") == 0) { 1216f9291ceSJung-uk Kim if (argc-- < 1) 122*aeb5019cSJung-uk Kim goto usage; 12374664626SKris Kennaway CAfile = *(++argv); 1246f9291ceSJung-uk Kim } else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) { 1253b4e3dcbSSimon L. B. Nielsen if (badarg) 126*aeb5019cSJung-uk Kim goto usage; 1273b4e3dcbSSimon L. B. Nielsen continue; 1286f9291ceSJung-uk Kim } else if (strcmp(*argv, "-untrusted") == 0) { 1296f9291ceSJung-uk Kim if (argc-- < 1) 130*aeb5019cSJung-uk Kim goto usage; 131f579bf8eSKris Kennaway untfile = *(++argv); 1326f9291ceSJung-uk Kim } else if (strcmp(*argv, "-trusted") == 0) { 1336f9291ceSJung-uk Kim if (argc-- < 1) 134*aeb5019cSJung-uk Kim goto usage; 135ddd58736SKris Kennaway trustfile = *(++argv); 1366f9291ceSJung-uk Kim } else if (strcmp(*argv, "-CRLfile") == 0) { 1376f9291ceSJung-uk Kim if (argc-- < 1) 138*aeb5019cSJung-uk Kim goto usage; 1391f13597dSJung-uk Kim crlfile = *(++argv); 1407bded2dbSJung-uk Kim } else if (strcmp(*argv, "-crl_download") == 0) 1417bded2dbSJung-uk Kim crl_download = 1; 142fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_ENGINE 1436f9291ceSJung-uk Kim else if (strcmp(*argv, "-engine") == 0) { 1446f9291ceSJung-uk Kim if (--argc < 1) 145*aeb5019cSJung-uk Kim goto usage; 1465c87c606SMark Murray engine = *(++argv); 1475c87c606SMark Murray } 148fceca8a3SJacques Vidrine #endif 14974664626SKris Kennaway else if (strcmp(*argv, "-help") == 0) 150*aeb5019cSJung-uk Kim goto usage; 15174664626SKris Kennaway else if (strcmp(*argv, "-verbose") == 0) 15274664626SKris Kennaway v_verbose = 1; 15374664626SKris Kennaway else if (argv[0][0] == '-') 154*aeb5019cSJung-uk Kim goto usage; 15574664626SKris Kennaway else 15674664626SKris Kennaway break; 15774664626SKris Kennaway argc--; 15874664626SKris Kennaway argv++; 1596f9291ceSJung-uk Kim } else 16074664626SKris Kennaway break; 16174664626SKris Kennaway } 16274664626SKris Kennaway 163fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_ENGINE 1645c87c606SMark Murray e = setup_engine(bio_err, engine, 0); 165fceca8a3SJacques Vidrine #endif 1665c87c606SMark Murray 1673b4e3dcbSSimon L. B. Nielsen if (vpm) 1683b4e3dcbSSimon L. B. Nielsen X509_STORE_set1_param(cert_ctx, vpm); 1693b4e3dcbSSimon L. B. Nielsen 17074664626SKris Kennaway lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file()); 1716f9291ceSJung-uk Kim if (lookup == NULL) 1726f9291ceSJung-uk Kim abort(); 173f579bf8eSKris Kennaway if (CAfile) { 174f579bf8eSKris Kennaway i = X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM); 175f579bf8eSKris Kennaway if (!i) { 176f579bf8eSKris Kennaway BIO_printf(bio_err, "Error loading file %s\n", CAfile); 177f579bf8eSKris Kennaway ERR_print_errors(bio_err); 178f579bf8eSKris Kennaway goto end; 179f579bf8eSKris Kennaway } 1806f9291ceSJung-uk Kim } else 1816f9291ceSJung-uk Kim X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); 18274664626SKris Kennaway 18374664626SKris Kennaway lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir()); 1846f9291ceSJung-uk Kim if (lookup == NULL) 1856f9291ceSJung-uk Kim abort(); 186f579bf8eSKris Kennaway if (CApath) { 187f579bf8eSKris Kennaway i = X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM); 188f579bf8eSKris Kennaway if (!i) { 189f579bf8eSKris Kennaway BIO_printf(bio_err, "Error loading directory %s\n", CApath); 190f579bf8eSKris Kennaway ERR_print_errors(bio_err); 191f579bf8eSKris Kennaway goto end; 192f579bf8eSKris Kennaway } 1936f9291ceSJung-uk Kim } else 1946f9291ceSJung-uk Kim X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); 19574664626SKris Kennaway 19674664626SKris Kennaway ERR_clear_error(); 197f579bf8eSKris Kennaway 1986f9291ceSJung-uk Kim if (untfile) { 1991f13597dSJung-uk Kim untrusted = load_certs(bio_err, untfile, FORMAT_PEM, 2001f13597dSJung-uk Kim NULL, e, "untrusted certificates"); 2011f13597dSJung-uk Kim if (!untrusted) 202f579bf8eSKris Kennaway goto end; 203f579bf8eSKris Kennaway } 204f579bf8eSKris Kennaway 2056f9291ceSJung-uk Kim if (trustfile) { 2061f13597dSJung-uk Kim trusted = load_certs(bio_err, trustfile, FORMAT_PEM, 2071f13597dSJung-uk Kim NULL, e, "trusted certificates"); 2081f13597dSJung-uk Kim if (!trusted) 209ddd58736SKris Kennaway goto end; 210ddd58736SKris Kennaway } 2111f13597dSJung-uk Kim 2126f9291ceSJung-uk Kim if (crlfile) { 2136f9291ceSJung-uk Kim crls = load_crls(bio_err, crlfile, FORMAT_PEM, NULL, e, "other CRLs"); 2141f13597dSJung-uk Kim if (!crls) 2151f13597dSJung-uk Kim goto end; 216ddd58736SKris Kennaway } 217ddd58736SKris Kennaway 21874664626SKris Kennaway ret = 0; 2197bded2dbSJung-uk Kim 2207bded2dbSJung-uk Kim if (crl_download) 2217bded2dbSJung-uk Kim store_setup_crl_download(cert_ctx); 2226f9291ceSJung-uk Kim if (argc < 1) { 22309286989SJung-uk Kim if (1 != check(cert_ctx, NULL, untrusted, trusted, crls, e)) 22409286989SJung-uk Kim ret = -1; 2256f9291ceSJung-uk Kim } else { 22609286989SJung-uk Kim for (i = 0; i < argc; i++) 22709286989SJung-uk Kim if (1 != check(cert_ctx, argv[i], untrusted, trusted, crls, e)) 22809286989SJung-uk Kim ret = -1; 22909286989SJung-uk Kim } 23009286989SJung-uk Kim 231*aeb5019cSJung-uk Kim usage: 232f579bf8eSKris Kennaway if (ret == 1) { 2336f9291ceSJung-uk Kim BIO_printf(bio_err, 2346f9291ceSJung-uk Kim "usage: verify [-verbose] [-CApath path] [-CAfile file] [-purpose purpose] [-crl_check]"); 235ed6b93beSJung-uk Kim BIO_printf(bio_err, " [-no_alt_chains] [-attime timestamp]"); 236fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_ENGINE 237fceca8a3SJacques Vidrine BIO_printf(bio_err, " [-engine e]"); 238fceca8a3SJacques Vidrine #endif 239fceca8a3SJacques Vidrine BIO_printf(bio_err, " cert1 cert2 ...\n"); 24009286989SJung-uk Kim 241f579bf8eSKris Kennaway BIO_printf(bio_err, "recognized usages:\n"); 2426f9291ceSJung-uk Kim for (i = 0; i < X509_PURPOSE_get_count(); i++) { 243f579bf8eSKris Kennaway X509_PURPOSE *ptmp; 244f579bf8eSKris Kennaway ptmp = X509_PURPOSE_get0(i); 24509286989SJung-uk Kim BIO_printf(bio_err, "\t%-10s\t%s\n", 24609286989SJung-uk Kim X509_PURPOSE_get0_sname(ptmp), 247f579bf8eSKris Kennaway X509_PURPOSE_get0_name(ptmp)); 248f579bf8eSKris Kennaway } 249f579bf8eSKris Kennaway } 250*aeb5019cSJung-uk Kim end: 2516f9291ceSJung-uk Kim if (vpm) 2526f9291ceSJung-uk Kim X509_VERIFY_PARAM_free(vpm); 2536f9291ceSJung-uk Kim if (cert_ctx != NULL) 2546f9291ceSJung-uk Kim X509_STORE_free(cert_ctx); 255f579bf8eSKris Kennaway sk_X509_pop_free(untrusted, X509_free); 256ddd58736SKris Kennaway sk_X509_pop_free(trusted, X509_free); 2571f13597dSJung-uk Kim sk_X509_CRL_pop_free(crls, X509_CRL_free); 2585c87c606SMark Murray apps_shutdown(); 25909286989SJung-uk Kim OPENSSL_EXIT(ret < 0 ? 2 : ret); 26074664626SKris Kennaway } 26174664626SKris Kennaway 2621f13597dSJung-uk Kim static int check(X509_STORE *ctx, char *file, 2631f13597dSJung-uk Kim STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, 2641f13597dSJung-uk Kim STACK_OF(X509_CRL) *crls, ENGINE *e) 26574664626SKris Kennaway { 26674664626SKris Kennaway X509 *x = NULL; 26774664626SKris Kennaway int i = 0, ret = 0; 268f579bf8eSKris Kennaway X509_STORE_CTX *csc; 26974664626SKris Kennaway 2705c87c606SMark Murray x = load_cert(bio_err, file, FORMAT_PEM, NULL, e, "certificate file"); 27174664626SKris Kennaway if (x == NULL) 27274664626SKris Kennaway goto end; 27374664626SKris Kennaway fprintf(stdout, "%s: ", (file == NULL) ? "stdin" : file); 27474664626SKris Kennaway 275f579bf8eSKris Kennaway csc = X509_STORE_CTX_new(); 2766f9291ceSJung-uk Kim if (csc == NULL) { 277f579bf8eSKris Kennaway ERR_print_errors(bio_err); 278f579bf8eSKris Kennaway goto end; 279f579bf8eSKris Kennaway } 2805c87c606SMark Murray X509_STORE_set_flags(ctx, vflags); 2816f9291ceSJung-uk Kim if (!X509_STORE_CTX_init(csc, ctx, x, uchain)) { 2825c87c606SMark Murray ERR_print_errors(bio_err); 2835c87c606SMark Murray goto end; 2845c87c606SMark Murray } 2856f9291ceSJung-uk Kim if (tchain) 2866f9291ceSJung-uk Kim X509_STORE_CTX_trusted_stack(csc, tchain); 2871f13597dSJung-uk Kim if (crls) 2881f13597dSJung-uk Kim X509_STORE_CTX_set0_crls(csc, crls); 289f579bf8eSKris Kennaway i = X509_verify_cert(csc); 290f579bf8eSKris Kennaway X509_STORE_CTX_free(csc); 29174664626SKris Kennaway 29274664626SKris Kennaway ret = 0; 29374664626SKris Kennaway end: 2946f9291ceSJung-uk Kim if (i > 0) { 29574664626SKris Kennaway fprintf(stdout, "OK\n"); 29674664626SKris Kennaway ret = 1; 2976f9291ceSJung-uk Kim } else 29874664626SKris Kennaway ERR_print_errors(bio_err); 2996f9291ceSJung-uk Kim if (x != NULL) 3006f9291ceSJung-uk Kim X509_free(x); 30174664626SKris Kennaway 30274664626SKris Kennaway return (ret); 30374664626SKris Kennaway } 30474664626SKris Kennaway 30574664626SKris Kennaway static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx) 30674664626SKris Kennaway { 3071f13597dSJung-uk Kim int cert_error = X509_STORE_CTX_get_error(ctx); 3081f13597dSJung-uk Kim X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx); 30974664626SKris Kennaway 3106f9291ceSJung-uk Kim if (!ok) { 3116f9291ceSJung-uk Kim if (current_cert) { 3121f13597dSJung-uk Kim X509_NAME_print_ex_fp(stdout, 3131f13597dSJung-uk Kim X509_get_subject_name(current_cert), 3141f13597dSJung-uk Kim 0, XN_FLAG_ONELINE); 3151f13597dSJung-uk Kim printf("\n"); 3163b4e3dcbSSimon L. B. Nielsen } 3171f13597dSJung-uk Kim printf("%serror %d at %d depth lookup:%s\n", 3181f13597dSJung-uk Kim X509_STORE_CTX_get0_parent_ctx(ctx) ? "[CRL path]" : "", 3191f13597dSJung-uk Kim cert_error, 3201f13597dSJung-uk Kim X509_STORE_CTX_get_error_depth(ctx), 3211f13597dSJung-uk Kim X509_verify_cert_error_string(cert_error)); 3226f9291ceSJung-uk Kim switch (cert_error) { 3231f13597dSJung-uk Kim case X509_V_ERR_NO_EXPLICIT_POLICY: 3241f13597dSJung-uk Kim policies_print(NULL, ctx); 3251f13597dSJung-uk Kim case X509_V_ERR_CERT_HAS_EXPIRED: 3261f13597dSJung-uk Kim 3276f9291ceSJung-uk Kim /* 3286f9291ceSJung-uk Kim * since we are just checking the certificates, it is ok if they 3296f9291ceSJung-uk Kim * are self signed. But we should still warn the user. 330f579bf8eSKris Kennaway */ 3313b4e3dcbSSimon L. B. Nielsen 3321f13597dSJung-uk Kim case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: 3331f13597dSJung-uk Kim /* Continue after extension errors too */ 3341f13597dSJung-uk Kim case X509_V_ERR_INVALID_CA: 3351f13597dSJung-uk Kim case X509_V_ERR_INVALID_NON_CA: 3361f13597dSJung-uk Kim case X509_V_ERR_PATH_LENGTH_EXCEEDED: 3371f13597dSJung-uk Kim case X509_V_ERR_INVALID_PURPOSE: 3381f13597dSJung-uk Kim case X509_V_ERR_CRL_HAS_EXPIRED: 3391f13597dSJung-uk Kim case X509_V_ERR_CRL_NOT_YET_VALID: 3401f13597dSJung-uk Kim case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: 3411f13597dSJung-uk Kim ok = 1; 3421f13597dSJung-uk Kim 3431f13597dSJung-uk Kim } 3441f13597dSJung-uk Kim 3453b4e3dcbSSimon L. B. Nielsen return ok; 3463b4e3dcbSSimon L. B. Nielsen 34774664626SKris Kennaway } 3481f13597dSJung-uk Kim if (cert_error == X509_V_OK && ok == 2) 3493b4e3dcbSSimon L. B. Nielsen policies_print(NULL, ctx); 35074664626SKris Kennaway if (!v_verbose) 35174664626SKris Kennaway ERR_clear_error(); 35274664626SKris Kennaway return (ok); 35374664626SKris Kennaway } 354