@@ -151,11 +151,11 @@ static int x509_subject_cmp(X509 **a, X509 **b)
151151
152152int X509_verify_cert (X509_STORE_CTX * ctx )
153153{
154- X509 * x , * xtmp , * chain_ss = NULL ;
154+ X509 * x , * xtmp , * xtmp2 , * chain_ss = NULL ;
155155 int bad_chain = 0 ;
156156 X509_VERIFY_PARAM * param = ctx -> param ;
157157 int depth , i , ok = 0 ;
158- int num ;
158+ int num , j , retry ;
159159 int (* cb ) (int xok , X509_STORE_CTX * xctx );
160160 STACK_OF (X509 ) * sktmp = NULL ;
161161 if (ctx -> cert == NULL ) {
@@ -224,85 +224,116 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
224224 break ;
225225 }
226226
227+ /* Remember how many untrusted certs we have */
228+ j = num ;
227229 /*
228230 * at this point, chain should contain a list of untrusted certificates.
229231 * We now need to add at least one trusted one, if possible, otherwise we
230232 * complain.
231233 */
232234
233- /*
234- * Examine last certificate in chain and see if it is self signed.
235- */
236-
237- i = sk_X509_num (ctx -> chain );
238- x = sk_X509_value (ctx -> chain , i - 1 );
239- if (ctx -> check_issued (ctx , x , x )) {
240- /* we have a self signed certificate */
241- if (sk_X509_num (ctx -> chain ) == 1 ) {
242- /*
243- * We have a single self signed certificate: see if we can find
244- * it in the store. We must have an exact match to avoid possible
245- * impersonation.
246- */
247- ok = ctx -> get_issuer (& xtmp , ctx , x );
248- if ((ok <= 0 ) || X509_cmp (x , xtmp )) {
249- ctx -> error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ;
250- ctx -> current_cert = x ;
251- ctx -> error_depth = i - 1 ;
252- if (ok == 1 )
253- X509_free (xtmp );
254- bad_chain = 1 ;
255- ok = cb (0 , ctx );
256- if (!ok )
257- goto end ;
235+ do {
236+ /*
237+ * Examine last certificate in chain and see if it is self signed.
238+ */
239+ i = sk_X509_num (ctx -> chain );
240+ x = sk_X509_value (ctx -> chain , i - 1 );
241+ if (ctx -> check_issued (ctx , x , x )) {
242+ /* we have a self signed certificate */
243+ if (sk_X509_num (ctx -> chain ) == 1 ) {
244+ /*
245+ * We have a single self signed certificate: see if we can
246+ * find it in the store. We must have an exact match to avoid
247+ * possible impersonation.
248+ */
249+ ok = ctx -> get_issuer (& xtmp , ctx , x );
250+ if ((ok <= 0 ) || X509_cmp (x , xtmp )) {
251+ ctx -> error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ;
252+ ctx -> current_cert = x ;
253+ ctx -> error_depth = i - 1 ;
254+ if (ok == 1 )
255+ X509_free (xtmp );
256+ bad_chain = 1 ;
257+ ok = cb (0 , ctx );
258+ if (!ok )
259+ goto end ;
260+ } else {
261+ /*
262+ * We have a match: replace certificate with store
263+ * version so we get any trust settings.
264+ */
265+ X509_free (x );
266+ x = xtmp ;
267+ (void )sk_X509_set (ctx -> chain , i - 1 , x );
268+ ctx -> last_untrusted = 0 ;
269+ }
258270 } else {
259271 /*
260- * We have a match: replace certificate with store version so
261- * we get any trust settings.
272+ * extract and save self signed certificate for later use
262273 */
263- X509_free (x );
264- x = xtmp ;
265- (void )sk_X509_set (ctx -> chain , i - 1 , x );
266- ctx -> last_untrusted = 0 ;
274+ chain_ss = sk_X509_pop (ctx -> chain );
275+ ctx -> last_untrusted -- ;
276+ num -- ;
277+ j -- ;
278+ x = sk_X509_value (ctx -> chain , num - 1 );
267279 }
268- } else {
269- /*
270- * extract and save self signed certificate for later use
271- */
272- chain_ss = sk_X509_pop (ctx -> chain );
273- ctx -> last_untrusted -- ;
274- num -- ;
275- x = sk_X509_value (ctx -> chain , num - 1 );
276280 }
277- }
278-
279- /* We now lookup certs from the certificate store */
280- for (;;) {
281- /* If we have enough, we break */
282- if (depth < num )
283- break ;
284-
285- /* If we are self signed, we break */
286- if (ctx -> check_issued (ctx , x , x ))
287- break ;
288-
289- ok = ctx -> get_issuer (& xtmp , ctx , x );
281+ /* We now lookup certs from the certificate store */
282+ for (;;) {
283+ /* If we have enough, we break */
284+ if (depth < num )
285+ break ;
286+ /* If we are self signed, we break */
287+ if (ctx -> check_issued (ctx , x , x ))
288+ break ;
289+ ok = ctx -> get_issuer (& xtmp , ctx , x );
290+ if (ok < 0 )
291+ return ok ;
292+ if (ok == 0 )
293+ break ;
294+ x = xtmp ;
295+ if (!sk_X509_push (ctx -> chain , x )) {
296+ X509_free (xtmp );
297+ X509err (X509_F_X509_VERIFY_CERT , ERR_R_MALLOC_FAILURE );
298+ return 0 ;
299+ }
300+ num ++ ;
301+ }
290302
291- if (ok < 0 )
292- return ok ;
293- if (ok == 0 )
294- break ;
303+ /*
304+ * If we haven't got a least one certificate from our store then check
305+ * if there is an alternative chain that could be used.
306+ */
307+ retry = 0 ;
308+ if (j == ctx -> last_untrusted ) {
309+ while (j -- > 1 ) {
310+ xtmp2 = sk_X509_value (ctx -> chain , j - 1 );
311+ ok = ctx -> get_issuer (& xtmp , ctx , xtmp2 );
312+ if (ok < 0 )
313+ goto end ;
314+ /* Check if we found an alternate chain */
315+ if (ok > 0 ) {
316+ /*
317+ * Free up the found cert we'll add it again later
318+ */
319+ X509_free (xtmp );
295320
296- x = xtmp ;
297- if (!sk_X509_push (ctx -> chain , x )) {
298- X509_free (xtmp );
299- X509err (X509_F_X509_VERIFY_CERT , ERR_R_MALLOC_FAILURE );
300- return 0 ;
321+ /*
322+ * Dump all the certs above this point - we've found an
323+ * alternate chain
324+ */
325+ while (num > j ) {
326+ xtmp = sk_X509_pop (ctx -> chain );
327+ X509_free (xtmp );
328+ num -- ;
329+ ctx -> last_untrusted -- ;
330+ }
331+ retry = 1 ;
332+ break ;
333+ }
334+ }
301335 }
302- num ++ ;
303- }
304-
305- /* we now have our chain, lets check it... */
336+ } while (retry );
306337
307338 /* Is last certificate looked up self signed? */
308339 if (!ctx -> check_issued (ctx , x , x )) {
0 commit comments