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

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