Blob Blame History Raw
From b38981c6e140ada6dd34bc817c508e8dd9714494 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Fri, 9 Jul 2021 20:49:28 +0000
Subject: [PATCH] Add SCEP config option to treat the challenge password as an
 OTP

SCEP RFC 8894 specifies that a challenge password SHOULD be
removed from subsequent requests but that it MAY be included.

This adds a new configuration option to treat the challenge password
as a one-time password (OTP) so that it will not be sent on
subsequent requests, like renewals, by removing it completely
from the tracking request.

This allows certmonger to be able to renew AD-issued SCEP certificates
if the AD registry entry DisableRenewalSubjectNameMatch is set to 1.

https://bugzilla.redhat.com/show_bug.cgi?id=1577570

Signed-off-by: Rob Crittenden <rcritten@redhat.com>
---
 src/certmonger.conf.5.in |  9 +++++++++
 src/certsave.c           | 13 +++++++++++++
 src/prefs.c              | 15 +++++++++++++++
 src/prefs.h              |  4 ++++
 4 files changed, 41 insertions(+)

diff --git a/src/certmonger.conf.5.in b/src/certmonger.conf.5.in
index 6a42d3cb..1b941b9d 100644
--- a/src/certmonger.conf.5.in
+++ b/src/certmonger.conf.5.in
@@ -126,6 +126,15 @@ If not set, the value of the \fIvalidity_period\fR setting from the
 \fIselfsign\fR section, if one is set there, will be used.  The default value
 is \fI@CM_DEFAULT_CERT_LIFETIME@\fR.
 
+.SH SCEP
+Within the \fIscep\fR section, these variables and values are recognized:
+
+.IP challenge_password_otp
+This controls whether the SCEP challenge password is treated as a one-time
+password. If set to yes then the challenge password and/or challenge password
+file will be removed from the tracking request after the first certificate
+issuance so will not be sent with renewal requests.  The default is no.
+
 .SH BUGS
 Please file tickets for any that you find at https://fedorahosted.org/certmonger/
 
diff --git a/src/certsave.c b/src/certsave.c
index 6eaafe59..f8503662 100644
--- a/src/certsave.c
+++ b/src/certsave.c
@@ -18,12 +18,25 @@
 #include "config.h"
 #include "certsave.h"
 #include "certsave-int.h"
+#include "prefs.h"
 #include "store-int.h"
+#include "talloc.h"
 
 /* Start writing the certificate from the entry to the configured location. */
 struct cm_certsave_state *
 cm_certsave_start(struct cm_store_entry *entry)
 {
+    /* If saving a SCEP certificate wipe out the challenge password */
+    if ((cm_prefs_scep_password_otp()) &&
+        (entry->cm_template_challenge_password != NULL) &&
+        (entry->cm_scep_nonce != NULL))
+    {
+        talloc_free(entry->cm_template_challenge_password);
+        entry->cm_template_challenge_password = NULL;
+        talloc_free(entry->cm_template_challenge_password_file);
+        entry->cm_template_challenge_password_file = NULL;
+    }
+
 	switch (entry->cm_cert_storage_type) {
 #ifdef HAVE_OPENSSL
 	case cm_cert_storage_file:
diff --git a/src/prefs.c b/src/prefs.c
index 669e8f1f..52ffc908 100644
--- a/src/prefs.c
+++ b/src/prefs.c
@@ -595,3 +595,18 @@ prefs_max_key_use_count(void)
 	}
 	return count;
 }
+
+int
+cm_prefs_scep_password_otp(void)
+{
+    static int populate = -1;
+    if (populate == -1) {
+        const char *val;
+        val = cm_prefs_config("scep", "challenge_password_otp");
+        if (val == NULL) {
+            val = "no";
+        }
+        populate = cm_prefs_yesno(val);
+    }
+    return populate != -1 ? populate : 0;
+}
diff --git a/src/prefs.h b/src/prefs.h
index 248e1016..a107fb6c 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -18,6 +18,8 @@
 #ifndef cmprefs_h
 #define cmprefs_h
 
+#include <time.h>
+
 enum cm_prefs_cipher {
 	cm_prefs_aes128,
 	cm_prefs_aes192,
@@ -73,4 +75,6 @@ const char *cm_prefs_dogtag_sslpinfile(void);
 long long prefs_key_end_of_life(time_t ref);
 long prefs_max_key_use_count(void);
 
+int cm_prefs_scep_password_otp(void);
+
 #endif
-- 
2.31.1