diff --git a/deps/openssl/openssl/crypto/x509/x509_vfy.c b/deps/openssl/openssl/crypto/x509/x509_vfy.c index 1196a2ada94e0d..f3e9c56b091715 100644 --- a/deps/openssl/openssl/crypto/x509/x509_vfy.c +++ b/deps/openssl/openssl/crypto/x509/x509_vfy.c @@ -187,11 +187,11 @@ static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) int X509_verify_cert(X509_STORE_CTX *ctx) { - X509 *x, *xtmp, *chain_ss = NULL; + X509 *x, *xtmp, *xtmp2, *chain_ss = NULL; int bad_chain = 0; X509_VERIFY_PARAM *param = ctx->param; int depth, i, ok = 0; - int num; + int num, j, retry; int (*cb) (int xok, X509_STORE_CTX *xctx); STACK_OF(X509) *sktmp = NULL; if (ctx->cert == NULL) { @@ -276,91 +276,128 @@ int X509_verify_cert(X509_STORE_CTX *ctx) break; } + /* Remember how many untrusted certs we have */ + j = num; /* * at this point, chain should contain a list of untrusted certificates. * We now need to add at least one trusted one, if possible, otherwise we * complain. */ - /* - * Examine last certificate in chain and see if it is self signed. - */ - - i = sk_X509_num(ctx->chain); - x = sk_X509_value(ctx->chain, i - 1); - if (cert_self_signed(x)) { - /* we have a self signed certificate */ - if (sk_X509_num(ctx->chain) == 1) { - /* - * We have a single self signed certificate: see if we can find - * it in the store. We must have an exact match to avoid possible - * impersonation. - */ - ok = ctx->get_issuer(&xtmp, ctx, x); - if ((ok <= 0) || X509_cmp(x, xtmp)) { - ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; - 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; + do { + /* + * Examine last certificate in chain and see if it is self signed. + */ + i = sk_X509_num(ctx->chain); + x = sk_X509_value(ctx->chain, i - 1); + if (cert_self_signed(x)) { + /* we have a self signed certificate */ + if (sk_X509_num(ctx->chain) == 1) { + /* + * We have a single self signed certificate: see if we can + * find it in the store. We must have an exact match to avoid + * possible impersonation. + */ + ok = ctx->get_issuer(&xtmp, ctx, x); + if ((ok <= 0) || X509_cmp(x, xtmp)) { + ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; + 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; + } else { + /* + * We have a match: replace certificate with store + * version so we get any trust settings. + */ + X509_free(x); + x = xtmp; + (void)sk_X509_set(ctx->chain, i - 1, x); + ctx->last_untrusted = 0; + } } else { /* - * We have a match: replace certificate with store version so - * we get any trust settings. + * extract and save self signed certificate for later use */ - X509_free(x); - x = xtmp; - (void)sk_X509_set(ctx->chain, i - 1, x); - ctx->last_untrusted = 0; + chain_ss = sk_X509_pop(ctx->chain); + ctx->last_untrusted--; + num--; + j--; + x = sk_X509_value(ctx->chain, num - 1); } - } else { - /* - * extract and save self signed certificate for later use - */ - chain_ss = sk_X509_pop(ctx->chain); - ctx->last_untrusted--; - num--; - x = sk_X509_value(ctx->chain, num - 1); } - } - - /* We now lookup certs from the certificate store */ - for (;;) { - /* If we have enough, we break */ - if (depth < num) - break; + /* We now lookup certs from the certificate store */ + for (;;) { + /* If we have enough, we break */ + if (depth < num) + break; + /* If we are self signed, we break */ + if (cert_self_signed(x)) + break; + ok = ctx->get_issuer(&xtmp, ctx, x); - /* If we are self signed, we break */ - if (cert_self_signed(x)) - break; + if (ok < 0) + return ok; + 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); + return 0; + } + num++; + } - ok = ctx->get_issuer(&xtmp, ctx, x); + /* we now have our chain, lets check it... */ + i = check_trust(ctx); - if (ok < 0) - return ok; - if (ok == 0) - break; + /* 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 + * checked via TRUSTED_FIRST and the user hasn't switched off alternate + * chain checking + */ + retry = 0; + if (i != 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; + /* Check if we found an alternate chain */ + if (ok > 0) { + /* + * Free up the found cert we'll add it again later + */ + X509_free(xtmp); - x = xtmp; - if (!sk_X509_push(ctx->chain, x)) { - X509_free(xtmp); - X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); - return 0; + /* + * Dump all the certs above this point - we've found an + * alternate chain + */ + while (num > j) { + xtmp = sk_X509_pop(ctx->chain); + X509_free(xtmp); + num--; + ctx->last_untrusted--; + } + retry = 1; + break; + } + } } - num++; - } + } while (retry); - /* we now have our chain, lets check it... */ - - i = check_trust(ctx); - - /* If explicitly rejected error */ - if (i == X509_TRUST_REJECTED) - goto end; /* * If not explicitly trusted then indicate error unless it's a single * self signed certificate in which case we've indicated an error already diff --git a/deps/openssl/openssl/crypto/x509/x509_vfy.h b/deps/openssl/openssl/crypto/x509/x509_vfy.h index a6f0df54c9be29..4b236c06143b69 100644 --- a/deps/openssl/openssl/crypto/x509/x509_vfy.h +++ b/deps/openssl/openssl/crypto/x509/x509_vfy.h @@ -432,6 +432,12 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); /* Allow partial chains if at least one certificate is in trusted store */ # define X509_V_FLAG_PARTIAL_CHAIN 0x80000 +/* + * If the initial chain is not trusted, do not attempt to build an alternative + * chain. Alternate chain checking was introduced in 1.1.0. Setting this flag + * will force the behaviour to match that of previous versions. + */ +# define X509_V_FLAG_NO_ALT_CHAINS 0x100000 # define X509_VP_FLAG_DEFAULT 0x1 # define X509_VP_FLAG_OVERWRITE 0x2