source: trunk/third/openssl/apps/verify.c @ 18442

Revision 18442, 10.5 KB checked in by zacheiss, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18441, which included commits to RCS files with non-trunk default branches.
Line 
1/* apps/verify.c */
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#include "apps.h"
63#include <openssl/bio.h>
64#include <openssl/err.h>
65#include <openssl/x509.h>
66#include <openssl/x509v3.h>
67#include <openssl/pem.h>
68
69#undef PROG
70#define PROG    verify_main
71
72static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx);
73static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, int purpose, ENGINE *e);
74static STACK_OF(X509) *load_untrusted(char *file);
75static int v_verbose=0, vflags = 0;
76
77int MAIN(int, char **);
78
79int MAIN(int argc, char **argv)
80        {
81        ENGINE *e = NULL;
82        int i,ret=1;
83        int purpose = -1;
84        char *CApath=NULL,*CAfile=NULL;
85        char *untfile = NULL, *trustfile = NULL;
86        STACK_OF(X509) *untrusted = NULL, *trusted = NULL;
87        X509_STORE *cert_ctx=NULL;
88        X509_LOOKUP *lookup=NULL;
89        char *engine=NULL;
90
91        cert_ctx=X509_STORE_new();
92        if (cert_ctx == NULL) goto end;
93        X509_STORE_set_verify_cb_func(cert_ctx,cb);
94
95        ERR_load_crypto_strings();
96
97        apps_startup();
98
99        if (bio_err == NULL)
100                if ((bio_err=BIO_new(BIO_s_file())) != NULL)
101                        BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
102
103        if (!load_config(bio_err, NULL))
104                goto end;
105
106        argc--;
107        argv++;
108        for (;;)
109                {
110                if (argc >= 1)
111                        {
112                        if (strcmp(*argv,"-CApath") == 0)
113                                {
114                                if (argc-- < 1) goto end;
115                                CApath= *(++argv);
116                                }
117                        else if (strcmp(*argv,"-CAfile") == 0)
118                                {
119                                if (argc-- < 1) goto end;
120                                CAfile= *(++argv);
121                                }
122                        else if (strcmp(*argv,"-purpose") == 0)
123                                {
124                                X509_PURPOSE *xptmp;
125                                if (argc-- < 1) goto end;
126                                i = X509_PURPOSE_get_by_sname(*(++argv));
127                                if(i < 0)
128                                        {
129                                        BIO_printf(bio_err, "unrecognized purpose\n");
130                                        goto end;
131                                        }
132                                xptmp = X509_PURPOSE_get0(i);
133                                purpose = X509_PURPOSE_get_id(xptmp);
134                                }
135                        else if (strcmp(*argv,"-untrusted") == 0)
136                                {
137                                if (argc-- < 1) goto end;
138                                untfile= *(++argv);
139                                }
140                        else if (strcmp(*argv,"-trusted") == 0)
141                                {
142                                if (argc-- < 1) goto end;
143                                trustfile= *(++argv);
144                                }
145                        else if (strcmp(*argv,"-engine") == 0)
146                                {
147                                if (--argc < 1) goto end;
148                                engine= *(++argv);
149                                }
150                        else if (strcmp(*argv,"-help") == 0)
151                                goto end;
152                        else if (strcmp(*argv,"-ignore_critical") == 0)
153                                vflags |= X509_V_FLAG_IGNORE_CRITICAL;
154                        else if (strcmp(*argv,"-issuer_checks") == 0)
155                                vflags |= X509_V_FLAG_CB_ISSUER_CHECK;
156                        else if (strcmp(*argv,"-crl_check") == 0)
157                                vflags |= X509_V_FLAG_CRL_CHECK;
158                        else if (strcmp(*argv,"-crl_check_all") == 0)
159                                vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
160                        else if (strcmp(*argv,"-verbose") == 0)
161                                v_verbose=1;
162                        else if (argv[0][0] == '-')
163                                goto end;
164                        else
165                                break;
166                        argc--;
167                        argv++;
168                        }
169                else
170                        break;
171                }
172
173        e = setup_engine(bio_err, engine, 0);
174
175        lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_file());
176        if (lookup == NULL) abort();
177        if (CAfile) {
178                i=X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM);
179                if(!i) {
180                        BIO_printf(bio_err, "Error loading file %s\n", CAfile);
181                        ERR_print_errors(bio_err);
182                        goto end;
183                }
184        } else X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
185               
186        lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_hash_dir());
187        if (lookup == NULL) abort();
188        if (CApath) {
189                i=X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM);
190                if(!i) {
191                        BIO_printf(bio_err, "Error loading directory %s\n", CApath);
192                        ERR_print_errors(bio_err);
193                        goto end;
194                }
195        } else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
196
197        ERR_clear_error();
198
199        if(untfile) {
200                if(!(untrusted = load_untrusted(untfile))) {
201                        BIO_printf(bio_err, "Error loading untrusted file %s\n", untfile);
202                        ERR_print_errors(bio_err);
203                        goto end;
204                }
205        }
206
207        if(trustfile) {
208                if(!(trusted = load_untrusted(trustfile))) {
209                        BIO_printf(bio_err, "Error loading untrusted file %s\n", trustfile);
210                        ERR_print_errors(bio_err);
211                        goto end;
212                }
213        }
214
215        if (argc < 1) check(cert_ctx, NULL, untrusted, trusted, purpose, e);
216        else
217                for (i=0; i<argc; i++)
218                        check(cert_ctx,argv[i], untrusted, trusted, purpose, e);
219        ret=0;
220end:
221        if (ret == 1) {
222                BIO_printf(bio_err,"usage: verify [-verbose] [-CApath path] [-CAfile file] [-purpose purpose] [-crl_check] [-engine e] cert1 cert2 ...\n");
223                BIO_printf(bio_err,"recognized usages:\n");
224                for(i = 0; i < X509_PURPOSE_get_count(); i++) {
225                        X509_PURPOSE *ptmp;
226                        ptmp = X509_PURPOSE_get0(i);
227                        BIO_printf(bio_err, "\t%-10s\t%s\n", X509_PURPOSE_get0_sname(ptmp),
228                                                                X509_PURPOSE_get0_name(ptmp));
229                }
230        }
231        if (cert_ctx != NULL) X509_STORE_free(cert_ctx);
232        sk_X509_pop_free(untrusted, X509_free);
233        sk_X509_pop_free(trusted, X509_free);
234        apps_shutdown();
235        OPENSSL_EXIT(ret);
236        }
237
238static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, int purpose, ENGINE *e)
239        {
240        X509 *x=NULL;
241        int i=0,ret=0;
242        X509_STORE_CTX *csc;
243
244        x = load_cert(bio_err, file, FORMAT_PEM, NULL, e, "certificate file");
245        if (x == NULL)
246                goto end;
247        fprintf(stdout,"%s: ",(file == NULL)?"stdin":file);
248
249        csc = X509_STORE_CTX_new();
250        if (csc == NULL)
251                {
252                ERR_print_errors(bio_err);
253                goto end;
254                }
255        X509_STORE_set_flags(ctx, vflags);
256        if(!X509_STORE_CTX_init(csc,ctx,x,uchain))
257                {
258                ERR_print_errors(bio_err);
259                goto end;
260                }
261        if(tchain) X509_STORE_CTX_trusted_stack(csc, tchain);
262        if(purpose >= 0) X509_STORE_CTX_set_purpose(csc, purpose);
263        i=X509_verify_cert(csc);
264        X509_STORE_CTX_free(csc);
265
266        ret=0;
267end:
268        if (i)
269                {
270                fprintf(stdout,"OK\n");
271                ret=1;
272                }
273        else
274                ERR_print_errors(bio_err);
275        if (x != NULL) X509_free(x);
276
277        return(ret);
278        }
279
280static STACK_OF(X509) *load_untrusted(char *certfile)
281{
282        STACK_OF(X509_INFO) *sk=NULL;
283        STACK_OF(X509) *stack=NULL, *ret=NULL;
284        BIO *in=NULL;
285        X509_INFO *xi;
286
287        if(!(stack = sk_X509_new_null())) {
288                BIO_printf(bio_err,"memory allocation failure\n");
289                goto end;
290        }
291
292        if(!(in=BIO_new_file(certfile, "r"))) {
293                BIO_printf(bio_err,"error opening the file, %s\n",certfile);
294                goto end;
295        }
296
297        /* This loads from a file, a stack of x509/crl/pkey sets */
298        if(!(sk=PEM_X509_INFO_read_bio(in,NULL,NULL,NULL))) {
299                BIO_printf(bio_err,"error reading the file, %s\n",certfile);
300                goto end;
301        }
302
303        /* scan over it and pull out the certs */
304        while (sk_X509_INFO_num(sk))
305                {
306                xi=sk_X509_INFO_shift(sk);
307                if (xi->x509 != NULL)
308                        {
309                        sk_X509_push(stack,xi->x509);
310                        xi->x509=NULL;
311                        }
312                X509_INFO_free(xi);
313                }
314        if(!sk_X509_num(stack)) {
315                BIO_printf(bio_err,"no certificates in file, %s\n",certfile);
316                sk_X509_free(stack);
317                goto end;
318        }
319        ret=stack;
320end:
321        BIO_free(in);
322        sk_X509_INFO_free(sk);
323        return(ret);
324        }
325
326static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx)
327        {
328        char buf[256];
329
330        if (!ok)
331                {
332                X509_NAME_oneline(
333                                X509_get_subject_name(ctx->current_cert),buf,
334                                sizeof buf);
335                printf("%s\n",buf);
336                printf("error %d at %d depth lookup:%s\n",ctx->error,
337                        ctx->error_depth,
338                        X509_verify_cert_error_string(ctx->error));
339                if (ctx->error == X509_V_ERR_CERT_HAS_EXPIRED) ok=1;
340                /* since we are just checking the certificates, it is
341                 * ok if they are self signed. But we should still warn
342                 * the user.
343                 */
344                if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1;
345                /* Continue after extension errors too */
346                if (ctx->error == X509_V_ERR_INVALID_CA) ok=1;
347                if (ctx->error == X509_V_ERR_PATH_LENGTH_EXCEEDED) ok=1;
348                if (ctx->error == X509_V_ERR_INVALID_PURPOSE) ok=1;
349                if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1;
350                if (ctx->error == X509_V_ERR_CRL_HAS_EXPIRED) ok=1;
351                if (ctx->error == X509_V_ERR_CRL_NOT_YET_VALID) ok=1;
352                if (ctx->error == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION) ok=1;
353                }
354        if (!v_verbose)
355                ERR_clear_error();
356        return(ok);
357        }
358
Note: See TracBrowser for help on using the repository browser.