Tidy up x509_vfy callback handling
[openssl.git] / crypto / x509 / x509_lu.c
index f77e59df3766c97acee7fb985894c1b0c3c6b692..f9802c5a80a9b1f76bd216ffcc015c5c1170c534 100644 (file)
@@ -1,4 +1,3 @@
-/* crypto/x509/x509_lu.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  */
 
 #include <stdio.h>
-#include "cryptlib.h"
+#include "internal/cryptlib.h"
 #include <openssl/lhash.h>
 #include <openssl/x509.h>
+#include "internal/x509_int.h"
 #include <openssl/x509v3.h>
 #include "x509_lcl.h"
 
@@ -67,15 +67,11 @@ X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
 {
     X509_LOOKUP *ret;
 
-    ret = (X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP));
+    ret = OPENSSL_zalloc(sizeof(*ret));
     if (ret == NULL)
         return NULL;
 
-    ret->init = 0;
-    ret->skip = 0;
     ret->method = method;
-    ret->method_data = NULL;
-    ret->store_ctx = NULL;
     if ((method->new_item != NULL) && !method->new_item(ret)) {
         OPENSSL_free(ret);
         return NULL;
@@ -184,39 +180,39 @@ X509_STORE *X509_STORE_new(void)
 {
     X509_STORE *ret;
 
-    if ((ret = (X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL)
+    if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL)
         return NULL;
-    ret->objs = sk_X509_OBJECT_new(x509_object_cmp);
+    if ((ret->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL)
+        goto err;
     ret->cache = 1;
-    ret->get_cert_methods = sk_X509_LOOKUP_new_null();
-    ret->verify = 0;
-    ret->verify_cb = 0;
+    if ((ret->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL)
+        goto err;
 
     if ((ret->param = X509_VERIFY_PARAM_new()) == NULL)
-        return NULL;
+        goto err;
 
-    ret->get_issuer = 0;
-    ret->check_issued = 0;
-    ret->check_revocation = 0;
-    ret->get_crl = 0;
-    ret->check_crl = 0;
-    ret->cert_crl = 0;
-    ret->lookup_certs = 0;
-    ret->lookup_crls = 0;
-    ret->cleanup = 0;
-
-    if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data)) {
-        sk_X509_OBJECT_free(ret->objs);
-        OPENSSL_free(ret);
-        return NULL;
-    }
+    if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data))
+        goto err;
+
+    ret->lock = CRYPTO_THREAD_lock_new();
+    if (ret->lock == NULL)
+        goto err;
 
     ret->references = 1;
     return ret;
+
+err:
+    X509_VERIFY_PARAM_free(ret->param);
+    sk_X509_OBJECT_free(ret->objs);
+    sk_X509_LOOKUP_free(ret->get_cert_methods);
+    OPENSSL_free(ret);
+    return NULL;
 }
 
 static void cleanup(X509_OBJECT *a)
 {
+    if (!a)
+        return;
     if (a->type == X509_LU_X509) {
         X509_free(a->data.x509);
     } else if (a->type == X509_LU_CRL) {
@@ -237,18 +233,11 @@ void X509_STORE_free(X509_STORE *vfy)
     if (vfy == NULL)
         return;
 
-    i = CRYPTO_add(&vfy->references, -1, CRYPTO_LOCK_X509_STORE);
-#ifdef REF_PRINT
-    REF_PRINT("X509_STORE", vfy);
-#endif
+    CRYPTO_atomic_add(&vfy->references, -1, &i, vfy->lock);
+    REF_PRINT_COUNT("X509_STORE", vfy);
     if (i > 0)
         return;
-#ifdef REF_CHECK
-    if (i < 0) {
-        fprintf(stderr, "X509_STORE_free, bad reference count\n");
-        abort();                /* ok */
-    }
-#endif
+    REF_ASSERT_ISNT(i < 0);
 
     sk = vfy->get_cert_methods;
     for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
@@ -260,11 +249,23 @@ void X509_STORE_free(X509_STORE *vfy)
     sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
 
     CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data);
-    if (vfy->param)
-        X509_VERIFY_PARAM_free(vfy->param);
+    X509_VERIFY_PARAM_free(vfy->param);
+    CRYPTO_THREAD_lock_free(vfy->lock);
     OPENSSL_free(vfy);
 }
 
+int X509_STORE_up_ref(X509_STORE *vfy)
+{
+    int i;
+
+    if (CRYPTO_atomic_add(&vfy->references, 1, &i, vfy->lock) <= 0)
+        return 0;
+
+    REF_PRINT_COUNT("X509_STORE", a);
+    REF_ASSERT_ISNT(i < 2);
+    return ((i > 1) ? 1 : 0);
+}
+
 X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
 {
     int i;
@@ -293,17 +294,17 @@ X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
     }
 }
 
-int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
-                              X509_OBJECT *ret)
+int X509_STORE_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type,
+                              X509_NAME *name, X509_OBJECT *ret)
 {
     X509_STORE *ctx = vs->ctx;
     X509_LOOKUP *lu;
     X509_OBJECT stmp, *tmp;
     int i, j;
 
-    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+    CRYPTO_THREAD_write_lock(ctx->lock);
     tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name);
-    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+    CRYPTO_THREAD_unlock(ctx->lock);
 
     if (tmp == NULL || type == X509_LU_CRL) {
         for (i = vs->current_method;
@@ -341,7 +342,7 @@ int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
 
     if (x == NULL)
         return 0;
-    obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
+    obj = OPENSSL_malloc(sizeof(*obj));
     if (obj == NULL) {
         X509err(X509_F_X509_STORE_ADD_CERT, ERR_R_MALLOC_FAILURE);
         return 0;
@@ -349,7 +350,7 @@ int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
     obj->type = X509_LU_X509;
     obj->data.x509 = x;
 
-    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+    CRYPTO_THREAD_write_lock(ctx->lock);
 
     X509_OBJECT_up_ref_count(obj);
 
@@ -362,7 +363,7 @@ int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
     } else
         sk_X509_OBJECT_push(ctx->objs, obj);
 
-    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+    CRYPTO_THREAD_unlock(ctx->lock);
 
     return ret;
 }
@@ -374,7 +375,7 @@ int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
 
     if (x == NULL)
         return 0;
-    obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
+    obj = OPENSSL_malloc(sizeof(*obj));
     if (obj == NULL) {
         X509err(X509_F_X509_STORE_ADD_CRL, ERR_R_MALLOC_FAILURE);
         return 0;
@@ -382,7 +383,7 @@ int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
     obj->type = X509_LU_CRL;
     obj->data.crl = x;
 
-    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+    CRYPTO_THREAD_write_lock(ctx->lock);
 
     X509_OBJECT_up_ref_count(obj);
 
@@ -394,7 +395,7 @@ int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
     } else
         sk_X509_OBJECT_push(ctx->objs, obj);
 
-    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+    CRYPTO_THREAD_unlock(ctx->lock);
 
     return ret;
 }
@@ -402,18 +403,24 @@ int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
 void X509_OBJECT_up_ref_count(X509_OBJECT *a)
 {
     switch (a->type) {
+    default:
+        break;
     case X509_LU_X509:
-        CRYPTO_add(&a->data.x509->references, 1, CRYPTO_LOCK_X509);
+        X509_up_ref(a->data.x509);
         break;
     case X509_LU_CRL:
-        CRYPTO_add(&a->data.crl->references, 1, CRYPTO_LOCK_X509_CRL);
+        X509_CRL_up_ref(a->data.crl);
         break;
     }
 }
 
 void X509_OBJECT_free_contents(X509_OBJECT *a)
 {
+    if (!a)
+        return;
     switch (a->type) {
+    default:
+        break;
     case X509_LU_X509:
         X509_free(a->data.x509);
         break;
@@ -428,22 +435,18 @@ static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type,
 {
     X509_OBJECT stmp;
     X509 x509_s;
-    X509_CINF cinf_s;
     X509_CRL crl_s;
-    X509_CRL_INFO crl_info_s;
     int idx;
 
     stmp.type = type;
     switch (type) {
     case X509_LU_X509:
         stmp.data.x509 = &x509_s;
-        x509_s.cert_info = &cinf_s;
-        cinf_s.subject = name;
+        x509_s.cert_info.subject = name;
         break;
     case X509_LU_CRL:
         stmp.data.crl = &crl_s;
-        crl_s.crl = &crl_info_s;
-        crl_info_s.issuer = name;
+        crl_s.crl.issuer = name;
         break;
     default:
         /* abort(); */
@@ -489,7 +492,7 @@ STACK_OF(X509) *X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
     X509 *x;
     X509_OBJECT *obj;
     sk = sk_X509_new_null();
-    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+    CRYPTO_THREAD_write_lock(ctx->ctx->lock);
     idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
     if (idx < 0) {
         /*
@@ -497,16 +500,16 @@ STACK_OF(X509) *X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
          * cache
          */
         X509_OBJECT xobj;
-        CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+        CRYPTO_THREAD_unlock(ctx->ctx->lock);
         if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) {
             sk_X509_free(sk);
             return NULL;
         }
         X509_OBJECT_free_contents(&xobj);
-        CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+        CRYPTO_THREAD_write_lock(ctx->ctx->lock);
         idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
         if (idx < 0) {
-            CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+            CRYPTO_THREAD_unlock(ctx->ctx->lock);
             sk_X509_free(sk);
             return NULL;
         }
@@ -514,15 +517,15 @@ STACK_OF(X509) *X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
     for (i = 0; i < cnt; i++, idx++) {
         obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
         x = obj->data.x509;
-        CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+        X509_up_ref(x);
         if (!sk_X509_push(sk, x)) {
-            CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+            CRYPTO_THREAD_unlock(ctx->ctx->lock);
             X509_free(x);
             sk_X509_pop_free(sk, X509_free);
             return NULL;
         }
     }
-    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+    CRYPTO_THREAD_unlock(ctx->ctx->lock);
     return sk;
 
 }
@@ -534,23 +537,19 @@ STACK_OF(X509_CRL) *X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
     X509_CRL *x;
     X509_OBJECT *obj, xobj;
     sk = sk_X509_CRL_new_null();
-    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
-    /* Check cache first */
-    idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
 
     /*
      * Always do lookup to possibly add new CRLs to cache
      */
-    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
     if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj)) {
         sk_X509_CRL_free(sk);
         return NULL;
     }
     X509_OBJECT_free_contents(&xobj);
-    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+    CRYPTO_THREAD_write_lock(ctx->ctx->lock);
     idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
     if (idx < 0) {
-        CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+        CRYPTO_THREAD_unlock(ctx->ctx->lock);
         sk_X509_CRL_free(sk);
         return NULL;
     }
@@ -558,15 +557,15 @@ STACK_OF(X509_CRL) *X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
     for (i = 0; i < cnt; i++, idx++) {
         obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
         x = obj->data.crl;
-        CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL);
+        X509_CRL_up_ref(x);
         if (!sk_X509_CRL_push(sk, x)) {
-            CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+            CRYPTO_THREAD_unlock(ctx->ctx->lock);
             X509_CRL_free(x);
             sk_X509_CRL_pop_free(sk, X509_CRL_free);
             return NULL;
         }
     }
-    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+    CRYPTO_THREAD_unlock(ctx->ctx->lock);
     return sk;
 }
 
@@ -631,7 +630,7 @@ 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)) {
-        if (x509_check_cert_time(ctx, obj.data.x509, 1)) {
+        if (x509_check_cert_time(ctx, obj.data.x509, -1)) {
             *issuer = obj.data.x509;
             return 1;
         }
@@ -640,7 +639,7 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
 
     /* Else find index of first cert accepted by 'check_issued' */
     ret = 0;
-    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+    CRYPTO_THREAD_write_lock(ctx->ctx->lock);
     idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
     if (idx != -1) {            /* should be true as we've had at least one
                                  * match */
@@ -662,14 +661,14 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
                  * match if no certificate time is OK.
                  */
 
-                if (x509_check_cert_time(ctx, *issuer, 1))
+                if (x509_check_cert_time(ctx, *issuer, -1))
                     break;
             }
         }
     }
-    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+    CRYPTO_THREAD_unlock(ctx->ctx->lock);
     if (*issuer)
-        CRYPTO_add(&(*issuer)->references, 1, CRYPTO_LOCK_X509);
+        X509_up_ref(*issuer);
     return ret;
 }