| 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 |