Added support for policyConstraints to x509 plugin
authorMartin Willi <martin@revosec.ch>
Wed, 15 Dec 2010 16:45:32 +0000 (17:45 +0100)
committerMartin Willi <martin@revosec.ch>
Wed, 5 Jan 2011 15:46:02 +0000 (16:46 +0100)
src/libstrongswan/asn1/oid.txt
src/libstrongswan/credentials/builder.c
src/libstrongswan/credentials/builder.h
src/libstrongswan/credentials/certificates/x509.h
src/libstrongswan/plugins/openssl/openssl_x509.c
src/libstrongswan/plugins/x509/x509_cert.c

index 7b74552..3c8ea11 100644 (file)
@@ -55,7 +55,7 @@
       0x00                   "anyPolicy"                               OID_ANY_POLICY
     0x21                     "policyMappings"                  OID_POLICY_MAPPINGS
     0x23                     "authorityKeyIdentifier"  OID_AUTHORITY_KEY_ID
-    0x24                     "policyConstraints"
+    0x24                     "policyConstraints"               OID_POLICY_CONSTRAINTS
     0x25                     "extendedKeyUsage"                        OID_EXTENDED_KEY_USAGE
       0x00                   "anyExtendedKeyUsage"
     0x2E                     "freshestCRL"                             OID_FRESHEST_CRL
index cdf5c70..1220019 100644 (file)
@@ -48,6 +48,8 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END,
        "BUILD_EXCLUDED_NAME_CONSTRAINTS",
        "BUILD_CERTIFICATE_POLICIES",
        "BUILD_POLICY_MAPPINGS",
+       "BUILD_POLICY_CONSTRAINT_EXPLICIT",
+       "BUILD_POLICY_CONSTRAINT_INHIBIT",
        "BUILD_X509_FLAG",
        "BUILD_REVOKED_ENUMERATOR",
        "BUILD_CHALLENGE_PWD",
index f2b3f44..56eee3c 100644 (file)
@@ -103,6 +103,10 @@ enum builder_part_t {
        BUILD_CERTIFICATE_POLICIES,
        /** policyMapping OIDs, linked_list_t* of x509_policy_mapping_t* */
        BUILD_POLICY_MAPPINGS,
+       /** requireExplicitPolicy constraint, int */
+       BUILD_POLICY_CONSTRAINT_EXPLICIT,
+       /** inhibitPolicyMapping constraint, int */
+       BUILD_POLICY_CONSTRAINT_INHIBIT,
        /** enforce an additional X509 flag, x509_flag_t */
        BUILD_X509_FLAG,
        /** enumerator_t over (chunk_t serial, time_t date, crl_reason_t reason) */
index d620bbd..f4ec730 100644 (file)
@@ -121,11 +121,19 @@ struct x509_t {
        /**
         * Get an optional path length constraint.
         *
-        * @return                      pathLenConstraint, -1 if no constraint exists
+        * @return                      pathLenConstraint, X509_NO_CONSTRAINT if none found
         */
        int (*get_pathLenConstraint)(x509_t *this);
 
        /**
+        * Get a policyConstraint, inhibitPolicyMapping or requireExplicitPolicy.
+        *
+        * @param inhibit       TRUE to get inhibitPolicyMapping
+        * @return                      constraint, X509_NO_CONSTRAINT if none found
+        */
+       int (*get_policyConstraint)(x509_t *this, bool inhibit);
+
+       /**
         * Create an enumerator over all subjectAltNames.
         *
         * @return                      enumerator over subjectAltNames as identification_t*
@@ -174,6 +182,8 @@ struct x509_t {
         * @return                      enumerator over x509_policy_mapping
         */
        enumerator_t* (*create_policy_mapping_enumerator)(x509_t *this);
+
+
 };
 
 #endif /** X509_H_ @}*/
index 7b6ac12..58b58b6 100644 (file)
@@ -277,6 +277,12 @@ METHOD(x509_t, get_pathLenConstraint, int,
        return this->pathlen;
 }
 
+METHOD(x509_t, get_policyConstraint, int,
+       private_openssl_x509_t *this, bool inhibit)
+{
+       return X509_NO_CONSTRAINT;
+}
+
 METHOD(x509_t, create_subjectAltName_enumerator, enumerator_t*,
        private_openssl_x509_t *this)
 {
@@ -568,6 +574,7 @@ static private_openssl_x509_t *create_empty()
                                .get_subjectKeyIdentifier = _get_subjectKeyIdentifier,
                                .get_authKeyIdentifier = _get_authKeyIdentifier,
                                .get_pathLenConstraint = _get_pathLenConstraint,
+                               .get_policyConstraint = _get_policyConstraint,
                                .create_subjectAltName_enumerator = _create_subjectAltName_enumerator,
                                .create_crl_uri_enumerator = _create_crl_uri_enumerator,
                                .create_ocsp_uri_enumerator = _create_ocsp_uri_enumerator,
index 4f6cdaa..4d34de4 100644 (file)
@@ -174,7 +174,17 @@ struct private_x509_cert_t {
        /**
         * Path Length Constraint
         */
-       int pathLenConstraint;
+       char pathLenConstraint;
+
+       /**
+        * requireExplicitPolicy Constraint
+        */
+       char explicit_policy_constraint;
+
+       /**
+        * inhibitPolicyMapping Constraint
+        */
+       char inhibit_policy_constraint;
 
        /**
         * x509 constraints and other flags
@@ -1031,6 +1041,66 @@ static void parse_policyMappings(chunk_t blob, int level0,
 }
 
 /**
+ * ASN.1 definition of a policyConstraints extension
+ */
+static const asn1Object_t policyConstraintsObjects[] = {
+       { 0, "policyConstraints",               ASN1_SEQUENCE,          ASN1_NONE                       }, /*  0 */
+       { 1,   "requireExplicitPolicy", ASN1_CONTEXT_C_0,       ASN1_OPT|ASN1_NONE      }, /*  1 */
+       { 2,     "SkipCerts",                   ASN1_INTEGER,           ASN1_BODY                       }, /*  2 */
+       { 1,   "end opt",                               ASN1_EOC,                       ASN1_END                        }, /*  3 */
+       { 1,   "inhibitPolicyMapping",  ASN1_CONTEXT_C_1,       ASN1_OPT|ASN1_NONE      }, /*  4 */
+       { 2,     "SkipCerts",                   ASN1_INTEGER,           ASN1_BODY                       }, /*  5 */
+       { 1,   "end opt",                               ASN1_EOC,                       ASN1_END                        }, /*  6 */
+       { 0, "exit",                                    ASN1_EOC,                       ASN1_EXIT                       }
+};
+#define POLICY_CONSTRAINT_EXPLICIT 2
+#define POLICY_CONSTRAINT_INHIBIT  5
+
+/**
+ * Parse policyConstraints
+ */
+static void parse_policyConstraints(chunk_t blob, int level0,
+                                                                       private_x509_cert_t *this)
+{
+       asn1_parser_t *parser;
+       chunk_t object;
+       int objectID;
+
+       parser = asn1_parser_create(policyConstraintsObjects, blob);
+       parser->set_top_level(parser, level0);
+
+       while (parser->iterate(parser, &objectID, &object))
+       {
+               switch (objectID)
+               {
+                       case POLICY_CONSTRAINT_EXPLICIT:
+                               if (object.len == 0)
+                               {
+                                       this->explicit_policy_constraint = 0;
+                               }
+                               else if (object.len == 1)
+                               {
+                                       this->explicit_policy_constraint = *object.ptr;
+                               }
+                               break;
+                       case POLICY_CONSTRAINT_INHIBIT:
+                               if (object.len == 0)
+                               {
+                                       this->inhibit_policy_constraint = 0;
+                               }
+                               else if (object.len == 1)
+                               {
+                                       this->inhibit_policy_constraint = *object.ptr;
+                               }
+                               break;
+                       default:
+                               break;
+               }
+       }
+       parser->destroy(parser);
+}
+
+/**
  * ASN.1 definition of ipAddrBlocks according to RFC 3779
  */
 static const asn1Object_t ipAddrBlocksObjects[] = {
@@ -1348,6 +1418,9 @@ static bool parse_certificate(private_x509_cert_t *this)
                                        case OID_POLICY_MAPPINGS:
                                                parse_policyMappings(object, level, this);
                                                break;
+                                       case OID_POLICY_CONSTRAINTS:
+                                               parse_policyConstraints(object, level, this);
+                                               break;
                                        case OID_NS_REVOCATION_URL:
                                        case OID_NS_CA_REVOCATION_URL:
                                        case OID_NS_CA_POLICY_URL:
@@ -1646,6 +1719,16 @@ METHOD(x509_t, get_pathLenConstraint, int,
        return this->pathLenConstraint;
 }
 
+METHOD(x509_t, get_policyConstraint, int,
+       private_x509_cert_t *this, bool inhibit)
+{
+       if (inhibit)
+       {
+               return this->inhibit_policy_constraint;
+       }
+       return this->explicit_policy_constraint;
+}
+
 METHOD(x509_t, create_subjectAltName_enumerator, enumerator_t*,
        private_x509_cert_t *this)
 {
@@ -1782,6 +1865,7 @@ static private_x509_cert_t* create_empty(void)
                                .get_subjectKeyIdentifier = _get_subjectKeyIdentifier,
                                .get_authKeyIdentifier = _get_authKeyIdentifier,
                                .get_pathLenConstraint = _get_pathLenConstraint,
+                               .get_policyConstraint = _get_policyConstraint,
                                .create_subjectAltName_enumerator = _create_subjectAltName_enumerator,
                                .create_crl_uri_enumerator = _create_crl_uri_enumerator,
                                .create_ocsp_uri_enumerator = _create_ocsp_uri_enumerator,
@@ -1801,6 +1885,8 @@ static private_x509_cert_t* create_empty(void)
                .cert_policies = linked_list_create(),
                .policy_mappings = linked_list_create(),
                .pathLenConstraint = X509_NO_CONSTRAINT,
+               .explicit_policy_constraint = X509_NO_CONSTRAINT,
+               .inhibit_policy_constraint = X509_NO_CONSTRAINT,
                .ref = 1,
        );
        return this;
@@ -1880,6 +1966,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
        chunk_t subjectAltNames = chunk_empty, policyMappings = chunk_empty;
        chunk_t subjectKeyIdentifier = chunk_empty, authKeyIdentifier = chunk_empty;
        chunk_t crlDistributionPoints = chunk_empty, authorityInfoAccess = chunk_empty;
+       chunk_t policyConstraints = chunk_empty;
        identification_t *issuer, *subject;
        crl_uri_t *entry;
        chunk_t key_info;
@@ -1999,9 +2086,8 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
 
                if (cert->pathLenConstraint != X509_NO_CONSTRAINT)
                {
-                       char pathlen = (char)cert->pathLenConstraint;
-
-                       pathLenConstraint = asn1_integer("c", chunk_from_thing(pathlen));
+                       pathLenConstraint = asn1_integer("c",
+                                                                       chunk_from_thing(cert->pathLenConstraint));
                }
                basicConstraints = asn1_wrap(ASN1_SEQUENCE, "mmm",
                                                                asn1_build_known_oid(OID_BASIC_CONSTRAINTS),
@@ -2184,16 +2270,40 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
                                                                asn1_wrap(ASN1_SEQUENCE, "m", policyMappings)));
        }
 
+       if (cert->inhibit_policy_constraint != X509_NO_CONSTRAINT ||
+               cert->explicit_policy_constraint != X509_NO_CONSTRAINT)
+       {
+               chunk_t inhibit = chunk_empty, explicit = chunk_empty;
+
+               if (cert->explicit_policy_constraint != X509_NO_CONSTRAINT)
+               {
+                       explicit = asn1_wrap(ASN1_CONTEXT_C_0, "m",
+                                               asn1_integer("c",
+                                                       chunk_from_thing(cert->explicit_policy_constraint)));
+               }
+               if (cert->inhibit_policy_constraint != X509_NO_CONSTRAINT)
+               {
+                       inhibit = asn1_wrap(ASN1_CONTEXT_C_1, "m",
+                                               asn1_integer("c",
+                                                       chunk_from_thing(cert->inhibit_policy_constraint)));
+               }
+               policyConstraints = asn1_wrap(ASN1_SEQUENCE, "mm",
+                                                               asn1_build_known_oid(OID_POLICY_CONSTRAINTS),
+                                                               asn1_wrap(ASN1_OCTET_STRING, "m",
+                                                                       asn1_wrap(ASN1_SEQUENCE, "mm",
+                                                                               explicit, inhibit)));
+       }
+
        if (basicConstraints.ptr || subjectAltNames.ptr || authKeyIdentifier.ptr ||
                crlDistributionPoints.ptr || nameConstraints.ptr)
        {
                extensions = asn1_wrap(ASN1_CONTEXT_C_3, "m",
-                                               asn1_wrap(ASN1_SEQUENCE, "mmmmmmmmmmm",
+                                               asn1_wrap(ASN1_SEQUENCE, "mmmmmmmmmmmm",
                                                        basicConstraints, keyUsage, subjectKeyIdentifier,
                                                        authKeyIdentifier, subjectAltNames,
                                                        extendedKeyUsage, crlDistributionPoints,
                                                        authorityInfoAccess, nameConstraints, certPolicies,
-                                                       policyMappings));
+                                                       policyMappings, policyConstraints));
        }
 
        cert->tbsCertificate = asn1_wrap(ASN1_SEQUENCE, "mmmcmcmm",
@@ -2436,6 +2546,12 @@ x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args)
                                enumerator->destroy(enumerator);
                                continue;
                        }
+                       case BUILD_POLICY_CONSTRAINT_EXPLICIT:
+                               cert->explicit_policy_constraint = va_arg(args, int);
+                               continue;
+                       case BUILD_POLICY_CONSTRAINT_INHIBIT:
+                               cert->inhibit_policy_constraint = va_arg(args, int);
+                               continue;
                        case BUILD_NOT_BEFORE_TIME:
                                cert->notBefore = va_arg(args, time_t);
                                continue;