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