X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fx509%2Fx509_vfy.c;h=fadf712e4b9a4ea9b24c1044c7545ed06b38901c;hp=87ebf62525cad5e2579d6708a47859a2945b7e45;hb=da7b0b2261d0365b3bc7110adf2a8773cf513cf4;hpb=446a6a8af7774900ee1f0333a047da9d66f8e742 diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index 87ebf62525..fadf712e4b 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -149,11 +149,19 @@ static int x509_subject_cmp(X509 **a, X509 **b) return X509_subject_name_cmp(*a,*b); } #endif +/* Return 1 is a certificate is self signed */ +static int cert_self_signed(X509 *x) + { + X509_check_purpose(x, -1, 0); + if (x->ex_flags & EXFLAG_SS) + return 1; + else + return 0; + } 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; @@ -205,8 +213,23 @@ int X509_verify_cert(X509_STORE_CTX *ctx) */ /* If we are self signed, we break */ - xn=X509_get_issuer_name(x); - if (ctx->check_issued(ctx, x,x)) break; + if (cert_self_signed(x)) + break; + /* If asked see if we can find issuer in trusted store first */ + if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) + { + ok = ctx->get_issuer(&xtmp, ctx, x); + if (ok < 0) + return ok; + /* If successful for now free up cert so it + * will be picked up again later. + */ + if (ok > 0) + { + X509_free(xtmp); + break; + } + } /* If we were passed a cert chain, use it first */ if (ctx->untrusted != NULL) @@ -242,8 +265,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx) i=sk_X509_num(ctx->chain); x=sk_X509_value(ctx->chain,i-1); - xn = X509_get_subject_name(x); - if (ctx->check_issued(ctx, x, x)) + if (cert_self_signed(x)) { /* we have a self signed certificate */ if (sk_X509_num(ctx->chain) == 1) @@ -291,8 +313,8 @@ int X509_verify_cert(X509_STORE_CTX *ctx) if (depth < num) break; /* If we are self signed, we break */ - xn=X509_get_issuer_name(x); - if (ctx->check_issued(ctx,x,x)) break; + if (cert_self_signed(x)) + break; ok = ctx->get_issuer(&xtmp, ctx, x); @@ -310,10 +332,14 @@ int X509_verify_cert(X509_STORE_CTX *ctx) } /* we now have our chain, lets check it... */ - xn=X509_get_issuer_name(x); - /* Is last certificate looked up self signed? */ - if (!ctx->check_issued(ctx,x,x)) + i = check_trust(ctx); + + /* If explicitly rejected error */ + if (i == X509_TRUST_REJECTED) + goto end; + /* If not explicitly trusted then indicate error */ + if (i != X509_TRUST_TRUSTED) { if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) { @@ -351,12 +377,6 @@ int X509_verify_cert(X509_STORE_CTX *ctx) if (!ok) goto end; - /* The chain extensions are OK: check trust */ - - if (param->trust > 0) ok = check_trust(ctx); - - if (!ok) goto end; - /* We may as well copy down any DSA parameters that are required */ X509_get_pubkey_parameters(NULL,ctx->chain); @@ -647,28 +667,35 @@ static int check_name_constraints(X509_STORE_CTX *ctx) static int check_trust(X509_STORE_CTX *ctx) { -#ifdef OPENSSL_NO_CHAIN_VERIFY - return 1; -#else int i, ok; - X509 *x; + X509 *x = NULL; int (*cb)(int xok,X509_STORE_CTX *xctx); cb=ctx->verify_cb; -/* 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->param->trust, 0); - if (ok == X509_TRUST_TRUSTED) - return 1; - ctx->error_depth = i; - ctx->current_cert = x; - if (ok == X509_TRUST_REJECTED) - ctx->error = X509_V_ERR_CERT_REJECTED; - else - ctx->error = X509_V_ERR_CERT_UNTRUSTED; - ok = cb(0, ctx); - return ok; -#endif + /* Check all trusted certificates in chain */ + for (i = ctx->last_untrusted; i < sk_X509_num(ctx->chain); i++) + { + x = sk_X509_value(ctx->chain, i); + ok = X509_check_trust(x, ctx->param->trust, 0); + /* If explicitly trusted return trusted */ + if (ok == X509_TRUST_TRUSTED) + return X509_TRUST_TRUSTED; + /* If explicitly rejected notify callback and reject if + * not overridden. + */ + if (ok == X509_TRUST_REJECTED) + { + ctx->error_depth = i; + ctx->current_cert = x; + ctx->error = X509_V_ERR_CERT_REJECTED; + ok = cb(0, ctx); + if (!ok) + return X509_TRUST_REJECTED; + } + } + /* If no trusted certs in chain at all return untrusted and + * allow standard (no issuer cert) etc errors to be indicated. + */ + return X509_TRUST_UNTRUSTED; } static int check_revocation(X509_STORE_CTX *ctx) @@ -2034,7 +2061,7 @@ 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; + ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT|X509_VP_FLAG_ONCE; if (store) {