]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Allow client certificate to be changed without a rebuild
authorMichael Brown <mcb30@ipxe.org>
Tue, 24 Apr 2012 12:17:29 +0000 (13:17 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 24 Apr 2012 12:17:29 +0000 (13:17 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/crypto/clientcert.c
src/include/ipxe/dhcp.h

index 03c7528430cda33b73a76fe529388ab266533855..692aafb466587d2e7bfb7b0e0d618c3c671a8bf3 100644 (file)
 FILE_LICENCE ( GPL2_OR_LATER );
 
 #include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/settings.h>
 #include <ipxe/clientcert.h>
 
 /** @file
@@ -55,12 +59,6 @@ __asm__ ( ".section \".rodata\", \"a\", @progbits\n\t"
          ".equ client_certificate_len, ( . - client_certificate_data )\n\t"
          ".previous\n\t" );
 
-/** Client certificate */
-struct client_certificate client_certificate = {
-       .data = client_certificate_data,
-       .len = ( ( size_t ) client_certificate_len ),
-};
-
 /* Raw client private key data */
 extern char client_private_key_data[];
 extern char client_private_key_len[];
@@ -73,8 +71,93 @@ __asm__ ( ".section \".rodata\", \"a\", @progbits\n\t"
          ".equ client_private_key_len, ( . - client_private_key_data )\n\t"
          ".previous\n\t" );
 
+/** Client certificate */
+struct client_certificate client_certificate;
+
 /** Client private key */
-struct client_private_key client_private_key = {
-       .data = client_private_key_data,
-       .len = ( ( size_t ) client_private_key_len ),
+struct client_private_key client_private_key;
+
+/** Client certificate setting */
+struct setting cert_setting __setting ( SETTING_CRYPTO ) = {
+       .name = "cert",
+       .description = "Client certificate",
+       .tag = DHCP_EB_CERT,
+       .type = &setting_type_hex,
+};
+
+/** Client private key setting */
+struct setting key_setting __setting ( SETTING_CRYPTO ) = {
+       .name = "key",
+       .description = "Client private key",
+       .tag = DHCP_EB_KEY,
+       .type = &setting_type_hex,
+};
+
+/**
+ * Apply client certificate store configuration settings
+ *
+ * @ret rc             Return status code
+ */
+static int clientcert_apply_settings ( void ) {
+       static void *cert;
+       static void *key;
+       int len;
+       int rc;
+
+       /* Restore default client certificate */
+       client_certificate.data = client_certificate_data;
+       client_certificate.len = ( ( size_t ) client_certificate_len );
+
+       /* Fetch new client certificate, if any */
+       free ( cert );
+       len = fetch_setting_copy ( NULL, &cert_setting, &cert );
+       if ( len < 0 ) {
+               rc = len;
+               DBGC ( &client_certificate, "CLIENTCERT cannot fetch client "
+                      "certificate: %s\n", strerror ( rc ) );
+               return rc;
+       }
+       if ( cert ) {
+               client_certificate.data = cert;
+               client_certificate.len = len;
+       }
+
+       /* Restore default client private key */
+       client_private_key.data = client_private_key_data;
+       client_private_key.len = ( ( size_t ) client_private_key_len );
+
+       /* Fetch new client private key, if any */
+       free ( key );
+       len = fetch_setting_copy ( NULL, &key_setting, &key );
+       if ( len < 0 ) {
+               rc = len;
+               DBGC ( &client_certificate, "CLIENTCERT cannot fetch client "
+                      "private key: %s\n", strerror ( rc ) );
+               return rc;
+       }
+       if ( key ) {
+               client_private_key.data = key;
+               client_private_key.len = len;
+       }
+
+       /* Debug */
+       if ( have_client_certificate() ) {
+               DBGC ( &client_certificate, "CLIENTCERT using %s "
+                      "certificate:\n", ( cert ? "external" : "built-in" ) );
+               DBGC_HDA ( &client_certificate, 0, client_certificate.data,
+                          client_certificate.len );
+               DBGC ( &client_certificate, "CLIENTCERT using %s private "
+                      "key:\n", ( key ? "external" : "built-in" ) );
+               DBGC_HDA ( &client_certificate, 0, client_private_key.data,
+                          client_private_key.len );
+       } else {
+               DBGC ( &client_certificate, "CLIENTCERT has no certificate\n" );
+       }
+
+       return 0;
+}
+
+/** Client certificate store settings applicator */
+struct settings_applicator clientcert_applicator __settings_applicator = {
+       .apply = clientcert_apply_settings,
 };
index cc594ab1e9a4eee94db12b7eb798ac51d18bce34..dc8a6fc7f073fefa0abbe05ae72955673854d1f2 100644 (file)
@@ -358,6 +358,12 @@ struct dhcp_client_uuid {
 /** Trusted root certficate fingerprints */
 #define DHCP_EB_TRUST DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x5a )
 
+/** Client certficate */
+#define DHCP_EB_CERT DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x5b )
+
+/** Client private key */
+#define DHCP_EB_KEY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x5c )
+
 /** Skip PXE DHCP protocol extensions such as ProxyDHCP
  *
  * If set to a non-zero value, iPXE will not wait for ProxyDHCP offers