|
|
7a8c6d |
From 616bc539e7054f7e561ca66672019f7990759811 Mon Sep 17 00:00:00 2001
|
|
|
7a8c6d |
From: Fraser Tweedale <ftweedal@redhat.com>
|
|
|
7a8c6d |
Date: Thu, 17 Aug 2017 18:10:37 +1000
|
|
|
7a8c6d |
Subject: [PATCH] MS cert template: add template extension to CSR
|
|
|
7a8c6d |
|
|
|
7a8c6d |
Add the MS V2 certificate template extension to the CSR, when the
|
|
|
7a8c6d |
attribute is set. Failure to parse the value (as stored) merely
|
|
|
7a8c6d |
causes the extension to be skipped.
|
|
|
7a8c6d |
|
|
|
7a8c6d |
Part of: https://pagure.io/certmonger/issue/78
|
|
|
7a8c6d |
---
|
|
|
7a8c6d |
src/certext.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
|
|
|
7a8c6d |
1 file changed, 84 insertions(+), 2 deletions(-)
|
|
|
7a8c6d |
|
|
|
7a8c6d |
diff --git a/src/certext.c b/src/certext.c
|
|
|
7a8c6d |
index 64ae05a..5f8a743 100644
|
|
|
7a8c6d |
--- a/src/certext.c
|
|
|
7a8c6d |
+++ b/src/certext.c
|
|
|
7a8c6d |
@@ -69,7 +69,7 @@ struct kerberos_principal_name {
|
|
|
7a8c6d |
struct ms_template {
|
|
|
7a8c6d |
SECItem id;
|
|
|
7a8c6d |
SECItem major;
|
|
|
7a8c6d |
- SECItem *minor;
|
|
|
7a8c6d |
+ SECItem minor;
|
|
|
7a8c6d |
};
|
|
|
7a8c6d |
|
|
|
7a8c6d |
/* KerberosString: RFC 4120, 5.2.1 */
|
|
|
7a8c6d |
@@ -180,7 +180,7 @@ cm_ms_template_template[] = {
|
|
|
7a8c6d |
.kind = SEC_ASN1_SEQUENCE,
|
|
|
7a8c6d |
.offset = 0,
|
|
|
7a8c6d |
.sub = NULL,
|
|
|
7a8c6d |
- .size = sizeof(struct kerberos_principal_name),
|
|
|
7a8c6d |
+ .size = sizeof(struct ms_template),
|
|
|
7a8c6d |
},
|
|
|
7a8c6d |
{
|
|
|
7a8c6d |
.kind = SEC_ASN1_OBJECT_ID,
|
|
|
7a8c6d |
@@ -1593,6 +1593,76 @@ cm_certext_build_profile(struct cm_store_entry *entry,
|
|
|
7a8c6d |
return item;
|
|
|
7a8c6d |
}
|
|
|
7a8c6d |
|
|
|
7a8c6d |
+/* Build a Microsoft certificate template extension value. */
|
|
|
7a8c6d |
+static SECItem *
|
|
|
7a8c6d |
+cm_certext_build_certificate_template(
|
|
|
7a8c6d |
+ PLArenaPool *arena,
|
|
|
7a8c6d |
+ char *template_spec)
|
|
|
7a8c6d |
+{
|
|
|
7a8c6d |
+ struct ms_template template_data;
|
|
|
7a8c6d |
+ memset(&template_data, 0, sizeof(struct ms_template));
|
|
|
7a8c6d |
+
|
|
|
7a8c6d |
+ if (NULL == template_spec || *template_spec == '\0')
|
|
|
7a8c6d |
+ return NULL;
|
|
|
7a8c6d |
+
|
|
|
7a8c6d |
+ /* strtok overwrites delimiters with null bytes;
|
|
|
7a8c6d |
+ * therefore duplicate the input string */
|
|
|
7a8c6d |
+ char *template_spec_dup = PORT_ArenaStrdup(arena, template_spec);
|
|
|
7a8c6d |
+ if (NULL == template_spec_dup)
|
|
|
7a8c6d |
+ return NULL;
|
|
|
7a8c6d |
+
|
|
|
7a8c6d |
+ int i = 0;
|
|
|
7a8c6d |
+ char *saveptr, *endptr;
|
|
|
7a8c6d |
+ for (
|
|
|
7a8c6d |
+ char *part = strtok_r(template_spec_dup, ":", &saveptr);
|
|
|
7a8c6d |
+ part != NULL;
|
|
|
7a8c6d |
+ part = strtok_r(NULL, ":", &saveptr)
|
|
|
7a8c6d |
+ ) {
|
|
|
7a8c6d |
+ if (i == 0) {
|
|
|
7a8c6d |
+ // parse OID
|
|
|
7a8c6d |
+ if (SECSuccess != SEC_StringToOID(arena, &template_data.id, part, 0))
|
|
|
7a8c6d |
+ return NULL;
|
|
|
7a8c6d |
+ }
|
|
|
7a8c6d |
+ else if (i == 1) {
|
|
|
7a8c6d |
+ // parse major version
|
|
|
7a8c6d |
+ long x = strtol(part, &endptr, 10);
|
|
|
7a8c6d |
+ if (*part == '\0' || *endptr != '\0') {
|
|
|
7a8c6d |
+ // string was empty or contained non-digits
|
|
|
7a8c6d |
+ return NULL;
|
|
|
7a8c6d |
+ }
|
|
|
7a8c6d |
+ if (SEC_ASN1EncodeInteger(arena, &template_data.major, x)
|
|
|
7a8c6d |
+ != &template_data.major)
|
|
|
7a8c6d |
+ return NULL;
|
|
|
7a8c6d |
+ }
|
|
|
7a8c6d |
+ else if (i == 2) {
|
|
|
7a8c6d |
+ // parse minor version
|
|
|
7a8c6d |
+ long x = strtol(part, &endptr, 10);
|
|
|
7a8c6d |
+ if (*part == '\0' || *endptr != '\0') {
|
|
|
7a8c6d |
+ // string was empty or contained non-digits
|
|
|
7a8c6d |
+ return NULL;
|
|
|
7a8c6d |
+ }
|
|
|
7a8c6d |
+ if (SEC_ASN1EncodeInteger(arena, &template_data.minor, x)
|
|
|
7a8c6d |
+ != &template_data.minor)
|
|
|
7a8c6d |
+ return NULL;
|
|
|
7a8c6d |
+ }
|
|
|
7a8c6d |
+ else {
|
|
|
7a8c6d |
+ // there are too many parts!
|
|
|
7a8c6d |
+ return NULL;
|
|
|
7a8c6d |
+ }
|
|
|
7a8c6d |
+ i++;
|
|
|
7a8c6d |
+ }
|
|
|
7a8c6d |
+ if (i < 2) {
|
|
|
7a8c6d |
+ // there are too few parts! (OID and major version are required)
|
|
|
7a8c6d |
+ return NULL;
|
|
|
7a8c6d |
+ }
|
|
|
7a8c6d |
+
|
|
|
7a8c6d |
+ SECItem encoded;
|
|
|
7a8c6d |
+ if (SEC_ASN1EncodeItem(arena, &encoded, &template_data,
|
|
|
7a8c6d |
+ cm_ms_template_template) != &encoded)
|
|
|
7a8c6d |
+ return NULL;
|
|
|
7a8c6d |
+ return SECITEM_ArenaDupItem(arena, &encoded);
|
|
|
7a8c6d |
+}
|
|
|
7a8c6d |
+
|
|
|
7a8c6d |
/* Build a Netscape certtype extension value. */
|
|
|
7a8c6d |
static SECItem *
|
|
|
7a8c6d |
cm_certext_build_ns_certtype(struct cm_store_entry *entry,
|
|
|
7a8c6d |
@@ -1840,6 +1910,18 @@ cm_certext_build_csr_extensions(struct cm_store_entry *entry,
|
|
|
7a8c6d |
i++;
|
|
|
7a8c6d |
}
|
|
|
7a8c6d |
}
|
|
|
7a8c6d |
+ if (entry->cm_template_certificate_template != NULL) {
|
|
|
7a8c6d |
+ oid = (SECOidData *) &oid_microsoft_certificate_template;
|
|
|
7a8c6d |
+ item = cm_certext_build_certificate_template(
|
|
|
7a8c6d |
+ arena, entry->cm_template_certificate_template);
|
|
|
7a8c6d |
+ if ((item != NULL) && (oid != NULL)) {
|
|
|
7a8c6d |
+ ext[i].id = oid->oid;
|
|
|
7a8c6d |
+ ext[i].critical = der_false;
|
|
|
7a8c6d |
+ ext[i].value = *item;
|
|
|
7a8c6d |
+ exts[i] = &ext[i];
|
|
|
7a8c6d |
+ i++;
|
|
|
7a8c6d |
+ }
|
|
|
7a8c6d |
+ }
|
|
|
7a8c6d |
if (entry->cm_template_ns_certtype != NULL) {
|
|
|
7a8c6d |
oid = SECOID_FindOIDByTag(SEC_OID_NS_CERT_EXT_CERT_TYPE);
|
|
|
7a8c6d |
item = cm_certext_build_ns_certtype(entry, arena,
|
|
|
7a8c6d |
--
|
|
|
7a8c6d |
2.14.4
|
|
|
7a8c6d |
|