[ipxe-devel] [PATCH v2 2/2] [crypto] Allow TRUST to be overriden by scripts

Ladi Prosek lprosek at redhat.com
Wed Sep 20 09:52:17 UTC 2017


The list of trusted root certificates can be currently overriden only
by rebuilding iPXE with the TRUST=... build parameter or by settings
coming from trusted sources, namely VMWare GuestInfo and non-volatile
options.

There are scenarios when one would want to set trusted root certificates
from an iPXE script that is considered trusted, i.e. not downloaded
over the network.

This commit adds the possibility to build iPXE with this relaxed
configuration by defining ALLOW_TRUST_OVERRIDE to 2. If TRUST was not
supplied at build time (or via VMWare GuestInfo or non-volatile
options), a script may execute the 'set trust ...' command to set
the list of trusted root certificates. This can be done only once,
subsequent attempts to set the 'trust' variable will have no effect.

Signed-off-by: Ladi Prosek <lprosek at redhat.com>
---
 src/crypto/rootcert.c | 55 +++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 47 insertions(+), 8 deletions(-)

diff --git a/src/crypto/rootcert.c b/src/crypto/rootcert.c
index f7b9dcfb..8158c9f0 100644
--- a/src/crypto/rootcert.c
+++ b/src/crypto/rootcert.c
@@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <ipxe/dhcp.h>
 #include <ipxe/init.h>
 #include <ipxe/rootcert.h>
+#include <config/general.h>
 
 /** @file
  *
@@ -41,12 +42,23 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 /** Length of a root certificate fingerprint */
 #define FINGERPRINT_LEN SHA256_DIGEST_SIZE
 
-/* Allow trusted certificates to be overridden if not explicitly specified */
+/**
+ * Allow trusted certificates to be overridden if not explicitly specified
+ *
+ * The ALLOW_TRUST_OVERRIDE macro may be defined to one of the following values:
+ * 0 - iPXE will use only the build-time TRUSTED root CA
+ * 1 - iPXE will allow override but only at startup (e.g. from VMware GuestInfo)
+ * 2 - iPXE will allow override from any source but only once
+ *
+ * The default values are 0 if TRUSTED is defined, 1 otherwise.
+ */
+#ifndef ALLOW_TRUST_OVERRIDE
 #ifdef TRUSTED
 #define ALLOW_TRUST_OVERRIDE 0
 #else
 #define ALLOW_TRUST_OVERRIDE 1
 #endif
+#endif /* ALLOW_TRUST_OVERRIDE */
 
 /* Use iPXE root CA if no trusted certificates are explicitly specified */
 #ifndef TRUSTED
@@ -85,14 +97,19 @@ struct x509_root root_certificates = {
  *
  * If no certificates were explicitly specified, then we allow the
  * list of trusted root certificate fingerprints to be overridden
- * using the "trust" setting, but only at the point of iPXE
- * initialisation.  This prevents untrusted sources of settings
+ * using the "trust" setting, but, by default, only at the point of
+ * iPXE initialisation.  This prevents untrusted sources of settings
  * (e.g. DHCP) from subverting the chain of trust, while allowing
  * trustworthy sources (e.g. VMware GuestInfo or non-volatile stored
  * options) to specify the trusted root certificate without requiring
  * a rebuild.
+ *
+ * ALLOW_TRUST_OVERRIDE may be defined to 2 to relax this and allow
+ * the list of fingerprints to be set at any time, but only once.
+ * This is useful for environments with a trusted (e.g. local) iPXE
+ * script.
  */
-static void rootcert_init ( void ) {
+static int rootcert_apply ( void ) {
 	static int initialised;
 	void *external = NULL;
 	int len;
@@ -109,16 +126,38 @@ static void rootcert_init ( void ) {
 						      &external ) ) >= 0 ) {
 			root_certificates.fingerprints = external;
 			root_certificates.count = ( len / FINGERPRINT_LEN );
-		}
 
-		/* Prevent subsequent modifications */
-		initialised = 1;
+			/* Prevent subsequent modifications */
+			initialised = 1;
+		} else if ( ALLOW_TRUST_OVERRIDE == 1 ) {
+			/* Prevent subsequent modifications even if the setting
+			 * was not found.
+			 */
+			initialised = 1;
+		}
 	}
 
 	DBGC ( &root_certificates, "ROOTCERT using %d %s certificate(s):\n",
-	       root_certificates.count, ( external ? "external" : "built-in" ));
+	       root_certificates.count,
+	       ( root_certificates.fingerprints == fingerprints ?
+	         "built-in" : "external" ) );
 	DBGC_HDA ( &root_certificates, 0, root_certificates.fingerprints,
 		   ( root_certificates.count * FINGERPRINT_LEN ) );
+	return 0;
+}
+
+static int rootcert_apply_empty ( void ) {
+	return 0;
+}
+
+/** Root certificate settings applicator */
+struct settings_applicator rootcert_applicator __settings_applicator = {
+	.apply = rootcert_apply_empty,
+};
+
+static void rootcert_init ( void ) {
+	rootcert_apply ();
+	rootcert_applicator.apply = rootcert_apply;
 }
 
 /** Root certificate initialiser */
-- 
2.13.5




More information about the ipxe-devel mailing list