Added policyMappings support to x509 plugin
This commit is contained in:
@@ -47,6 +47,7 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END,
|
|||||||
"BUILD_PERMITTED_NAME_CONSTRAINTS",
|
"BUILD_PERMITTED_NAME_CONSTRAINTS",
|
||||||
"BUILD_EXCLUDED_NAME_CONSTRAINTS",
|
"BUILD_EXCLUDED_NAME_CONSTRAINTS",
|
||||||
"BUILD_CERTIFICATE_POLICIES",
|
"BUILD_CERTIFICATE_POLICIES",
|
||||||
|
"BUILD_POLICY_MAPPINGS",
|
||||||
"BUILD_X509_FLAG",
|
"BUILD_X509_FLAG",
|
||||||
"BUILD_REVOKED_ENUMERATOR",
|
"BUILD_REVOKED_ENUMERATOR",
|
||||||
"BUILD_CHALLENGE_PWD",
|
"BUILD_CHALLENGE_PWD",
|
||||||
|
|||||||
@@ -101,6 +101,8 @@ enum builder_part_t {
|
|||||||
BUILD_EXCLUDED_NAME_CONSTRAINTS,
|
BUILD_EXCLUDED_NAME_CONSTRAINTS,
|
||||||
/** certificatePolicy OIDs, linked_list_t* of x509_cert_policy_t* */
|
/** certificatePolicy OIDs, linked_list_t* of x509_cert_policy_t* */
|
||||||
BUILD_CERTIFICATE_POLICIES,
|
BUILD_CERTIFICATE_POLICIES,
|
||||||
|
/** policyMapping OIDs, linked_list_t* of x509_policy_mapping_t* */
|
||||||
|
BUILD_POLICY_MAPPINGS,
|
||||||
/** enforce an additional X509 flag, x509_flag_t */
|
/** enforce an additional X509 flag, x509_flag_t */
|
||||||
BUILD_X509_FLAG,
|
BUILD_X509_FLAG,
|
||||||
/** enumerator_t over (chunk_t serial, time_t date, crl_reason_t reason) */
|
/** enumerator_t over (chunk_t serial, time_t date, crl_reason_t reason) */
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
typedef struct x509_t x509_t;
|
typedef struct x509_t x509_t;
|
||||||
typedef struct x509_cert_policy_t x509_cert_policy_t;
|
typedef struct x509_cert_policy_t x509_cert_policy_t;
|
||||||
|
typedef struct x509_policy_mapping_t x509_policy_mapping_t;
|
||||||
typedef enum x509_flag_t x509_flag_t;
|
typedef enum x509_flag_t x509_flag_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,6 +67,16 @@ struct x509_cert_policy_t {
|
|||||||
char *unotice_text;
|
char *unotice_text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* X.509 policyMapping extension
|
||||||
|
*/
|
||||||
|
struct x509_policy_mapping_t {
|
||||||
|
/** OID of issuerDomainPolicy */
|
||||||
|
chunk_t issuer;
|
||||||
|
/** OID of subjectDomainPolicy */
|
||||||
|
chunk_t subject;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* X.509 certificate interface.
|
* X.509 certificate interface.
|
||||||
*
|
*
|
||||||
@@ -156,6 +167,13 @@ struct x509_t {
|
|||||||
* @return enumerator over x509_cert_policy_t
|
* @return enumerator over x509_cert_policy_t
|
||||||
*/
|
*/
|
||||||
enumerator_t* (*create_cert_policy_enumerator)(x509_t *this);
|
enumerator_t* (*create_cert_policy_enumerator)(x509_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an enumerator over policy mappings.
|
||||||
|
*
|
||||||
|
* @return enumerator over x509_policy_mapping
|
||||||
|
*/
|
||||||
|
enumerator_t* (*create_policy_mapping_enumerator)(x509_t *this);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /** X509_H_ @}*/
|
#endif /** X509_H_ @}*/
|
||||||
|
|||||||
@@ -574,6 +574,7 @@ static private_openssl_x509_t *create_empty()
|
|||||||
.create_ipAddrBlock_enumerator = (void*)enumerator_create_empty,
|
.create_ipAddrBlock_enumerator = (void*)enumerator_create_empty,
|
||||||
.create_name_constraint_enumerator = (void*)enumerator_create_empty,
|
.create_name_constraint_enumerator = (void*)enumerator_create_empty,
|
||||||
.create_cert_policy_enumerator = (void*)enumerator_create_empty,
|
.create_cert_policy_enumerator = (void*)enumerator_create_empty,
|
||||||
|
.create_policy_mapping_enumerator = (void*)enumerator_create_empty,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.subjectAltNames = linked_list_create(),
|
.subjectAltNames = linked_list_create(),
|
||||||
|
|||||||
@@ -146,6 +146,11 @@ struct private_x509_cert_t {
|
|||||||
*/
|
*/
|
||||||
linked_list_t *cert_policies;
|
linked_list_t *cert_policies;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of policyMappings, as x509_policy_mapping_t
|
||||||
|
*/
|
||||||
|
linked_list_t *policy_mappings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* certificate's embedded public key
|
* certificate's embedded public key
|
||||||
*/
|
*/
|
||||||
@@ -244,6 +249,16 @@ static void cert_policy_destroy(x509_cert_policy_t *this)
|
|||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free policy mapping
|
||||||
|
*/
|
||||||
|
static void policy_mapping_destroy(x509_policy_mapping_t *mapping)
|
||||||
|
{
|
||||||
|
free(mapping->issuer.ptr);
|
||||||
|
free(mapping->subject.ptr);
|
||||||
|
free(mapping);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASN.1 definition of a basicConstraints extension
|
* ASN.1 definition of a basicConstraints extension
|
||||||
*/
|
*/
|
||||||
@@ -959,6 +974,62 @@ static void parse_certificatePolicies(chunk_t blob, int level0,
|
|||||||
parser->destroy(parser);
|
parser->destroy(parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ASN.1 definition of a policyMappings extension
|
||||||
|
*/
|
||||||
|
static const asn1Object_t policyMappingsObjects[] = {
|
||||||
|
{ 0, "policyMappings", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
|
||||||
|
{ 1, "policyMapping", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
|
||||||
|
{ 2, "issuerPolicy", ASN1_OID, ASN1_BODY }, /* 2 */
|
||||||
|
{ 2, "subjectPolicy", ASN1_OID, ASN1_BODY }, /* 3 */
|
||||||
|
{ 0, "end loop", ASN1_EOC, ASN1_END }, /* 4 */
|
||||||
|
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
|
||||||
|
};
|
||||||
|
#define POLICY_MAPPING 1
|
||||||
|
#define POLICY_MAPPING_ISSUER 2
|
||||||
|
#define POLICY_MAPPING_SUBJECT 3
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse policyMappings
|
||||||
|
*/
|
||||||
|
static void parse_policyMappings(chunk_t blob, int level0,
|
||||||
|
private_x509_cert_t *this)
|
||||||
|
{
|
||||||
|
x509_policy_mapping_t *map = NULL;
|
||||||
|
asn1_parser_t *parser;
|
||||||
|
chunk_t object;
|
||||||
|
int objectID;
|
||||||
|
|
||||||
|
parser = asn1_parser_create(policyMappingsObjects, blob);
|
||||||
|
parser->set_top_level(parser, level0);
|
||||||
|
|
||||||
|
while (parser->iterate(parser, &objectID, &object))
|
||||||
|
{
|
||||||
|
switch (objectID)
|
||||||
|
{
|
||||||
|
case POLICY_MAPPING:
|
||||||
|
INIT(map);
|
||||||
|
this->policy_mappings->insert_last(this->policy_mappings, map);
|
||||||
|
break;
|
||||||
|
case POLICY_MAPPING_ISSUER:
|
||||||
|
if (map && !map->issuer.len)
|
||||||
|
{
|
||||||
|
map->issuer = chunk_clone(object);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case POLICY_MAPPING_SUBJECT:
|
||||||
|
if (map && !map->subject.len)
|
||||||
|
{
|
||||||
|
map->subject = chunk_clone(object);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parser->destroy(parser);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASN.1 definition of ipAddrBlocks according to RFC 3779
|
* ASN.1 definition of ipAddrBlocks according to RFC 3779
|
||||||
*/
|
*/
|
||||||
@@ -1274,6 +1345,9 @@ static bool parse_certificate(private_x509_cert_t *this)
|
|||||||
case OID_CERTIFICATE_POLICIES:
|
case OID_CERTIFICATE_POLICIES:
|
||||||
parse_certificatePolicies(object, level, this);
|
parse_certificatePolicies(object, level, this);
|
||||||
break;
|
break;
|
||||||
|
case OID_POLICY_MAPPINGS:
|
||||||
|
parse_policyMappings(object, level, this);
|
||||||
|
break;
|
||||||
case OID_NS_REVOCATION_URL:
|
case OID_NS_REVOCATION_URL:
|
||||||
case OID_NS_CA_REVOCATION_URL:
|
case OID_NS_CA_REVOCATION_URL:
|
||||||
case OID_NS_CA_POLICY_URL:
|
case OID_NS_CA_POLICY_URL:
|
||||||
@@ -1638,6 +1712,12 @@ METHOD(x509_t, create_cert_policy_enumerator, enumerator_t*,
|
|||||||
return this->cert_policies->create_enumerator(this->cert_policies);
|
return this->cert_policies->create_enumerator(this->cert_policies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(x509_t, create_policy_mapping_enumerator, enumerator_t*,
|
||||||
|
private_x509_cert_t *this)
|
||||||
|
{
|
||||||
|
return this->policy_mappings->create_enumerator(this->policy_mappings);
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(certificate_t, destroy, void,
|
METHOD(certificate_t, destroy, void,
|
||||||
private_x509_cert_t *this)
|
private_x509_cert_t *this)
|
||||||
{
|
{
|
||||||
@@ -1655,6 +1735,8 @@ METHOD(certificate_t, destroy, void,
|
|||||||
offsetof(identification_t, destroy));
|
offsetof(identification_t, destroy));
|
||||||
this->cert_policies->destroy_function(this->cert_policies,
|
this->cert_policies->destroy_function(this->cert_policies,
|
||||||
(void*)cert_policy_destroy);
|
(void*)cert_policy_destroy);
|
||||||
|
this->policy_mappings->destroy_function(this->policy_mappings,
|
||||||
|
(void*)policy_mapping_destroy);
|
||||||
DESTROY_IF(this->issuer);
|
DESTROY_IF(this->issuer);
|
||||||
DESTROY_IF(this->subject);
|
DESTROY_IF(this->subject);
|
||||||
DESTROY_IF(this->public_key);
|
DESTROY_IF(this->public_key);
|
||||||
@@ -1706,6 +1788,7 @@ static private_x509_cert_t* create_empty(void)
|
|||||||
.create_ipAddrBlock_enumerator = _create_ipAddrBlock_enumerator,
|
.create_ipAddrBlock_enumerator = _create_ipAddrBlock_enumerator,
|
||||||
.create_name_constraint_enumerator = _create_name_constraint_enumerator,
|
.create_name_constraint_enumerator = _create_name_constraint_enumerator,
|
||||||
.create_cert_policy_enumerator = _create_cert_policy_enumerator,
|
.create_cert_policy_enumerator = _create_cert_policy_enumerator,
|
||||||
|
.create_policy_mapping_enumerator = _create_policy_mapping_enumerator,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.version = 1,
|
.version = 1,
|
||||||
@@ -1716,6 +1799,7 @@ static private_x509_cert_t* create_empty(void)
|
|||||||
.permitted_names = linked_list_create(),
|
.permitted_names = linked_list_create(),
|
||||||
.excluded_names = linked_list_create(),
|
.excluded_names = linked_list_create(),
|
||||||
.cert_policies = linked_list_create(),
|
.cert_policies = linked_list_create(),
|
||||||
|
.policy_mappings = linked_list_create(),
|
||||||
.pathLenConstraint = X509_NO_PATH_LEN_CONSTRAINT,
|
.pathLenConstraint = X509_NO_PATH_LEN_CONSTRAINT,
|
||||||
.ref = 1,
|
.ref = 1,
|
||||||
);
|
);
|
||||||
@@ -1793,7 +1877,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
|
|||||||
chunk_t ocspSigning = chunk_empty, certPolicies = chunk_empty;
|
chunk_t ocspSigning = chunk_empty, certPolicies = chunk_empty;
|
||||||
chunk_t basicConstraints = chunk_empty, nameConstraints = chunk_empty;
|
chunk_t basicConstraints = chunk_empty, nameConstraints = chunk_empty;
|
||||||
chunk_t keyUsage = chunk_empty, keyUsageBits = chunk_empty;
|
chunk_t keyUsage = chunk_empty, keyUsageBits = chunk_empty;
|
||||||
chunk_t subjectAltNames = chunk_empty;
|
chunk_t subjectAltNames = chunk_empty, policyMappings = chunk_empty;
|
||||||
chunk_t subjectKeyIdentifier = chunk_empty, authKeyIdentifier = chunk_empty;
|
chunk_t subjectKeyIdentifier = chunk_empty, authKeyIdentifier = chunk_empty;
|
||||||
chunk_t crlDistributionPoints = chunk_empty, authorityInfoAccess = chunk_empty;
|
chunk_t crlDistributionPoints = chunk_empty, authorityInfoAccess = chunk_empty;
|
||||||
identification_t *issuer, *subject;
|
identification_t *issuer, *subject;
|
||||||
@@ -2078,15 +2162,38 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
|
|||||||
asn1_wrap(ASN1_SEQUENCE, "m", certPolicies)));
|
asn1_wrap(ASN1_SEQUENCE, "m", certPolicies)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cert->policy_mappings->get_count(cert->policy_mappings))
|
||||||
|
{
|
||||||
|
x509_policy_mapping_t *mapping;
|
||||||
|
|
||||||
|
enumerator = create_policy_mapping_enumerator(cert);
|
||||||
|
while (enumerator->enumerate(enumerator, &mapping))
|
||||||
|
{
|
||||||
|
chunk_t chunk;
|
||||||
|
|
||||||
|
chunk = asn1_wrap(ASN1_SEQUENCE, "mm",
|
||||||
|
asn1_wrap(ASN1_OID, "c", mapping->issuer),
|
||||||
|
asn1_wrap(ASN1_OID, "c", mapping->subject));
|
||||||
|
policyMappings = chunk_cat("mm", policyMappings, chunk);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
policyMappings = asn1_wrap(ASN1_SEQUENCE, "mm",
|
||||||
|
asn1_build_known_oid(OID_POLICY_MAPPINGS),
|
||||||
|
asn1_wrap(ASN1_OCTET_STRING, "m",
|
||||||
|
asn1_wrap(ASN1_SEQUENCE, "m", policyMappings)));
|
||||||
|
}
|
||||||
|
|
||||||
if (basicConstraints.ptr || subjectAltNames.ptr || authKeyIdentifier.ptr ||
|
if (basicConstraints.ptr || subjectAltNames.ptr || authKeyIdentifier.ptr ||
|
||||||
crlDistributionPoints.ptr || nameConstraints.ptr)
|
crlDistributionPoints.ptr || nameConstraints.ptr)
|
||||||
{
|
{
|
||||||
extensions = asn1_wrap(ASN1_CONTEXT_C_3, "m",
|
extensions = asn1_wrap(ASN1_CONTEXT_C_3, "m",
|
||||||
asn1_wrap(ASN1_SEQUENCE, "mmmmmmmmmm",
|
asn1_wrap(ASN1_SEQUENCE, "mmmmmmmmmmm",
|
||||||
basicConstraints, keyUsage, subjectKeyIdentifier,
|
basicConstraints, keyUsage, subjectKeyIdentifier,
|
||||||
authKeyIdentifier, subjectAltNames,
|
authKeyIdentifier, subjectAltNames,
|
||||||
extendedKeyUsage, crlDistributionPoints,
|
extendedKeyUsage, crlDistributionPoints,
|
||||||
authorityInfoAccess, nameConstraints, certPolicies));
|
authorityInfoAccess, nameConstraints, certPolicies,
|
||||||
|
policyMappings));
|
||||||
}
|
}
|
||||||
|
|
||||||
cert->tbsCertificate = asn1_wrap(ASN1_SEQUENCE, "mmmcmcmm",
|
cert->tbsCertificate = asn1_wrap(ASN1_SEQUENCE, "mmmcmcmm",
|
||||||
@@ -2309,6 +2416,26 @@ x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args)
|
|||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
case BUILD_POLICY_MAPPINGS:
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
linked_list_t *list;
|
||||||
|
x509_policy_mapping_t* mapping, *in;
|
||||||
|
|
||||||
|
list = va_arg(args, linked_list_t*);
|
||||||
|
enumerator = list->create_enumerator(list);
|
||||||
|
while (enumerator->enumerate(enumerator, &in))
|
||||||
|
{
|
||||||
|
INIT(mapping,
|
||||||
|
.issuer = chunk_clone(in->issuer),
|
||||||
|
.subject = chunk_clone(in->subject),
|
||||||
|
);
|
||||||
|
cert->policy_mappings->insert_last(cert->policy_mappings,
|
||||||
|
mapping);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
case BUILD_NOT_BEFORE_TIME:
|
case BUILD_NOT_BEFORE_TIME:
|
||||||
cert->notBefore = va_arg(args, time_t);
|
cert->notBefore = va_arg(args, time_t);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
Reference in New Issue
Block a user