If not checking all certificates don't attempt to find a CRL
[oweals/openssl.git] / crypto / x509 / x509_vfy.c
index cb7936f2b3d89658bdffa55fc43c2dffa84183c7..f5f632a45dd45dd62dd2136f5add5cb76de05b03 100644 (file)
@@ -679,7 +679,12 @@ static int check_revocation(X509_STORE_CTX *ctx)
        if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
                last = sk_X509_num(ctx->chain) - 1;
        else
+               {
+               /* If checking CRL paths this isn't the EE certificate */
+               if (ctx->parent)
+                       return 1;
                last = 0;
+               }
        for(i = 0; i <= last; i++)
                {
                ctx->error_depth = i;
@@ -820,10 +825,11 @@ static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl,
                        STACK_OF(X509_CRL) *crls)
        {
        int i, crl_score, best_score = *pscore;
-       unsigned int reasons, best_reasons;
+       unsigned int reasons, best_reasons = 0;
        X509 *x = ctx->current_cert;
        X509_CRL *crl, *best_crl = NULL;
-       X509 *crl_issuer, *best_crl_issuer = NULL;
+       X509 *crl_issuer = NULL, *best_crl_issuer = NULL;
+
        for (i = 0; i < sk_X509_CRL_num(crls); i++)
                {
                crl = sk_X509_CRL_value(crls, i);
@@ -1123,7 +1129,7 @@ static int check_crl_path(X509_STORE_CTX *ctx, X509 *x)
        /* Verify CRL issuer */
        ret = X509_verify_cert(&crl_ctx);
 
-       if (!ret)
+       if (ret <= 0)
                goto err;
 
        /* Check chain is acceptable */
@@ -1386,7 +1392,7 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
 
                        if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH))
                                {
-                               if (!check_crl_path(ctx, ctx->current_issuer))
+                               if (check_crl_path(ctx, ctx->current_issuer) <= 0)
                                        {
                                        ctx->error = X509_V_ERR_CRL_PATH_VALIDATION_ERROR;
                                        ok = ctx->verify_cb(0, ctx);
@@ -1608,7 +1614,12 @@ static int internal_verify(X509_STORE_CTX *ctx)
        while (n >= 0)
                {
                ctx->error_depth=n;
-               if (!xs->valid)
+
+               /* Skip signature check for self signed certificates unless
+                * explicitly asked for. It doesn't add any security and
+                * just wastes time.
+                */
+               if (!xs->valid && (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)))
                        {
                        if ((pkey=X509_get_pubkey(xi)) == NULL)
                                {
@@ -1618,13 +1629,6 @@ static int internal_verify(X509_STORE_CTX *ctx)
                                if (!ok) goto end;
                                }
                        else if (X509_verify(xs,pkey) <= 0)
-                               /* XXX  For the final trusted self-signed cert,
-                                * this is a waste of time.  That check should
-                                * optional so that e.g. 'openssl x509' can be
-                                * used to detect invalid self-signatures, but
-                                * we don't verify again and again in SSL
-                                * handshakes and the like once the cert has
-                                * been declared trusted. */
                                {
                                ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
                                ctx->current_cert=xs;
@@ -1751,19 +1755,28 @@ ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
        return X509_time_adj(s, adj, NULL);
 }
 
-ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *in_tm)
+ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm)
+       {
+       return X509_time_adj_ex(s, 0, offset_sec, in_tm);
+       }
+
+ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s,
+                               int offset_day, long offset_sec, time_t *in_tm)
        {
        time_t t;
-       int type = -1;
 
        if (in_tm) t = *in_tm;
        else time(&t);
 
-       t+=adj;
-       if (s) type = s->type;
-       if (type == V_ASN1_UTCTIME) return ASN1_UTCTIME_set(s,t);
-       if (type == V_ASN1_GENERALIZEDTIME) return ASN1_GENERALIZEDTIME_set(s, t);
-       return ASN1_TIME_set(s, t);
+       if (s && !(s->flags & ASN1_STRING_FLAG_MSTRING))
+               {
+               if (s->type == V_ASN1_UTCTIME)
+                       return ASN1_UTCTIME_adj(s,t, offset_day, offset_sec);
+               if (s->type == V_ASN1_GENERALIZEDTIME)
+                       return ASN1_GENERALIZEDTIME_adj(s, t, offset_day,
+                                                               offset_sec);
+               }
+       return ASN1_TIME_adj(s, t, offset_day, offset_sec);
        }
 
 int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)