Initial support for delta CRLs. If "use deltas" flag is set attempt to find
[openssl.git] / crypto / x509v3 / v3_purp.c
index e64a528bf757d495e4f301571a273696b0b5132e..1ca370dc0b86caacf76af44c5c3e74a4eba4433b 100644 (file)
@@ -287,8 +287,17 @@ int X509_supported_extension(X509_EXTENSION *ex)
                NID_key_usage,          /* 83 */
                NID_subject_alt_name,   /* 85 */
                NID_basic_constraints,  /* 87 */
+               NID_certificate_policies, /* 89 */
                NID_ext_key_usage,      /* 126 */
-               NID_proxyCertInfo       /* 661 */
+#ifndef OPENSSL_NO_RFC3779
+               NID_sbgp_ipAddrBlock,   /* 290 */
+               NID_sbgp_autonomousSysNum, /* 291 */
+#endif
+               NID_policy_constraints, /* 401 */
+               NID_proxyCertInfo,      /* 663 */
+               NID_name_constraints,   /* 666 */
+               NID_policy_mappings,    /* 747 */
+               NID_inhibit_any_policy  /* 748 */
        };
 
        int ex_nid;
@@ -304,7 +313,46 @@ 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->reasons)
+               {
+               if (dp->reasons->length > 0)
+                       dp->dp_reasons = dp->reasons->data[0];
+               if (dp->reasons->length > 1)
+                       dp->dp_reasons |= (dp->reasons->data[1] << 8);
+               dp->dp_reasons &= CRLDP_ALL_REASONS;
+               }
+       else
+               dp->dp_reasons = CRLDP_ALL_REASONS;
+       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)
 {
@@ -322,7 +370,7 @@ static void x509v3_cache_extensions(X509 *x)
 #endif
        /* Does subject name match issuer ? */
        if(!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x)))
-                        x->ex_flags |= EXFLAG_SS;
+                        x->ex_flags |= EXFLAG_SI;
        /* V1 should mean no extensions ... */
        if(!X509_get_version(x)) x->ex_flags |= EXFLAG_V1;
        /* Handle basic constraints */
@@ -412,11 +460,25 @@ 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->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+       x->nc = X509_get_ext_d2i(x, NID_name_constraints, &i, NULL);
+       if (!x->nc && (i != -1))
+               x->ex_flags |= EXFLAG_INVALID;
+       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,
+                                         NULL, NULL);
+#endif
        for (i = 0; i < X509_get_ext_count(x); i++)
                {
                ex = X509_get_ext(x, i);
                if (!X509_EXTENSION_get_critical(ex))
                        continue;
+               if (OBJ_obj2nid(X509_EXTENSION_get_object(ex))
+                                       == NID_freshest_crl)
+                       x->ex_flags |= EXFLAG_FRESHEST;
                if (!X509_supported_extension(ex))
                        {
                        x->ex_flags |= EXFLAG_CRITICAL;
@@ -643,39 +705,14 @@ int X509_check_issued(X509 *issuer, X509 *subject)
                                return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
        x509v3_cache_extensions(issuer);
        x509v3_cache_extensions(subject);
-       if(subject->akid) {
-               /* Check key ids (if present) */
-               if(subject->akid->keyid && issuer->skid &&
-                ASN1_OCTET_STRING_cmp(subject->akid->keyid, issuer->skid) )
-                               return X509_V_ERR_AKID_SKID_MISMATCH;
-               /* Check serial number */
-               if(subject->akid->serial &&
-                       ASN1_INTEGER_cmp(X509_get_serialNumber(issuer),
-                                               subject->akid->serial))
-                               return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
-               /* Check issuer name */
-               if(subject->akid->issuer) {
-                       /* Ugh, for some peculiar reason AKID includes
-                        * SEQUENCE OF GeneralName. So look for a DirName.
-                        * There may be more than one but we only take any
-                        * notice of the first.
-                        */
-                       GENERAL_NAMES *gens;
-                       GENERAL_NAME *gen;
-                       X509_NAME *nm = NULL;
-                       int i;
-                       gens = subject->akid->issuer;
-                       for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
-                               gen = sk_GENERAL_NAME_value(gens, i);
-                               if(gen->type == GEN_DIRNAME) {
-                                       nm = gen->d.dirn;
-                                       break;
-                               }
-                       }
-                       if(nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)))
-                               return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
+
+       if(subject->akid)
+               {
+               int ret = X509_check_akid(issuer, subject->akid);
+               if (ret != X509_V_OK)
+                       return ret;
                }
-       }
+
        if(subject->ex_flags & EXFLAG_PROXY)
                {
                if(ku_reject(issuer, KU_DIGITAL_SIGNATURE))
@@ -686,3 +723,45 @@ int X509_check_issued(X509 *issuer, X509 *subject)
        return X509_V_OK;
 }
 
+int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid)
+       {
+
+       if(!akid)
+               return X509_V_OK;
+
+       /* Check key ids (if present) */
+       if(akid->keyid && issuer->skid &&
+                ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid) )
+                               return X509_V_ERR_AKID_SKID_MISMATCH;
+       /* Check serial number */
+       if(akid->serial &&
+               ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial))
+                               return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
+       /* Check issuer name */
+       if(akid->issuer)
+               {
+               /* Ugh, for some peculiar reason AKID includes
+                * SEQUENCE OF GeneralName. So look for a DirName.
+                * There may be more than one but we only take any
+                * notice of the first.
+                */
+               GENERAL_NAMES *gens;
+               GENERAL_NAME *gen;
+               X509_NAME *nm = NULL;
+               int i;
+               gens = akid->issuer;
+               for(i = 0; i < sk_GENERAL_NAME_num(gens); i++)
+                       {
+                       gen = sk_GENERAL_NAME_value(gens, i);
+                       if(gen->type == GEN_DIRNAME)
+                               {
+                               nm = gen->d.dirn;
+                               break;
+                               }
+                       }
+               if(nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)))
+                       return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
+               }
+       return X509_V_OK;
+       }
+