diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2004-09-06 18:43:01 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2004-09-06 18:43:01 +0000 |
commit | 5d7c222db8f26a53c00646cc1dde2bdded38027e (patch) | |
tree | 7ce0523e1f46b97b427eec9c348e79c3221a8ccc | |
parent | d993addbed0a3502c3fa6ef2ae2bd9b7fd002d01 (diff) |
New X509_VERIFY_PARAM structure and associated functionality.
This tidies up verify parameters and adds support for integrated policy
checking.
Add support for policy related command line options. Currently only in smime
application.
WARNING: experimental code subject to change.
-rw-r--r-- | CHANGES | 8 | ||||
-rw-r--r-- | apps/Makefile.ssl | 6 | ||||
-rw-r--r-- | apps/apps.c | 65 | ||||
-rw-r--r-- | apps/apps.h | 1 | ||||
-rw-r--r-- | apps/smime.c | 80 | ||||
-rw-r--r-- | crypto/stack/safestack.h | 21 | ||||
-rw-r--r-- | crypto/x509/Makefile.ssl | 4 | ||||
-rw-r--r-- | crypto/x509/x509_lu.c | 28 | ||||
-rw-r--r-- | crypto/x509/x509_txt.c | 9 | ||||
-rw-r--r-- | crypto/x509/x509_vfy.c | 181 | ||||
-rw-r--r-- | crypto/x509/x509_vfy.h | 105 | ||||
-rw-r--r-- | crypto/x509/x509_vpm.c | 400 | ||||
-rw-r--r-- | ssl/ssl.h | 10 | ||||
-rw-r--r-- | ssl/ssl_cert.c | 14 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 41 |
15 files changed, 881 insertions, 92 deletions
@@ -4,6 +4,14 @@ Changes between 0.9.7e and 0.9.8 [xx XXX xxxx] + *) New structure X509_VERIFY_PARAM which combines current verify parameters, + update associated structures and add various utility functions. + + Add new policy related verify parameters, include policy checking in + standard verify code. Enhance 'smime' application with extra parameters + to support policy checking and print out. + [Steve Henson] + *) Add a new engine to support VIA PadLock ACE extensions in the VIA C3 Nehemiah processors. These extensions support AES encryption in hardware as well as RNG (though RNG support is currently disabled). diff --git a/apps/Makefile.ssl b/apps/Makefile.ssl index 3d75664660..03e2ba34b4 100644 --- a/apps/Makefile.ssl +++ b/apps/Makefile.ssl @@ -62,14 +62,16 @@ E_OBJ= verify.o asn1pars.o req.o dgst.o dh.o dhparam.o enc.o passwd.o gendh.o er rsa.o rsautl.o dsa.o dsaparam.o ec.o ecparam.o \ x509.o genrsa.o gendsa.o s_server.o s_client.o speed.o \ s_time.o $(A_OBJ) $(S_OBJ) $(RAND_OBJ) version.o sess_id.o \ - ciphers.o nseq.o pkcs12.o pkcs8.o spkac.o smime.o rand.o engine.o ocsp.o + ciphers.o nseq.o pkcs12.o pkcs8.o spkac.o smime.o rand.o engine.o \ + ocsp.o E_SRC= verify.c asn1pars.c req.c dgst.c dh.c enc.c passwd.c gendh.c errstr.c ca.c \ pkcs7.c crl2p7.c crl.c \ rsa.c rsautl.c dsa.c dsaparam.c ec.c ecparam.c \ x509.c genrsa.c gendsa.c s_server.c s_client.c speed.c \ s_time.c $(A_SRC) $(S_SRC) $(RAND_SRC) version.c sess_id.c \ - ciphers.c nseq.c pkcs12.c pkcs8.c spkac.c smime.c rand.c engine.c ocsp.c + ciphers.c nseq.c pkcs12.c pkcs8.c spkac.c smime.c rand.c engine.c \ + ocsp.c SRC=$(E_SRC) diff --git a/apps/apps.c b/apps/apps.c index 3c3a11ce4d..6bc3562cdb 100644 --- a/apps/apps.c +++ b/apps/apps.c @@ -2140,3 +2140,68 @@ int WIN32_rename(char *from, char *to) #endif } #endif + +int args_verify(char ***pargs, int *badarg, BIO *err, X509_VERIFY_PARAM **pm) + { + ASN1_OBJECT *otmp = NULL; + unsigned long flags = 0; + char *arg = **pargs, *argn = (*pargs)[1]; + if (!strcmp(arg, "-policy")) + { + if (!argn) + *badarg = 1; + else + { + otmp = OBJ_txt2obj(argn, 0); + if (!otmp) + { + BIO_printf(err, "Invalid Policy \"%s\"\n", + argn); + *badarg = 1; + } + } + (*pargs)++; + } + else if (!strcmp(arg, "-ignore_critical")) + flags |= X509_V_FLAG_IGNORE_CRITICAL; + else if (!strcmp(arg, "-issuer_checks")) + flags |= X509_V_FLAG_CB_ISSUER_CHECK; + else if (!strcmp(arg, "-crl_check")) + flags |= X509_V_FLAG_CRL_CHECK; + else if (!strcmp(arg, "-crl_check_all")) + flags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; + else if (!strcmp(arg, "-policy_check")) + flags |= X509_V_FLAG_POLICY_CHECK; + else if (!strcmp(arg, "-explicit_policy")) + flags |= X509_V_FLAG_EXPLICIT_POLICY; + else if (!strcmp(arg, "-x509_strict")) + flags |= X509_V_FLAG_X509_STRICT; + else if (!strcmp(arg, "-policy_print")) + flags |= X509_V_FLAG_NOTIFY_POLICY; + else + return 0; + + if (*badarg) + { + if (*pm) + X509_VERIFY_PARAM_free(*pm); + *pm = NULL; + return 1; + } + + if (!*pm && !(*pm = X509_VERIFY_PARAM_new())) + { + *badarg = 1; + return 1; + } + + if (otmp) + X509_VERIFY_PARAM_add0_policy(*pm, otmp); + if (flags) + X509_VERIFY_PARAM_set_flags(*pm, flags); + + (*pargs)++; + + return 1; + + } diff --git a/apps/apps.h b/apps/apps.h index e653bf1b46..ede0c462fc 100644 --- a/apps/apps.h +++ b/apps/apps.h @@ -317,6 +317,7 @@ int index_name_cmp(const char **a, const char **b); int parse_yesno(char *str, int def); X509_NAME *parse_name(char *str, long chtype, int multirdn); +int args_verify(char ***pargs, int *badarg, BIO *err, X509_VERIFY_PARAM **pm); #define FORMAT_UNDEF 0 #define FORMAT_ASN1 1 diff --git a/apps/smime.c b/apps/smime.c index 418e03cd66..d193fef7b5 100644 --- a/apps/smime.c +++ b/apps/smime.c @@ -3,7 +3,7 @@ * project. */ /* ==================================================================== - * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -64,10 +64,13 @@ #include <openssl/crypto.h> #include <openssl/pem.h> #include <openssl/err.h> +#include <openssl/x509_vfy.h> +#include <openssl/x509v3.h> #undef PROG #define PROG smime_main static int save_certs(char *signerfile, STACK_OF(X509) *signers); +static int smime_cb(int ok, X509_STORE_CTX *ctx); #define SMIME_OP 0x10 #define SMIME_ENCRYPT (1 | SMIME_OP) @@ -96,7 +99,7 @@ int MAIN(int argc, char **argv) STACK_OF(X509) *encerts = NULL, *other = NULL; BIO *in = NULL, *out = NULL, *indata = NULL; int badarg = 0; - int flags = PKCS7_DETACHED, store_flags = 0; + int flags = PKCS7_DETACHED; char *to = NULL, *from = NULL, *subject = NULL; char *CAfile = NULL, *CApath = NULL; char *passargin = NULL, *passin = NULL; @@ -108,6 +111,8 @@ int MAIN(int argc, char **argv) char *engine=NULL; #endif + X509_VERIFY_PARAM *vpm = NULL; + args = argv + 1; ret = 1; @@ -172,10 +177,6 @@ int MAIN(int argc, char **argv) flags |= PKCS7_NOOLDMIMETYPE; else if (!strcmp (*args, "-crlfeol")) flags |= PKCS7_CRLFEOL; - else if (!strcmp (*args, "-crl_check")) - store_flags |= X509_V_FLAG_CRL_CHECK; - else if (!strcmp (*args, "-crl_check_all")) - store_flags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; else if (!strcmp(*args,"-rand")) { if (args[1]) { args++; @@ -269,10 +270,14 @@ int MAIN(int argc, char **argv) args++; contfile = *args; } else badarg = 1; - } else badarg = 1; + } else if (args_verify(&args, &badarg, bio_err, &vpm)) + continue; + else + badarg = 1; args++; } + if(operation == SMIME_SIGN) { if(!signerfile) { BIO_printf(bio_err, "No signer certificate specified\n"); @@ -473,7 +478,9 @@ int MAIN(int argc, char **argv) if(operation == SMIME_VERIFY) { if(!(store = setup_verify(bio_err, CAfile, CApath))) goto end; - X509_STORE_set_flags(store, store_flags); + X509_STORE_set_verify_cb_func(store, smime_cb); + if (vpm) + X509_STORE_set1_param(store, vpm); } @@ -569,6 +576,8 @@ end: if(ret) ERR_print_errors(bio_err); sk_X509_pop_free(encerts, X509_free); sk_X509_pop_free(other, X509_free); + if (vpm) + X509_VERIFY_PARAM_free(vpm); X509_STORE_free(store); X509_free(cert); X509_free(recip); @@ -595,3 +604,58 @@ static int save_certs(char *signerfile, STACK_OF(X509) *signers) return 1; } + +static void nodes_print(BIO *out, char *name, STACK_OF(X509_POLICY_NODE) *nodes) + { + X509_POLICY_NODE *node; + int i; + BIO_printf(out, "%s Policies:", name); + if (nodes) + { + BIO_puts(out, "\n"); + for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) + { + node = sk_X509_POLICY_NODE_value(nodes, i); + X509_POLICY_NODE_print(out, node, 2); + } + } + else + BIO_puts(out, " <empty>\n"); + } + +static void policies_print(BIO *out, X509_STORE_CTX *ctx) + { + X509_POLICY_TREE *tree; + int explicit; + tree = X509_STORE_CTX_get0_policy_tree(ctx); + explicit = X509_STORE_CTX_get_explicit_policy(ctx); + + BIO_printf(out, "Require explicit Policy: %s\n", + explicit ? "True" : "False"); + + nodes_print(out, "Authority", X509_policy_tree_get0_policies(tree)); + nodes_print(out, "User", X509_policy_tree_get0_user_policies(tree)); + } + +/* Minimal callback just to output policy info (if any) */ + +static int smime_cb(int ok, X509_STORE_CTX *ctx) + { + BIO *out; + int error; + + error = X509_STORE_CTX_get_error(ctx); + + if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) + && ((error != X509_V_OK) || (ok != 2))) + return ok; + + out = BIO_new_fp(stderr, BIO_NOCLOSE); + + policies_print(out, ctx); + + BIO_free(out); + + return ok; + + } diff --git a/crypto/stack/safestack.h b/crypto/stack/safestack.h index e52a859eb3..0b38337d03 100644 --- a/crypto/stack/safestack.h +++ b/crypto/stack/safestack.h @@ -1486,6 +1486,27 @@ STACK_OF(type) \ #define sk_X509_TRUST_pop(st) SKM_sk_pop(X509_TRUST, (st)) #define sk_X509_TRUST_sort(st) SKM_sk_sort(X509_TRUST, (st)) +#define sk_X509_VERIFY_PARAM_new(st) SKM_sk_new(X509_VERIFY_PARAM, (st)) +#define sk_X509_VERIFY_PARAM_new_null() SKM_sk_new_null(X509_VERIFY_PARAM) +#define sk_X509_VERIFY_PARAM_free(st) SKM_sk_free(X509_VERIFY_PARAM, (st)) +#define sk_X509_VERIFY_PARAM_num(st) SKM_sk_num(X509_VERIFY_PARAM, (st)) +#define sk_X509_VERIFY_PARAM_value(st, i) SKM_sk_value(X509_VERIFY_PARAM, (st), (i)) +#define sk_X509_VERIFY_PARAM_set(st, i, val) SKM_sk_set(X509_VERIFY_PARAM, (st), (i), (val)) +#define sk_X509_VERIFY_PARAM_zero(st) SKM_sk_zero(X509_VERIFY_PARAM, (st)) +#define sk_X509_VERIFY_PARAM_push(st, val) SKM_sk_push(X509_VERIFY_PARAM, (st), (val)) +#define sk_X509_VERIFY_PARAM_unshift(st, val) SKM_sk_unshift(X509_VERIFY_PARAM, (st), (val)) +#define sk_X509_VERIFY_PARAM_find(st, val) SKM_sk_find(X509_VERIFY_PARAM, (st), (val)) +#define sk_X509_VERIFY_PARAM_find_ex(st, val) SKM_sk_find_ex(X509_VERIFY_PARAM, (st), (val)) +#define sk_X509_VERIFY_PARAM_delete(st, i) SKM_sk_delete(X509_VERIFY_PARAM, (st), (i)) +#define sk_X509_VERIFY_PARAM_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_VERIFY_PARAM, (st), (ptr)) +#define sk_X509_VERIFY_PARAM_insert(st, val, i) SKM_sk_insert(X509_VERIFY_PARAM, (st), (val), (i)) +#define sk_X509_VERIFY_PARAM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_VERIFY_PARAM, (st), (cmp)) +#define sk_X509_VERIFY_PARAM_dup(st) SKM_sk_dup(X509_VERIFY_PARAM, st) +#define sk_X509_VERIFY_PARAM_pop_free(st, free_func) SKM_sk_pop_free(X509_VERIFY_PARAM, (st), (free_func)) +#define sk_X509_VERIFY_PARAM_shift(st) SKM_sk_shift(X509_VERIFY_PARAM, (st)) +#define sk_X509_VERIFY_PARAM_pop(st) SKM_sk_pop(X509_VERIFY_PARAM, (st)) +#define sk_X509_VERIFY_PARAM_sort(st) SKM_sk_sort(X509_VERIFY_PARAM, (st)) + #define d2i_ASN1_SET_OF_ACCESS_DESCRIPTION(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ SKM_ASN1_SET_OF_d2i(ACCESS_DESCRIPTION, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) #define i2d_ASN1_SET_OF_ACCESS_DESCRIPTION(st, pp, i2d_func, ex_tag, ex_class, is_set) \ diff --git a/crypto/x509/Makefile.ssl b/crypto/x509/Makefile.ssl index 031b0a1230..26ab668266 100644 --- a/crypto/x509/Makefile.ssl +++ b/crypto/x509/Makefile.ssl @@ -28,13 +28,13 @@ LIBSRC= x509_def.c x509_d2.c x509_r2x.c x509_cmp.c \ x509_set.c x509cset.c x509rset.c x509_err.c \ x509name.c x509_v3.c x509_ext.c x509_att.c \ x509type.c x509_lu.c x_all.c x509_txt.c \ - x509_trs.c by_file.c by_dir.c + x509_trs.c by_file.c by_dir.c x509_vpm.c LIBOBJ= x509_def.o x509_d2.o x509_r2x.o x509_cmp.o \ x509_obj.o x509_req.o x509spki.o x509_vfy.o \ x509_set.o x509cset.o x509rset.o x509_err.o \ x509name.o x509_v3.o x509_ext.o x509_att.o \ x509type.o x509_lu.o x_all.o x509_txt.o \ - x509_trs.o by_file.o by_dir.o + x509_trs.o by_file.o by_dir.o x509_vpm.o SRC= $(LIBSRC) diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c index b780dae5e2..8c7f22b0d9 100644 --- a/crypto/x509/x509_lu.c +++ b/crypto/x509/x509_lu.c @@ -187,10 +187,8 @@ X509_STORE *X509_STORE_new(void) ret->verify=0; ret->verify_cb=0; - ret->purpose = 0; - ret->trust = 0; - - ret->flags = 0; + if ((ret->param = X509_VERIFY_PARAM_new()) == NULL) + return NULL; ret->get_issuer = 0; ret->check_issued = 0; @@ -202,7 +200,6 @@ X509_STORE *X509_STORE_new(void) CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data); ret->references=1; - ret->depth=0; return ret; } @@ -244,6 +241,8 @@ void X509_STORE_free(X509_STORE *vfy) sk_X509_OBJECT_pop_free(vfy->objs, cleanup); CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data); + if (vfy->param) + X509_VERIFY_PARAM_free(vfy->param); OPENSSL_free(vfy); } @@ -538,19 +537,30 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) return 0; } -void X509_STORE_set_flags(X509_STORE *ctx, long flags) +int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags) { - ctx->flags |= flags; + return X509_VERIFY_PARAM_set_flags(ctx->param, flags); + } + +int X509_STORE_set_depth(X509_STORE *ctx, int depth) + { + X509_VERIFY_PARAM_set_depth(ctx->param, depth); + return 1; } int X509_STORE_set_purpose(X509_STORE *ctx, int purpose) { - return X509_PURPOSE_set(&ctx->purpose, purpose); + return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose); } int X509_STORE_set_trust(X509_STORE *ctx, int trust) { - return X509_TRUST_set(&ctx->trust, trust); + return X509_VERIFY_PARAM_set_trust(ctx->param, trust); + } + +int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param) + { + return X509_VERIFY_PARAM_set1(ctx->param, param); } IMPLEMENT_STACK_OF(X509_LOOKUP) diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c index e31ebc6741..ddc3b9b355 100644 --- a/crypto/x509/x509_txt.c +++ b/crypto/x509/x509_txt.c @@ -153,6 +153,15 @@ const char *X509_verify_cert_error_string(long n) case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: return("unhandled critical CRL extension"); + case X509_V_ERR_INVALID_EXTENSION: + return("invalid or inconsistent certificate extension"); + + case X509_V_ERR_INVALID_POLICY_EXTENSION: + return("invalid or inconsistent certificate policy extension"); + + case X509_V_ERR_NO_EXPLICIT_POLICY: + return("no explicit policy"); + default: BIO_snprintf(buf,sizeof buf,"error number %ld",n); return(buf); diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index 3e82f95486..4d9b53e997 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -77,6 +77,7 @@ static int check_chain_purpose(X509_STORE_CTX *ctx); static int check_trust(X509_STORE_CTX *ctx); static int check_revocation(X509_STORE_CTX *ctx); static int check_cert(X509_STORE_CTX *ctx); +static int check_policy(X509_STORE_CTX *ctx); static int internal_verify(X509_STORE_CTX *ctx); const char *X509_version="X.509" OPENSSL_VERSION_PTEXT; @@ -97,11 +98,12 @@ int X509_verify_cert(X509_STORE_CTX *ctx) { X509 *x,*xtmp,*chain_ss=NULL; X509_NAME *xn; + int bad_chain = 0; + X509_VERIFY_PARAM *param = ctx->param; int depth,i,ok=0; int num; int (*cb)(); STACK_OF(X509) *sktmp=NULL; - if (ctx->cert == NULL) { X509err(X509_F_X509_VERIFY_CERT,X509_R_NO_CERT_SET_FOR_US_TO_VERIFY); @@ -134,7 +136,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx) num=sk_X509_num(ctx->chain); x=sk_X509_value(ctx->chain,num-1); - depth=ctx->depth; + depth=param->depth; for (;;) @@ -201,6 +203,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx) ctx->current_cert=x; ctx->error_depth=i-1; if (ok == 1) X509_free(xtmp); + bad_chain = 1; ok=cb(0,ctx); if (!ok) goto end; } @@ -276,18 +279,19 @@ int X509_verify_cert(X509_STORE_CTX *ctx) } ctx->error_depth=num-1; + bad_chain = 1; ok=cb(0,ctx); if (!ok) goto end; } /* We have the chain complete: now we need to check its purpose */ - if (ctx->purpose > 0) ok = check_chain_purpose(ctx); + if (param->purpose > 0) ok = check_chain_purpose(ctx); if (!ok) goto end; /* The chain extensions are OK: check trust */ - if (ctx->trust > 0) ok = check_trust(ctx); + if (param->trust > 0) ok = check_trust(ctx); if (!ok) goto end; @@ -301,11 +305,17 @@ int X509_verify_cert(X509_STORE_CTX *ctx) ok = ctx->check_revocation(ctx); if(!ok) goto end; - /* At this point, we have a chain and just need to verify it */ + /* At this point, we have a chain and need to verify it */ if (ctx->verify != NULL) ok=ctx->verify(ctx); else ok=internal_verify(ctx); + if(!ok) goto end; + + /* If we get this far evaluate policies */ + if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK)) + ok = ctx->check_policy(ctx); + if(!ok) goto end; if (0) { end: @@ -342,7 +352,7 @@ static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer) if (ret == X509_V_OK) return 1; /* If we haven't asked for issuer errors don't set ctx */ - if (!(ctx->flags & X509_V_FLAG_CB_ISSUER_CHECK)) + if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK)) return 0; ctx->error = ret; @@ -385,7 +395,7 @@ static int check_chain_purpose(X509_STORE_CTX *ctx) { int ret; x = sk_X509_value(ctx->chain, i); - if (!(ctx->flags & X509_V_FLAG_IGNORE_CRITICAL) + if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) && (x->ex_flags & EXFLAG_CRITICAL)) { ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION; @@ -394,9 +404,9 @@ static int check_chain_purpose(X509_STORE_CTX *ctx) ok=cb(0,ctx); if (!ok) goto end; } - ret = X509_check_purpose(x, ctx->purpose, i); + ret = X509_check_purpose(x, ctx->param->purpose, i); if ((ret == 0) - || ((ctx->flags & X509_V_FLAG_X509_STRICT) + || ((ctx->param->flags & X509_V_FLAG_X509_STRICT) && (ret != 1))) { if (i) @@ -437,7 +447,7 @@ static int check_trust(X509_STORE_CTX *ctx) /* For now just check the last certificate in the chain */ i = sk_X509_num(ctx->chain) - 1; x = sk_X509_value(ctx->chain, i); - ok = X509_check_trust(x, ctx->trust, 0); + ok = X509_check_trust(x, ctx->param->trust, 0); if (ok == X509_TRUST_TRUSTED) return 1; ctx->error_depth = i; @@ -454,9 +464,9 @@ static int check_trust(X509_STORE_CTX *ctx) static int check_revocation(X509_STORE_CTX *ctx) { int i, last, ok; - if (!(ctx->flags & X509_V_FLAG_CRL_CHECK)) + if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK)) return 1; - if (ctx->flags & X509_V_FLAG_CRL_CHECK_ALL) + if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) last = sk_X509_num(ctx->chain) - 1; else last = 0; @@ -506,8 +516,8 @@ static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) time_t *ptime; int i; ctx->current_crl = crl; - if (ctx->flags & X509_V_FLAG_USE_CHECK_TIME) - ptime = &ctx->check_time; + if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) + ptime = &ctx->param->check_time; else ptime = NULL; @@ -707,7 +717,7 @@ static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) if (!ok) return 0; } - if (ctx->flags & X509_V_FLAG_IGNORE_CRITICAL) + if (ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) return 1; /* See if we have any critical CRL extensions: since we @@ -734,13 +744,60 @@ static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) return 1; } +static int check_policy(X509_STORE_CTX *ctx) + { + int ret; + ret = X509_policy_check(&ctx->tree, &ctx->explicit, ctx->chain, + ctx->param->policies, ctx->param->flags); + if (ret == 0) + { + X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE); + return 0; + } + /* Invalid or inconsistent extensions */ + if (ret == -1) + { + /* Locate certificates with bad extensions and notify + * callback. + */ + X509 *x; + int i; + for (i = 1; i < sk_X509_num(ctx->chain); i++) + { + x = sk_X509_value(ctx->chain, i); + if (!(x->ex_flags & EXFLAG_INVALID_POLICY)) + continue; + ctx->current_cert = x; + ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION; + ret = ctx->verify_cb(0, ctx); + } + return 1; + } + if (ret == -2) + { + ctx->current_cert = NULL; + ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY; + return ctx->verify_cb(0, ctx); + } + + if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) + { + ctx->current_cert = NULL; + ctx->error = X509_V_OK; + if (!ctx->verify_cb(2, ctx)) + return 0; + } + + return 1; + } + static int check_cert_time(X509_STORE_CTX *ctx, X509 *x) { time_t *ptime; int i; - if (ctx->flags & X509_V_FLAG_USE_CHECK_TIME) - ptime = &ctx->check_time; + if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) + ptime = &ctx->param->check_time; else ptime = NULL; @@ -1151,8 +1208,8 @@ int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, } } - if (purpose && !ctx->purpose) ctx->purpose = purpose; - if (trust && !ctx->trust) ctx->trust = trust; + if (purpose && !ctx->param->purpose) ctx->param->purpose = purpose; + if (trust && !ctx->param->trust) ctx->param->trust = trust; return 1; } @@ -1178,20 +1235,30 @@ void X509_STORE_CTX_free(X509_STORE_CTX *ctx) int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, STACK_OF(X509) *chain) { + int ret = 1; ctx->ctx=store; ctx->current_method=0; ctx->cert=x509; ctx->untrusted=chain; + ctx->crls = NULL; ctx->last_untrusted=0; - ctx->check_time=0; ctx->other_ctx=NULL; ctx->valid=0; ctx->chain=NULL; - ctx->depth=9; ctx->error=0; + ctx->explicit=0; ctx->error_depth=0; ctx->current_cert=NULL; ctx->current_issuer=NULL; + ctx->tree = NULL; + + ctx->param = X509_VERIFY_PARAM_new(); + + if (!ctx->param) + { + X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE); + return 0; + } /* Inherit callbacks and flags from X509_STORE if not set * use defaults. @@ -1199,18 +1266,26 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, if (store) + ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param); + else + ctx->param->flags |= X509_VP_FLAG_DEFAULT|X509_VP_FLAG_ONCE; + + if (store) { - ctx->purpose=store->purpose; - ctx->trust=store->trust; - ctx->flags = store->flags; + ctx->verify_cb = store->verify_cb; ctx->cleanup = store->cleanup; } else - { - ctx->purpose = 0; - ctx->trust = 0; - ctx->flags = 0; ctx->cleanup = 0; + + if (ret) + ret = X509_VERIFY_PARAM_inherit(ctx->param, + X509_VERIFY_PARAM_lookup("default")); + + if (ret == 0) + { + X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE); + return 0; } if (store && store->check_issued) @@ -1253,6 +1328,8 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, else ctx->cert_crl = cert_crl; + ctx->check_policy = check_policy; + /* This memset() can't make any sense anyway, so it's removed. As * X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we put a @@ -1281,6 +1358,9 @@ void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) { if (ctx->cleanup) ctx->cleanup(ctx); + X509_VERIFY_PARAM_free(ctx->param); + if (ctx->tree) + X509_policy_tree_free(ctx->tree); if (ctx->chain != NULL) { sk_X509_pop_free(ctx->chain,X509_free); @@ -1290,15 +1370,19 @@ void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA)); } -void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, long flags) +void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth) { - ctx->flags |= flags; + X509_VERIFY_PARAM_set_depth(ctx->param, depth); } -void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, long flags, time_t t) +void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags) { - ctx->check_time = t; - ctx->flags |= X509_V_FLAG_USE_CHECK_TIME; + X509_VERIFY_PARAM_set_flags(ctx->param, flags); + } + +void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, time_t t) + { + X509_VERIFY_PARAM_set_time(ctx->param, t); } void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, @@ -1307,6 +1391,37 @@ void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, ctx->verify_cb=verify_cb; } +X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx) + { + return ctx->tree; + } + +int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx) + { + return ctx->explicit; + } + +int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name) + { + const X509_VERIFY_PARAM *param; + param = X509_VERIFY_PARAM_lookup(name); + if (!param) + return 0; + return X509_VERIFY_PARAM_inherit(ctx->param, param); + } + +X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx) + { + return ctx->param; + } + +void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param) + { + if (ctx->param) + X509_VERIFY_PARAM_free(ctx->param); + ctx->param = param; + } + IMPLEMENT_STACK_OF(X509) IMPLEMENT_ASN1_SET_OF(X509) diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h index 5a5741df08..d8d34879af 100644 --- a/crypto/x509/x509_vfy.h +++ b/crypto/x509/x509_vfy.h @@ -156,6 +156,25 @@ typedef struct x509_lookup_method_st X509_OBJECT *ret); } X509_LOOKUP_METHOD; +/* This structure hold all parameters associated with a verify operation + * by including an X509_VERIFY_PARAM structure in related structures the + * parameters used can be customized + */ + +typedef struct X509_VERIFY_PARAM_st + { + char *name; + time_t check_time; /* Time to use */ + unsigned long inh_flags; /* Inheritance flags */ + unsigned long flags; /* Various verify flags */ + int purpose; /* purpose to check untrusted certificates */ + int trust; /* trust setting to check */ + int depth; /* Verify depth */ + STACK_OF(ASN1_OBJECT) *policies; /* Permissible policies */ + } X509_VERIFY_PARAM; + +DECLARE_STACK_OF(X509_VERIFY_PARAM) + /* This is used to hold everything. It is used for all certificate * validation. Once we have a certificate chain, the 'verify' * function is then called to actually check the cert chain. */ @@ -168,13 +187,8 @@ struct x509_store_st /* These are external lookup methods */ STACK_OF(X509_LOOKUP) *get_cert_methods; - /* The following fields are not used by X509_STORE but are - * inherited by X509_STORE_CTX when it is initialised. - */ + X509_VERIFY_PARAM *param; - unsigned long flags; /* Various verify flags */ - int purpose; - int trust; /* Callbacks for various operations */ int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */ int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */ @@ -188,10 +202,9 @@ struct x509_store_st CRYPTO_EX_DATA ex_data; int references; - int depth; /* how deep to look (still unused -- X509_STORE_CTX's depth is used) */ } /* X509_STORE */; -#define X509_STORE_set_depth(ctx,d) ((ctx)->depth=(d)) +int X509_STORE_set_depth(X509_STORE *store, int depth); #define X509_STORE_set_verify_cb_func(ctx,func) ((ctx)->verify_cb=(func)) #define X509_STORE_set_verify_func(ctx,func) ((ctx)->verify=(func)) @@ -218,11 +231,9 @@ struct x509_store_ctx_st /* X509_STORE_CTX */ /* The following are set by the caller */ X509 *cert; /* The cert to check */ STACK_OF(X509) *untrusted; /* chain of X509s - untrusted - passed in */ - STACK_OF(X509_CRL) *crls; /* CRLs */ - int purpose; /* purpose to check untrusted certificates */ - int trust; /* trust setting to check */ - time_t check_time; /* time to make verify at */ - unsigned long flags; /* Various verify flags */ + STACK_OF(X509_CRL) *crls; /* set of CRLs passed in */ + + X509_VERIFY_PARAM *param; void *other_ctx; /* Other info for use with get_issuer() */ /* Callbacks for various operations */ @@ -234,13 +245,16 @@ struct x509_store_ctx_st /* X509_STORE_CTX */ int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */ int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */ int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */ + int (*check_policy)(X509_STORE_CTX *ctx); int (*cleanup)(X509_STORE_CTX *ctx); /* The following is built up */ - int depth; /* how far to go looking up certs */ int valid; /* if 0, rebuild chain */ int last_untrusted; /* index of last untrusted cert */ STACK_OF(X509) *chain; /* chain of X509s - built up and trusted */ + X509_POLICY_TREE *tree; /* Valid policy tree */ + + int explicit; /* Require explicit policy value */ /* When something goes wrong, this is why */ int error_depth; @@ -252,7 +266,7 @@ struct x509_store_ctx_st /* X509_STORE_CTX */ CRYPTO_EX_DATA ex_data; } /* X509_STORE_CTX */; -#define X509_STORE_CTX_set_depth(ctx,d) ((ctx)->depth=(d)) +void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); #define X509_STORE_CTX_set_app_data(ctx,data) \ X509_STORE_CTX_set_ex_data(ctx,0,data) @@ -309,6 +323,11 @@ struct x509_store_ctx_st /* X509_STORE_CTX */ |