Fix missing ok=0 with locally blacklisted CAs
Also in X509_verify_cert() avoid using "i" not only as a loop counter, but also as a trust outcome and as an error ordinal. Finally, make sure that all "goto end" jumps return an error, with "end" renamed to "err" accordingly. [ The 1.1.0 version of X509_verify_cert() is major rewrite, which addresses these issues in a more systemic way. ] Reviewed-by: Rich Salz <rsalz@openssl.org>
This commit is contained in:
parent
093d20a8cb
commit
a3baa17105
@ -194,6 +194,9 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
||||
int num, j, retry;
|
||||
int (*cb) (int xok, X509_STORE_CTX *xctx);
|
||||
STACK_OF(X509) *sktmp = NULL;
|
||||
int trust = X509_TRUST_UNTRUSTED;
|
||||
int err;
|
||||
|
||||
if (ctx->cert == NULL) {
|
||||
X509err(X509_F_X509_VERIFY_CERT, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
|
||||
return -1;
|
||||
@ -216,7 +219,8 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
||||
if (((ctx->chain = sk_X509_new_null()) == NULL) ||
|
||||
(!sk_X509_push(ctx->chain, ctx->cert))) {
|
||||
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
|
||||
goto end;
|
||||
ok = -1;
|
||||
goto err;
|
||||
}
|
||||
CRYPTO_add(&ctx->cert->references, 1, CRYPTO_LOCK_X509);
|
||||
ctx->last_untrusted = 1;
|
||||
@ -225,7 +229,8 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
||||
if (ctx->untrusted != NULL
|
||||
&& (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) {
|
||||
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
|
||||
goto end;
|
||||
ok = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
num = sk_X509_num(ctx->chain);
|
||||
@ -249,7 +254,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
||||
if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) {
|
||||
ok = ctx->get_issuer(&xtmp, ctx, x);
|
||||
if (ok < 0)
|
||||
goto end;
|
||||
goto err;
|
||||
/*
|
||||
* If successful for now free up cert so it will be picked up
|
||||
* again later.
|
||||
@ -266,7 +271,8 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
||||
if (xtmp != NULL) {
|
||||
if (!sk_X509_push(ctx->chain, xtmp)) {
|
||||
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
|
||||
goto end;
|
||||
ok = -1;
|
||||
goto err;
|
||||
}
|
||||
CRYPTO_add(&xtmp->references, 1, CRYPTO_LOCK_X509);
|
||||
(void)sk_X509_delete_ptr(sktmp, xtmp);
|
||||
@ -314,7 +320,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
||||
bad_chain = 1;
|
||||
ok = cb(0, ctx);
|
||||
if (!ok)
|
||||
goto end;
|
||||
goto err;
|
||||
} else {
|
||||
/*
|
||||
* We have a match: replace certificate with store
|
||||
@ -347,25 +353,26 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
||||
ok = ctx->get_issuer(&xtmp, ctx, x);
|
||||
|
||||
if (ok < 0)
|
||||
goto end;
|
||||
goto err;
|
||||
if (ok == 0)
|
||||
break;
|
||||
x = xtmp;
|
||||
if (!sk_X509_push(ctx->chain, x)) {
|
||||
X509_free(xtmp);
|
||||
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
|
||||
ok = 0;
|
||||
goto end;
|
||||
ok = -1;
|
||||
goto err;
|
||||
}
|
||||
num++;
|
||||
}
|
||||
|
||||
/* we now have our chain, lets check it... */
|
||||
i = check_trust(ctx);
|
||||
if ((trust = check_trust(ctx)) == X509_TRUST_REJECTED) {
|
||||
/* Callback already issued */
|
||||
ok = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* If explicitly rejected error */
|
||||
if (i == X509_TRUST_REJECTED)
|
||||
goto end;
|
||||
/*
|
||||
* If it's not explicitly trusted then check if there is an alternative
|
||||
* chain that could be used. We only do this if we haven't already
|
||||
@ -373,14 +380,14 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
||||
* chain checking
|
||||
*/
|
||||
retry = 0;
|
||||
if (i != X509_TRUST_TRUSTED
|
||||
if (trust != X509_TRUST_TRUSTED
|
||||
&& !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST)
|
||||
&& !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) {
|
||||
while (j-- > 1) {
|
||||
xtmp2 = sk_X509_value(ctx->chain, j - 1);
|
||||
ok = ctx->get_issuer(&xtmp, ctx, xtmp2);
|
||||
if (ok < 0)
|
||||
goto end;
|
||||
goto err;
|
||||
/* Check if we found an alternate chain */
|
||||
if (ok > 0) {
|
||||
/*
|
||||
@ -410,7 +417,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
||||
* self signed certificate in which case we've indicated an error already
|
||||
* and set bad_chain == 1
|
||||
*/
|
||||
if (i != X509_TRUST_TRUSTED && !bad_chain) {
|
||||
if (trust != X509_TRUST_TRUSTED && !bad_chain) {
|
||||
if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) {
|
||||
if (ctx->last_untrusted >= num)
|
||||
ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
|
||||
@ -431,26 +438,26 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
||||
bad_chain = 1;
|
||||
ok = cb(0, ctx);
|
||||
if (!ok)
|
||||
goto end;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* We have the chain complete: now we need to check its purpose */
|
||||
ok = check_chain_extensions(ctx);
|
||||
|
||||
if (!ok)
|
||||
goto end;
|
||||
goto err;
|
||||
|
||||
/* Check name constraints */
|
||||
|
||||
ok = check_name_constraints(ctx);
|
||||
|
||||
if (!ok)
|
||||
goto end;
|
||||
goto err;
|
||||
|
||||
ok = check_id(ctx);
|
||||
|
||||
if (!ok)
|
||||
goto end;
|
||||
goto err;
|
||||
|
||||
/* We may as well copy down any DSA parameters that are required */
|
||||
X509_get_pubkey_parameters(NULL, ctx->chain);
|
||||
@ -462,16 +469,16 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
||||
|
||||
ok = ctx->check_revocation(ctx);
|
||||
if (!ok)
|
||||
goto end;
|
||||
goto err;
|
||||
|
||||
i = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain,
|
||||
ctx->param->flags);
|
||||
if (i != X509_V_OK) {
|
||||
ctx->error = i;
|
||||
err = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain,
|
||||
ctx->param->flags);
|
||||
if (err != X509_V_OK) {
|
||||
ctx->error = err;
|
||||
ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth);
|
||||
ok = cb(0, ctx);
|
||||
if (!ok)
|
||||
goto end;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* At this point, we have a chain and need to verify it */
|
||||
@ -480,25 +487,28 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
||||
else
|
||||
ok = internal_verify(ctx);
|
||||
if (!ok)
|
||||
goto end;
|
||||
goto err;
|
||||
|
||||
#ifndef OPENSSL_NO_RFC3779
|
||||
/* RFC 3779 path validation, now that CRL check has been done */
|
||||
ok = v3_asid_validate_path(ctx);
|
||||
if (!ok)
|
||||
goto end;
|
||||
goto err;
|
||||
ok = v3_addr_validate_path(ctx);
|
||||
if (!ok)
|
||||
goto end;
|
||||
goto err;
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
goto err;
|
||||
if (0) {
|
||||
end:
|
||||
err:
|
||||
/* Ensure we return an error */
|
||||
if (ok > 0)
|
||||
ok = 0;
|
||||
X509_get_pubkey_parameters(NULL, ctx->chain);
|
||||
}
|
||||
if (sktmp != NULL)
|
||||
|
Loading…
Reference in New Issue
Block a user