Add verify callback functions to lookup a STACK of matching certs or CRLs
authorDr. Stephen Henson <steve@openssl.org>
Sun, 10 Sep 2006 12:38:37 +0000 (12:38 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 10 Sep 2006 12:38:37 +0000 (12:38 +0000)
based on subject name.

New thread safe functions to retrieve matching STACK from X509_STORE.

Cache some IDP components.

crypto/asn1/x_crl.c
crypto/x509/x509.h
crypto/x509/x509_lu.c
crypto/x509/x509_vfy.c
crypto/x509/x509_vfy.h
crypto/x509v3/x509v3.h

index 8943b84..f8ad1f3 100644 (file)
@@ -64,6 +64,7 @@
 
 static int X509_REVOKED_cmp(const X509_REVOKED * const *a,
                                const X509_REVOKED * const *b);
+static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp);
 
 ASN1_SEQUENCE(X509_REVOKED) = {
        ASN1_SIMPLE(X509_REVOKED,serialNumber, ASN1_INTEGER),
@@ -116,6 +117,8 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
                case ASN1_OP_NEW_POST:
                crl->idp = NULL;
                crl->akid = NULL;
+               crl->flags = 0;
+               crl->idp_flags = 0;
                break;
 
                case ASN1_OP_D2I_POST:
@@ -124,6 +127,9 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
 #endif
                crl->idp = X509_CRL_get_ext_d2i(crl,
                                NID_issuing_distribution_point, NULL, NULL);
+               if (crl->idp)
+                       setup_idp(crl, crl->idp);
+
                crl->akid = X509_CRL_get_ext_d2i(crl,
                                NID_authority_key_identifier, NULL, NULL);      
                break;
@@ -138,6 +144,46 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
        return 1;
        }
 
+/* Convert IDP into a more convenient form */
+
+static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp)
+       {
+       int idp_only = 0;
+       /* Set various flags according to IDP */
+       crl->idp_flags |= IDP_PRESENT;
+       if (idp->onlyuser > 0)
+               {
+               idp_only++;
+               crl->idp_flags |= IDP_ONLYUSER;
+               }
+       if (idp->onlyCA > 0)
+               {
+               idp_only++;
+               crl->idp_flags |= IDP_ONLYCA;
+               }
+       if (idp->onlyattr > 0)
+               {
+               idp_only++;
+               crl->idp_flags |= IDP_ONLYATTR;
+               }
+
+       if (idp_only > 1)
+               crl->idp_flags |= IDP_INVALID;
+
+       if (idp->indirectCRL > 0)
+               crl->idp_flags |= IDP_INDIRECT;
+
+       if (idp->onlysomereasons)
+               {
+               crl->idp_flags |= IDP_REASONS;
+               if (idp->onlysomereasons->length > 0)
+                       crl->idp_reasons = idp->onlysomereasons->data[0];
+               if (idp->onlysomereasons->length > 1)
+                       crl->idp_reasons |=
+                               (idp->onlysomereasons->data[1] << 8);
+               }
+       }
+
 ASN1_SEQUENCE_ref(X509_CRL, crl_cb, CRYPTO_LOCK_X509_CRL) = {
        ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO),
        ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR),
index 31bc753..de93bf9 100644 (file)
@@ -454,6 +454,9 @@ struct X509_crl_st
        /* Copies of various extensions */
        AUTHORITY_KEYID *akid;
        ISSUING_DIST_POINT *idp;
+       /* Convenient breakdown of IDP */
+       int idp_flags;
+       int idp_reasons;
 #ifndef OPENSSL_NO_SHA
        unsigned char sha1_hash[SHA_DIGEST_LENGTH];
 #endif
index fbb1497..35a8e35 100644 (file)
@@ -414,14 +414,15 @@ void X509_OBJECT_free_contents(X509_OBJECT *a)
                }
        }
 
-int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
-            X509_NAME *name)
+static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type,
+            X509_NAME *name, int *pnmatch)
        {
        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)
@@ -441,7 +442,29 @@ int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
                return -1;
                }
 
-       return sk_X509_OBJECT_find(h,&stmp);
+       idx = sk_X509_OBJECT_find(h,&stmp);
+       if (idx >= 0 && pnmatch)
+               {
+               int tidx;
+               const X509_OBJECT *tobj, *pstmp;
+               *pnmatch = 1;
+               pstmp = &stmp;
+               for (tidx = idx + 1; tidx < sk_X509_OBJECT_num(h); tidx++)
+                       {
+                       tobj = sk_X509_OBJECT_value(h, tidx);
+                       if (!x509_object_cmp(&tobj, &pstmp))
+                               break;
+                       *pnmatch++;
+                       }
+               }
+       return idx;
+       }
+
+
+int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
+            X509_NAME *name)
+       {
+       return x509_object_idx_cnt(h, type, name, NULL);
        }
 
 X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, int type,
@@ -453,6 +476,72 @@ X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, int type,
        return sk_X509_OBJECT_value(h, idx);
 }
 
+STACK_OF(X509)* X509_STORE_get_certs(X509_STORE *st, X509_NAME *nm)
+       {
+       int i, idx, cnt;
+       STACK_OF(X509) *sk;
+       X509 *x;
+       X509_OBJECT *obj;
+       sk = sk_X509_new_null();
+       CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE);
+       idx = x509_object_idx_cnt(st->objs, X509_LU_X509, nm, &cnt);
+       if (idx < 0)
+               {
+               CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE);
+               sk_X509_free(sk);
+               return NULL;
+               }
+       for (i = 0; i < cnt; i++, idx++)
+               {
+               obj = sk_X509_OBJECT_value(st->objs, i);
+               x = obj->data.x509;
+               CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+               if (!sk_X509_push(sk, x))
+                       {
+                       CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE);
+                       X509_free(x);
+                       sk_X509_pop_free(sk, X509_free);
+                       return NULL;
+                       }
+               }
+       CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE);
+       return sk;
+
+       }
+
+STACK_OF(X509_CRL)* X509_STORE_get_crls(X509_STORE *st, X509_NAME *nm)
+       {
+       int i, idx, cnt;
+       STACK_OF(X509_CRL) *sk;
+       X509_CRL *x;
+       X509_OBJECT *obj;
+       sk = sk_X509_CRL_new_null();
+       CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE);
+       idx = x509_object_idx_cnt(st->objs, X509_LU_CRL, nm, &cnt);
+       if (idx < 0)
+               {
+               CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE);
+               sk_X509_CRL_free(sk);
+               return NULL;
+               }
+       for (i = 0; i < cnt; i++, idx++)
+               {
+               obj = sk_X509_OBJECT_value(st->objs, i);
+               x = obj->data.crl;
+               CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL);
+               if (!sk_X509_CRL_push(sk, x))
+                       {
+                       CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE);
+                       X509_CRL_free(x);
+                       sk_X509_CRL_pop_free(sk, X509_CRL_free);
+                       return NULL;
+                       }
+               }
+       CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE);
+       return sk;
+
+       }
+
 X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x)
 {
        int idx, i;
index e2109a4..51db631 100644 (file)
@@ -79,6 +79,8 @@ static int check_revocation(X509_STORE_CTX *ctx);
 static int check_cert(X509_STORE_CTX *ctx);
 static int check_policy(X509_STORE_CTX *ctx);
 static int internal_verify(X509_STORE_CTX *ctx);
+static STACK_OF(X509) * lookup_certs(X509_STORE_CTX *ctx, X509_NAME *nm);
+static STACK_OF(X509_CRL) * lookup_crls(X509_STORE_CTX *ctx, X509_NAME *nm);
 const char *X509_version="X.509" OPENSSL_VERSION_PTEXT;
 
 
@@ -669,7 +671,7 @@ static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl,
                if (check_crl_time(ctx, crl, 0))
                        {
                        *pcrl = crl;
-                       CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509);
+                       CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL);
                        return 1;
                        }
                best_crl = crl;
@@ -874,6 +876,16 @@ static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
        return 1;
        }
 
+static STACK_OF(X509) * lookup_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
+       {
+       return X509_STORE_get_certs(ctx->ctx, nm);
+       }
+
+static STACK_OF(X509_CRL) * lookup_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
+       {
+       return X509_STORE_get_crls(ctx->ctx, nm);
+       }
+
 static int check_policy(X509_STORE_CTX *ctx)
        {
        int ret;
@@ -1461,6 +1473,16 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
        else
                ctx->cert_crl = cert_crl;
 
+       if (store && store->lookup_certs)
+               ctx->lookup_certs = store->lookup_certs;
+       else
+               ctx->lookup_certs = lookup_certs;
+
+       if (store && store->lookup_crls)
+               ctx->lookup_crls = store->lookup_crls;
+       else
+               ctx->lookup_crls = lookup_crls;
+
        ctx->check_policy = check_policy;
 
 
index 3f16330..3c550e1 100644 (file)
@@ -198,6 +198,8 @@ struct x509_store_st
        int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */
        int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */
        int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */
+       STACK_OF(X509) * (*lookup_certs)(X509_STORE_CTX *ctx, X509_NAME *nm);
+       STACK_OF(X509_CRL) * (*lookup_crls)(X509_STORE_CTX *ctx, X509_NAME *nm);
        int (*cleanup)(X509_STORE_CTX *ctx);
 
        CRYPTO_EX_DATA ex_data;
@@ -246,6 +248,8 @@ struct x509_store_ctx_st      /* X509_STORE_CTX */
        int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */
        int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */
        int (*check_policy)(X509_STORE_CTX *ctx);
+       STACK_OF(X509) * (*lookup_certs)(X509_STORE_CTX *ctx, X509_NAME *nm);
+       STACK_OF(X509_CRL) * (*lookup_crls)(X509_STORE_CTX *ctx, X509_NAME *nm);
        int (*cleanup)(X509_STORE_CTX *ctx);
 
        /* The following is built up */
@@ -383,6 +387,8 @@ void X509_OBJECT_free_contents(X509_OBJECT *a);
 X509_STORE *X509_STORE_new(void );
 void X509_STORE_free(X509_STORE *v);
 
+STACK_OF(X509)* X509_STORE_get_certs(X509_STORE *st, X509_NAME *nm);
+STACK_OF(X509_CRL)* X509_STORE_get_crls(X509_STORE *st, X509_NAME *nm);
 int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags);
 int X509_STORE_set_purpose(X509_STORE *ctx, int purpose);
 int X509_STORE_set_trust(X509_STORE *ctx, int trust);
index 1e2f00a..da349e5 100644 (file)
@@ -339,6 +339,22 @@ struct ISSUING_DIST_POINT_st
        int onlyattr;
        };
 
+/* Values in idp_flags field */
+/* IDP present */
+#define        IDP_PRESENT     0x1
+/* IDP values inconsistent */
+#define IDP_INVALID    0x2
+/* onlyuser true */
+#define        IDP_ONLYUSER    0x4
+/* onlyCA true */
+#define        IDP_ONLYCA      0x8
+/* onlyattr true */
+#define IDP_ONLYATTR   0x10
+/* indirectCRL true */
+#define IDP_INDIRECT   0x20
+/* onlysomereasons present */
+#define IDP_REASONS    0x40
+
 #define X509V3_conf_err(val) ERR_add_error_data(6, "section:", val->section, \
 ",name:", val->name, ",value:", val->value);