Don't use expired certificates if possible.
authorDr. Stephen Henson <steve@openssl.org>
Sat, 24 May 2014 22:55:19 +0000 (23:55 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 25 May 2014 03:50:15 +0000 (04:50 +0100)
When looking for the issuer of a certificate, if current candidate is
expired, continue looking. Only return an expired certificate if no valid
certificates are found.

PR#3359

crypto/x509/x509_lcl.h
crypto/x509/x509_lu.c
crypto/x509/x509_vfy.c

index 55c791550ba9b626d42ee2391f9470cc106a9192..f994cb9c27ff971f9b63afa127817f99df60d59c 100644 (file)
@@ -68,3 +68,5 @@ struct X509_VERIFY_PARAM_ID_st
        unsigned char *ip;      /* If not NULL IP address to match */
        size_t iplen;           /* Length of IP address */
        };
+
+int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet);
index cce90848a260a6f1c3d38421d92ea94ccdbee6bd..79281c6bdb16feac014880f142cddf67384285e8 100644 (file)
@@ -61,6 +61,7 @@
 #include <openssl/lhash.h>
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
+#include "x509_lcl.h"
 
 X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
        {
@@ -639,6 +640,7 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
        X509_NAME *xn;
        X509_OBJECT obj, *pobj;
        int i, ok, idx, ret;
+       *issuer = NULL;
        xn=X509_get_issuer_name(x);
        ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj);
        if (ok != X509_LU_X509)
@@ -660,8 +662,11 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
        /* If certificate matches all OK */
        if (ctx->check_issued(ctx, x, obj.data.x509))
                {
-               *issuer = obj.data.x509;
-               return 1;
+               if (x509_check_cert_time(ctx, obj.data.x509, 1))
+                       {
+                       *issuer = obj.data.x509;
+                       return 1;
+                       }
                }
        X509_OBJECT_free_contents(&obj);
 
@@ -683,13 +688,22 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
                        if (ctx->check_issued(ctx, x, pobj->data.x509))
                                {
                                *issuer = pobj->data.x509;
-                               X509_OBJECT_up_ref_count(pobj);
                                ret = 1;
-                               break;
+                               /*
+                                * If times check, exit with match,
+                                * otherwise keep looking. Leave last
+                                * match in issuer so we return nearest
+                                * match if no certificate time is OK.
+                                */
+
+                               if (x509_check_cert_time(ctx, *issuer, 1))
+                                       break;
                                }
                        }
                }
        CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+       if (*issuer)
+               CRYPTO_add(&(*issuer)->references,1,CRYPTO_LOCK_X509);
        return ret;
        }
 
index 563737ecec57e5ec4dbdf4becebe45ab4e8cc379..30fc974a2091f58e67820972b4cd1f6b5896dc7a 100644 (file)
@@ -469,14 +469,18 @@ end:
 static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x)
 {
        int i;
-       X509 *issuer;
+       X509 *issuer, *rv = NULL;;
        for (i = 0; i < sk_X509_num(sk); i++)
                {
                issuer = sk_X509_value(sk, i);
                if (ctx->check_issued(ctx, x, issuer))
-                       return issuer;
+                       {
+                       rv = issuer;
+                       if (x509_check_cert_time(ctx, rv, 1))
+                               break;
+                       }
                }
-       return NULL;
+       return rv;
 }
 
 /* Given a possible certificate and issuer check them */
@@ -1694,7 +1698,7 @@ static int check_policy(X509_STORE_CTX *ctx)
        return 1;
        }
 
-static int check_cert_time(X509_STORE_CTX *ctx, X509 *x)
+int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet)
        {
        time_t *ptime;
        int i;
@@ -1707,6 +1711,8 @@ static int check_cert_time(X509_STORE_CTX *ctx, X509 *x)
        i=X509_cmp_time(X509_get_notBefore(x), ptime);
        if (i == 0)
                {
+               if (quiet)
+                       return 0;
                ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
                ctx->current_cert=x;
                if (!ctx->verify_cb(0, ctx))
@@ -1715,6 +1721,8 @@ static int check_cert_time(X509_STORE_CTX *ctx, X509 *x)
 
        if (i > 0)
                {
+               if (quiet)
+                       return 0;
                ctx->error=X509_V_ERR_CERT_NOT_YET_VALID;
                ctx->current_cert=x;
                if (!ctx->verify_cb(0, ctx))
@@ -1724,6 +1732,8 @@ static int check_cert_time(X509_STORE_CTX *ctx, X509 *x)
        i=X509_cmp_time(X509_get_notAfter(x), ptime);
        if (i == 0)
                {
+               if (quiet)
+                       return 0;
                ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
                ctx->current_cert=x;
                if (!ctx->verify_cb(0, ctx))
@@ -1732,6 +1742,8 @@ static int check_cert_time(X509_STORE_CTX *ctx, X509 *x)
 
        if (i < 0)
                {
+               if (quiet)
+                       return 0;
                ctx->error=X509_V_ERR_CERT_HAS_EXPIRED;
                ctx->current_cert=x;
                if (!ctx->verify_cb(0, ctx))
@@ -1815,7 +1827,7 @@ static int internal_verify(X509_STORE_CTX *ctx)
                xs->valid = 1;
 
                check_cert:
-               ok = check_cert_time(ctx, xs);
+               ok = x509_check_cert_time(ctx, xs, 0);
                if (!ok)
                        goto end;