diff --git a/SOURCES/0012-Remove-trailing-CR-LF-when-reading-passwords-from-a-.patch b/SOURCES/0012-Remove-trailing-CR-LF-when-reading-passwords-from-a-.patch
new file mode 100644
index 0000000..dbca807
--- /dev/null
+++ b/SOURCES/0012-Remove-trailing-CR-LF-when-reading-passwords-from-a-.patch
@@ -0,0 +1,35 @@
+From a55000a067d68cbf7aaf201b73ba2eb14090f916 Mon Sep 17 00:00:00 2001
+From: Rob Crittenden <rcritten@redhat.com>
+Date: Wed, 21 Feb 2018 15:28:38 -0500
+Subject: [PATCH] Remove trailing CR/LF when reading passwords from a file.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1547641
+---
+ src/dogtag.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/src/dogtag.c b/src/dogtag.c
+index 5b55b04d..871f3875 100644
+--- a/src/dogtag.c
++++ b/src/dogtag.c
+@@ -476,9 +476,17 @@ main(int argc, const char **argv)
+ 	/* Read the client password and/or PIN, if we need to. */
+ 	if ((pwdfile != NULL) && (pwd == NULL)) {
+ 		pwd = cm_submit_u_from_file(pwdfile);
++        if (pwd != NULL) {
++            pwd = talloc_strndup(ctx, pwd,
++                        strcspn(pwd, "\r\n"));
++		}
+ 	}
+ 	if ((pinfile != NULL) && (pin == NULL)) {
+ 		pin = cm_submit_u_from_file(pinfile);
++        if (pin != NULL) {
++            pin = talloc_strndup(ctx, pin,
++                        strcspn(pin, "\r\n"));
++		}
+ 	}
+ 
+ 	/* Figure out which form and arguments to use. */
+-- 
+2.13.6
+
diff --git a/SOURCES/0013-Disable-the-10-iterate-tests-which-randomly-fail.patch b/SOURCES/0013-Disable-the-10-iterate-tests-which-randomly-fail.patch
new file mode 100644
index 0000000..b0fe84e
--- /dev/null
+++ b/SOURCES/0013-Disable-the-10-iterate-tests-which-randomly-fail.patch
@@ -0,0 +1,35 @@
+From 80e016cc4efef1b7f9abc73e209e83bcd3fa0c6f Mon Sep 17 00:00:00 2001
+From: Rob Crittenden <rcritten@redhat.com>
+Date: Tue, 17 Jul 2018 16:22:02 -0400
+Subject: [PATCH] Disable the 10-iterate tests which randomly fail
+
+Sometimes the dates are off just enough to cause the comparison
+to fail.
+---
+ tests/Makefile.am | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index f60e571..bbcd06e 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -62,8 +62,6 @@ EXTRA_DIST = \
+ 	008-certread/expected.out \
+ 	009-oiddict/run.sh \
+ 	009-oiddict/expected.out \
+-	010-iterate/run.sh \
+-	010-iterate/expected.out \
+ 	011-dbinit/expected.out \
+ 	011-dbinit/run.sh \
+ 	011-dbinit-dbm/expected.out \
+@@ -166,7 +164,6 @@ subdirs = \
+ 	007-certsave \
+ 	008-certread \
+ 	009-oiddict \
+-	010-iterate \
+ 	011-dbinit \
+ 	012-dbadd \
+ 	013-enckey \
+-- 
+2.13.6
+
diff --git a/SOURCES/0014-MS-cert-template-add-D-Bus-property-and-storage.patch b/SOURCES/0014-MS-cert-template-add-D-Bus-property-and-storage.patch
new file mode 100644
index 0000000..f4fa5c6
--- /dev/null
+++ b/SOURCES/0014-MS-cert-template-add-D-Bus-property-and-storage.patch
@@ -0,0 +1,198 @@
+From afe1fc05a5da349c3e24e8c96b1e185e4da53613 Mon Sep 17 00:00:00 2001
+From: Fraser Tweedale <ftweedal@redhat.com>
+Date: Thu, 17 Aug 2017 11:38:43 +1000
+Subject: [PATCH] MS cert template: add D-Bus property and storage
+
+Add a D-Bus property and storage for a new template attribute, which
+will hold data to be included in CSRs in the MS V2 certificate
+template extension.
+
+The server does not validate the extension data (validation
+behaviour is implemented in a subsequent commit).
+
+Part of: https://pagure.io/certmonger/issue/78
+---
+ doc/api.txt                 |  2 ++
+ src/store-files.c           | 10 ++++++++++
+ src/store-int.h             |  1 +
+ src/tdbus.h                 |  1 +
+ src/tdbush.c                | 29 ++++++++++++++++++++++++++++-
+ tests/028-dbus/expected.out |  1 +
+ 6 files changed, 43 insertions(+), 1 deletion(-)
+
+diff --git a/doc/api.txt b/doc/api.txt
+index 31016be..83cf375 100644
+--- a/doc/api.txt
++++ b/doc/api.txt
+@@ -56,6 +56,7 @@ o object layout
+                {("template-crldp"),array-of-string (CRL distribution point URIs)}
+                {("template-ns-comment"),string (Netscape comment)}
+                {("template-profile"),string (certificate profile)}
++               {("template-ms-certificate-template"),string (MS V2 template specifier; format: <oid>:<major-version>[:<minor-version>] )}
+                {("template-issuer"),string (requested issuer)}
+                {("template-challenge-password"),string (password to add to CSR)}
+                {("template-challenge-password-file"),string (password file)
+@@ -165,6 +166,7 @@ o object layout
+                {("template-crldp"),array-of-string (CRL distribution point URIs)}
+                {("template-ns-comment"),string (Netscape comment)}
+                {("template-profile"),string (certificate profile)}
++               {("template-ms-certificate-template"),string (MS V2 template specifier; format: <oid>:<major-version>[:<minor-version>] )}
+                {("template-issuer"),string (requested issuer)}
+                {("template-challenge-password"),string (password to add to CSR)}
+                {("template-challenge-password-file"),string (password file)
+diff --git a/src/store-files.c b/src/store-files.c
+index 889829c..977e896 100644
+--- a/src/store-files.c
++++ b/src/store-files.c
+@@ -130,6 +130,7 @@ enum cm_store_file_field {
+ 	cm_store_entry_field_template_ns_comment,
+ 	cm_store_entry_field_template_profile,
+ 	cm_store_entry_field_template_issuer,
++	cm_store_entry_field_template_certificate_template,
+ 	cm_store_entry_field_template_no_ocsp_check,
+ 	cm_store_entry_field_template_ns_certtype,
+ 
+@@ -305,6 +306,7 @@ static struct cm_store_file_field_list {
+ 	{cm_store_entry_field_template_profile, "template_profile"}, /* right */
+ 	{cm_store_entry_field_template_profile, "ca_profile"}, /* wrong */
+ 	{cm_store_entry_field_template_issuer, "template_issuer"},
++	{cm_store_entry_field_template_certificate_template, "template_certificate_template"},
+ 	{cm_store_entry_field_template_no_ocsp_check, "template_no_ocsp_check"},
+ 	{cm_store_entry_field_template_ns_certtype, "template_ns_certtype"},
+ 
+@@ -1129,6 +1131,9 @@ cm_store_entry_read(void *parent, const char *filename, FILE *fp)
+ 			case cm_store_entry_field_template_profile:
+ 				ret->cm_template_profile = free_if_empty(p);
+ 				break;
++			case cm_store_entry_field_template_certificate_template:
++				ret->cm_template_certificate_template = free_if_empty(p);
++				break;
+ 			case cm_store_entry_field_template_issuer:
+ 				ret->cm_template_issuer = free_if_empty(p);
+ 				break;
+@@ -1375,6 +1380,7 @@ cm_store_ca_read(void *parent, const char *filename, FILE *fp)
+ 			case cm_store_entry_field_template_ocsp_location:
+ 			case cm_store_entry_field_template_ns_comment:
+ 			case cm_store_entry_field_template_profile:
++			case cm_store_entry_field_template_certificate_template:
+ 			case cm_store_entry_field_template_issuer:
+ 			case cm_store_entry_field_template_no_ocsp_check:
+ 			case cm_store_entry_field_template_ns_certtype:
+@@ -1984,6 +1990,8 @@ cm_store_entry_write(FILE *fp, struct cm_store_entry *entry)
+ 				entry->cm_template_no_ocsp_check ? 1 : 0);
+ 	cm_store_file_write_str(fp, cm_store_entry_field_template_ns_certtype,
+ 				entry->cm_template_ns_certtype);
++	cm_store_file_write_str(fp, cm_store_entry_field_template_certificate_template,
++				entry->cm_template_certificate_template);
+ 
+ 	cm_store_file_write_str(fp, cm_store_entry_field_challenge_password,
+ 				entry->cm_template_challenge_password);
+@@ -2745,6 +2753,8 @@ cm_store_entry_dup(void *parent, struct cm_store_entry *entry)
+ 	ret->cm_template_profile = cm_store_maybe_strdup(ret, entry->cm_template_profile);
+ 	ret->cm_template_issuer = cm_store_maybe_strdup(ret, entry->cm_template_issuer);
+ 	ret->cm_template_no_ocsp_check = entry->cm_template_no_ocsp_check;
++	ret->cm_template_certificate_template =
++		cm_store_maybe_strdup(ret, entry->cm_template_certificate_template);
+ 	ret->cm_template_ns_certtype = cm_store_maybe_strdup(ret,
+ 							     entry->cm_template_ns_certtype);
+ 
+diff --git a/src/store-int.h b/src/store-int.h
+index 2d3a353..98b37e6 100644
+--- a/src/store-int.h
++++ b/src/store-int.h
+@@ -144,6 +144,7 @@ struct cm_store_entry {
+ 	char *cm_template_profile;
+ 	char *cm_template_issuer;
+ 	char *cm_template_ns_certtype;
++	char *cm_template_certificate_template;
+ 	unsigned int cm_template_no_ocsp_check: 1;
+ 	/* A challenge password, which may be included (in cleartext form!) in
+ 	 * a CSR. */
+diff --git a/src/tdbus.h b/src/tdbus.h
+index 496f2dd..7164f11 100644
+--- a/src/tdbus.h
++++ b/src/tdbus.h
+@@ -110,6 +110,7 @@
+ #define CM_DBUS_PROP_TEMPLATE_PROFILE "template-profile"
+ #define CM_DBUS_PROP_TEMPLATE_ISSUER "template-issuer"
+ #define CM_DBUS_PROP_TEMPLATE_NS_CERTTYPE "template-ns-certtype"
++#define CM_DBUS_PROP_TEMPLATE_MS_CERTIFICATE_TEMPLATE "template-ms-certificate-template"
+ #define CM_DBUS_SIGNAL_REQUEST_CERT_SAVED "SavedCertificate"
+ #define CM_DBUS_PROP_CA_PRESAVE_COMMAND "ca-presave-command"
+ #define CM_DBUS_PROP_CA_PRESAVE_UID "ca-presave-uid"
+diff --git a/src/tdbush.c b/src/tdbush.c
+index 631da3e..94bf793 100644
+--- a/src/tdbush.c
++++ b/src/tdbush.c
+@@ -1568,6 +1568,14 @@ base_add_request(DBusConnection *conn, DBusMessage *msg,
+ 		new_entry->cm_template_issuer = maybe_strdup(new_entry,
+ 							     param->value.s);
+ 	}
++	param = cm_tdbusm_find_dict_entry(d,
++					  CM_DBUS_PROP_TEMPLATE_MS_CERTIFICATE_TEMPLATE,
++					  cm_tdbusm_dict_s);
++	if (param != NULL) {
++		// TODO check validity
++		new_entry->cm_template_certificate_template = maybe_strdup(new_entry,
++									   param->value.s);
++	}
+ 	param = cm_tdbusm_find_dict_entry(d,
+ 					  CM_DBUS_PROP_TEMPLATE_CHALLENGE_PASSWORD,
+ 					  cm_tdbusm_dict_s);
+@@ -3320,6 +3328,17 @@ request_modify(DBusConnection *conn, DBusMessage *msg,
+ 					propname[n_propname++] = CM_DBUS_PROP_TEMPLATE_ISSUER;
+ 				}
+ 			} else
++			if ((param->value_type == cm_tdbusm_dict_s) &&
++			    (strcasecmp(param->key, CM_DBUS_PROP_TEMPLATE_MS_CERTIFICATE_TEMPLATE) == 0)) {
++				talloc_free(entry->cm_template_certificate_template);
++				// TODO check validity
++				entry->cm_template_certificate_template =
++					maybe_strdup(entry, param->value.s);
++				if (n_propname + 2 < sizeof(propname) / sizeof(propname[0])) {
++					propname[n_propname++] =
++						CM_DBUS_PROP_TEMPLATE_MS_CERTIFICATE_TEMPLATE;
++				}
++			} else
+ 			if ((param->value_type == cm_tdbusm_dict_s) &&
+ 			    (strcasecmp(param->key, CM_DBUS_PROP_TEMPLATE_CHALLENGE_PASSWORD) == 0)) {
+ 				talloc_free(entry->cm_template_challenge_password);
+@@ -6734,6 +6753,14 @@ cm_tdbush_iface_request(void)
+ 								       offsetof(struct cm_store_entry, cm_template_issuer),
+ 								       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 								       NULL),
++				     make_interface_item(cm_tdbush_interface_property,
++							 make_property(CM_DBUS_PROP_TEMPLATE_MS_CERTIFICATE_TEMPLATE,
++								       cm_tdbush_property_string,
++								       cm_tdbush_property_readwrite,
++								       cm_tdbush_property_char_p,
++								       offsetof(struct cm_store_entry, cm_template_certificate_template),
++								       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++								       NULL),
+ 				     make_interface_item(cm_tdbush_interface_property,
+ 							 make_property(CM_DBUS_PROP_TEMPLATE_NS_CERTTYPE,
+ 								       cm_tdbush_property_string,
+@@ -7179,7 +7206,7 @@ cm_tdbush_iface_request(void)
+ 				     make_interface_item(cm_tdbush_interface_signal,
+ 							 make_signal(CM_DBUS_SIGNAL_REQUEST_CERT_SAVED,
+ 								     NULL),
+-							 NULL))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))));
++							 NULL)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))));
+ 	}
+ 	return ret;
+ }
+diff --git a/tests/028-dbus/expected.out b/tests/028-dbus/expected.out
+index 93cc4d1..8a81a7f 100644
+--- a/tests/028-dbus/expected.out
++++ b/tests/028-dbus/expected.out
+@@ -330,6 +330,7 @@ OK
+   <property name="template-ns-comment" type="s" access="readwrite"/>
+   <property name="template-profile" type="s" access="readwrite"/>
+   <property name="template-issuer" type="s" access="readwrite"/>
++  <property name="template-ms-certificate-template" type="s" access="readwrite"/>
+   <property name="template-ns-certtype" type="s" access="readwrite"/>
+   <property name="template-challenge-password" type="s" access="readwrite"/>
+   <property name="template-challenge-password-file" type="s" access="readwrite"/>
+-- 
+2.14.4
+
diff --git a/SOURCES/0015-MS-cert-template-add-template-extension-to-CSR.patch b/SOURCES/0015-MS-cert-template-add-template-extension-to-CSR.patch
new file mode 100644
index 0000000..bcb14f1
--- /dev/null
+++ b/SOURCES/0015-MS-cert-template-add-template-extension-to-CSR.patch
@@ -0,0 +1,135 @@
+From 616bc539e7054f7e561ca66672019f7990759811 Mon Sep 17 00:00:00 2001
+From: Fraser Tweedale <ftweedal@redhat.com>
+Date: Thu, 17 Aug 2017 18:10:37 +1000
+Subject: [PATCH] MS cert template: add template extension to CSR
+
+Add the MS V2 certificate template extension to the CSR, when the
+attribute is set.  Failure to parse the value (as stored) merely
+causes the extension to be skipped.
+
+Part of: https://pagure.io/certmonger/issue/78
+---
+ src/certext.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 84 insertions(+), 2 deletions(-)
+
+diff --git a/src/certext.c b/src/certext.c
+index 64ae05a..5f8a743 100644
+--- a/src/certext.c
++++ b/src/certext.c
+@@ -69,7 +69,7 @@ struct kerberos_principal_name {
+ struct ms_template {
+ 	SECItem id;
+ 	SECItem major;
+-	SECItem *minor;
++	SECItem minor;
+ };
+ 
+ /* KerberosString: RFC 4120, 5.2.1 */
+@@ -180,7 +180,7 @@ cm_ms_template_template[] = {
+ 	.kind = SEC_ASN1_SEQUENCE,
+ 	.offset = 0,
+ 	.sub = NULL,
+-	.size = sizeof(struct kerberos_principal_name),
++	.size = sizeof(struct ms_template),
+ 	},
+ 	{
+ 	.kind = SEC_ASN1_OBJECT_ID,
+@@ -1593,6 +1593,76 @@ cm_certext_build_profile(struct cm_store_entry *entry,
+ 	return item;
+ }
+ 
++/* Build a Microsoft certificate template extension value. */
++static SECItem *
++cm_certext_build_certificate_template(
++	PLArenaPool *arena,
++	char *template_spec)
++{
++	struct ms_template template_data;
++	memset(&template_data, 0, sizeof(struct ms_template));
++
++	if (NULL == template_spec || *template_spec == '\0')
++		return NULL;
++
++	/* strtok overwrites delimiters with null bytes;
++	 * therefore duplicate the input string */
++	char *template_spec_dup = PORT_ArenaStrdup(arena, template_spec);
++	if (NULL == template_spec_dup)
++		return NULL;
++
++	int i = 0;
++	char *saveptr, *endptr;
++	for (
++		char *part = strtok_r(template_spec_dup, ":", &saveptr);
++		part != NULL;
++		part = strtok_r(NULL, ":", &saveptr)
++	) {
++		if (i == 0) {
++			// parse OID
++			if (SECSuccess != SEC_StringToOID(arena, &template_data.id, part, 0))
++				return NULL;
++		}
++		else if (i == 1) {
++			// parse major version
++			long x = strtol(part, &endptr, 10);
++			if (*part == '\0' || *endptr != '\0') {
++				// string was empty or contained non-digits
++				return NULL;
++			}
++			if (SEC_ASN1EncodeInteger(arena, &template_data.major, x)
++					!= &template_data.major)
++				return NULL;
++		}
++		else if (i == 2) {
++			// parse minor version
++			long x = strtol(part, &endptr, 10);
++			if (*part == '\0' || *endptr != '\0') {
++				// string was empty or contained non-digits
++				return NULL;
++			}
++			if (SEC_ASN1EncodeInteger(arena, &template_data.minor, x)
++					!= &template_data.minor)
++				return NULL;
++		}
++		else {
++			// there are too many parts!
++			return NULL;
++		}
++		i++;
++	}
++	if (i < 2) {
++		// there are too few parts! (OID and major version are required)
++		return NULL;
++	}
++
++	SECItem encoded;
++	if (SEC_ASN1EncodeItem(arena, &encoded, &template_data,
++			       cm_ms_template_template) != &encoded)
++		return NULL;
++	return SECITEM_ArenaDupItem(arena, &encoded);
++}
++
+ /* Build a Netscape certtype extension value. */
+ static SECItem *
+ cm_certext_build_ns_certtype(struct cm_store_entry *entry,
+@@ -1840,6 +1910,18 @@ cm_certext_build_csr_extensions(struct cm_store_entry *entry,
+ 			i++;
+ 		}
+ 	}
++	if (entry->cm_template_certificate_template != NULL) {
++		oid = (SECOidData *) &oid_microsoft_certificate_template;
++		item = cm_certext_build_certificate_template(
++			arena, entry->cm_template_certificate_template);
++		if ((item != NULL) && (oid != NULL)) {
++			ext[i].id = oid->oid;
++			ext[i].critical = der_false;
++			ext[i].value = *item;
++			exts[i] = &ext[i];
++			i++;
++		}
++	}
+ 	if (entry->cm_template_ns_certtype != NULL) {
+ 		oid = SECOID_FindOIDByTag(SEC_OID_NS_CERT_EXT_CERT_TYPE);
+ 		item = cm_certext_build_ns_certtype(entry, arena,
+-- 
+2.14.4
+
diff --git a/SOURCES/0016-MS-cert-template-add-option-to-command-line-programs.patch b/SOURCES/0016-MS-cert-template-add-option-to-command-line-programs.patch
new file mode 100644
index 0000000..5270264
--- /dev/null
+++ b/SOURCES/0016-MS-cert-template-add-option-to-command-line-programs.patch
@@ -0,0 +1,246 @@
+From 199a97c11d4fc3a9e0f10e4eebf44f9f3841f8b1 Mon Sep 17 00:00:00 2001
+From: Fraser Tweedale <ftweedal@redhat.com>
+Date: Fri, 18 Aug 2017 13:03:05 +1000
+Subject: [PATCH] MS cert template: add option to command line programs
+
+Add the --ms-template-spec command line argument for specifying the
+value of the V2 Certificate Template extension.
+
+Part of: https://pagure.io/certmonger/issue/78
+---
+ src/getcert-request.1.in        |  6 ++++++
+ src/getcert-resubmit.1.in       |  6 ++++++
+ src/getcert-start-tracking.1.in |  6 ++++++
+ src/getcert.c                   | 46 +++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 64 insertions(+)
+
+diff --git a/src/getcert-request.1.in b/src/getcert-request.1.in
+index b6578dc..8269b78 100644
+--- a/src/getcert-request.1.in
++++ b/src/getcert-request.1.in
+@@ -88,6 +88,12 @@ the CA should correspond to one listed by \fIgetcert list-cas\fR.
+ Request a certificate using the named profile, template, or certtype,
+ from the specified CA.
+ .TP
++\fB\-\-ms-template-spec\fR SPEC
++Include a V2 Certificate Template extension in the signing request.
++This datum includes an Object Identifier, a major version number
++(positive integer) and an optional minor version number.  The format
++is: \fB<oid>:<majorVersion>[:<minorVersion>]\fR.
++.TP
+ \fB\-X\fR NAME
+ Request a certificate using the named issuer from the specified CA.
+ 
+diff --git a/src/getcert-resubmit.1.in b/src/getcert-resubmit.1.in
+index 165940e..62d5f28 100644
+--- a/src/getcert-resubmit.1.in
++++ b/src/getcert-resubmit.1.in
+@@ -48,6 +48,12 @@ the CA should correspond to one listed by \fIgetcert list-cas\fR.
+ Request a certificate using the named profile, template, or certtype,
+ from the specified CA.
+ .TP
++\fB\-\-ms-template-spec\fR SPEC
++Include a V2 Certificate Template extension in the signing request.
++This datum includes an Object Identifier, a major version number
++(positive integer) and an optional minor version number.  The format
++is: \fB<oid>:<majorVersion>[:<minorVersion>]\fR.
++.TP
+ \fB\-X\fR NAME
+ Request a certificate using the named issuer from the specified CA.
+ .TP
+diff --git a/src/getcert-start-tracking.1.in b/src/getcert-start-tracking.1.in
+index a46f535..9daeed3 100644
+--- a/src/getcert-start-tracking.1.in
++++ b/src/getcert-start-tracking.1.in
+@@ -86,6 +86,12 @@ useful in combination with \fB\-r\fR.
+ Request a certificate using the named profile, template, or certtype,
+ from the specified CA.
+ .TP
++\fB\-\-ms-template-spec\fR SPEC
++Include a V2 Certificate Template extension in the signing request.
++This datum includes an Object Identifier, a major version number
++(positive integer) and an optional minor version number.  The format
++is: \fB<oid>:<majorVersion>[:<minorVersion>]\fR.
++.TP
+ \fB\-X\fR NAME
+ Request a certificate using the named issuer from the specified CA.
+ 
+diff --git a/src/getcert.c b/src/getcert.c
+index c84273a..5277a15 100644
+--- a/src/getcert.c
++++ b/src/getcert.c
+@@ -692,6 +692,7 @@ request(const char *argv0, int argc, const char **argv)
+ 	int keysize = 0, auto_renew = 1, verbose = 0, ku = 0, kubit, c, i, j;
+ 	char *ca = DEFAULT_CA, *subject = NULL, **eku = NULL, *oid, *id = NULL;
+ 	char *profile = NULL, *issuer = NULL, kustring[16];
++	char *ms_template_spec = NULL;
+ 	char **principal = NULL, **dns = NULL, **email = NULL, **ipaddr = NULL;
+ 	char *key_owner = NULL, *key_perms = NULL;
+ 	char *cert_owner = NULL, *cert_perms = NULL;
+@@ -732,6 +733,7 @@ request(const char *argv0, int argc, const char **argv)
+ 		{"ca", 'c', POPT_ARG_STRING, &ca, 0, _("use the specified CA configuration rather than the default"), HELP_TYPE_NAME},
+ #endif
+ 		{"profile", 'T', POPT_ARG_STRING, NULL, 'T', _("ask the CA to process the request using the named profile or template"), HELP_TYPE_NAME},
++		{"ms-template-spec", 0, POPT_ARG_STRING, NULL, 'Y', _("include V2 template specifier in CSR (format: OID:MAJOR-VERSION[:MINOR-VERSION])"), HELP_TYPE_NAME},
+ 		{"issuer", 'X', POPT_ARG_STRING, NULL, 'X', _("ask the CA to process the request using the named issuer"), HELP_TYPE_NAME},
+ 		{"subject-name", 'N', POPT_ARG_STRING, NULL, 'N', _("set requested subject name (default: CN=<hostname>)"), HELP_TYPE_SUBJECT},
+ 		{"key-usage", 'u', POPT_ARG_STRING, NULL, 'u', _("set requested key usage value"), HELP_TYPE_KU},
+@@ -859,6 +861,9 @@ request(const char *argv0, int argc, const char **argv)
+ 		case 'T':
+ 			profile = talloc_strdup(globals.tctx, poptarg);
+ 			break;
++		case 'Y':
++			ms_template_spec = talloc_strdup(globals.tctx, poptarg);
++			break;
+ 		case 'X':
+ 			issuer = talloc_strdup(globals.tctx, poptarg);
+ 			break;
+@@ -1293,6 +1298,13 @@ request(const char *argv0, int argc, const char **argv)
+ 		params[i] = &param[i];
+ 		i++;
+ 	}
++	if (ms_template_spec != NULL) {
++		param[i].key = CM_DBUS_PROP_TEMPLATE_MS_CERTIFICATE_TEMPLATE;
++		param[i].value_type = cm_tdbusm_dict_s;
++		param[i].value.s = ms_template_spec;
++		params[i] = &param[i];
++		i++;
++	}
+ 	if (issuer != NULL) {
+ 		param[i].key = CM_DBUS_PROP_TEMPLATE_ISSUER;
+ 		param[i].value_type = cm_tdbusm_dict_s;
+@@ -1492,6 +1504,7 @@ add_basic_request(enum cm_tdbus_type bus, char *id,
+ 		  char *pin, char *pinfile,
+ 		  char *cpass, char *cpassfile,
+ 		  char *ca, char *profile, char *issuer,
++		  char *ms_template_spec,
+ 		  char *precommand, char *postcommand,
+ 		  char **anchor_dbs, char **anchor_files,
+ 		  dbus_bool_t auto_renew_stop, int waitreq,
+@@ -1655,6 +1668,13 @@ add_basic_request(enum cm_tdbus_type bus, char *id,
+ 		params[i] = &param[i];
+ 		i++;
+ 	}
++	if (ms_template_spec != NULL) {
++		param[i].key = CM_DBUS_PROP_TEMPLATE_MS_CERTIFICATE_TEMPLATE;
++		param[i].value_type = cm_tdbusm_dict_s;
++		param[i].value.s = ms_template_spec;
++		params[i] = &param[i];
++		i++;
++	}
+ 	if (issuer != NULL) {
+ 		param[i].key = CM_DBUS_PROP_TEMPLATE_ISSUER;
+ 		param[i].value_type = cm_tdbusm_dict_s;
+@@ -1745,6 +1765,7 @@ set_tracking(const char *argv0, const char *category,
+ 	char *id = NULL, *new_id = NULL, *new_request;
+ 	char *keyfile = NULL, *certfile = NULL, *ca = DEFAULT_CA;
+ 	char *profile = NULL, *issuer = NULL;
++	char *ms_template_spec = NULL;
+ 	char *pin = NULL, *pinfile = NULL, *cpass = NULL, *cpassfile = NULL;
+ 	char *key_owner = NULL, *key_perms = NULL;
+ 	char *cert_owner = NULL, *cert_perms = NULL;
+@@ -1785,6 +1806,7 @@ set_tracking(const char *argv0, const char *category,
+ 		{"ca", 'c', POPT_ARG_STRING, &ca, 0, _("use the specified CA configuration rather than the default"), HELP_TYPE_NAME},
+ #endif
+ 		{"profile", 'T', POPT_ARG_STRING, NULL, 'T', _("ask the CA to process the request using the named profile or template"), HELP_TYPE_NAME},
++		{"ms-template-spec", 0, POPT_ARG_STRING, NULL, 'Y', _("include V2 template specifier in CSR (format: OID:MAJOR-VERSION[:MINOR-VERSION])"), HELP_TYPE_NAME},
+ 		{"issuer", 'X', POPT_ARG_STRING, NULL, 'X', _("ask the CA to process the request using the named issuer"), HELP_TYPE_NAME},
+ 		{"key-usage", 'u', POPT_ARG_STRING, NULL, 'u', _("override requested key usage value"), HELP_TYPE_KU},
+ 		{"extended-key-usage", 'U', POPT_ARG_STRING, NULL, 'U', _("override requested extended key usage OID"), HELP_TYPE_EKU},
+@@ -1887,6 +1909,9 @@ set_tracking(const char *argv0, const char *category,
+ 		case 'T':
+ 			profile = talloc_strdup(globals.tctx, poptarg);
+ 			break;
++		case 'Y':
++			ms_template_spec = talloc_strdup(globals.tctx, poptarg);
++			break;
+ 		case 'i':
+ 			id = talloc_strdup(globals.tctx, poptarg);
+ 			break;
+@@ -2311,6 +2336,7 @@ set_tracking(const char *argv0, const char *category,
+ 						 pin, pinfile,
+ 						 cpass, cpassfile,
+ 						 ca, profile, issuer,
++						 ms_template_spec,
+ 						 precommand, postcommand,
+ 						 anchor_dbs, anchor_files,
+ 						 (auto_renew_stop > 0),
+@@ -2386,6 +2412,7 @@ rekey_or_resubmit(const char *argv0, const char *category, int argc,
+ 	char *subject = NULL, **eku = NULL, *oid = NULL;
+ 	char **principal = NULL, **dns = NULL, **email = NULL, **ipaddr = NULL;
+ 	char *profile = NULL, *issuer = NULL, kustring[16];
++	char *ms_template_spec = NULL;
+ 	char *key_owner = NULL, *key_perms = NULL;
+ 	char *cert_owner = NULL, *cert_perms = NULL;
+ 	char *keytype = NULL;
+@@ -2422,6 +2449,7 @@ rekey_or_resubmit(const char *argv0, const char *category, int argc,
+ 		{"ca", 'c', POPT_ARG_STRING, &ca, 0, _("use the specified CA configuration rather than the current one"), HELP_TYPE_NAME},
+ #endif
+ 		{"profile", 'T', POPT_ARG_STRING, NULL, 'T', _("ask the CA to process the request using the named profile or template"), HELP_TYPE_NAME},
++		{"ms-template-spec", 0, POPT_ARG_STRING, NULL, 'Y', _("include V2 template specifier in CSR (format: OID:MAJOR-VERSION[:MINOR-VERSION])"), HELP_TYPE_NAME},
+ 		{"issuer", 'X', POPT_ARG_STRING, NULL, 'X', _("ask the CA to process the request using the named issuer"), HELP_TYPE_NAME},
+ 		{"subject-name", 'N', POPT_ARG_STRING, NULL, 'N', _("set requested subject name (default: CN=<hostname>)"), HELP_TYPE_SUBJECT},
+ 		{"key-usage", 'u', POPT_ARG_STRING, NULL, 'u', _("set requested key usage value"), HELP_TYPE_KU},
+@@ -2497,6 +2525,9 @@ rekey_or_resubmit(const char *argv0, const char *category, int argc,
+ 		case 'T':
+ 			profile = talloc_strdup(globals.tctx, poptarg);
+ 			break;
++		case 'Y':
++			ms_template_spec = talloc_strdup(globals.tctx, poptarg);
++			break;
+ 		case 'X':
+ 			issuer = talloc_strdup(globals.tctx, poptarg);
+ 			break;
+@@ -2861,6 +2892,13 @@ rekey_or_resubmit(const char *argv0, const char *category, int argc,
+ 		params[i] = &param[i];
+ 		i++;
+ 	}
++	if (ms_template_spec != NULL) {
++		param[i].key = CM_DBUS_PROP_TEMPLATE_MS_CERTIFICATE_TEMPLATE;
++		param[i].value_type = cm_tdbusm_dict_s;
++		param[i].value.s = ms_template_spec;
++		params[i] = &param[i];
++		i++;
++	}
+ 	if (issuer != NULL) {
+ 		param[i].key = CM_DBUS_PROP_TEMPLATE_ISSUER;
+ 		param[i].value_type = cm_tdbusm_dict_s;
+@@ -4677,6 +4715,8 @@ help(const char *twopartcmd, const char *category)
+ 		N_("  -c CA		use the specified CA rather than the default\n"),
+ #endif
+ 		N_("  -T PROFILE	ask the CA to process the request using the named profile or template\n"),
++		N_("  --ms-template-spec SPEC\n"),
++		N_("	 include V2 template specifier in CSR (format: OID:MAJOR-VERSION[:MINOR-VERSION])\n"),
+ 		N_("  -X ISSUER	ask the CA to process the request using the named issuer\n"),
+ 		N_("* Parameters for the signing request:\n"),
+ 		N_("  -N NAME	set requested subject name (default: CN=<hostname>)\n"),
+@@ -4726,6 +4766,8 @@ help(const char *twopartcmd, const char *category)
+ 		N_("  -c CA		use the specified CA rather than the default\n"),
+ #endif
+ 		N_("  -T PROFILE	ask the CA to process the request using the named profile or template\n"),
++		N_("  --ms-template-spec SPEC\n"),
++		N_("	 include V2 template specifier in CSR (format: OID:MAJOR-VERSION[:MINOR-VERSION])\n"),
+ 		N_("  -X ISSUER	ask the CA to process the request using the named issuer\n"),
+ 		N_("* Parameters for the signing request at renewal time:\n"),
+ 		N_("  -U EXTUSAGE	override requested extended key usage OID\n"),
+@@ -4805,6 +4847,8 @@ help(const char *twopartcmd, const char *category)
+ 		N_("  -c CA		use the specified CA rather than the current one\n"),
+ #endif
+ 		N_("  -T PROFILE	ask the CA to process the request using the named profile or template\n"),
++		N_("  --ms-template-spec SPEC\n"),
++		N_("	 include V2 template specifier in CSR (format: OID:MAJOR-VERSION[:MINOR-VERSION])\n"),
+ 		N_("  -X ISSUER	ask the CA to process the request using the named issuer\n"),
+ 		N_("* Bus options:\n"),
+ 		N_("  -S		connect to the certmonger service on the system bus\n"),
+@@ -4853,6 +4897,8 @@ help(const char *twopartcmd, const char *category)
+ 		N_("  -c CA		use the specified CA rather than the current one\n"),
+ #endif
+ 		N_("  -T PROFILE	ask the CA to process the request using the named profile or template\n"),
++		N_("  --ms-template-spec SPEC\n"),
++		N_("	 include V2 template specifier in CSR (format: OID:MAJOR-VERSION[:MINOR-VERSION])\n"),
+ 		N_("  -X ISSUER	ask the CA to process the request using the named issuer\n"),
+ 		N_("  -G TYPE	type of new key to be generated\n"),
+ 		N_("  -g SIZE	size of new key to be generated\n"),
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0017-MS-cert-template-validate-argument.patch b/SOURCES/0017-MS-cert-template-validate-argument.patch
new file mode 100644
index 0000000..cf4d2f6
--- /dev/null
+++ b/SOURCES/0017-MS-cert-template-validate-argument.patch
@@ -0,0 +1,143 @@
+From 481fb8581fdf891b768eeb0bc88855c27689722b Mon Sep 17 00:00:00 2001
+From: Fraser Tweedale <ftweedal@redhat.com>
+Date: Fri, 18 Aug 2017 16:17:49 +1000
+Subject: [PATCH] MS cert template: validate argument
+
+Update the server to validate the MS V2 certificate template option
+argument when adding or updating a request.
+
+Fixes: https://pagure.io/certmonger/issue/78
+---
+ src/Makefile.am |  4 +++-
+ src/certext.c   | 13 +++++++++++++
+ src/certext.h   |  5 +++++
+ src/tdbush.c    | 25 +++++++++++++++++++++++--
+ 4 files changed, 44 insertions(+), 3 deletions(-)
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 479903c..213bfa9 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -186,7 +186,7 @@ tdbusm_check_SOURCES = tdbusm-check.c tm.c tm.h
+ tdbusm_check_LDADD = libcm.a $(CERTMONGER_LIBS) $(POPT_LIBS)
+ serial_check_LDADD = libcm.a $(CERTMONGER_LIBS) $(LTLIBICONV)
+ nl_check_LDADD = libcm.a $(CERTMONGER_LIBS)
+-submit_x_CFLAGS = $(AM_CFLAGS) -DCM_SUBMIT_X_MAIN
++submit_x_CFLAGS = $(AM_CFLAGS) $(NSS_CFLAGS) -DCM_SUBMIT_X_MAIN
+ submit_x_SOURCES = submit-x.c submit-x.h submit-u.c submit-u.h log.c log.h \
+ 	tm.c tm.h
+ submit_x_LDADD = $(XMLRPC_LIBS) $(KRB5_LIBS) $(TALLOC_LIBS) \
+@@ -205,12 +205,14 @@ pkglibexec_PROGRAMS += local-submit
+ pkglibexec_PROGRAMS += scep-submit
+ endif
+ noinst_PROGRAMS += submit-h submit-d
++ipa_submit_CFLAGS = $(AM_CFLAGS) $(NSS_CFLAGS)
+ ipa_submit_SOURCES = ipa.c srvloc.c srvloc.h store.h store-gen.c \
+ 		submit-x.c submit-x.h submit-u.c submit-u.h \
+ 		submit-e.h util.c util.h log.c log.h tm.c tm.h
+ ipa_submit_LDADD = $(XMLRPC_LIBS) $(LDAP_LIBS) $(KRB5_LIBS) $(TALLOC_LIBS) \
+ 		   $(GMP_LIBS) $(IDN_LIBS) $(OPENSSL_LIBS) $(UUID_LIBS) \
+ 		   $(RESOLV_LIBS) $(LTLIBICONV) $(POPT_LIBS)
++certmaster_submit_CFLAGS = $(AM_CFLAGS) $(NSS_CFLAGS)
+ certmaster_submit_SOURCES = certmaster.c submit-x.c submit-x.h \
+ 		submit-e.h submit-u.c submit-u.h util.c util.h log.c log.h \
+ 		tm.c tm.h
+diff --git a/src/certext.c b/src/certext.c
+index 5f8a743..587496f 100644
+--- a/src/certext.c
++++ b/src/certext.c
+@@ -1663,6 +1663,19 @@ cm_certext_build_certificate_template(
+ 	return SECITEM_ArenaDupItem(arena, &encoded);
+ }
+ 
++/* Validate a V2 template spec */
++PRBool cm_ms_template_valid(char *template_spec) {
++	PLArenaPool *arena = PORT_NewArena(sizeof(double));
++	if (arena == NULL)
++		return PR_FALSE;
++	SECItem *result =
++		cm_certext_build_certificate_template(arena, template_spec);
++	PORT_FreeArena(arena, PR_FALSE);
++	// *result has been freed, but we don't read it;
++	// we only need to know whether the parse succeeded
++	return result != NULL;
++}
++
+ /* Build a Netscape certtype extension value. */
+ static SECItem *
+ cm_certext_build_ns_certtype(struct cm_store_entry *entry,
+diff --git a/src/certext.h b/src/certext.h
+index 530ece4..5e95835 100644
+--- a/src/certext.h
++++ b/src/certext.h
+@@ -15,6 +15,8 @@
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  */
+ 
++#include <prtypes.h>
++
+ #ifndef cmcertext_h
+ #define cmcertext_h
+ 
+@@ -25,4 +27,7 @@ void cm_certext_build_csr_extensions(struct cm_store_entry *entry,
+ 				     struct NSSInitContextStr *ctx,
+ 				     unsigned char **encoded, size_t *length);
+ 
++/* Validate a V2 template spec */
++PRBool cm_ms_template_valid(char *template_spec);
++
+ #endif
+diff --git a/src/tdbush.c b/src/tdbush.c
+index 9e2a372..04fe57e 100644
+--- a/src/tdbush.c
++++ b/src/tdbush.c
+@@ -32,6 +32,7 @@
+ 
+ #include "log.h"
+ #include "cm.h"
++#include "certext.h"
+ #include "prefs.h"
+ #include "store.h"
+ #include "store-int.h"
+@@ -1572,7 +1573,18 @@ base_add_request(DBusConnection *conn, DBusMessage *msg,
+ 					  CM_DBUS_PROP_TEMPLATE_MS_CERTIFICATE_TEMPLATE,
+ 					  cm_tdbusm_dict_s);
+ 	if (param != NULL) {
+-		// TODO check validity
++		if (param->value.s != NULL
++		    && strlen(param->value.s) > 0
++		    && !cm_ms_template_valid(param->value.s)) {
++			cm_log(1, "Invalid V2 certificate template specifier: %s", param->value.s);
++			ret = send_internal_base_bad_arg_error(
++				conn, msg,
++				_("Invalid V2 certificate template specifier: %s"),
++				param->value.s,
++				CM_DBUS_PROP_TEMPLATE_MS_CERTIFICATE_TEMPLATE);
++			talloc_free(parent);
++			return ret;
++		}
+ 		new_entry->cm_template_certificate_template = maybe_strdup(new_entry,
+ 									   param->value.s);
+ 	}
+@@ -3330,8 +3342,17 @@ request_modify(DBusConnection *conn, DBusMessage *msg,
+ 			} else
+ 			if ((param->value_type == cm_tdbusm_dict_s) &&
+ 			    (strcasecmp(param->key, CM_DBUS_PROP_TEMPLATE_MS_CERTIFICATE_TEMPLATE) == 0)) {
++				if (param->value.s != NULL
++				    && strlen(param->value.s) > 0
++				    && !cm_ms_template_valid(param->value.s)) {
++					cm_log(1, "Invalid V2 certificate template specifier: %s", param->value.s);
++					return send_internal_base_bad_arg_error(
++						conn, msg,
++						_("Invalid V2 certificate template specifier: %s"),
++						param->value.s,
++						CM_DBUS_PROP_TEMPLATE_MS_CERTIFICATE_TEMPLATE);
++				}
+ 				talloc_free(entry->cm_template_certificate_template);
+-				// TODO check validity
+ 				entry->cm_template_certificate_template =
+ 					maybe_strdup(entry, param->value.s);
+ 				if (n_propname + 2 < sizeof(propname) / sizeof(propname[0])) {
+-- 
+2.14.4
+
diff --git a/SOURCES/0018-MS-cert-template-add-tests.patch b/SOURCES/0018-MS-cert-template-add-tests.patch
new file mode 100644
index 0000000..22da5ab
--- /dev/null
+++ b/SOURCES/0018-MS-cert-template-add-tests.patch
@@ -0,0 +1,165 @@
+From c33a8fe36d340447641d4dc623c98d2bf9a2d650 Mon Sep 17 00:00:00 2001
+From: Fraser Tweedale <ftweedal@redhat.com>
+Date: Thu, 24 Aug 2017 13:37:36 +1000
+Subject: [PATCH] MS cert template: add tests
+
+Part of: https://pagure.io/certmonger/issue/78
+---
+ tests/038-ms-v2-template/expected.out       | 19 ++++++++++
+ tests/038-ms-v2-template/extract-extdata.py | 29 ++++++++++++++++
+ tests/038-ms-v2-template/run.sh             | 54 +++++++++++++++++++++++++++++
+ tests/Makefile.am                           |  8 +++--
+ 4 files changed, 108 insertions(+), 2 deletions(-)
+ create mode 100644 tests/038-ms-v2-template/expected.out
+ create mode 100755 tests/038-ms-v2-template/extract-extdata.py
+ create mode 100755 tests/038-ms-v2-template/run.sh
+
+diff --git a/tests/038-ms-v2-template/expected.out b/tests/038-ms-v2-template/expected.out
+new file mode 100644
+index 0000000..7338a5f
+--- /dev/null
++++ b/tests/038-ms-v2-template/expected.out
+@@ -0,0 +1,19 @@
++[key]
++OK.
++[csr : bogus oid]
++extension not present
++[csr : bogus major version]
++extension not present
++[csr : missing major version]
++extension not present
++[csr : too many parts]
++extension not present
++[csr : oid, major version]
++    0:d=0  hl=2 l=   8 cons: SEQUENCE          
++    2:d=1  hl=2 l=   3 prim: OBJECT            :1.2.3.4
++    7:d=1  hl=2 l=   1 prim: INTEGER           :2A
++[csr : oid, major version, minor version]
++    0:d=0  hl=2 l=  11 cons: SEQUENCE          
++    2:d=1  hl=2 l=   3 prim: OBJECT            :1.2.3.4
++    7:d=1  hl=2 l=   1 prim: INTEGER           :2A
++   10:d=1  hl=2 l=   1 prim: INTEGER           :11
+diff --git a/tests/038-ms-v2-template/extract-extdata.py b/tests/038-ms-v2-template/extract-extdata.py
+new file mode 100755
+index 0000000..cd96f99
+--- /dev/null
++++ b/tests/038-ms-v2-template/extract-extdata.py
+@@ -0,0 +1,29 @@
++#!/bin/python2
++
++# Given `openssl asn1parse` output of a CSR, look for the V2 Template
++# extension and output its data if found.  Nonzero exit status if
++# not found.
++
++import binascii
++import re
++import sys
++
++STATE_SEARCH, STATE_FOUND, STATE_DONE = range(3)
++
++state = STATE_SEARCH
++
++for line in sys.stdin:
++    if state == STATE_SEARCH and ':1.3.6.1.4.1.311.21.7' in line:
++        state = STATE_FOUND
++        continue
++
++    # look for first OCTET STRING once we're in STATE_FOUND
++    #
++    if state == STATE_FOUND and 'OCTET STRING' in line:
++        result = re.search(r'\[HEX DUMP\]:(\w*)', line)
++        sys.stdout.write(binascii.unhexlify(result.group(1)))
++        state = STATE_DONE
++        break
++
++if state != STATE_DONE:
++    sys.exit(1)
+diff --git a/tests/038-ms-v2-template/run.sh b/tests/038-ms-v2-template/run.sh
+new file mode 100755
+index 0000000..0eeb7f9
+--- /dev/null
++++ b/tests/038-ms-v2-template/run.sh
+@@ -0,0 +1,54 @@
++#!/bin/bash -e
++
++srcdir=$PWD
++cd $tmpdir
++
++mkconfig() {
++	cat > request <<- EOF
++	key_storage_type=FILE
++	key_storage_location=$tmpdir/key
++	cert_storage_type=FILE
++	cert_storage_location=$tmpdir/cert
++	template_subject=CN=MS V2 Certificate Template test
++	EOF
++}
++
++echo "[key]"
++mkconfig
++$toolsdir/keygen request
++
++echo "[csr : bogus oid]"
++mkconfig
++echo "template_certificate_template=NotAnOid:42" >> request
++$toolsdir/csrgen request | openssl asn1parse \
++	| $srcdir/extract-extdata.py || echo "extension not present"
++
++echo "[csr : bogus major version]"
++mkconfig
++echo "template_certificate_template=1.2.3.4:wat" >> request
++$toolsdir/csrgen request | openssl asn1parse \
++	| $srcdir/extract-extdata.py || echo "extension not present"
++
++echo "[csr : missing major version]"
++mkconfig
++echo "template_certificate_template=1.2.3.4" >> request
++$toolsdir/csrgen request | openssl asn1parse \
++	| $srcdir/extract-extdata.py || echo "extension not present"
++
++echo "[csr : too many parts]"
++mkconfig
++echo "template_certificate_template=1.2.3.4:1:1:1" >> request
++$toolsdir/csrgen request | openssl asn1parse \
++	| $srcdir/extract-extdata.py || echo "extension not present"
++
++echo "[csr : oid, major version]"
++mkconfig
++echo "template_certificate_template=1.2.3.4:42" >> request
++$toolsdir/csrgen request | openssl asn1parse \
++	| $srcdir/extract-extdata.py | openssl asn1parse -inform DER
++
++echo "[csr : oid, major version, minor version]"
++mkconfig
++echo "template_certificate_template=1.2.3.4:42:17" >> request
++$toolsdir/csrgen request | openssl asn1parse \
++	| $srcdir/extract-extdata.py | openssl asn1parse -inform DER
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index bbcd06e..562b027 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -148,7 +148,10 @@ EXTRA_DIST = \
+ 	036-getcert/expected.out \
+ 	036-getcert/run.sh \
+ 	037-rekey2/expected.out \
+-	037-rekey2/run.sh
++	037-rekey2/run.sh \
++	038-ms-v2-template/expected.out \
++	038-ms-v2-template/extract-extdata.py \
++	038-ms-v2-template/run.sh
+ 
+ subdirs = \
+ 	001-keyiread \
+@@ -189,7 +192,8 @@ subdirs = \
+ 	034-perms \
+ 	035-json \
+ 	036-getcert \
+-	037-rekey2
++	037-rekey2 \
++	038-ms-v2-template
+ 
+ if HAVE_DBM_NSSDB
+ subdirs += \
+-- 
+2.14.4
+
diff --git a/SOURCES/0019-Fix-C99-build-error-on-EL7-systems.patch b/SOURCES/0019-Fix-C99-build-error-on-EL7-systems.patch
new file mode 100644
index 0000000..6f711a9
--- /dev/null
+++ b/SOURCES/0019-Fix-C99-build-error-on-EL7-systems.patch
@@ -0,0 +1,37 @@
+From f1c410e315ebf70cc18296c959f40c8870d1a105 Mon Sep 17 00:00:00 2001
+From: Trevor Vaughan <tvaughan@onyxpoint.com>
+Date: Fri, 23 Feb 2018 16:10:29 -0500
+Subject: [PATCH] Fix C99 build error on EL7 systems
+
+Needed for testing #89
+---
+ src/certext.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/certext.c b/src/certext.c
+index 587496f..c44c8bb 100644
+--- a/src/certext.c
++++ b/src/certext.c
+@@ -1,6 +1,6 @@
+ /*
+  * Copyright (C) 2009,2011,2012,2013,2014,2015 Red Hat, Inc.
+- * 
++ *
+  * This program is free software: you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation, either version 3 of the License, or
+@@ -1612,9 +1612,9 @@ cm_certext_build_certificate_template(
+ 		return NULL;
+ 
+ 	int i = 0;
+-	char *saveptr, *endptr;
++	char *saveptr, *endptr, *part;
+ 	for (
+-		char *part = strtok_r(template_spec_dup, ":", &saveptr);
++		part = strtok_r(template_spec_dup, ":", &saveptr);
+ 		part != NULL;
+ 		part = strtok_r(NULL, ":", &saveptr)
+ 	) {
+-- 
+1.8.3.1
+
diff --git a/SOURCES/1001-Remove-rekey-feature.patch b/SOURCES/1001-Remove-rekey-feature.patch
index dba4798..525ab6b 100644
--- a/SOURCES/1001-Remove-rekey-feature.patch
+++ b/SOURCES/1001-Remove-rekey-feature.patch
@@ -1,4 +1,4 @@
-From c47a439f510adffe4e2225408261d0e93059e077 Mon Sep 17 00:00:00 2001
+From 3c763332adc224d0e325502cb3e5b97d4155bb0c Mon Sep 17 00:00:00 2001
 From: Jan Cholasta <jcholast@redhat.com>
 Date: Fri, 7 Aug 2015 13:40:41 +0200
 Subject: [PATCH] Remove rekey feature
@@ -20,7 +20,7 @@ https://bugzilla.redhat.com/show_bug.cgi?id=1250397
  12 files changed, 23 insertions(+), 113 deletions(-)
 
 diff --git a/src/certmonger-scep-submit.8.in b/src/certmonger-scep-submit.8.in
-index 7319c6a42c090420eb035515d94fd0640d990dda..31203c37fde407d2306de9d7f5aba9d3541eaaa3 100644
+index 7319c6a..31203c3 100644
 --- a/src/certmonger-scep-submit.8.in
 +++ b/src/certmonger-scep-submit.8.in
 @@ -80,14 +80,6 @@ When called with the \fB-c\fR or \fB-C\fR flag, this option can be used to
@@ -39,7 +39,7 @@ index 7319c6a42c090420eb035515d94fd0640d990dda..31203c37fde407d2306de9d7f5aba9d3
  Increases the logging level.  Use twice for more logging.  This option
  is mainly useful for troubleshooting.
 diff --git a/src/certmonger.conf.5.in b/src/certmonger.conf.5.in
-index 241f48b07b5045708aa118663b569d5ac3947782..e1220f134c30e760af73fb0abc88a498e94f23d2 100644
+index 241f48b..e1220f1 100644
 --- a/src/certmonger.conf.5.in
 +++ b/src/certmonger.conf.5.in
 @@ -72,25 +72,6 @@ These are the trust attributes which are applied to certificates which are not
@@ -69,7 +69,7 @@ index 241f48b07b5045708aa118663b569d5ac3947782..e1220f134c30e760af73fb0abc88a498
  Within the \fIselfsign\fR section, these variables and values are recognized:
  
 diff --git a/src/getcert-add-scep-ca.1.in b/src/getcert-add-scep-ca.1.in
-index f07b9002a206526ea7f0334f5ba0071d8fffd3ae..64f0f5e80cd0fa3ae01fcf27828f97935dfb99c7 100644
+index f07b900..64f0f5e 100644
 --- a/src/getcert-add-scep-ca.1.in
 +++ b/src/getcert-add-scep-ca.1.in
 @@ -46,14 +46,6 @@ A CA identifier value which will passed to the server when the
@@ -88,10 +88,10 @@ index f07b9002a206526ea7f0334f5ba0071d8fffd3ae..64f0f5e80cd0fa3ae01fcf27828f9793
  Be verbose about errors.  Normally, the details of an error received from
  the daemon will be suppressed if the client can make a diagnostic suggestion.
 diff --git a/src/getcert.c b/src/getcert.c
-index c84273a9bfc8730422f18ade87ce174fbbc44634..dcdbdd455dd8c61c1aeaad6a5c7feef21b56feab 100644
+index 26a88f3..966ff41 100644
 --- a/src/getcert.c
 +++ b/src/getcert.c
-@@ -4625,7 +4625,6 @@ static struct {
+@@ -4663,7 +4663,6 @@ static struct {
  	{"start-tracking", start_tracking},
  	{"stop-tracking", stop_tracking},
  	{"resubmit", resubmit},
@@ -99,7 +99,7 @@ index c84273a9bfc8730422f18ade87ce174fbbc44634..dcdbdd455dd8c61c1aeaad6a5c7feef2
  	{"refresh", refresh},
  	{"list", list},
  	{"status", status},
-@@ -5041,8 +5040,6 @@ help(const char *twopartcmd, const char *category)
+@@ -5087,8 +5086,6 @@ help(const char *twopartcmd, const char *category)
  		 N_("stop monitoring a certificate\n")},
  		{"resubmit", resubmit_help,
  		 N_("resubmit an in-progress enrollment request, or start a new one\n")},
@@ -109,7 +109,7 @@ index c84273a9bfc8730422f18ade87ce174fbbc44634..dcdbdd455dd8c61c1aeaad6a5c7feef2
  		 N_("check on the status of an in-progress enrollment request\n")},
  		{"list", list_help,
 diff --git a/src/prefs.c b/src/prefs.c
-index ab363bbc2c08f834e7fc1bede8f1cf2c50229f1c..0a8e166ce30f3b0288cd7430568ae18d0e5ab914 100644
+index ab363bb..0a8e166 100644
 --- a/src/prefs.c
 +++ b/src/prefs.c
 @@ -545,36 +545,11 @@ cm_prefs_nss_other_trust(void)
@@ -151,7 +151,7 @@ index ab363bbc2c08f834e7fc1bede8f1cf2c50229f1c..0a8e166ce30f3b0288cd7430568ae18d
 +	return -1;
  }
 diff --git a/src/scep.c b/src/scep.c
-index d3bbc050947a1a0472187503110682c9028f9c6f..11f9ae3cc193981d3c2bf986a4a5c4c7d81506f5 100644
+index d3bbc05..11f9ae3 100644
 --- a/src/scep.c
 +++ b/src/scep.c
 @@ -231,7 +231,6 @@ main(int argc, const char **argv)
@@ -181,7 +181,7 @@ index d3bbc050947a1a0472187503110682c9028f9c6f..11f9ae3cc193981d3c2bf986a4a5c4c7
  		} else
  		if (strcasecmp(mode, CM_OP_FETCH_SCEP_CA_CERTS) == 0) {
 diff --git a/src/submit-e.c b/src/submit-e.c
-index befd01e0fd00b8f9e239752ffbd80c985fae5057..af05efeb762933e31fecc67b1204001b7e81c697 100644
+index befd01e..af05efe 100644
 --- a/src/submit-e.c
 +++ b/src/submit-e.c
 @@ -446,12 +446,6 @@ cm_submit_e_need_scep_messages(struct cm_submit_state *state)
@@ -198,13 +198,14 @@ index befd01e0fd00b8f9e239752ffbd80c985fae5057..af05efeb762933e31fecc67b1204001b
  }
  
 diff --git a/src/tdbush.c b/src/tdbush.c
-index 631da3ed2bbb1f6828d576760299ad51d7e41923..aec5e9d0a36a7cb5c035e1aefda04c2b32b1e100 100644
+index 7fb3d16..04fe57e 100644
 --- a/src/tdbush.c
 +++ b/src/tdbush.c
-@@ -7117,14 +7117,6 @@ cm_tdbush_iface_request(void)
+@@ -7164,14 +7164,6 @@ cm_tdbush_iface_request(void)
+ 										     cm_tdbush_method_arg_out,
  										     NULL))),
  								     NULL),
- 				     make_interface_item(cm_tdbush_interface_method,
+-				     make_interface_item(cm_tdbush_interface_method,
 -							 make_method("rekey",
 -								     request_rekey,
 -								     make_method_arg("working",
@@ -212,21 +213,20 @@ index 631da3ed2bbb1f6828d576760299ad51d7e41923..aec5e9d0a36a7cb5c035e1aefda04c2b
 -										     cm_tdbush_method_arg_out,
 -										     NULL),
 -								     NULL),
--				     make_interface_item(cm_tdbush_interface_method,
+ 				     make_interface_item(cm_tdbush_interface_method,
  							 make_method("resubmit",
  								     request_resubmit,
- 								     make_method_arg("working",
-@@ -7179,7 +7171,7 @@ cm_tdbush_iface_request(void)
+@@ -7227,7 +7219,7 @@ cm_tdbush_iface_request(void)
  				     make_interface_item(cm_tdbush_interface_signal,
  							 make_signal(CM_DBUS_SIGNAL_REQUEST_CERT_SAVED,
  								     NULL),
--							 NULL))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))));
-+							 NULL)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))));
+-							 NULL)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))));
++							 NULL))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))));
  	}
  	return ret;
  }
 diff --git a/tests/010-iterate/expected.out b/tests/010-iterate/expected.out
-index bd57a01ba8725418978259018441f6a9a6672758..85d07b3baef83dbafd39c03888881cb665518733 100644
+index bd57a01..85d07b3 100644
 --- a/tests/010-iterate/expected.out
 +++ b/tests/010-iterate/expected.out
 @@ -398,19 +398,15 @@ HAVE_CSR
@@ -255,10 +255,10 @@ index bd57a01ba8725418978259018441f6a9a6672758..85d07b3baef83dbafd39c03888881cb6
  
  [Enroll until we notice we have no specified CA.]
 diff --git a/tests/028-dbus/expected.out b/tests/028-dbus/expected.out
-index 93cc4d184524c4b1aeba02a650c94d832462c236..26850efaedb966cd94ecd0db42d6adb378b47f37 100644
+index 8a81a7f..4c33e9a 100644
 --- a/tests/028-dbus/expected.out
 +++ b/tests/028-dbus/expected.out
-@@ -403,9 +403,6 @@ OK
+@@ -404,9 +404,6 @@ OK
     <arg name="status" type="b" direction="out"/>
     <arg name="path" type="o" direction="out"/>
    </method>
@@ -268,7 +268,7 @@ index 93cc4d184524c4b1aeba02a650c94d832462c236..26850efaedb966cd94ecd0db42d6adb3
    <method name="resubmit">
     <arg name="working" type="b" direction="out"/>
    </method>
-@@ -483,9 +480,6 @@ recently
+@@ -484,9 +481,6 @@ recently
  1 on /org/fedorahosted/certmonger/requests/Request2
  After setting template-eku to 1.2.3.4.5.6.7.8.9.10, we got dbus.Array([dbus.String(u'1.2.3.4.5.6.7.8.9.10')], signature=dbus.Signature('s'), variant_level=1)
  
@@ -279,7 +279,7 @@ index 93cc4d184524c4b1aeba02a650c94d832462c236..26850efaedb966cd94ecd0db42d6adb3
  1
  
 diff --git a/tests/036-getcert/expected.out b/tests/036-getcert/expected.out
-index c1a13c8e058e39285ee842b173356002da2fd0e6..b6d1eaf7c733e04d5b928e7a59edeca43a27a5ef 100644
+index c1a13c8..b6d1eaf 100644
 --- a/tests/036-getcert/expected.out
 +++ b/tests/036-getcert/expected.out
 @@ -11,20 +11,21 @@ certs:1
@@ -349,7 +349,7 @@ index c1a13c8e058e39285ee842b173356002da2fd0e6..b6d1eaf7c733e04d5b928e7a59edeca4
  cert:1
  key:1
 diff --git a/tests/037-rekey2/expected.out b/tests/037-rekey2/expected.out
-index bd8cca7c3eedb5a02249f450451b651bb270ec24..62a1c746f86bb53fe79d1226ab9194825f7642d8 100644
+index bd8cca7..62a1c74 100644
 --- a/tests/037-rekey2/expected.out
 +++ b/tests/037-rekey2/expected.out
 @@ -112,7 +112,7 @@ MONITORING
@@ -370,5 +370,5 @@ index bd8cca7c3eedb5a02249f450451b651bb270ec24..62a1c746f86bb53fe79d1226ab919482
  -STOP-
  Test complete.
 -- 
-2.7.4
+2.14.4
 
diff --git a/SPECS/certmonger.spec b/SPECS/certmonger.spec
index bb359aa..f817f50 100644
--- a/SPECS/certmonger.spec
+++ b/SPECS/certmonger.spec
@@ -26,14 +26,14 @@
 
 Name:		certmonger
 Version:	0.78.4
-Release:	3%{?dist}.1
+Release:	10%{?dist}
 Summary:	Certificate status monitor and PKI enrollment client
 
 Group:		System Environment/Daemons
 License:	GPLv3+
-URL:		http://certmonger.fedorahosted.org
-Source0:	http://fedorahosted.org/released/certmonger/certmonger-%{version}.tar.gz
-Source1:	http://fedorahosted.org/released/certmonger/certmonger-%{version}.tar.gz.sig
+URL:		https://pagure.io/certmonger/
+Source0:	https://releases.pagure.org/certmonger/certmonger-%{version}.tar.gz
+Source1:	https://releases.pagure.org/released/certmonger/certmonger-%{version}.tar.gz.sig
 BuildRoot:	%(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
 
 Patch0001:	0001-Stop-assuming-RSA-512-works.patch
@@ -47,6 +47,14 @@ Patch0008:	0008-Document-the-X-option-in-the-ipa-submit-man-page.patch
 Patch0009:	0009-Fix-a-flakiness-in-the-028-dbus-test.patch
 Patch0010:	0010-Set-all-bits-to-1-in-local-CA-Basic-Constraint-to-se.patch
 Patch0011:	0011-Fix-conversions-of-bit-lengths-to-byte-lengths.patch
+Patch0012:	0012-Remove-trailing-CR-LF-when-reading-passwords-from-a-.patch
+Patch0013:	0013-Disable-the-10-iterate-tests-which-randomly-fail.patch
+Patch0014:	0014-MS-cert-template-add-D-Bus-property-and-storage.patch
+Patch0015:	0015-MS-cert-template-add-template-extension-to-CSR.patch
+Patch0016:	0016-MS-cert-template-add-option-to-command-line-programs.patch
+Patch0017:	0017-MS-cert-template-validate-argument.patch
+Patch0018:	0018-MS-cert-template-add-tests.patch
+Patch0019:	0019-Fix-C99-build-error-on-EL7-systems.patch
 
 Patch1001:	1001-Remove-rekey-feature.patch
 Patch1002:	1002-Fix-CA-option-name-for-ipa-cert-request.patch
@@ -90,10 +98,18 @@ BuildRequires:	/usr/bin/which
 BuildRequires:	dbus-python
 #  for popt or popt-devel, depending on the build environment
 BuildRequires: /usr/include/popt.h
+BuildRequires:  autoconf
+BuildRequires:  automake
+BuildRequires:  pkgconfig
+BuildRequires:  libtool
+BuildRequires:	gettext-devel
 
 # we need a running system bus
 Requires:	dbus
 
+# for killall in post script
+Requires:      psmisc
+
 %if %{systemd}
 BuildRequires:	systemd-units
 Requires(post):	systemd-units
@@ -136,6 +152,7 @@ sed -i 's,^# chkconfig: - ,# chkconfig: 345 ,g' sysvinit/certmonger.in
 %endif
 
 %build
+autoreconf -i -f
 %configure \
 %if %{systemd}
 	--enable-systemd \
@@ -258,10 +275,34 @@ exit 0
 %endif
 
 %changelog
-* Tue Mar 27 2018 Rob Crittenden <rcritten@redhat.com> - 0.78.4-3.1
-- Use required DER encoding when setting CA basic constraint (#1560961)
+* Fri Aug 24 2018 Rob Crittenden <rcritten@redhat.com> - 0.78.4-10
+- Backport patches to add support for the MS Certificate Template V2
+  extension (#1622184)
+
+* Mon Aug 13 2018 Rob Crittenden <rcritten@redhat.com> - 0.78.4-9
+- Remove patch to pass _PROXY, _proxy, LANG and LC_* environment
+  variables to helpers. The root cause was a bug in IPA (#1596161)
+
+* Tue Jul 17 2018 Rob Crittenden <rcritten@redhat.com> - 0.78.4-8
+- Disable iterate-10 test which fails intermitently (#1596161)
+- Add BuildRequires for running autoreconf
+
+* Tue Jul 17 2018 Rob Crittenden <rcritten@redhat.com> - 0.78.4-7
+- Pass _PROXY, _proxy, LANG and LC_* environment variables to
+  helpers (#1596161)
+
+* Tue May 29 2018 Rob Crittenden <rcritten@redhat.com> - 0.78.4-6
+- Remove reference to unused patch
+
+* Mon May 21 2018 Rob Crittenden <rcritten@redhat.com> - 0.78.4-5
+- Add Requires on psmsic for killall in post script (#1458890)
+- upstream project migrated from fedorahosted.org to pagure.io (#1501723)
+- Strip CR/LF from passwords read from a file (#1545935)
+
+* Mon Mar  5 2018 Rob Crittenden <rcritten@redhat.com> - 0.78.4-4
+- Use required DER encoding when setting CA basic constraint (#1551635)
 - NSS 3.34 more strictly enforces length checking when verifying signatures
-  (#1560960)
+  (#1551702)
 
 * Tue Sep  6 2016 Jan Cholasta <jcholast@redhat.com> - 0.78.4-3
 - Resolves: #1367683 getcert request command fails to use Sub CA using -X