OLD | NEW |
1 /* apps/verify.c */ | 1 /* apps/verify.c */ |
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 * All rights reserved. | 3 * All rights reserved. |
4 * | 4 * |
5 * This package is an SSL implementation written | 5 * This package is an SSL implementation written |
6 * by Eric Young (eay@cryptsoft.com). | 6 * by Eric Young (eay@cryptsoft.com). |
7 * The implementation was written so as to conform with Netscapes SSL. | 7 * The implementation was written so as to conform with Netscapes SSL. |
8 * | 8 * |
9 * This library is free for commercial and non-commercial use as long as | 9 * This library is free for commercial and non-commercial use as long as |
10 * the following conditions are aheared to. The following conditions | 10 * the following conditions are aheared to. The following conditions |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 #include <openssl/bio.h> | 63 #include <openssl/bio.h> |
64 #include <openssl/err.h> | 64 #include <openssl/err.h> |
65 #include <openssl/x509.h> | 65 #include <openssl/x509.h> |
66 #include <openssl/x509v3.h> | 66 #include <openssl/x509v3.h> |
67 #include <openssl/pem.h> | 67 #include <openssl/pem.h> |
68 | 68 |
69 #undef PROG | 69 #undef PROG |
70 #define PROG verify_main | 70 #define PROG verify_main |
71 | 71 |
72 static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx); | 72 static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx); |
73 static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, STACK_OF(X
509) *tchain, int purpose, ENGINE *e); | 73 static int check(X509_STORE *ctx, char *file, |
74 static STACK_OF(X509) *load_untrusted(char *file); | 74 » » STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, |
| 75 » » STACK_OF(X509_CRL) *crls, ENGINE *e); |
75 static int v_verbose=0, vflags = 0; | 76 static int v_verbose=0, vflags = 0; |
76 | 77 |
77 int MAIN(int, char **); | 78 int MAIN(int, char **); |
78 | 79 |
79 int MAIN(int argc, char **argv) | 80 int MAIN(int argc, char **argv) |
80 { | 81 { |
81 ENGINE *e = NULL; | 82 ENGINE *e = NULL; |
82 int i,ret=1, badarg = 0; | 83 int i,ret=1, badarg = 0; |
83 int purpose = -1; | |
84 char *CApath=NULL,*CAfile=NULL; | 84 char *CApath=NULL,*CAfile=NULL; |
85 » char *untfile = NULL, *trustfile = NULL; | 85 » char *untfile = NULL, *trustfile = NULL, *crlfile = NULL; |
86 STACK_OF(X509) *untrusted = NULL, *trusted = NULL; | 86 STACK_OF(X509) *untrusted = NULL, *trusted = NULL; |
| 87 STACK_OF(X509_CRL) *crls = NULL; |
87 X509_STORE *cert_ctx=NULL; | 88 X509_STORE *cert_ctx=NULL; |
88 X509_LOOKUP *lookup=NULL; | 89 X509_LOOKUP *lookup=NULL; |
89 X509_VERIFY_PARAM *vpm = NULL; | 90 X509_VERIFY_PARAM *vpm = NULL; |
90 #ifndef OPENSSL_NO_ENGINE | 91 #ifndef OPENSSL_NO_ENGINE |
91 char *engine=NULL; | 92 char *engine=NULL; |
92 #endif | 93 #endif |
93 | 94 |
94 cert_ctx=X509_STORE_new(); | 95 cert_ctx=X509_STORE_new(); |
95 if (cert_ctx == NULL) goto end; | 96 if (cert_ctx == NULL) goto end; |
96 » X509_STORE_set_verify_cb_func(cert_ctx,cb); | 97 » X509_STORE_set_verify_cb(cert_ctx,cb); |
97 | 98 |
98 ERR_load_crypto_strings(); | 99 ERR_load_crypto_strings(); |
99 | 100 |
100 apps_startup(); | 101 apps_startup(); |
101 | 102 |
102 if (bio_err == NULL) | 103 if (bio_err == NULL) |
103 if ((bio_err=BIO_new(BIO_s_file())) != NULL) | 104 if ((bio_err=BIO_new(BIO_s_file())) != NULL) |
104 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); | 105 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); |
105 | 106 |
106 if (!load_config(bio_err, NULL)) | 107 if (!load_config(bio_err, NULL)) |
(...skipping 25 matching lines...) Expand all Loading... |
132 else if (strcmp(*argv,"-untrusted") == 0) | 133 else if (strcmp(*argv,"-untrusted") == 0) |
133 { | 134 { |
134 if (argc-- < 1) goto end; | 135 if (argc-- < 1) goto end; |
135 untfile= *(++argv); | 136 untfile= *(++argv); |
136 } | 137 } |
137 else if (strcmp(*argv,"-trusted") == 0) | 138 else if (strcmp(*argv,"-trusted") == 0) |
138 { | 139 { |
139 if (argc-- < 1) goto end; | 140 if (argc-- < 1) goto end; |
140 trustfile= *(++argv); | 141 trustfile= *(++argv); |
141 } | 142 } |
| 143 else if (strcmp(*argv,"-CRLfile") == 0) |
| 144 { |
| 145 if (argc-- < 1) goto end; |
| 146 crlfile= *(++argv); |
| 147 } |
142 #ifndef OPENSSL_NO_ENGINE | 148 #ifndef OPENSSL_NO_ENGINE |
143 else if (strcmp(*argv,"-engine") == 0) | 149 else if (strcmp(*argv,"-engine") == 0) |
144 { | 150 { |
145 if (--argc < 1) goto end; | 151 if (--argc < 1) goto end; |
146 engine= *(++argv); | 152 engine= *(++argv); |
147 } | 153 } |
148 #endif | 154 #endif |
149 else if (strcmp(*argv,"-help") == 0) | 155 else if (strcmp(*argv,"-help") == 0) |
150 goto end; | 156 goto end; |
151 else if (strcmp(*argv,"-verbose") == 0) | 157 else if (strcmp(*argv,"-verbose") == 0) |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 i=X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM); | 191 i=X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM); |
186 if(!i) { | 192 if(!i) { |
187 BIO_printf(bio_err, "Error loading directory %s\n", CApa
th); | 193 BIO_printf(bio_err, "Error loading directory %s\n", CApa
th); |
188 ERR_print_errors(bio_err); | 194 ERR_print_errors(bio_err); |
189 goto end; | 195 goto end; |
190 } | 196 } |
191 } else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT); | 197 } else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT); |
192 | 198 |
193 ERR_clear_error(); | 199 ERR_clear_error(); |
194 | 200 |
195 » if(untfile) { | 201 » if(untfile) |
196 » » if(!(untrusted = load_untrusted(untfile))) { | 202 » » { |
197 » » » BIO_printf(bio_err, "Error loading untrusted file %s\n",
untfile); | 203 » » untrusted = load_certs(bio_err, untfile, FORMAT_PEM, |
198 » » » ERR_print_errors(bio_err); | 204 » » » » » NULL, e, "untrusted certificates"); |
| 205 » » if(!untrusted) |
199 goto end; | 206 goto end; |
200 } | 207 } |
201 } | |
202 | 208 |
203 » if(trustfile) { | 209 » if(trustfile) |
204 » » if(!(trusted = load_untrusted(trustfile))) { | 210 » » { |
205 » » » BIO_printf(bio_err, "Error loading untrusted file %s\n",
trustfile); | 211 » » trusted = load_certs(bio_err, trustfile, FORMAT_PEM, |
206 » » » ERR_print_errors(bio_err); | 212 » » » » » NULL, e, "trusted certificates"); |
| 213 » » if(!trusted) |
207 goto end; | 214 goto end; |
208 } | 215 } |
209 } | |
210 | 216 |
211 » if (argc < 1) check(cert_ctx, NULL, untrusted, trusted, purpose, e); | 217 » if(crlfile) |
| 218 » » { |
| 219 » » crls = load_crls(bio_err, crlfile, FORMAT_PEM, |
| 220 » » » » » NULL, e, "other CRLs"); |
| 221 » » if(!crls) |
| 222 » » » goto end; |
| 223 » » } |
| 224 |
| 225 » if (argc < 1) check(cert_ctx, NULL, untrusted, trusted, crls, e); |
212 else | 226 else |
213 for (i=0; i<argc; i++) | 227 for (i=0; i<argc; i++) |
214 » » » check(cert_ctx,argv[i], untrusted, trusted, purpose, e); | 228 » » » check(cert_ctx,argv[i], untrusted, trusted, crls, e); |
215 ret=0; | 229 ret=0; |
216 end: | 230 end: |
217 if (ret == 1) { | 231 if (ret == 1) { |
218 BIO_printf(bio_err,"usage: verify [-verbose] [-CApath path] [-CA
file file] [-purpose purpose] [-crl_check]"); | 232 BIO_printf(bio_err,"usage: verify [-verbose] [-CApath path] [-CA
file file] [-purpose purpose] [-crl_check]"); |
219 #ifndef OPENSSL_NO_ENGINE | 233 #ifndef OPENSSL_NO_ENGINE |
220 BIO_printf(bio_err," [-engine e]"); | 234 BIO_printf(bio_err," [-engine e]"); |
221 #endif | 235 #endif |
222 BIO_printf(bio_err," cert1 cert2 ...\n"); | 236 BIO_printf(bio_err," cert1 cert2 ...\n"); |
223 BIO_printf(bio_err,"recognized usages:\n"); | 237 BIO_printf(bio_err,"recognized usages:\n"); |
224 for(i = 0; i < X509_PURPOSE_get_count(); i++) { | 238 for(i = 0; i < X509_PURPOSE_get_count(); i++) { |
225 X509_PURPOSE *ptmp; | 239 X509_PURPOSE *ptmp; |
226 ptmp = X509_PURPOSE_get0(i); | 240 ptmp = X509_PURPOSE_get0(i); |
227 BIO_printf(bio_err, "\t%-10s\t%s\n", X509_PURPOSE_get0_s
name(ptmp), | 241 BIO_printf(bio_err, "\t%-10s\t%s\n", X509_PURPOSE_get0_s
name(ptmp), |
228 X509_PURPOSE_get
0_name(ptmp)); | 242 X509_PURPOSE_get
0_name(ptmp)); |
229 } | 243 } |
230 } | 244 } |
231 if (vpm) X509_VERIFY_PARAM_free(vpm); | 245 if (vpm) X509_VERIFY_PARAM_free(vpm); |
232 if (cert_ctx != NULL) X509_STORE_free(cert_ctx); | 246 if (cert_ctx != NULL) X509_STORE_free(cert_ctx); |
233 sk_X509_pop_free(untrusted, X509_free); | 247 sk_X509_pop_free(untrusted, X509_free); |
234 sk_X509_pop_free(trusted, X509_free); | 248 sk_X509_pop_free(trusted, X509_free); |
| 249 sk_X509_CRL_pop_free(crls, X509_CRL_free); |
235 apps_shutdown(); | 250 apps_shutdown(); |
236 OPENSSL_EXIT(ret); | 251 OPENSSL_EXIT(ret); |
237 } | 252 } |
238 | 253 |
239 static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, STACK_OF(X
509) *tchain, int purpose, ENGINE *e) | 254 static int check(X509_STORE *ctx, char *file, |
| 255 » » STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, |
| 256 » » STACK_OF(X509_CRL) *crls, ENGINE *e) |
240 { | 257 { |
241 X509 *x=NULL; | 258 X509 *x=NULL; |
242 int i=0,ret=0; | 259 int i=0,ret=0; |
243 X509_STORE_CTX *csc; | 260 X509_STORE_CTX *csc; |
244 | 261 |
245 x = load_cert(bio_err, file, FORMAT_PEM, NULL, e, "certificate file"); | 262 x = load_cert(bio_err, file, FORMAT_PEM, NULL, e, "certificate file"); |
246 if (x == NULL) | 263 if (x == NULL) |
247 goto end; | 264 goto end; |
248 fprintf(stdout,"%s: ",(file == NULL)?"stdin":file); | 265 fprintf(stdout,"%s: ",(file == NULL)?"stdin":file); |
249 | 266 |
250 csc = X509_STORE_CTX_new(); | 267 csc = X509_STORE_CTX_new(); |
251 if (csc == NULL) | 268 if (csc == NULL) |
252 { | 269 { |
253 ERR_print_errors(bio_err); | 270 ERR_print_errors(bio_err); |
254 goto end; | 271 goto end; |
255 } | 272 } |
256 X509_STORE_set_flags(ctx, vflags); | 273 X509_STORE_set_flags(ctx, vflags); |
257 if(!X509_STORE_CTX_init(csc,ctx,x,uchain)) | 274 if(!X509_STORE_CTX_init(csc,ctx,x,uchain)) |
258 { | 275 { |
259 ERR_print_errors(bio_err); | 276 ERR_print_errors(bio_err); |
260 goto end; | 277 goto end; |
261 } | 278 } |
262 if(tchain) X509_STORE_CTX_trusted_stack(csc, tchain); | 279 if(tchain) X509_STORE_CTX_trusted_stack(csc, tchain); |
263 » if(purpose >= 0) X509_STORE_CTX_set_purpose(csc, purpose); | 280 » if (crls) |
| 281 » » X509_STORE_CTX_set0_crls(csc, crls); |
264 i=X509_verify_cert(csc); | 282 i=X509_verify_cert(csc); |
265 X509_STORE_CTX_free(csc); | 283 X509_STORE_CTX_free(csc); |
266 | 284 |
267 ret=0; | 285 ret=0; |
268 end: | 286 end: |
269 if (i > 0) | 287 if (i > 0) |
270 { | 288 { |
271 fprintf(stdout,"OK\n"); | 289 fprintf(stdout,"OK\n"); |
272 ret=1; | 290 ret=1; |
273 } | 291 } |
274 else | 292 else |
275 ERR_print_errors(bio_err); | 293 ERR_print_errors(bio_err); |
276 if (x != NULL) X509_free(x); | 294 if (x != NULL) X509_free(x); |
277 | 295 |
278 return(ret); | 296 return(ret); |
279 } | 297 } |
280 | 298 |
281 static STACK_OF(X509) *load_untrusted(char *certfile) | |
282 { | |
283 STACK_OF(X509_INFO) *sk=NULL; | |
284 STACK_OF(X509) *stack=NULL, *ret=NULL; | |
285 BIO *in=NULL; | |
286 X509_INFO *xi; | |
287 | |
288 if(!(stack = sk_X509_new_null())) { | |
289 BIO_printf(bio_err,"memory allocation failure\n"); | |
290 goto end; | |
291 } | |
292 | |
293 if(!(in=BIO_new_file(certfile, "r"))) { | |
294 BIO_printf(bio_err,"error opening the file, %s\n",certfile); | |
295 goto end; | |
296 } | |
297 | |
298 /* This loads from a file, a stack of x509/crl/pkey sets */ | |
299 if(!(sk=PEM_X509_INFO_read_bio(in,NULL,NULL,NULL))) { | |
300 BIO_printf(bio_err,"error reading the file, %s\n",certfile); | |
301 goto end; | |
302 } | |
303 | |
304 /* scan over it and pull out the certs */ | |
305 while (sk_X509_INFO_num(sk)) | |
306 { | |
307 xi=sk_X509_INFO_shift(sk); | |
308 if (xi->x509 != NULL) | |
309 { | |
310 sk_X509_push(stack,xi->x509); | |
311 xi->x509=NULL; | |
312 } | |
313 X509_INFO_free(xi); | |
314 } | |
315 if(!sk_X509_num(stack)) { | |
316 BIO_printf(bio_err,"no certificates in file, %s\n",certfile); | |
317 sk_X509_free(stack); | |
318 goto end; | |
319 } | |
320 ret=stack; | |
321 end: | |
322 BIO_free(in); | |
323 sk_X509_INFO_free(sk); | |
324 return(ret); | |
325 } | |
326 | |
327 static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx) | 299 static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx) |
328 { | 300 { |
329 » char buf[256]; | 301 » int cert_error = X509_STORE_CTX_get_error(ctx); |
| 302 » X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx); |
330 | 303 |
331 if (!ok) | 304 if (!ok) |
332 { | 305 { |
333 » » if (ctx->current_cert) | 306 » » if (current_cert) |
334 { | 307 { |
335 » » » X509_NAME_oneline( | 308 » » » X509_NAME_print_ex_fp(stdout, |
336 » » » » X509_get_subject_name(ctx->current_cert),buf, | 309 » » » » X509_get_subject_name(current_cert), |
337 » » » » sizeof buf); | 310 » » » » 0, XN_FLAG_ONELINE); |
338 » » » printf("%s\n",buf); | 311 » » » printf("\n"); |
339 } | 312 } |
340 » » printf("error %d at %d depth lookup:%s\n",ctx->error, | 313 » » printf("%serror %d at %d depth lookup:%s\n", |
341 » » » ctx->error_depth, | 314 » » » X509_STORE_CTX_get0_parent_ctx(ctx) ? "[CRL path]" : "", |
342 » » » X509_verify_cert_error_string(ctx->error)); | 315 » » » cert_error, |
343 » » if (ctx->error == X509_V_ERR_CERT_HAS_EXPIRED) ok=1; | 316 » » » X509_STORE_CTX_get_error_depth(ctx), |
344 » » /* since we are just checking the certificates, it is | 317 » » » X509_verify_cert_error_string(cert_error)); |
345 » » * ok if they are self signed. But we should still warn | 318 » » switch(cert_error) |
346 » » * the user. | 319 » » » { |
347 » » */ | 320 » » » case X509_V_ERR_NO_EXPLICIT_POLICY: |
348 » » if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1; | 321 » » » » policies_print(NULL, ctx); |
349 » » /* Continue after extension errors too */ | 322 » » » case X509_V_ERR_CERT_HAS_EXPIRED: |
350 » » if (ctx->error == X509_V_ERR_INVALID_CA) ok=1; | |
351 » » if (ctx->error == X509_V_ERR_INVALID_NON_CA) ok=1; | |
352 » » if (ctx->error == X509_V_ERR_PATH_LENGTH_EXCEEDED) ok=1; | |
353 » » if (ctx->error == X509_V_ERR_INVALID_PURPOSE) ok=1; | |
354 » » if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1; | |
355 » » if (ctx->error == X509_V_ERR_CRL_HAS_EXPIRED) ok=1; | |
356 » » if (ctx->error == X509_V_ERR_CRL_NOT_YET_VALID) ok=1; | |
357 » » if (ctx->error == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION) ok=1; | |
358 | 323 |
359 » » if (ctx->error == X509_V_ERR_NO_EXPLICIT_POLICY) | 324 » » » /* since we are just checking the certificates, it is |
360 » » » policies_print(NULL, ctx); | 325 » » » * ok if they are self signed. But we should still warn |
| 326 » » » * the user. |
| 327 » » » */ |
| 328 |
| 329 » » » case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: |
| 330 » » » /* Continue after extension errors too */ |
| 331 » » » case X509_V_ERR_INVALID_CA: |
| 332 » » » case X509_V_ERR_INVALID_NON_CA: |
| 333 » » » case X509_V_ERR_PATH_LENGTH_EXCEEDED: |
| 334 » » » case X509_V_ERR_INVALID_PURPOSE: |
| 335 » » » case X509_V_ERR_CRL_HAS_EXPIRED: |
| 336 » » » case X509_V_ERR_CRL_NOT_YET_VALID: |
| 337 » » » case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: |
| 338 » » » ok = 1; |
| 339 |
| 340 » » » } |
| 341 |
361 return ok; | 342 return ok; |
362 | 343 |
363 } | 344 } |
364 » if ((ctx->error == X509_V_OK) && (ok == 2)) | 345 » if (cert_error == X509_V_OK && ok == 2) |
365 policies_print(NULL, ctx); | 346 policies_print(NULL, ctx); |
366 if (!v_verbose) | 347 if (!v_verbose) |
367 ERR_clear_error(); | 348 ERR_clear_error(); |
368 return(ok); | 349 return(ok); |
369 } | 350 } |
OLD | NEW |