xref: /dflybsd-src/crypto/libressl/apps/openssl/verify.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: verify.c,v 1.14 2021/02/15 17:57:58 jsing Exp $ */
2f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3f5b1c8a1SJohn Marino  * All rights reserved.
4f5b1c8a1SJohn Marino  *
5f5b1c8a1SJohn Marino  * This package is an SSL implementation written
6f5b1c8a1SJohn Marino  * by Eric Young (eay@cryptsoft.com).
7f5b1c8a1SJohn Marino  * The implementation was written so as to conform with Netscapes SSL.
8f5b1c8a1SJohn Marino  *
9f5b1c8a1SJohn Marino  * This library is free for commercial and non-commercial use as long as
10f5b1c8a1SJohn Marino  * the following conditions are aheared to.  The following conditions
11f5b1c8a1SJohn Marino  * apply to all code found in this distribution, be it the RC4, RSA,
12f5b1c8a1SJohn Marino  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13f5b1c8a1SJohn Marino  * included with this distribution is covered by the same copyright terms
14f5b1c8a1SJohn Marino  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15f5b1c8a1SJohn Marino  *
16f5b1c8a1SJohn Marino  * Copyright remains Eric Young's, and as such any Copyright notices in
17f5b1c8a1SJohn Marino  * the code are not to be removed.
18f5b1c8a1SJohn Marino  * If this package is used in a product, Eric Young should be given attribution
19f5b1c8a1SJohn Marino  * as the author of the parts of the library used.
20f5b1c8a1SJohn Marino  * This can be in the form of a textual message at program startup or
21f5b1c8a1SJohn Marino  * in documentation (online or textual) provided with the package.
22f5b1c8a1SJohn Marino  *
23f5b1c8a1SJohn Marino  * Redistribution and use in source and binary forms, with or without
24f5b1c8a1SJohn Marino  * modification, are permitted provided that the following conditions
25f5b1c8a1SJohn Marino  * are met:
26f5b1c8a1SJohn Marino  * 1. Redistributions of source code must retain the copyright
27f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer.
28f5b1c8a1SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
29f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
30f5b1c8a1SJohn Marino  *    documentation and/or other materials provided with the distribution.
31f5b1c8a1SJohn Marino  * 3. All advertising materials mentioning features or use of this software
32f5b1c8a1SJohn Marino  *    must display the following acknowledgement:
33f5b1c8a1SJohn Marino  *    "This product includes cryptographic software written by
34f5b1c8a1SJohn Marino  *     Eric Young (eay@cryptsoft.com)"
35f5b1c8a1SJohn Marino  *    The word 'cryptographic' can be left out if the rouines from the library
36f5b1c8a1SJohn Marino  *    being used are not cryptographic related :-).
37f5b1c8a1SJohn Marino  * 4. If you include any Windows specific code (or a derivative thereof) from
38f5b1c8a1SJohn Marino  *    the apps directory (application code) you must include an acknowledgement:
39f5b1c8a1SJohn Marino  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40f5b1c8a1SJohn Marino  *
41f5b1c8a1SJohn Marino  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42f5b1c8a1SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43f5b1c8a1SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44f5b1c8a1SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45f5b1c8a1SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46f5b1c8a1SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47f5b1c8a1SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48f5b1c8a1SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49f5b1c8a1SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50f5b1c8a1SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51f5b1c8a1SJohn Marino  * SUCH DAMAGE.
52f5b1c8a1SJohn Marino  *
53f5b1c8a1SJohn Marino  * The licence and distribution terms for any publically available version or
54f5b1c8a1SJohn Marino  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55f5b1c8a1SJohn Marino  * copied and put under another distribution licence
56f5b1c8a1SJohn Marino  * [including the GNU Public Licence.]
57f5b1c8a1SJohn Marino  */
58f5b1c8a1SJohn Marino 
59f5b1c8a1SJohn Marino #include <stdio.h>
60f5b1c8a1SJohn Marino #include <stdlib.h>
61f5b1c8a1SJohn Marino #include <string.h>
62f5b1c8a1SJohn Marino 
63f5b1c8a1SJohn Marino #include "apps.h"
64f5b1c8a1SJohn Marino 
65f5b1c8a1SJohn Marino #include <openssl/bio.h>
66f5b1c8a1SJohn Marino #include <openssl/err.h>
67f5b1c8a1SJohn Marino #include <openssl/pem.h>
68f5b1c8a1SJohn Marino #include <openssl/x509.h>
69f5b1c8a1SJohn Marino #include <openssl/x509v3.h>
70f5b1c8a1SJohn Marino 
71f5b1c8a1SJohn Marino static int cb(int ok, X509_STORE_CTX *ctx);
72f5b1c8a1SJohn Marino static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain,
73f5b1c8a1SJohn Marino     STACK_OF(X509) *tchain, STACK_OF(X509_CRL) *crls);
748edacedfSDaniel Fojt static int vflags = 0;
758edacedfSDaniel Fojt 
768edacedfSDaniel Fojt static struct {
778edacedfSDaniel Fojt 	char *CAfile;
788edacedfSDaniel Fojt 	char *CApath;
798edacedfSDaniel Fojt 	char *crlfile;
808edacedfSDaniel Fojt 	char *trustfile;
818edacedfSDaniel Fojt 	char *untfile;
828edacedfSDaniel Fojt 	int verbose;
838edacedfSDaniel Fojt 	X509_VERIFY_PARAM *vpm;
848edacedfSDaniel Fojt } verify_config;
858edacedfSDaniel Fojt 
868edacedfSDaniel Fojt static int
verify_opt_args(int argc,char ** argv,int * argsused)878edacedfSDaniel Fojt verify_opt_args(int argc, char **argv, int *argsused)
888edacedfSDaniel Fojt {
898edacedfSDaniel Fojt 	int oargc = argc;
908edacedfSDaniel Fojt 	int badarg = 0;
918edacedfSDaniel Fojt 
928edacedfSDaniel Fojt 	if (!args_verify(&argv, &argc, &badarg, bio_err, &verify_config.vpm))
938edacedfSDaniel Fojt 		return (1);
948edacedfSDaniel Fojt 	if (badarg)
958edacedfSDaniel Fojt 		return (1);
968edacedfSDaniel Fojt 
978edacedfSDaniel Fojt 	*argsused = oargc - argc;
988edacedfSDaniel Fojt 
998edacedfSDaniel Fojt 	return (0);
1008edacedfSDaniel Fojt }
1018edacedfSDaniel Fojt 
1028edacedfSDaniel Fojt static const struct option verify_options[] = {
1038edacedfSDaniel Fojt 	{
1048edacedfSDaniel Fojt 		.name = "CAfile",
1058edacedfSDaniel Fojt 		.argname = "file",
1068edacedfSDaniel Fojt 		.desc = "Certificate Authority file",
1078edacedfSDaniel Fojt 		.type = OPTION_ARG,
1088edacedfSDaniel Fojt 		.opt.arg = &verify_config.CAfile,
1098edacedfSDaniel Fojt 	},
1108edacedfSDaniel Fojt 	{
1118edacedfSDaniel Fojt 		.name = "CApath",
1128edacedfSDaniel Fojt 		.argname = "path",
1138edacedfSDaniel Fojt 		.desc = "Certificate Authority path",
1148edacedfSDaniel Fojt 		.type = OPTION_ARG,
1158edacedfSDaniel Fojt 		.opt.arg = &verify_config.CApath,
1168edacedfSDaniel Fojt 	},
1178edacedfSDaniel Fojt 	{
1188edacedfSDaniel Fojt 		.name = "CRLfile",
1198edacedfSDaniel Fojt 		.argname = "file",
1208edacedfSDaniel Fojt 		.desc = "Certificate Revocation List file",
1218edacedfSDaniel Fojt 		.type = OPTION_ARG,
1228edacedfSDaniel Fojt 		.opt.arg = &verify_config.crlfile,
1238edacedfSDaniel Fojt 	},
1248edacedfSDaniel Fojt 	{
1258edacedfSDaniel Fojt 		.name = "trusted",
1268edacedfSDaniel Fojt 		.argname = "file",
1278edacedfSDaniel Fojt 		.desc = "Trusted certificates file",
1288edacedfSDaniel Fojt 		.type = OPTION_ARG,
1298edacedfSDaniel Fojt 		.opt.arg = &verify_config.trustfile,
1308edacedfSDaniel Fojt 	},
1318edacedfSDaniel Fojt 	{
1328edacedfSDaniel Fojt 		.name = "untrusted",
1338edacedfSDaniel Fojt 		.argname = "file",
1348edacedfSDaniel Fojt 		.desc = "Untrusted certificates file",
1358edacedfSDaniel Fojt 		.type = OPTION_ARG,
1368edacedfSDaniel Fojt 		.opt.arg = &verify_config.untfile,
1378edacedfSDaniel Fojt 	},
1388edacedfSDaniel Fojt 	{
1398edacedfSDaniel Fojt 		.name = "verbose",
1408edacedfSDaniel Fojt 		.desc = "Verbose",
1418edacedfSDaniel Fojt 		.type = OPTION_FLAG,
1428edacedfSDaniel Fojt 		.opt.flag = &verify_config.verbose,
1438edacedfSDaniel Fojt 	},
1448edacedfSDaniel Fojt 	{
1458edacedfSDaniel Fojt 		.name = NULL,
1468edacedfSDaniel Fojt 		.desc = "",
1478edacedfSDaniel Fojt 		.type = OPTION_ARGV_FUNC,
1488edacedfSDaniel Fojt 		.opt.argvfunc = verify_opt_args,
1498edacedfSDaniel Fojt 	},
1508edacedfSDaniel Fojt 	{ NULL },
1518edacedfSDaniel Fojt };
1528edacedfSDaniel Fojt 
1538edacedfSDaniel Fojt static const struct option verify_shared_options[] = {
1548edacedfSDaniel Fojt 	{
1558edacedfSDaniel Fojt 		.name = "attime",
1568edacedfSDaniel Fojt 		.argname = "epoch",
1578edacedfSDaniel Fojt 		.desc = "Use epoch as the verification time",
1588edacedfSDaniel Fojt 	},
1598edacedfSDaniel Fojt 	{
1608edacedfSDaniel Fojt 		.name = "check_ss_sig",
1618edacedfSDaniel Fojt 		.desc = "Check the root CA self-signed certificate signature",
1628edacedfSDaniel Fojt 	},
1638edacedfSDaniel Fojt 	{
1648edacedfSDaniel Fojt 		.name = "crl_check",
1658edacedfSDaniel Fojt 		.desc = "Enable CRL checking for the leaf certificate",
1668edacedfSDaniel Fojt 	},
1678edacedfSDaniel Fojt 	{
1688edacedfSDaniel Fojt 		.name = "crl_check_all",
1698edacedfSDaniel Fojt 		.desc = "Enable CRL checking for the entire certificate chain",
1708edacedfSDaniel Fojt 	},
1718edacedfSDaniel Fojt 	{
1728edacedfSDaniel Fojt 		.name = "explicit_policy",
1738edacedfSDaniel Fojt 		.desc = "Require explicit policy (per RFC 3280)",
1748edacedfSDaniel Fojt 	},
1758edacedfSDaniel Fojt 	{
1768edacedfSDaniel Fojt 		.name = "extended_crl",
1778edacedfSDaniel Fojt 		.desc = "Enable extended CRL support",
1788edacedfSDaniel Fojt 	},
1798edacedfSDaniel Fojt 	{
1808edacedfSDaniel Fojt 		.name = "ignore_critical",
1818edacedfSDaniel Fojt 		.desc = "Disable critical extension checking",
1828edacedfSDaniel Fojt 	},
1838edacedfSDaniel Fojt 	{
1848edacedfSDaniel Fojt 		.name = "inhibit_any",
1858edacedfSDaniel Fojt 		.desc = "Inhibit any policy (per RFC 3280)",
1868edacedfSDaniel Fojt 	},
1878edacedfSDaniel Fojt 	{
1888edacedfSDaniel Fojt 		.name = "inhibit_map",
1898edacedfSDaniel Fojt 		.desc = "Inhibit policy mapping (per RFC 3280)",
1908edacedfSDaniel Fojt 	},
1918edacedfSDaniel Fojt 	{
1928edacedfSDaniel Fojt 		.name = "issuer_checks",
1938edacedfSDaniel Fojt 		.desc = "Enable debugging of certificate issuer checks",
1948edacedfSDaniel Fojt 	},
1958edacedfSDaniel Fojt 	{
196*de0e0e4dSAntonio Huete Jimenez 		.name = "legacy_verify",
197*de0e0e4dSAntonio Huete Jimenez 		.desc = "Use legacy certificate chain verification",
198*de0e0e4dSAntonio Huete Jimenez 	},
199*de0e0e4dSAntonio Huete Jimenez 	{
2008edacedfSDaniel Fojt 		.name = "policy",
2018edacedfSDaniel Fojt 		.argname = "name",
2028edacedfSDaniel Fojt 		.desc = "Add given policy to the acceptable set",
2038edacedfSDaniel Fojt 	},
2048edacedfSDaniel Fojt 	{
2058edacedfSDaniel Fojt 		.name = "policy_check",
2068edacedfSDaniel Fojt 		.desc = "Enable certificate policy checking",
2078edacedfSDaniel Fojt 	},
2088edacedfSDaniel Fojt 	{
2098edacedfSDaniel Fojt 		.name = "policy_print",
2108edacedfSDaniel Fojt 		.desc = "Print policy",
2118edacedfSDaniel Fojt 	},
2128edacedfSDaniel Fojt 	{
2138edacedfSDaniel Fojt 		.name = "purpose",
2148edacedfSDaniel Fojt 		.argname = "name",
2158edacedfSDaniel Fojt 		.desc = "Verify for the given purpose",
2168edacedfSDaniel Fojt 	},
2178edacedfSDaniel Fojt 	{
2188edacedfSDaniel Fojt 		.name = "use_deltas",
2198edacedfSDaniel Fojt 		.desc = "Use delta CRLS (if present)",
2208edacedfSDaniel Fojt 	},
2218edacedfSDaniel Fojt 	{
2228edacedfSDaniel Fojt 		.name = "verify_depth",
2238edacedfSDaniel Fojt 		.argname = "num",
2248edacedfSDaniel Fojt 		.desc = "Limit verification to the given depth",
2258edacedfSDaniel Fojt 	},
2268edacedfSDaniel Fojt 	{
2278edacedfSDaniel Fojt 		.name = "x509_strict",
2288edacedfSDaniel Fojt 		.desc = "Use strict X.509 rules (disables workarounds)",
2298edacedfSDaniel Fojt 	},
2308edacedfSDaniel Fojt 	{ NULL },
2318edacedfSDaniel Fojt };
2328edacedfSDaniel Fojt 
2338edacedfSDaniel Fojt static void
verify_usage(void)2348edacedfSDaniel Fojt verify_usage(void)
2358edacedfSDaniel Fojt {
2368edacedfSDaniel Fojt 	int i;
2378edacedfSDaniel Fojt 
2388edacedfSDaniel Fojt 	fprintf(stderr,
2398edacedfSDaniel Fojt 	    "usage: verify [-CAfile file] [-CApath directory] [-check_ss_sig]\n"
2408edacedfSDaniel Fojt 	    "    [-CRLfile file] [-crl_check] [-crl_check_all]\n"
2418edacedfSDaniel Fojt 	    "    [-explicit_policy] [-extended_crl]\n"
2428edacedfSDaniel Fojt 	    "    [-ignore_critical] [-inhibit_any] [-inhibit_map]\n"
2438edacedfSDaniel Fojt 	    "    [-issuer_checks] [-policy_check] [-purpose purpose]\n"
2448edacedfSDaniel Fojt 	    "    [-trusted file] [-untrusted file] [-verbose]\n"
2458edacedfSDaniel Fojt 	    "    [-x509_strict] [certificates]\n\n");
2468edacedfSDaniel Fojt 
2478edacedfSDaniel Fojt 	options_usage(verify_options);
2488edacedfSDaniel Fojt 
2498edacedfSDaniel Fojt 	fprintf(stderr, "\nVerification options:\n\n");
2508edacedfSDaniel Fojt 	options_usage(verify_shared_options);
2518edacedfSDaniel Fojt 
2528edacedfSDaniel Fojt 	fprintf(stderr, "\nValid purposes:\n\n");
2538edacedfSDaniel Fojt 	for (i = 0; i < X509_PURPOSE_get_count(); i++) {
2548edacedfSDaniel Fojt 		X509_PURPOSE *ptmp = X509_PURPOSE_get0(i);
2558edacedfSDaniel Fojt 		fprintf(stderr, "  %-18s%s\n", X509_PURPOSE_get0_sname(ptmp),
2568edacedfSDaniel Fojt 		    X509_PURPOSE_get0_name(ptmp));
2578edacedfSDaniel Fojt 	}
2588edacedfSDaniel Fojt }
259f5b1c8a1SJohn Marino 
260f5b1c8a1SJohn Marino int
verify_main(int argc,char ** argv)261f5b1c8a1SJohn Marino verify_main(int argc, char **argv)
262f5b1c8a1SJohn Marino {
263f5b1c8a1SJohn Marino 	STACK_OF(X509) *untrusted = NULL, *trusted = NULL;
264f5b1c8a1SJohn Marino 	STACK_OF(X509_CRL) *crls = NULL;
265f5b1c8a1SJohn Marino 	X509_STORE *cert_ctx = NULL;
266f5b1c8a1SJohn Marino 	X509_LOOKUP *lookup = NULL;
2678edacedfSDaniel Fojt 	char **cert_files = NULL;
2688edacedfSDaniel Fojt 	int argsused;
269*de0e0e4dSAntonio Huete Jimenez 	int ret = 1;
270f5b1c8a1SJohn Marino 
271f5b1c8a1SJohn Marino 	if (single_execution) {
272f5b1c8a1SJohn Marino 		if (pledge("stdio rpath", NULL) == -1) {
273f5b1c8a1SJohn Marino 			perror("pledge");
274f5b1c8a1SJohn Marino 			exit(1);
275f5b1c8a1SJohn Marino 		}
276f5b1c8a1SJohn Marino 	}
277f5b1c8a1SJohn Marino 
2788edacedfSDaniel Fojt 	memset(&verify_config, 0, sizeof(verify_config));
2798edacedfSDaniel Fojt 
2808edacedfSDaniel Fojt 	if (options_parse(argc, argv, verify_options, NULL, &argsused) != 0) {
2818edacedfSDaniel Fojt 		verify_usage();
2828edacedfSDaniel Fojt 		goto end;
2838edacedfSDaniel Fojt 	}
2848edacedfSDaniel Fojt 
2858edacedfSDaniel Fojt 	if (argsused < argc)
2868edacedfSDaniel Fojt 		cert_files = &argv[argsused];
2878edacedfSDaniel Fojt 
288f5b1c8a1SJohn Marino 	cert_ctx = X509_STORE_new();
289f5b1c8a1SJohn Marino 	if (cert_ctx == NULL)
290f5b1c8a1SJohn Marino 		goto end;
291f5b1c8a1SJohn Marino 	X509_STORE_set_verify_cb(cert_ctx, cb);
292f5b1c8a1SJohn Marino 
2938edacedfSDaniel Fojt 	if (verify_config.vpm)
2948edacedfSDaniel Fojt 		X509_STORE_set1_param(cert_ctx, verify_config.vpm);
295f5b1c8a1SJohn Marino 
296f5b1c8a1SJohn Marino 	lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());
297f5b1c8a1SJohn Marino 	if (lookup == NULL)
2988edacedfSDaniel Fojt 		abort(); /* XXX */
2998edacedfSDaniel Fojt 	if (verify_config.CAfile) {
300*de0e0e4dSAntonio Huete Jimenez 		if (!X509_LOOKUP_load_file(lookup, verify_config.CAfile,
301*de0e0e4dSAntonio Huete Jimenez 		    X509_FILETYPE_PEM)) {
302*de0e0e4dSAntonio Huete Jimenez 			BIO_printf(bio_err, "Error loading file %s\n",
303*de0e0e4dSAntonio Huete Jimenez 			    verify_config.CAfile);
304f5b1c8a1SJohn Marino 			ERR_print_errors(bio_err);
305f5b1c8a1SJohn Marino 			goto end;
306f5b1c8a1SJohn Marino 		}
307f5b1c8a1SJohn Marino 	} else
308f5b1c8a1SJohn Marino 		X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
309f5b1c8a1SJohn Marino 
310f5b1c8a1SJohn Marino 	lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir());
311f5b1c8a1SJohn Marino 	if (lookup == NULL)
3128edacedfSDaniel Fojt 		abort(); /* XXX */
3138edacedfSDaniel Fojt 	if (verify_config.CApath) {
314*de0e0e4dSAntonio Huete Jimenez 		if (!X509_LOOKUP_add_dir(lookup, verify_config.CApath,
315*de0e0e4dSAntonio Huete Jimenez 		    X509_FILETYPE_PEM)) {
316*de0e0e4dSAntonio Huete Jimenez 			BIO_printf(bio_err, "Error loading directory %s\n",
317*de0e0e4dSAntonio Huete Jimenez 			    verify_config.CApath);
318f5b1c8a1SJohn Marino 			ERR_print_errors(bio_err);
319f5b1c8a1SJohn Marino 			goto end;
320f5b1c8a1SJohn Marino 		}
321f5b1c8a1SJohn Marino 	} else
322f5b1c8a1SJohn Marino 		X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
323f5b1c8a1SJohn Marino 
324f5b1c8a1SJohn Marino 	ERR_clear_error();
325f5b1c8a1SJohn Marino 
3268edacedfSDaniel Fojt 	if (verify_config.untfile) {
327*de0e0e4dSAntonio Huete Jimenez 		untrusted = load_certs(bio_err, verify_config.untfile,
328*de0e0e4dSAntonio Huete Jimenez 		    FORMAT_PEM, NULL, "untrusted certificates");
329f5b1c8a1SJohn Marino 		if (!untrusted)
330f5b1c8a1SJohn Marino 			goto end;
331f5b1c8a1SJohn Marino 	}
3328edacedfSDaniel Fojt 	if (verify_config.trustfile) {
333*de0e0e4dSAntonio Huete Jimenez 		trusted = load_certs(bio_err, verify_config.trustfile,
334*de0e0e4dSAntonio Huete Jimenez 		    FORMAT_PEM, NULL, "trusted certificates");
335f5b1c8a1SJohn Marino 		if (!trusted)
336f5b1c8a1SJohn Marino 			goto end;
337f5b1c8a1SJohn Marino 	}
3388edacedfSDaniel Fojt 	if (verify_config.crlfile) {
3398edacedfSDaniel Fojt 		crls = load_crls(bio_err, verify_config.crlfile, FORMAT_PEM,
340f5b1c8a1SJohn Marino 		    NULL, "other CRLs");
341f5b1c8a1SJohn Marino 		if (!crls)
342f5b1c8a1SJohn Marino 			goto end;
343f5b1c8a1SJohn Marino 	}
344f5b1c8a1SJohn Marino 	ret = 0;
3458edacedfSDaniel Fojt 	if (cert_files == NULL) {
346f5b1c8a1SJohn Marino 		if (1 != check(cert_ctx, NULL, untrusted, trusted, crls))
347f5b1c8a1SJohn Marino 			ret = -1;
348f5b1c8a1SJohn Marino 	} else {
3498edacedfSDaniel Fojt 		do {
350*de0e0e4dSAntonio Huete Jimenez 			if (1 != check(cert_ctx, *cert_files++, untrusted,
351*de0e0e4dSAntonio Huete Jimenez 			    trusted, crls))
352f5b1c8a1SJohn Marino 				ret = -1;
3538edacedfSDaniel Fojt 		} while (*cert_files != NULL);
354f5b1c8a1SJohn Marino 	}
355f5b1c8a1SJohn Marino 
356f5b1c8a1SJohn Marino  end:
3578edacedfSDaniel Fojt 	if (verify_config.vpm)
3588edacedfSDaniel Fojt 		X509_VERIFY_PARAM_free(verify_config.vpm);
359f5b1c8a1SJohn Marino 	if (cert_ctx != NULL)
360f5b1c8a1SJohn Marino 		X509_STORE_free(cert_ctx);
361f5b1c8a1SJohn Marino 	sk_X509_pop_free(untrusted, X509_free);
362f5b1c8a1SJohn Marino 	sk_X509_pop_free(trusted, X509_free);
363f5b1c8a1SJohn Marino 	sk_X509_CRL_pop_free(crls, X509_CRL_free);
364f5b1c8a1SJohn Marino 
365f5b1c8a1SJohn Marino 	return (ret < 0 ? 2 : ret);
366f5b1c8a1SJohn Marino }
367f5b1c8a1SJohn Marino 
368f5b1c8a1SJohn Marino static int
check(X509_STORE * ctx,char * file,STACK_OF (X509)* uchain,STACK_OF (X509)* tchain,STACK_OF (X509_CRL)* crls)369f5b1c8a1SJohn Marino check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain,
370f5b1c8a1SJohn Marino     STACK_OF(X509) *tchain, STACK_OF(X509_CRL) *crls)
371f5b1c8a1SJohn Marino {
372f5b1c8a1SJohn Marino 	X509 *x = NULL;
373*de0e0e4dSAntonio Huete Jimenez 	X509_STORE_CTX *csc = NULL;
374*de0e0e4dSAntonio Huete Jimenez 	const char *certfile = (file == NULL) ? "stdin" : file;
375*de0e0e4dSAntonio Huete Jimenez 	int verify_err;
376f5b1c8a1SJohn Marino 	int i = 0, ret = 0;
377f5b1c8a1SJohn Marino 
378f5b1c8a1SJohn Marino 	x = load_cert(bio_err, file, FORMAT_PEM, NULL, "certificate file");
379f5b1c8a1SJohn Marino 	if (x == NULL)
380f5b1c8a1SJohn Marino 		goto end;
381f5b1c8a1SJohn Marino 
382*de0e0e4dSAntonio Huete Jimenez 	if ((csc = X509_STORE_CTX_new()) == NULL)
383f5b1c8a1SJohn Marino 		goto end;
384f5b1c8a1SJohn Marino 	X509_STORE_set_flags(ctx, vflags);
385*de0e0e4dSAntonio Huete Jimenez 	if (!X509_STORE_CTX_init(csc, ctx, x, uchain))
386f5b1c8a1SJohn Marino 		goto end;
387f5b1c8a1SJohn Marino 	if (tchain)
388f5b1c8a1SJohn Marino 		X509_STORE_CTX_trusted_stack(csc, tchain);
389f5b1c8a1SJohn Marino 	if (crls)
390f5b1c8a1SJohn Marino 		X509_STORE_CTX_set0_crls(csc, crls);
391f5b1c8a1SJohn Marino 
392*de0e0e4dSAntonio Huete Jimenez 	i = X509_verify_cert(csc);
393*de0e0e4dSAntonio Huete Jimenez 	verify_err = X509_STORE_CTX_get_error(csc);
394*de0e0e4dSAntonio Huete Jimenez 
395*de0e0e4dSAntonio Huete Jimenez 	if (i > 0 && verify_err == X509_V_OK) {
396*de0e0e4dSAntonio Huete Jimenez 		fprintf(stdout, "%s: OK\n", certfile);
397*de0e0e4dSAntonio Huete Jimenez 		ret = 1;
398*de0e0e4dSAntonio Huete Jimenez 	} else {
399*de0e0e4dSAntonio Huete Jimenez 		fprintf(stdout, "%s: verification failed: %d (%s)\n", certfile,
400*de0e0e4dSAntonio Huete Jimenez 		    verify_err, X509_verify_cert_error_string(verify_err));
401*de0e0e4dSAntonio Huete Jimenez 	}
402f5b1c8a1SJohn Marino 
403f5b1c8a1SJohn Marino  end:
404*de0e0e4dSAntonio Huete Jimenez 	if (i <= 0)
405f5b1c8a1SJohn Marino 		ERR_print_errors(bio_err);
406f5b1c8a1SJohn Marino 	X509_free(x);
407*de0e0e4dSAntonio Huete Jimenez 	X509_STORE_CTX_free(csc);
408f5b1c8a1SJohn Marino 
409f5b1c8a1SJohn Marino 	return (ret);
410f5b1c8a1SJohn Marino }
411f5b1c8a1SJohn Marino 
412f5b1c8a1SJohn Marino static int
cb(int ok,X509_STORE_CTX * ctx)413f5b1c8a1SJohn Marino cb(int ok, X509_STORE_CTX *ctx)
414f5b1c8a1SJohn Marino {
415f5b1c8a1SJohn Marino 	int cert_error = X509_STORE_CTX_get_error(ctx);
416f5b1c8a1SJohn Marino 	X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx);
417f5b1c8a1SJohn Marino 
418f5b1c8a1SJohn Marino 	if (!ok) {
419f5b1c8a1SJohn Marino 		if (current_cert) {
420f5b1c8a1SJohn Marino 			X509_NAME_print_ex_fp(stdout,
421f5b1c8a1SJohn Marino 			    X509_get_subject_name(current_cert),
422f5b1c8a1SJohn Marino 			    0, XN_FLAG_ONELINE);
423f5b1c8a1SJohn Marino 			printf("\n");
424f5b1c8a1SJohn Marino 		}
425f5b1c8a1SJohn Marino 		printf("%serror %d at %d depth lookup:%s\n",
426f5b1c8a1SJohn Marino 		    X509_STORE_CTX_get0_parent_ctx(ctx) ? "[CRL path]" : "",
427f5b1c8a1SJohn Marino 		    cert_error,
428f5b1c8a1SJohn Marino 		    X509_STORE_CTX_get_error_depth(ctx),
429f5b1c8a1SJohn Marino 		    X509_verify_cert_error_string(cert_error));
430f5b1c8a1SJohn Marino 		switch (cert_error) {
431f5b1c8a1SJohn Marino 		case X509_V_ERR_NO_EXPLICIT_POLICY:
432f5b1c8a1SJohn Marino 			policies_print(NULL, ctx);
433f5b1c8a1SJohn Marino 		case X509_V_ERR_CERT_HAS_EXPIRED:
434f5b1c8a1SJohn Marino 
435f5b1c8a1SJohn Marino 			/*
436f5b1c8a1SJohn Marino 			 * since we are just checking the certificates, it is
437f5b1c8a1SJohn Marino 			 * ok if they are self signed. But we should still
438f5b1c8a1SJohn Marino 			 * warn the user.
439f5b1c8a1SJohn Marino 			 */
440f5b1c8a1SJohn Marino 
441f5b1c8a1SJohn Marino 		case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
442f5b1c8a1SJohn Marino 			/* Continue after extension errors too */
443f5b1c8a1SJohn Marino 		case X509_V_ERR_INVALID_CA:
444f5b1c8a1SJohn Marino 		case X509_V_ERR_INVALID_NON_CA:
445f5b1c8a1SJohn Marino 		case X509_V_ERR_PATH_LENGTH_EXCEEDED:
446f5b1c8a1SJohn Marino 		case X509_V_ERR_INVALID_PURPOSE:
447f5b1c8a1SJohn Marino 		case X509_V_ERR_CRL_HAS_EXPIRED:
448f5b1c8a1SJohn Marino 		case X509_V_ERR_CRL_NOT_YET_VALID:
449f5b1c8a1SJohn Marino 		case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
450f5b1c8a1SJohn Marino 			ok = 1;
451f5b1c8a1SJohn Marino 
452f5b1c8a1SJohn Marino 		}
453f5b1c8a1SJohn Marino 
454f5b1c8a1SJohn Marino 		return ok;
455f5b1c8a1SJohn Marino 
456f5b1c8a1SJohn Marino 	}
457f5b1c8a1SJohn Marino 	if (cert_error == X509_V_OK && ok == 2)
458f5b1c8a1SJohn Marino 		policies_print(NULL, ctx);
4598edacedfSDaniel Fojt 	if (!verify_config.verbose)
460f5b1c8a1SJohn Marino 		ERR_clear_error();
461f5b1c8a1SJohn Marino 	return (ok);
462f5b1c8a1SJohn Marino }
463