Add support for nameRelativeToCRLIssuer field in distribution point name
authorDr. Stephen Henson <steve@openssl.org>
Mon, 4 Aug 2008 15:34:27 +0000 (15:34 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 4 Aug 2008 15:34:27 +0000 (15:34 +0000)
fields.

crypto/asn1/x_crl.c
crypto/x509/x509_vfy.c
crypto/x509v3/v3_crld.c
crypto/x509v3/v3_purp.c
crypto/x509v3/x509v3.h

index d7093df..6edc6f2 100644 (file)
@@ -236,6 +236,8 @@ static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp)
                        crl->idp_reasons |=
                                (idp->onlysomereasons->data[1] << 8);
                }
+
+       DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
        }
 
 ASN1_SEQUENCE_ref(X509_CRL, crl_cb, CRYPTO_LOCK_X509_CRL) = {
index caa3995..1b1630a 100644 (file)
@@ -780,13 +780,82 @@ static int crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer)
        return 0;
        }
 
+/* Check for match between two dist point names: three separate cases.
+ * 1. Both are relative names and compare X509_NAME types.
+ * 2. One full, one relative. Compare X509_NAME to GENERAL_NAMES.
+ * 3. Both are full names and compare two GENERAL_NAMES.
+ */
+
+
+static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b)
+       {
+       X509_NAME *nm = NULL;
+       GENERAL_NAMES *gens = NULL;
+       GENERAL_NAME *gena, *genb;
+       int i, j;
+       if (a->type == 1)
+               {
+               if (!a->dpname)
+                       return 0;
+               /* Case 1: two X509_NAME */
+               if (b->type == 1)
+                       {
+                       if (!b->dpname)
+                               return 0;
+                       if (!X509_NAME_cmp(a->dpname, b->dpname))
+                               return 1;
+                       else
+                               return 0;
+                       }
+               /* Case 2: set name and GENERAL_NAMES appropriately */
+               nm = a->dpname;
+               gens = b->name.fullname;
+               }
+       else if (b->type == 1)
+               {
+               if (!b->dpname)
+                       return 0;
+               /* Case 2: set name and GENERAL_NAMES appropriately */
+               gens = a->name.fullname;
+               nm = b->dpname;
+               }
+
+       /* Handle case 2 with one GENERAL_NAMES and one X509_NAME */
+       if (nm)
+               {
+               for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
+                       {
+                       gena = sk_GENERAL_NAME_value(gens, i);  
+                       if (gena->type != GEN_DIRNAME)
+                               continue;
+                       if (!X509_NAME_cmp(nm, gena->d.directoryName))
+                               return 1;
+                       }
+               return 0;
+               }
+
+       /* Else case 3: two GENERAL_NAMES */
+
+       for (i = 0; i < sk_GENERAL_NAME_num(a->name.fullname); i++)
+               {
+               gena = sk_GENERAL_NAME_value(a->name.fullname, i);
+               for (j = 0; j < sk_GENERAL_NAME_num(b->name.fullname); j++)
+                       {
+                       genb = sk_GENERAL_NAME_value(b->name.fullname, j);
+                       if (!GENERAL_NAME_cmp(gena, genb))
+                               return 1;
+                       }
+               }
+
+       return 0;
+
+       }
 
 /* Check IDP name matches at least one CRLDP name */
 
 static int idp_check_scope(X509 *x, X509_CRL *crl)
        {
-       int i, j, k;
-       GENERAL_NAMES *inames, *dnames;
+       int i;
        if (crl->idp_flags & IDP_ONLYATTR)
                return 0;
        if (x->ex_flags & EXFLAG_CA)
@@ -801,31 +870,16 @@ static int idp_check_scope(X509 *x, X509_CRL *crl)
                }
        if (!crl->idp->distpoint)
                return 1;
-       if (crl->idp->distpoint->type != 0)
-               return 1;
        if (!x->crldp)
                return 0;
-       inames = crl->idp->distpoint->name.fullname;
-       for (i = 0; i < sk_GENERAL_NAME_num(inames); i++)
+       for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++)
                {
-               GENERAL_NAME *igen = sk_GENERAL_NAME_value(inames, i);
-               for (j = 0; j < sk_DIST_POINT_num(x->crldp); j++)
-                       {
-                       DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, j);
-                       /* We don't handle these at present */
-                       if (dp->reasons || dp->CRLissuer)
-                               continue;
-                       if (!dp->distpoint || (dp->distpoint->type != 0))
-                               continue;
-                       dnames = dp->distpoint->name.fullname;
-                       for (k = 0; k < sk_GENERAL_NAME_num(dnames); k++)
-                               {
-                               GENERAL_NAME *cgen =
-                                       sk_GENERAL_NAME_value(dnames, k);
-                               if (!GENERAL_NAME_cmp(igen, cgen))
-                                       return 1;
-                               }
-                       }
+               DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i);
+               /* We don't handle these at present */
+               if (dp->reasons || dp->CRLissuer)
+                       continue;
+               if (idp_check_dp(dp->distpoint, crl->idp->distpoint))
+                       return 1;
                }
        return 0;
        }
index 26a26d1..4d06ea6 100644 (file)
@@ -3,7 +3,7 @@
  * project 1999.
  */
 /* ====================================================================
- * Copyright (c) 1999, 2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2008 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -361,11 +361,31 @@ static void *v2i_crld(X509V3_EXT_METHOD *method,
 IMPLEMENT_STACK_OF(DIST_POINT)
 IMPLEMENT_ASN1_SET_OF(DIST_POINT)
 
+static int dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+                                                               void *exarg)
+       {
+       DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval;
+
+       switch(operation)
+               {
+               case ASN1_OP_NEW_POST:
+               dpn->dpname = NULL;
+               break;
+
+               case ASN1_OP_FREE_POST:
+               if (dpn->dpname)
+                       X509_NAME_free(dpn->dpname);
+               break;
+               }
+       return 1;
+       }
 
-ASN1_CHOICE(DIST_POINT_NAME) = {
+
+ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = {
        ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0),
        ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1)
-} ASN1_CHOICE_END(DIST_POINT_NAME)
+} ASN1_CHOICE_END_cb(DIST_POINT_NAME, DIST_POINT_NAME, type)
+
 
 IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME)
 
@@ -550,3 +570,34 @@ static int i2r_crldp(X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
                }
        return 1;
        }
+
+int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname)
+       {
+       int i;
+       STACK_OF(X509_NAME_ENTRY) *frag;
+       X509_NAME_ENTRY *ne;
+       if (!dpn || (dpn->type != 1))
+               return 1;
+       frag = dpn->name.relativename;
+       dpn->dpname = X509_NAME_dup(iname);
+       if (!dpn->dpname)
+               return 0;
+       for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++)
+               {
+               ne = sk_X509_NAME_ENTRY_value(frag, i);
+               if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1))
+                       {
+                       X509_NAME_free(dpn->dpname);
+                       dpn->dpname = NULL;
+                       return 0;
+                       }
+               }
+       /* generate cached encoding of name */
+       if (i2d_X509_NAME(dpn->dpname, NULL) < 0)
+               {
+               X509_NAME_free(dpn->dpname);
+               dpn->dpname = NULL;
+               return 0;
+               }
+       return 1;
+       }
index 9d48db3..caf80e6 100644 (file)
@@ -311,7 +311,36 @@ int X509_supported_extension(X509_EXTENSION *ex)
                return 1;
        return 0;
        }
+
+static void setup_dp(X509 *x, DIST_POINT *dp)
+       {
+       X509_NAME *iname = NULL;
+       int i;
+       if (!dp->distpoint || (dp->distpoint->type != 1))
+               return;
+       for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++)
+               {
+               GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
+               if (gen->type == GEN_DIRNAME)
+                       {
+                       iname = gen->d.directoryName;
+                       break;
+                       }
+               }
+       if (!iname)
+               iname = X509_get_issuer_name(x);
+
+       DIST_POINT_set_dpname(dp->distpoint, iname);
+
+       }
+
+static void setup_crldp(X509 *x)
+       {
+       int i;
+       x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
+       for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++)
+               setup_dp(x, sk_DIST_POINT_value(x->crldp, i));
+       }
 
 static void x509v3_cache_extensions(X509 *x)
 {
@@ -419,7 +448,9 @@ static void x509v3_cache_extensions(X509 *x)
        }
        x->skid =X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL);
        x->akid =X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL);
-       x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
+       setup_crldp(x);
+                       
+                       
 #ifndef OPENSSL_NO_RFC3779
        x->rfc3779_addr =X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL);
        x->rfc3779_asid =X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum,
index 7cc2434..5babc2b 100644 (file)
@@ -220,6 +220,8 @@ union {
        GENERAL_NAMES *fullname;
        STACK_OF(X509_NAME_ENTRY) *relativename;
 } name;
+/* If relativename then this contains the full distribution point name */
+X509_NAME *dpname;
 } DIST_POINT_NAME;
 
 struct DIST_POINT_st {
@@ -545,6 +547,8 @@ DECLARE_ASN1_FUNCTIONS(DIST_POINT)
 DECLARE_ASN1_FUNCTIONS(DIST_POINT_NAME)
 DECLARE_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
 
+int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname);
+
 DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION)
 DECLARE_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS)