Skip to content

Commit 90368ee

Browse files
mattcaswellShigeki Ohtsu
authored andcommitted
deps: backport openssl patch of alt cert chains 1
This a backport of da084a5ec6cebd67ae27f2463ebe4a50bb840fa5 in https://github.com/openssl/openssl as In certain situations the server provided certificate chain may no longer be valid. However the issuer of the leaf, or some intermediate cert is in fact in the trust store. When building a trust chain if the first attempt fails, then try to see if alternate chains could be constructed that are trusted.
1 parent 7a53863 commit 90368ee

1 file changed

Lines changed: 105 additions & 70 deletions

File tree

deps/openssl/openssl/crypto/x509/x509_vfy.c

Lines changed: 105 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,11 @@ static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x)
187187

188188
int X509_verify_cert(X509_STORE_CTX *ctx)
189189
{
190-
X509 *x, *xtmp, *chain_ss = NULL;
190+
X509 *x, *xtmp, *xtmp2, *chain_ss = NULL;
191191
int bad_chain = 0;
192192
X509_VERIFY_PARAM *param = ctx->param;
193193
int depth, i, ok = 0;
194-
int num;
194+
int num, j, retry;
195195
int (*cb) (int xok, X509_STORE_CTX *xctx);
196196
STACK_OF(X509) *sktmp = NULL;
197197
if (ctx->cert == NULL) {
@@ -276,91 +276,126 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
276276
break;
277277
}
278278

279+
/* Remember how many untrusted certs we have */
280+
j = num;
279281
/*
280282
* at this point, chain should contain a list of untrusted certificates.
281283
* We now need to add at least one trusted one, if possible, otherwise we
282284
* complain.
283285
*/
284286

285-
/*
286-
* Examine last certificate in chain and see if it is self signed.
287-
*/
288-
289-
i = sk_X509_num(ctx->chain);
290-
x = sk_X509_value(ctx->chain, i - 1);
291-
if (cert_self_signed(x)) {
292-
/* we have a self signed certificate */
293-
if (sk_X509_num(ctx->chain) == 1) {
294-
/*
295-
* We have a single self signed certificate: see if we can find
296-
* it in the store. We must have an exact match to avoid possible
297-
* impersonation.
298-
*/
299-
ok = ctx->get_issuer(&xtmp, ctx, x);
300-
if ((ok <= 0) || X509_cmp(x, xtmp)) {
301-
ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
302-
ctx->current_cert = x;
303-
ctx->error_depth = i - 1;
304-
if (ok == 1)
305-
X509_free(xtmp);
306-
bad_chain = 1;
307-
ok = cb(0, ctx);
308-
if (!ok)
309-
goto end;
287+
do {
288+
/*
289+
* Examine last certificate in chain and see if it is self signed.
290+
*/
291+
i = sk_X509_num(ctx->chain);
292+
x = sk_X509_value(ctx->chain, i - 1);
293+
if (cert_self_signed(x)) {
294+
/* we have a self signed certificate */
295+
if (sk_X509_num(ctx->chain) == 1) {
296+
/*
297+
* We have a single self signed certificate: see if we can
298+
* find it in the store. We must have an exact match to avoid
299+
* possible impersonation.
300+
*/
301+
ok = ctx->get_issuer(&xtmp, ctx, x);
302+
if ((ok <= 0) || X509_cmp(x, xtmp)) {
303+
ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
304+
ctx->current_cert = x;
305+
ctx->error_depth = i - 1;
306+
if (ok == 1)
307+
X509_free(xtmp);
308+
bad_chain = 1;
309+
ok = cb(0, ctx);
310+
if (!ok)
311+
goto end;
312+
} else {
313+
/*
314+
* We have a match: replace certificate with store
315+
* version so we get any trust settings.
316+
*/
317+
X509_free(x);
318+
x = xtmp;
319+
(void)sk_X509_set(ctx->chain, i - 1, x);
320+
ctx->last_untrusted = 0;
321+
}
310322
} else {
311323
/*
312-
* We have a match: replace certificate with store version so
313-
* we get any trust settings.
324+
* extract and save self signed certificate for later use
314325
*/
315-
X509_free(x);
316-
x = xtmp;
317-
(void)sk_X509_set(ctx->chain, i - 1, x);
318-
ctx->last_untrusted = 0;
326+
chain_ss = sk_X509_pop(ctx->chain);
327+
ctx->last_untrusted--;
328+
num--;
329+
j--;
330+
x = sk_X509_value(ctx->chain, num - 1);
319331
}
320-
} else {
321-
/*
322-
* extract and save self signed certificate for later use
323-
*/
324-
chain_ss = sk_X509_pop(ctx->chain);
325-
ctx->last_untrusted--;
326-
num--;
327-
x = sk_X509_value(ctx->chain, num - 1);
328332
}
329-
}
330-
331-
/* We now lookup certs from the certificate store */
332-
for (;;) {
333-
/* If we have enough, we break */
334-
if (depth < num)
335-
break;
333+
/* We now lookup certs from the certificate store */
334+
for (;;) {
335+
/* If we have enough, we break */
336+
if (depth < num)
337+
break;
338+
/* If we are self signed, we break */
339+
if (cert_self_signed(x))
340+
break;
341+
ok = ctx->get_issuer(&xtmp, ctx, x);
336342

337-
/* If we are self signed, we break */
338-
if (cert_self_signed(x))
339-
break;
343+
if (ok < 0)
344+
return ok;
345+
if (ok == 0)
346+
break;
347+
x = xtmp;
348+
if (!sk_X509_push(ctx->chain, x)) {
349+
X509_free(xtmp);
350+
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
351+
return 0;
352+
}
353+
num++;
354+
}
340355

341-
ok = ctx->get_issuer(&xtmp, ctx, x);
356+
/* we now have our chain, lets check it... */
357+
i = check_trust(ctx);
342358

343-
if (ok < 0)
344-
return ok;
345-
if (ok == 0)
346-
break;
359+
/* If explicitly rejected error */
360+
if (i == X509_TRUST_REJECTED)
361+
goto end;
362+
/*
363+
* If it's not explicitly trusted then check if there is an alternative
364+
* chain that could be used. We only do this if we haven't already
365+
* checked via TRUSTED_FIRST
366+
*/
367+
retry = 0;
368+
if (i != X509_TRUST_TRUSTED
369+
&& !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST)) {
370+
while (j-- > 1) {
371+
xtmp2 = sk_X509_value(ctx->chain, j - 1);
372+
ok = ctx->get_issuer(&xtmp, ctx, xtmp2);
373+
if (ok < 0)
374+
goto end;
375+
/* Check if we found an alternate chain */
376+
if (ok > 0) {
377+
/*
378+
* Free up the found cert we'll add it again later
379+
*/
380+
X509_free(xtmp);
347381

348-
x = xtmp;
349-
if (!sk_X509_push(ctx->chain, x)) {
350-
X509_free(xtmp);
351-
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
352-
return 0;
382+
/*
383+
* Dump all the certs above this point - we've found an
384+
* alternate chain
385+
*/
386+
while (num > j) {
387+
xtmp = sk_X509_pop(ctx->chain);
388+
X509_free(xtmp);
389+
num--;
390+
ctx->last_untrusted--;
391+
}
392+
retry = 1;
393+
break;
394+
}
395+
}
353396
}
354-
num++;
355-
}
397+
} while (retry);
356398

357-
/* we now have our chain, lets check it... */
358-
359-
i = check_trust(ctx);
360-
361-
/* If explicitly rejected error */
362-
if (i == X509_TRUST_REJECTED)
363-
goto end;
364399
/*
365400
* If not explicitly trusted then indicate error unless it's a single
366401
* self signed certificate in which case we've indicated an error already

0 commit comments

Comments
 (0)