@@ -187,11 +187,11 @@ static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x)
187
187
188
188
int X509_verify_cert (X509_STORE_CTX * ctx )
189
189
{
190
- X509 * x , * xtmp , * chain_ss = NULL ;
190
+ X509 * x , * xtmp , * xtmp2 , * chain_ss = NULL ;
191
191
int bad_chain = 0 ;
192
192
X509_VERIFY_PARAM * param = ctx -> param ;
193
193
int depth , i , ok = 0 ;
194
- int num ;
194
+ int num , j , retry ;
195
195
int (* cb ) (int xok , X509_STORE_CTX * xctx );
196
196
STACK_OF (X509 ) * sktmp = NULL ;
197
197
if (ctx -> cert == NULL ) {
@@ -276,91 +276,128 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
276
276
break ;
277
277
}
278
278
279
+ /* Remember how many untrusted certs we have */
280
+ j = num ;
279
281
/*
280
282
* at this point, chain should contain a list of untrusted certificates.
281
283
* We now need to add at least one trusted one, if possible, otherwise we
282
284
* complain.
283
285
*/
284
286
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
+ }
310
322
} else {
311
323
/*
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
314
325
*/
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 );
319
331
}
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 );
328
332
}
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 );
336
342
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
+ }
340
355
341
- ok = ctx -> get_issuer (& xtmp , ctx , x );
356
+ /* we now have our chain, lets check it... */
357
+ i = check_trust (ctx );
342
358
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 and the user hasn't switched off alternate
366
+ * chain checking
367
+ */
368
+ retry = 0 ;
369
+ if (i != X509_TRUST_TRUSTED
370
+ && !(ctx -> param -> flags & X509_V_FLAG_TRUSTED_FIRST )
371
+ && !(ctx -> param -> flags & X509_V_FLAG_NO_ALT_CHAINS )) {
372
+ while (j -- > 1 ) {
373
+ xtmp2 = sk_X509_value (ctx -> chain , j - 1 );
374
+ ok = ctx -> get_issuer (& xtmp , ctx , xtmp2 );
375
+ if (ok < 0 )
376
+ goto end ;
377
+ /* Check if we found an alternate chain */
378
+ if (ok > 0 ) {
379
+ /*
380
+ * Free up the found cert we'll add it again later
381
+ */
382
+ X509_free (xtmp );
347
383
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 ;
384
+ /*
385
+ * Dump all the certs above this point - we've found an
386
+ * alternate chain
387
+ */
388
+ while (num > j ) {
389
+ xtmp = sk_X509_pop (ctx -> chain );
390
+ X509_free (xtmp );
391
+ num -- ;
392
+ ctx -> last_untrusted -- ;
393
+ }
394
+ retry = 1 ;
395
+ break ;
396
+ }
397
+ }
353
398
}
354
- num ++ ;
355
- }
399
+ } while (retry );
356
400
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 ;
364
401
/*
365
402
* If not explicitly trusted then indicate error unless it's a single
366
403
* self signed certificate in which case we've indicated an error already
0 commit comments