sl@0: /* apps/verify.c */ sl@0: /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) sl@0: * All rights reserved. sl@0: * sl@0: * This package is an SSL implementation written sl@0: * by Eric Young (eay@cryptsoft.com). sl@0: * The implementation was written so as to conform with Netscapes SSL. sl@0: * sl@0: * This library is free for commercial and non-commercial use as long as sl@0: * the following conditions are aheared to. The following conditions sl@0: * apply to all code found in this distribution, be it the RC4, RSA, sl@0: * lhash, DES, etc., code; not just the SSL code. The SSL documentation sl@0: * included with this distribution is covered by the same copyright terms sl@0: * except that the holder is Tim Hudson (tjh@cryptsoft.com). sl@0: * sl@0: * Copyright remains Eric Young's, and as such any Copyright notices in sl@0: * the code are not to be removed. sl@0: * If this package is used in a product, Eric Young should be given attribution sl@0: * as the author of the parts of the library used. sl@0: * This can be in the form of a textual message at program startup or sl@0: * in documentation (online or textual) provided with the package. sl@0: * sl@0: * Redistribution and use in source and binary forms, with or without sl@0: * modification, are permitted provided that the following conditions sl@0: * are met: sl@0: * 1. Redistributions of source code must retain the copyright sl@0: * notice, this list of conditions and the following disclaimer. sl@0: * 2. Redistributions in binary form must reproduce the above copyright sl@0: * notice, this list of conditions and the following disclaimer in the sl@0: * documentation and/or other materials provided with the distribution. sl@0: * 3. All advertising materials mentioning features or use of this software sl@0: * must display the following acknowledgement: sl@0: * "This product includes cryptographic software written by sl@0: * Eric Young (eay@cryptsoft.com)" sl@0: * The word 'cryptographic' can be left out if the rouines from the library sl@0: * being used are not cryptographic related :-). sl@0: * 4. If you include any Windows specific code (or a derivative thereof) from sl@0: * the apps directory (application code) you must include an acknowledgement: sl@0: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" sl@0: * sl@0: * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND sl@0: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE sl@0: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE sl@0: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE sl@0: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL sl@0: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS sl@0: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) sl@0: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT sl@0: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY sl@0: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF sl@0: * SUCH DAMAGE. sl@0: * sl@0: * The licence and distribution terms for any publically available version or sl@0: * derivative of this code cannot be changed. i.e. this code cannot simply be sl@0: * copied and put under another distribution licence sl@0: * [including the GNU Public Licence.] sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include "apps.h" sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #undef PROG sl@0: #define PROG verify_main sl@0: sl@0: static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx); sl@0: static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, int purpose, ENGINE *e); sl@0: static STACK_OF(X509) *load_untrusted(char *file); sl@0: static int v_verbose=0, vflags = 0; sl@0: sl@0: sl@0: sl@0: int MAIN(int, char **); sl@0: sl@0: int MAIN(int argc, char **argv) sl@0: { sl@0: ENGINE *e = NULL; sl@0: int i,ret=1, badarg = 0; sl@0: int purpose = -1; sl@0: char *CApath=NULL,*CAfile=NULL; sl@0: char *untfile = NULL, *trustfile = NULL; sl@0: STACK_OF(X509) *untrusted = NULL, *trusted = NULL; sl@0: X509_STORE *cert_ctx=NULL; sl@0: X509_LOOKUP *lookup=NULL; sl@0: X509_VERIFY_PARAM *vpm = NULL; sl@0: #ifndef OPENSSL_NO_ENGINE sl@0: char *engine=NULL; sl@0: #endif sl@0: sl@0: cert_ctx=X509_STORE_new(); sl@0: if (cert_ctx == NULL) goto end; sl@0: X509_STORE_set_verify_cb_func(cert_ctx,cb); sl@0: sl@0: ERR_load_crypto_strings(); sl@0: sl@0: apps_startup(); sl@0: sl@0: if (bio_err == NULL) sl@0: if ((bio_err=BIO_new(BIO_s_file())) != NULL) sl@0: BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); sl@0: sl@0: sl@0: if (!load_config(bio_err, NULL)) sl@0: goto end; sl@0: sl@0: argc--; sl@0: argv++; sl@0: for (;;) sl@0: { sl@0: if (argc >= 1) sl@0: { sl@0: if (strcmp(*argv,"-CApath") == 0) sl@0: { sl@0: if (argc-- < 1) goto end; sl@0: CApath= *(++argv); sl@0: } sl@0: else if (strcmp(*argv,"-CAfile") == 0) sl@0: { sl@0: if (argc-- < 1) goto end; sl@0: CAfile= *(++argv); sl@0: } sl@0: else if (args_verify(&argv, &argc, &badarg, bio_err, sl@0: &vpm)) sl@0: { sl@0: if (badarg) sl@0: goto end; sl@0: continue; sl@0: } sl@0: else if (strcmp(*argv,"-untrusted") == 0) sl@0: { sl@0: if (argc-- < 1) goto end; sl@0: untfile= *(++argv); sl@0: } sl@0: else if (strcmp(*argv,"-trusted") == 0) sl@0: { sl@0: if (argc-- < 1) goto end; sl@0: trustfile= *(++argv); sl@0: } sl@0: #ifndef OPENSSL_NO_ENGINE sl@0: else if (strcmp(*argv,"-engine") == 0) sl@0: { sl@0: if (--argc < 1) goto end; sl@0: engine= *(++argv); sl@0: } sl@0: #endif sl@0: else if (strcmp(*argv,"-help") == 0) sl@0: goto end; sl@0: else if (strcmp(*argv,"-verbose") == 0) sl@0: v_verbose=1; sl@0: else if (argv[0][0] == '-') sl@0: goto end; sl@0: else sl@0: break; sl@0: argc--; sl@0: argv++; sl@0: } sl@0: else sl@0: break; sl@0: } sl@0: sl@0: #ifndef OPENSSL_NO_ENGINE sl@0: e = setup_engine(bio_err, engine, 0); sl@0: #endif sl@0: sl@0: if (vpm) sl@0: X509_STORE_set1_param(cert_ctx, vpm); sl@0: sl@0: lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_file()); sl@0: if (lookup == NULL) abort(); sl@0: if (CAfile) { sl@0: i=X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM); sl@0: if(!i) { sl@0: BIO_printf(bio_err, "Error loading file %s\n", CAfile); sl@0: ERR_print_errors(bio_err); sl@0: goto end; sl@0: } sl@0: } else X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT); sl@0: sl@0: lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_hash_dir()); sl@0: if (lookup == NULL) abort(); sl@0: if (CApath) { sl@0: i=X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM); sl@0: if(!i) { sl@0: BIO_printf(bio_err, "Error loading directory %s\n", CApath); sl@0: ERR_print_errors(bio_err); sl@0: goto end; sl@0: } sl@0: } else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT); sl@0: sl@0: ERR_clear_error(); sl@0: sl@0: if(untfile) { sl@0: if(!(untrusted = load_untrusted(untfile))) { sl@0: BIO_printf(bio_err, "Error loading untrusted file %s\n", untfile); sl@0: ERR_print_errors(bio_err); sl@0: goto end; sl@0: } sl@0: } sl@0: sl@0: if(trustfile) { sl@0: if(!(trusted = load_untrusted(trustfile))) { sl@0: BIO_printf(bio_err, "Error loading untrusted file %s\n", trustfile); sl@0: ERR_print_errors(bio_err); sl@0: goto end; sl@0: } sl@0: } sl@0: sl@0: if (argc < 1) check(cert_ctx, NULL, untrusted, trusted, purpose, e); sl@0: else sl@0: for (i=0; i= 0) X509_STORE_CTX_set_purpose(csc, purpose); sl@0: i=X509_verify_cert(csc); sl@0: X509_STORE_CTX_free(csc); sl@0: sl@0: ret=0; sl@0: end: sl@0: if (i) sl@0: { sl@0: fprintf(stdout,"OK\n"); sl@0: ret=1; sl@0: } sl@0: else sl@0: ERR_print_errors(bio_err); sl@0: if (x != NULL) X509_free(x); sl@0: sl@0: return(ret); sl@0: } sl@0: sl@0: static STACK_OF(X509) *load_untrusted(char *certfile) sl@0: { sl@0: STACK_OF(X509_INFO) *sk=NULL; sl@0: STACK_OF(X509) *stack=NULL, *ret=NULL; sl@0: BIO *in=NULL; sl@0: X509_INFO *xi; sl@0: sl@0: if(!(stack = sk_X509_new_null())) { sl@0: BIO_printf(bio_err,"memory allocation failure\n"); sl@0: goto end; sl@0: } sl@0: sl@0: if(!(in=BIO_new_file(certfile, "r"))) { sl@0: BIO_printf(bio_err,"error opening the file, %s\n",certfile); sl@0: goto end; sl@0: } sl@0: sl@0: /* This loads from a file, a stack of x509/crl/pkey sets */ sl@0: if(!(sk=PEM_X509_INFO_read_bio(in,NULL,NULL,NULL))) { sl@0: BIO_printf(bio_err,"error reading the file, %s\n",certfile); sl@0: goto end; sl@0: } sl@0: sl@0: /* scan over it and pull out the certs */ sl@0: while (sk_X509_INFO_num(sk)) sl@0: { sl@0: xi=sk_X509_INFO_shift(sk); sl@0: if (xi->x509 != NULL) sl@0: { sl@0: sk_X509_push(stack,xi->x509); sl@0: xi->x509=NULL; sl@0: } sl@0: X509_INFO_free(xi); sl@0: } sl@0: if(!sk_X509_num(stack)) { sl@0: BIO_printf(bio_err,"no certificates in file, %s\n",certfile); sl@0: sk_X509_free(stack); sl@0: goto end; sl@0: } sl@0: ret=stack; sl@0: end: sl@0: BIO_free(in); sl@0: sk_X509_INFO_free(sk); sl@0: return(ret); sl@0: } sl@0: sl@0: static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx) sl@0: { sl@0: char buf[256]; sl@0: sl@0: if (!ok) sl@0: { sl@0: if (ctx->current_cert) sl@0: { sl@0: X509_NAME_oneline( sl@0: X509_get_subject_name(ctx->current_cert),buf, sl@0: sizeof buf); sl@0: printf("%s\n",buf); sl@0: } sl@0: printf("error %d at %d depth lookup:%s\n",ctx->error, sl@0: ctx->error_depth, sl@0: X509_verify_cert_error_string(ctx->error)); sl@0: if (ctx->error == X509_V_ERR_CERT_HAS_EXPIRED) ok=1; sl@0: /* since we are just checking the certificates, it is sl@0: * ok if they are self signed. But we should still warn sl@0: * the user. sl@0: */ sl@0: if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1; sl@0: /* Continue after extension errors too */ sl@0: if (ctx->error == X509_V_ERR_INVALID_CA) ok=1; sl@0: if (ctx->error == X509_V_ERR_INVALID_NON_CA) ok=1; sl@0: if (ctx->error == X509_V_ERR_PATH_LENGTH_EXCEEDED) ok=1; sl@0: if (ctx->error == X509_V_ERR_INVALID_PURPOSE) ok=1; sl@0: if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1; sl@0: if (ctx->error == X509_V_ERR_CRL_HAS_EXPIRED) ok=1; sl@0: if (ctx->error == X509_V_ERR_CRL_NOT_YET_VALID) ok=1; sl@0: if (ctx->error == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION) ok=1; sl@0: sl@0: if (ctx->error == X509_V_ERR_NO_EXPLICIT_POLICY) sl@0: policies_print(NULL, ctx); sl@0: return ok; sl@0: sl@0: } sl@0: if ((ctx->error == X509_V_OK) && (ok == 2)) sl@0: policies_print(NULL, ctx); sl@0: if (!v_verbose) sl@0: ERR_clear_error(); sl@0: return(ok); sl@0: } sl@0: