[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.6

1.6     ! doug        1: /* $OpenBSD: verify.c,v 1.5 2015/10/10 22:28:51 doug 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.1       jsing      74: static int v_verbose = 0, vflags = 0;
                     75:
                     76: int
                     77: verify_main(int argc, char **argv)
                     78: {
                     79:        int i, ret = 1, badarg = 0;
                     80:        char *CApath = NULL, *CAfile = NULL;
                     81:        char *untfile = NULL, *trustfile = NULL, *crlfile = NULL;
                     82:        STACK_OF(X509) * untrusted = NULL, *trusted = NULL;
                     83:        STACK_OF(X509_CRL) * crls = NULL;
                     84:        X509_STORE *cert_ctx = NULL;
                     85:        X509_LOOKUP *lookup = NULL;
                     86:        X509_VERIFY_PARAM *vpm = NULL;
1.5       doug       87:
                     88:        if (single_execution) {
1.6     ! doug       89:                if (pledge("stdio rpath", NULL) == -1) {
1.5       doug       90:                        perror("pledge");
1.6     ! doug       91:                        exit(1);
        !            92:                }
1.5       doug       93:        }
1.1       jsing      94:
                     95:        cert_ctx = X509_STORE_new();
                     96:        if (cert_ctx == NULL)
                     97:                goto end;
                     98:        X509_STORE_set_verify_cb(cert_ctx, cb);
                     99:
                    100:        argc--;
                    101:        argv++;
                    102:        for (;;) {
                    103:                if (argc >= 1) {
                    104:                        if (strcmp(*argv, "-CApath") == 0) {
                    105:                                if (argc-- < 1)
                    106:                                        goto end;
                    107:                                CApath = *(++argv);
                    108:                        } else if (strcmp(*argv, "-CAfile") == 0) {
                    109:                                if (argc-- < 1)
                    110:                                        goto end;
                    111:                                CAfile = *(++argv);
                    112:                        } else if (args_verify(&argv, &argc, &badarg, bio_err,
                    113:                            &vpm)) {
                    114:                                if (badarg)
                    115:                                        goto end;
                    116:                                continue;
                    117:                        } else if (strcmp(*argv, "-untrusted") == 0) {
                    118:                                if (argc-- < 1)
                    119:                                        goto end;
                    120:                                untfile = *(++argv);
                    121:                        } else if (strcmp(*argv, "-trusted") == 0) {
                    122:                                if (argc-- < 1)
                    123:                                        goto end;
                    124:                                trustfile = *(++argv);
                    125:                        } else if (strcmp(*argv, "-CRLfile") == 0) {
                    126:                                if (argc-- < 1)
                    127:                                        goto end;
                    128:                                crlfile = *(++argv);
                    129:                        }
                    130:                        else if (strcmp(*argv, "-help") == 0)
                    131:                                goto end;
                    132:                        else if (strcmp(*argv, "-verbose") == 0)
                    133:                                v_verbose = 1;
                    134:                        else if (argv[0][0] == '-')
                    135:                                goto end;
                    136:                        else
                    137:                                break;
                    138:                        argc--;
                    139:                        argv++;
                    140:                } else
                    141:                        break;
                    142:        }
                    143:
                    144:        if (vpm)
                    145:                X509_STORE_set1_param(cert_ctx, vpm);
                    146:
                    147:        lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());
                    148:        if (lookup == NULL)
                    149:                abort();
                    150:        if (CAfile) {
                    151:                i = X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM);
                    152:                if (!i) {
                    153:                        BIO_printf(bio_err, "Error loading file %s\n", CAfile);
                    154:                        ERR_print_errors(bio_err);
                    155:                        goto end;
                    156:                }
                    157:        } else
                    158:                X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
                    159:
                    160:        lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir());
                    161:        if (lookup == NULL)
                    162:                abort();
                    163:        if (CApath) {
                    164:                i = X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM);
                    165:                if (!i) {
                    166:                        BIO_printf(bio_err, "Error loading directory %s\n", CApath);
                    167:                        ERR_print_errors(bio_err);
                    168:                        goto end;
                    169:                }
                    170:        } else
                    171:                X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
                    172:
                    173:        ERR_clear_error();
                    174:
                    175:        if (untfile) {
                    176:                untrusted = load_certs(bio_err, untfile, FORMAT_PEM,
1.4       bcook     177:                    NULL, "untrusted certificates");
1.1       jsing     178:                if (!untrusted)
                    179:                        goto end;
                    180:        }
                    181:        if (trustfile) {
                    182:                trusted = load_certs(bio_err, trustfile, FORMAT_PEM,
1.4       bcook     183:                    NULL, "trusted certificates");
1.1       jsing     184:                if (!trusted)
                    185:                        goto end;
                    186:        }
                    187:        if (crlfile) {
                    188:                crls = load_crls(bio_err, crlfile, FORMAT_PEM,
1.4       bcook     189:                    NULL, "other CRLs");
1.1       jsing     190:                if (!crls)
                    191:                        goto end;
                    192:        }
                    193:        ret = 0;
                    194:        if (argc < 1) {
1.4       bcook     195:                if (1 != check(cert_ctx, NULL, untrusted, trusted, crls))
1.1       jsing     196:                        ret = -1;
                    197:        } else {
                    198:                for (i = 0; i < argc; i++)
                    199:                        if (1 != check(cert_ctx, argv[i], untrusted, trusted,
1.4       bcook     200:                            crls))
1.1       jsing     201:                                ret = -1;
                    202:        }
                    203:
                    204: end:
                    205:        if (ret == 1) {
                    206:                BIO_printf(bio_err, "usage: verify [-verbose] [-CApath path] [-CAfile file] [-purpose purpose] [-crl_check]");
                    207:                BIO_printf(bio_err, " [-attime timestamp]");
                    208:                BIO_printf(bio_err, " cert1 cert2 ...\n");
                    209:
                    210:                BIO_printf(bio_err, "recognized usages:\n");
                    211:                for (i = 0; i < X509_PURPOSE_get_count(); i++) {
                    212:                        X509_PURPOSE *ptmp;
                    213:                        ptmp = X509_PURPOSE_get0(i);
                    214:                        BIO_printf(bio_err, "\t%-10s\t%s\n",
                    215:                            X509_PURPOSE_get0_sname(ptmp),
                    216:                            X509_PURPOSE_get0_name(ptmp));
                    217:                }
                    218:        }
                    219:        if (vpm)
                    220:                X509_VERIFY_PARAM_free(vpm);
                    221:        if (cert_ctx != NULL)
                    222:                X509_STORE_free(cert_ctx);
                    223:        sk_X509_pop_free(untrusted, X509_free);
                    224:        sk_X509_pop_free(trusted, X509_free);
                    225:        sk_X509_CRL_pop_free(crls, X509_CRL_free);
                    226:
                    227:        return (ret < 0 ? 2 : ret);
                    228: }
                    229:
                    230: static int
                    231: check(X509_STORE * ctx, char *file, STACK_OF(X509) * uchain,
1.4       bcook     232:     STACK_OF(X509) * tchain, STACK_OF(X509_CRL) * crls)
1.1       jsing     233: {
                    234:        X509 *x = NULL;
                    235:        int i = 0, ret = 0;
                    236:        X509_STORE_CTX *csc;
                    237:
1.4       bcook     238:        x = load_cert(bio_err, file, FORMAT_PEM, NULL, "certificate file");
1.1       jsing     239:        if (x == NULL)
                    240:                goto end;
                    241:        fprintf(stdout, "%s: ", (file == NULL) ? "stdin" : file);
                    242:
                    243:        csc = X509_STORE_CTX_new();
                    244:        if (csc == NULL) {
                    245:                ERR_print_errors(bio_err);
                    246:                goto end;
                    247:        }
                    248:        X509_STORE_set_flags(ctx, vflags);
                    249:        if (!X509_STORE_CTX_init(csc, ctx, x, uchain)) {
                    250:                ERR_print_errors(bio_err);
                    251:                goto end;
                    252:        }
                    253:        if (tchain)
                    254:                X509_STORE_CTX_trusted_stack(csc, tchain);
                    255:        if (crls)
                    256:                X509_STORE_CTX_set0_crls(csc, crls);
                    257:        i = X509_verify_cert(csc);
                    258:        X509_STORE_CTX_free(csc);
                    259:
                    260:        ret = 0;
                    261:
                    262: end:
                    263:        if (i > 0) {
                    264:                fprintf(stdout, "OK\n");
                    265:                ret = 1;
                    266:        } else
                    267:                ERR_print_errors(bio_err);
                    268:        if (x != NULL)
                    269:                X509_free(x);
                    270:
                    271:        return (ret);
                    272: }
                    273:
                    274: static int
                    275: cb(int ok, X509_STORE_CTX * ctx)
                    276: {
                    277:        int cert_error = X509_STORE_CTX_get_error(ctx);
                    278:        X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx);
                    279:
                    280:        if (!ok) {
                    281:                if (current_cert) {
                    282:                        X509_NAME_print_ex_fp(stdout,
                    283:                            X509_get_subject_name(current_cert),
                    284:                            0, XN_FLAG_ONELINE);
                    285:                        printf("\n");
                    286:                }
                    287:                printf("%serror %d at %d depth lookup:%s\n",
                    288:                    X509_STORE_CTX_get0_parent_ctx(ctx) ? "[CRL path]" : "",
                    289:                    cert_error,
                    290:                    X509_STORE_CTX_get_error_depth(ctx),
                    291:                    X509_verify_cert_error_string(cert_error));
                    292:                switch (cert_error) {
                    293:                case X509_V_ERR_NO_EXPLICIT_POLICY:
                    294:                        policies_print(NULL, ctx);
                    295:                case X509_V_ERR_CERT_HAS_EXPIRED:
                    296:
                    297:                        /*
                    298:                         * since we are just checking the certificates, it is
                    299:                         * ok if they are self signed. But we should still
                    300:                         * warn the user.
                    301:                         */
                    302:
                    303:                case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
                    304:                        /* Continue after extension errors too */
                    305:                case X509_V_ERR_INVALID_CA:
                    306:                case X509_V_ERR_INVALID_NON_CA:
                    307:                case X509_V_ERR_PATH_LENGTH_EXCEEDED:
                    308:                case X509_V_ERR_INVALID_PURPOSE:
                    309:                case X509_V_ERR_CRL_HAS_EXPIRED:
                    310:                case X509_V_ERR_CRL_NOT_YET_VALID:
                    311:                case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
                    312:                        ok = 1;
                    313:
                    314:                }
                    315:
                    316:                return ok;
                    317:
                    318:        }
                    319:        if (cert_error == X509_V_OK && ok == 2)
                    320:                policies_print(NULL, ctx);
                    321:        if (!v_verbose)
                    322:                ERR_clear_error();
                    323:        return (ok);
                    324: }