[BACK]Return to verify.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / openssl

Annotation of src/usr.bin/openssl/verify.c, Revision 1.8

1.8     ! jsing       1: /* $OpenBSD: verify.c,v 1.7 2018/02/07 05:47:55 jsing Exp $ */
1.1       jsing       2: /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
                      3:  * All rights reserved.
                      4:  *
                      5:  * This package is an SSL implementation written
                      6:  * by Eric Young (eay@cryptsoft.com).
                      7:  * The implementation was written so as to conform with Netscapes SSL.
                      8:  *
                      9:  * This library is free for commercial and non-commercial use as long as
                     10:  * the following conditions are aheared to.  The following conditions
                     11:  * apply to all code found in this distribution, be it the RC4, RSA,
                     12:  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
                     13:  * included with this distribution is covered by the same copyright terms
                     14:  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
                     15:  *
                     16:  * Copyright remains Eric Young's, and as such any Copyright notices in
                     17:  * the code are not to be removed.
                     18:  * If this package is used in a product, Eric Young should be given attribution
                     19:  * as the author of the parts of the library used.
                     20:  * This can be in the form of a textual message at program startup or
                     21:  * in documentation (online or textual) provided with the package.
                     22:  *
                     23:  * Redistribution and use in source and binary forms, with or without
                     24:  * modification, are permitted provided that the following conditions
                     25:  * are met:
                     26:  * 1. Redistributions of source code must retain the copyright
                     27:  *    notice, this list of conditions and the following disclaimer.
                     28:  * 2. Redistributions in binary form must reproduce the above copyright
                     29:  *    notice, this list of conditions and the following disclaimer in the
                     30:  *    documentation and/or other materials provided with the distribution.
                     31:  * 3. All advertising materials mentioning features or use of this software
                     32:  *    must display the following acknowledgement:
                     33:  *    "This product includes cryptographic software written by
                     34:  *     Eric Young (eay@cryptsoft.com)"
                     35:  *    The word 'cryptographic' can be left out if the rouines from the library
                     36:  *    being used are not cryptographic related :-).
                     37:  * 4. If you include any Windows specific code (or a derivative thereof) from
                     38:  *    the apps directory (application code) you must include an acknowledgement:
                     39:  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
                     40:  *
                     41:  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
                     42:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     43:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     44:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     45:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     46:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     47:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     48:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     49:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     50:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     51:  * SUCH DAMAGE.
                     52:  *
                     53:  * The licence and distribution terms for any publically available version or
                     54:  * derivative of this code cannot be changed.  i.e. this code cannot simply be
                     55:  * copied and put under another distribution licence
                     56:  * [including the GNU Public Licence.]
                     57:  */
                     58:
                     59: #include <stdio.h>
                     60: #include <stdlib.h>
                     61: #include <string.h>
                     62:
                     63: #include "apps.h"
                     64:
                     65: #include <openssl/bio.h>
                     66: #include <openssl/err.h>
                     67: #include <openssl/pem.h>
                     68: #include <openssl/x509.h>
                     69: #include <openssl/x509v3.h>
                     70:
                     71: static int cb(int ok, X509_STORE_CTX * ctx);
                     72: static int check(X509_STORE * ctx, char *file, STACK_OF(X509) * uchain,
1.4       bcook      73:     STACK_OF(X509) * tchain, STACK_OF(X509_CRL) * crls);
1.8     ! jsing      74: static int vflags = 0;
        !            75:
        !            76: static struct {
        !            77:        char *CAfile;
        !            78:        char *CApath;
        !            79:        char *crlfile;
        !            80:        char *trustfile;
        !            81:        char *untfile;
        !            82:        int verbose;
        !            83:        X509_VERIFY_PARAM *vpm;
        !            84: } verify_config;
        !            85:
        !            86: static int
        !            87: verify_opt_args(int argc, char **argv, int *argsused)
        !            88: {
        !            89:        int oargc = argc;
        !            90:        int badarg = 0;
        !            91:
        !            92:        if (!args_verify(&argv, &argc, &badarg, bio_err, &verify_config.vpm))
        !            93:                return (1);
        !            94:        if (badarg)
        !            95:                return (1);
        !            96:
        !            97:        *argsused = oargc - argc;
        !            98:
        !            99:        return (0);
        !           100: }
        !           101:
        !           102: static const struct option verify_options[] = {
        !           103:        {
        !           104:                .name = "CAfile",
        !           105:                .argname = "file",
        !           106:                .desc = "Certificate Authority file",
        !           107:                .type = OPTION_ARG,
        !           108:                .opt.arg = &verify_config.CAfile,
        !           109:        },
        !           110:        {
        !           111:                .name = "CApath",
        !           112:                .argname = "path",
        !           113:                .desc = "Certificate Authority path",
        !           114:                .type = OPTION_ARG,
        !           115:                .opt.arg = &verify_config.CApath,
        !           116:        },
        !           117:        {
        !           118:                .name = "CRLfile",
        !           119:                .argname = "file",
        !           120:                .desc = "Certificate Revocation List file",
        !           121:                .type = OPTION_ARG,
        !           122:                .opt.arg = &verify_config.crlfile,
        !           123:        },
        !           124:        {
        !           125:                .name = "trusted",
        !           126:                .argname = "file",
        !           127:                .desc = "Trusted certificates file",
        !           128:                .type = OPTION_ARG,
        !           129:                .opt.arg = &verify_config.trustfile,
        !           130:        },
        !           131:        {
        !           132:                .name = "untrusted",
        !           133:                .argname = "file",
        !           134:                .desc = "Untrusted certificates file",
        !           135:                .type = OPTION_ARG,
        !           136:                .opt.arg = &verify_config.untfile,
        !           137:        },
        !           138:        {
        !           139:                .name = "verbose",
        !           140:                .desc = "Verbose",
        !           141:                .type = OPTION_FLAG,
        !           142:                .opt.flag = &verify_config.verbose,
        !           143:        },
        !           144:        {
        !           145:                .name = NULL,
        !           146:                .desc = "",
        !           147:                .type = OPTION_ARGV_FUNC,
        !           148:                .opt.argvfunc = verify_opt_args,
        !           149:        },
        !           150:        { NULL },
        !           151: };
        !           152:
        !           153: static const struct option verify_shared_options[] = {
        !           154:        {
        !           155:                .name = "attime",
        !           156:                .argname = "epoch",
        !           157:                .desc = "Use epoch as the verification time",
        !           158:        },
        !           159:        {
        !           160:                .name = "check_ss_sig",
        !           161:                .desc = "Check the root CA self-signed certificate signature",
        !           162:        },
        !           163:        {
        !           164:                .name = "crl_check",
        !           165:                .desc = "Enable CRL checking for the leaf certificate",
        !           166:        },
        !           167:        {
        !           168:                .name = "crl_check_all",
        !           169:                .desc = "Enable CRL checking for the entire certificate chain",
        !           170:        },
        !           171:        {
        !           172:                .name = "explicit_policy",
        !           173:                .desc = "Require explicit policy (per RFC 3280)",
        !           174:        },
        !           175:        {
        !           176:                .name = "extended_crl",
        !           177:                .desc = "Enable extended CRL support",
        !           178:        },
        !           179:        {
        !           180:                .name = "ignore_critical",
        !           181:                .desc = "Disable critical extension checking",
        !           182:        },
        !           183:        {
        !           184:                .name = "inhibit_any",
        !           185:                .desc = "Inhibit any policy (per RFC 3280)",
        !           186:        },
        !           187:        {
        !           188:                .name = "inhibit_map",
        !           189:                .desc = "Inhibit policy mapping (per RFC 3280)",
        !           190:        },
        !           191:        {
        !           192:                .name = "issuer_checks",
        !           193:                .desc = "Enable debugging of certificate issuer checks",
        !           194:        },
        !           195:        {
        !           196:                .name = "policy",
        !           197:                .argname = "name",
        !           198:                .desc = "Add given policy to the acceptable set",
        !           199:        },
        !           200:        {
        !           201:                .name = "policy_check",
        !           202:                .desc = "Enable certificate policy checking",
        !           203:        },
        !           204:        {
        !           205:                .name = "policy_print",
        !           206:                .desc = "Print policy",
        !           207:        },
        !           208:        {
        !           209:                .name = "purpose",
        !           210:                .argname = "name",
        !           211:                .desc = "Verify for the given purpose",
        !           212:        },
        !           213:        {
        !           214:                .name = "use_deltas",
        !           215:                .desc = "Use delta CRLS (if present)",
        !           216:        },
        !           217:        {
        !           218:                .name = "verify_depth",
        !           219:                .argname = "num",
        !           220:                .desc = "Limit verification to the given depth",
        !           221:        },
        !           222:        {
        !           223:                .name = "x509_strict",
        !           224:                .desc = "Use strict X.509 rules (disables workarounds)",
        !           225:        },
        !           226:        { NULL },
        !           227: };
        !           228:
        !           229: static void
        !           230: verify_usage(void)
        !           231: {
        !           232:        int i;
        !           233:
        !           234:        fprintf(stderr,
        !           235:            "usage: verify [-CAfile file] [-CApath directory] [-check_ss_sig]\n"
        !           236:            "    [-CRLfile file] [-crl_check] [-crl_check_all]\n"
        !           237:            "    [-explicit_policy] [-extended_crl]\n"
        !           238:            "    [-ignore_critical] [-inhibit_any] [-inhibit_map]\n"
        !           239:            "    [-issuer_checks] [-policy_check] [-purpose purpose]\n"
        !           240:            "    [-trusted file] [-untrusted file] [-verbose]\n"
        !           241:            "    [-x509_strict] [certificates]\n\n");
        !           242:
        !           243:        options_usage(verify_options);
        !           244:
        !           245:        fprintf(stderr, "\nVerification options:\n\n");
        !           246:        options_usage(verify_shared_options);
        !           247:
        !           248:        fprintf(stderr, "\nValid purposes:\n\n");
        !           249:        for (i = 0; i < X509_PURPOSE_get_count(); i++) {
        !           250:                X509_PURPOSE *ptmp = X509_PURPOSE_get0(i);
        !           251:                fprintf(stderr, "  %-18s%s\n", X509_PURPOSE_get0_sname(ptmp),
        !           252:                    X509_PURPOSE_get0_name(ptmp));
        !           253:        }
        !           254: }
1.1       jsing     255:
                    256: int
                    257: verify_main(int argc, char **argv)
                    258: {
1.8     ! jsing     259:        int i, ret = 1;
        !           260:        STACK_OF(X509) *untrusted = NULL, *trusted = NULL;
        !           261:        STACK_OF(X509_CRL) *crls = NULL;
1.1       jsing     262:        X509_STORE *cert_ctx = NULL;
                    263:        X509_LOOKUP *lookup = NULL;
1.8     ! jsing     264:        char **cert_files = NULL;
        !           265:        int argsused;
1.5       doug      266:
                    267:        if (single_execution) {
1.6       doug      268:                if (pledge("stdio rpath", NULL) == -1) {
1.5       doug      269:                        perror("pledge");
1.6       doug      270:                        exit(1);
                    271:                }
1.5       doug      272:        }
1.1       jsing     273:
1.8     ! jsing     274:        memset(&verify_config, 0, sizeof(verify_config));
        !           275:
        !           276:        if (options_parse(argc, argv, verify_options, NULL, &argsused) != 0) {
        !           277:                verify_usage();
        !           278:                goto end;
        !           279:        }
        !           280:
        !           281:        if (argsused < argc)
        !           282:                cert_files = &argv[argsused];
        !           283:
1.1       jsing     284:        cert_ctx = X509_STORE_new();
                    285:        if (cert_ctx == NULL)
                    286:                goto end;
                    287:        X509_STORE_set_verify_cb(cert_ctx, cb);
                    288:
1.8     ! jsing     289:        if (verify_config.vpm)
        !           290:                X509_STORE_set1_param(cert_ctx, verify_config.vpm);
1.1       jsing     291:
                    292:        lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());
                    293:        if (lookup == NULL)
1.8     ! jsing     294:                abort(); /* XXX */
        !           295:        if (verify_config.CAfile) {
        !           296:                i = X509_LOOKUP_load_file(lookup, verify_config.CAfile, X509_FILETYPE_PEM);
1.1       jsing     297:                if (!i) {
1.8     ! jsing     298:                        BIO_printf(bio_err, "Error loading file %s\n", verify_config.CAfile);
1.1       jsing     299:                        ERR_print_errors(bio_err);
                    300:                        goto end;
                    301:                }
                    302:        } else
                    303:                X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
                    304:
                    305:        lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir());
                    306:        if (lookup == NULL)
1.8     ! jsing     307:                abort(); /* XXX */
        !           308:        if (verify_config.CApath) {
        !           309:                i = X509_LOOKUP_add_dir(lookup, verify_config.CApath, X509_FILETYPE_PEM);
1.1       jsing     310:                if (!i) {
1.8     ! jsing     311:                        BIO_printf(bio_err, "Error loading directory %s\n", verify_config.CApath);
1.1       jsing     312:                        ERR_print_errors(bio_err);
                    313:                        goto end;
                    314:                }
                    315:        } else
                    316:                X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
                    317:
                    318:        ERR_clear_error();
                    319:
1.8     ! jsing     320:        if (verify_config.untfile) {
        !           321:                untrusted = load_certs(bio_err, verify_config.untfile, FORMAT_PEM,
1.4       bcook     322:                    NULL, "untrusted certificates");
1.1       jsing     323:                if (!untrusted)
                    324:                        goto end;
                    325:        }
1.8     ! jsing     326:        if (verify_config.trustfile) {
        !           327:                trusted = load_certs(bio_err, verify_config.trustfile, FORMAT_PEM,
1.4       bcook     328:                    NULL, "trusted certificates");
1.1       jsing     329:                if (!trusted)
                    330:                        goto end;
                    331:        }
1.8     ! jsing     332:        if (verify_config.crlfile) {
        !           333:                crls = load_crls(bio_err, verify_config.crlfile, FORMAT_PEM,
1.4       bcook     334:                    NULL, "other CRLs");
1.1       jsing     335:                if (!crls)
                    336:                        goto end;
                    337:        }
                    338:        ret = 0;
1.8     ! jsing     339:        if (cert_files == NULL) {
1.4       bcook     340:                if (1 != check(cert_ctx, NULL, untrusted, trusted, crls))
1.1       jsing     341:                        ret = -1;
                    342:        } else {
1.8     ! jsing     343:                do {
        !           344:                        if (1 != check(cert_ctx, *cert_files++, untrusted, trusted,
1.4       bcook     345:                            crls))
1.1       jsing     346:                                ret = -1;
1.8     ! jsing     347:                } while (*cert_files != NULL);
1.1       jsing     348:        }
                    349:
1.7       jsing     350:  end:
1.8     ! jsing     351:        if (verify_config.vpm)
        !           352:                X509_VERIFY_PARAM_free(verify_config.vpm);
1.1       jsing     353:        if (cert_ctx != NULL)
                    354:                X509_STORE_free(cert_ctx);
                    355:        sk_X509_pop_free(untrusted, X509_free);
                    356:        sk_X509_pop_free(trusted, X509_free);
                    357:        sk_X509_CRL_pop_free(crls, X509_CRL_free);
                    358:
                    359:        return (ret < 0 ? 2 : ret);
                    360: }
                    361:
                    362: static int
                    363: check(X509_STORE * ctx, char *file, STACK_OF(X509) * uchain,
1.4       bcook     364:     STACK_OF(X509) * tchain, STACK_OF(X509_CRL) * crls)
1.1       jsing     365: {
                    366:        X509 *x = NULL;
                    367:        int i = 0, ret = 0;
                    368:        X509_STORE_CTX *csc;
                    369:
1.4       bcook     370:        x = load_cert(bio_err, file, FORMAT_PEM, NULL, "certificate file");
1.1       jsing     371:        if (x == NULL)
                    372:                goto end;
                    373:        fprintf(stdout, "%s: ", (file == NULL) ? "stdin" : file);
                    374:
                    375:        csc = X509_STORE_CTX_new();
                    376:        if (csc == NULL) {
                    377:                ERR_print_errors(bio_err);
                    378:                goto end;
                    379:        }
                    380:        X509_STORE_set_flags(ctx, vflags);
                    381:        if (!X509_STORE_CTX_init(csc, ctx, x, uchain)) {
                    382:                ERR_print_errors(bio_err);
                    383:                goto end;
                    384:        }
                    385:        if (tchain)
                    386:                X509_STORE_CTX_trusted_stack(csc, tchain);
                    387:        if (crls)
                    388:                X509_STORE_CTX_set0_crls(csc, crls);
                    389:        i = X509_verify_cert(csc);
                    390:        X509_STORE_CTX_free(csc);
                    391:
                    392:        ret = 0;
                    393:
1.7       jsing     394:  end:
1.1       jsing     395:        if (i > 0) {
                    396:                fprintf(stdout, "OK\n");
                    397:                ret = 1;
                    398:        } else
                    399:                ERR_print_errors(bio_err);
                    400:        if (x != NULL)
                    401:                X509_free(x);
                    402:
                    403:        return (ret);
                    404: }
                    405:
                    406: static int
                    407: cb(int ok, X509_STORE_CTX * ctx)
                    408: {
                    409:        int cert_error = X509_STORE_CTX_get_error(ctx);
                    410:        X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx);
                    411:
                    412:        if (!ok) {
                    413:                if (current_cert) {
                    414:                        X509_NAME_print_ex_fp(stdout,
                    415:                            X509_get_subject_name(current_cert),
                    416:                            0, XN_FLAG_ONELINE);
                    417:                        printf("\n");
                    418:                }
                    419:                printf("%serror %d at %d depth lookup:%s\n",
                    420:                    X509_STORE_CTX_get0_parent_ctx(ctx) ? "[CRL path]" : "",
                    421:                    cert_error,
                    422:                    X509_STORE_CTX_get_error_depth(ctx),
                    423:                    X509_verify_cert_error_string(cert_error));
                    424:                switch (cert_error) {
                    425:                case X509_V_ERR_NO_EXPLICIT_POLICY:
                    426:                        policies_print(NULL, ctx);
                    427:                case X509_V_ERR_CERT_HAS_EXPIRED:
                    428:
                    429:                        /*
                    430:                         * since we are just checking the certificates, it is
                    431:                         * ok if they are self signed. But we should still
                    432:                         * warn the user.
                    433:                         */
                    434:
                    435:                case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
                    436:                        /* Continue after extension errors too */
                    437:                case X509_V_ERR_INVALID_CA:
                    438:                case X509_V_ERR_INVALID_NON_CA:
                    439:                case X509_V_ERR_PATH_LENGTH_EXCEEDED:
                    440:                case X509_V_ERR_INVALID_PURPOSE:
                    441:                case X509_V_ERR_CRL_HAS_EXPIRED:
                    442:                case X509_V_ERR_CRL_NOT_YET_VALID:
                    443:                case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
                    444:                        ok = 1;
                    445:
                    446:                }
                    447:
                    448:                return ok;
                    449:
                    450:        }
                    451:        if (cert_error == X509_V_OK && ok == 2)
                    452:                policies_print(NULL, ctx);
1.8     ! jsing     453:        if (!verify_config.verbose)
1.1       jsing     454:                ERR_clear_error();
                    455:        return (ok);
                    456: }