Blame SOURCES/0015-MS-cert-template-add-template-extension-to-CSR.patch

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