]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[eap] Allow MD5-Challenge authentication method to be disabled
authorMichael Brown <mcb30@ipxe.org>
Fri, 23 Feb 2024 12:33:57 +0000 (12:33 +0000)
committerMichael Brown <mcb30@ipxe.org>
Fri, 23 Feb 2024 16:24:44 +0000 (16:24 +0000)
RFC 3748 states that implementations must support the MD5-Challenge
method.  However, some network environments may wish to disable it as
a matter of policy.

Allow support for MD5-Challenge to be controllable via the build
configuration option EAP_METHOD_MD5 in config/general.h.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/config/config_eap.c [new file with mode: 0644]
src/config/general.h
src/include/ipxe/eap.h
src/include/ipxe/errfile.h
src/net/eap.c
src/net/eap_md5.c [new file with mode: 0644]

diff --git a/src/config/config_eap.c b/src/config/config_eap.c
new file mode 100644 (file)
index 0000000..d3fd77a
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <config/general.h>
+
+/** @file
+ *
+ * EAP configuration options
+ *
+ */
+
+PROVIDE_REQUIRING_SYMBOL();
+
+/*
+ * Drag in EAP authentication methods
+ */
+#ifdef EAP_METHOD_MD5
+REQUIRE_OBJECT ( eap_md5 );
+#endif
index 6e8e86b2b47ef462074b5d2b065a8c0cfe8f728b..de009a8787099ed37b30b7c12a86d1b929441f49 100644 (file)
@@ -91,6 +91,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #define        CRYPTO_80211_WPA        /* WPA Personal, authenticating with passphrase */
 #define        CRYPTO_80211_WPA2       /* Add support for stronger WPA cryptography */
 
+/*
+ * 802.1x EAP authentication methods
+ *
+ */
+#define EAP_METHOD_MD5         /* MD5-Challenge port authentication */
+
 /*
  * Name resolution modules
  *
index cf1c7c00d52c7cbece2f3dce8c70a59ea9622893..fe1bb5282319e10a3b1d1391adb3e7396aac491a 100644 (file)
@@ -166,6 +166,8 @@ struct eap_method {
 /** Declare an EAP method */
 #define __eap_method __table_entry ( EAP_METHODS, 01 )
 
+extern int eap_tx_response ( struct eap_supplicant *supplicant,
+                            const void *rsp, size_t rsp_len );
 extern int eap_rx ( struct eap_supplicant *supplicant,
                    const void *data, size_t len );
 
index f7a00dbe7a1c7345af2f04e0f5bc07e5998b75c1..1768748d9e5f57c6e884be8d8bfffbe0562fbf16 100644 (file)
@@ -297,6 +297,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #define ERRFILE_httpntlm               ( ERRFILE_NET | 0x004a0000 )
 #define ERRFILE_eap                    ( ERRFILE_NET | 0x004b0000 )
 #define ERRFILE_lldp                   ( ERRFILE_NET | 0x004c0000 )
+#define ERRFILE_eap_md5                        ( ERRFILE_NET | 0x004d0000 )
 
 #define ERRFILE_image                ( ERRFILE_IMAGE | 0x00000000 )
 #define ERRFILE_elf                  ( ERRFILE_IMAGE | 0x00010000 )
index 696b7fe991336297f0a3ecc0f9082b664e8d6852..87327d7235f013646d78048ac280e430903031a0 100644 (file)
@@ -28,8 +28,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <string.h>
 #include <byteswap.h>
 #include <ipxe/netdevice.h>
-#include <ipxe/md5.h>
-#include <ipxe/chap.h>
 #include <ipxe/eap.h>
 
 /** @file
@@ -46,8 +44,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  * @v rsp_len          Length of response type data
  * @ret rc             Return status code
  */
-static int eap_tx_response ( struct eap_supplicant *supplicant,
-                            const void *rsp, size_t rsp_len ) {
+int eap_tx_response ( struct eap_supplicant *supplicant,
+                     const void *rsp, size_t rsp_len ) {
        struct net_device *netdev = supplicant->netdev;
        struct eap_message *msg;
        size_t len;
@@ -167,84 +165,6 @@ struct eap_method eap_identity_method __eap_method = {
        .rx = eap_rx_identity,
 };
 
-/**
- * Handle EAP MD5-Challenge
- *
- * @v req              Request type data
- * @v req_len          Length of request type data
- * @ret rc             Return status code
- */
-static int eap_rx_md5 ( struct eap_supplicant *supplicant,
-                       const void *req, size_t req_len ) {
-       struct net_device *netdev = supplicant->netdev;
-       const struct eap_md5 *md5req = req;
-       struct {
-               uint8_t len;
-               uint8_t value[MD5_DIGEST_SIZE];
-       } __attribute__ (( packed )) md5rsp;
-       struct chap_response chap;
-       void *secret;
-       int secret_len;
-       int rc;
-
-       /* Sanity checks */
-       if ( req_len < sizeof ( *md5req ) ) {
-               DBGC ( netdev, "EAP %s underlength MD5-Challenge:\n",
-                      netdev->name );
-               DBGC_HDA ( netdev, 0, req, req_len );
-               rc = -EINVAL;
-               goto err_sanity;
-       }
-       if ( ( req_len - sizeof ( *md5req ) ) < md5req->len ) {
-               DBGC ( netdev, "EAP %s truncated MD5-Challenge:\n",
-                      netdev->name );
-               DBGC_HDA ( netdev, 0, req, req_len );
-               rc = -EINVAL;
-               goto err_sanity;
-       }
-
-       /* Construct response */
-       if ( ( rc = chap_init ( &chap, &md5_algorithm ) ) != 0 ) {
-               DBGC ( netdev, "EAP %s could not initialise CHAP: %s\n",
-                      netdev->name, strerror ( rc ) );
-               goto err_chap;
-       }
-       chap_set_identifier ( &chap, supplicant->id );
-       secret_len = fetch_raw_setting_copy ( netdev_settings ( netdev ),
-                                             &password_setting, &secret );
-       if ( secret_len < 0 ) {
-               rc = secret_len;
-               DBGC ( netdev, "EAP %s has no secret: %s\n",
-                      netdev->name, strerror ( rc ) );
-               goto err_secret;
-       }
-       chap_update ( &chap, secret, secret_len );
-       chap_update ( &chap, md5req->value, md5req->len );
-       chap_respond ( &chap );
-       assert ( chap.response_len == sizeof ( md5rsp.value ) );
-       md5rsp.len = sizeof ( md5rsp.value );
-       memcpy ( md5rsp.value, chap.response, sizeof ( md5rsp.value ) );
-
-       /* Transmit response */
-       if ( ( rc = eap_tx_response ( supplicant, &md5rsp,
-                                     sizeof ( md5rsp ) ) ) != 0 )
-               goto err_tx;
-
- err_tx:
-       free ( secret );
- err_secret:
-       chap_finish ( &chap );
- err_chap:
- err_sanity:
-       return rc;
-}
-
-/** EAP MD5-Challenge method */
-struct eap_method eap_md5_method __eap_method = {
-       .type = EAP_TYPE_MD5,
-       .rx = eap_rx_md5,
-};
-
 /**
  * Handle EAP Request
  *
@@ -370,3 +290,9 @@ int eap_rx ( struct eap_supplicant *supplicant, const void *data,
                return -ENOTSUP;
        }
 }
+
+/* Drag in objects via eap_rx() */
+REQUIRING_SYMBOL ( eap_rx );
+
+/* Drag in EAP configuration */
+REQUIRE_OBJECT ( config_eap );
diff --git a/src/net/eap_md5.c b/src/net/eap_md5.c
new file mode 100644 (file)
index 0000000..0664174
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * 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 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/md5.h>
+#include <ipxe/chap.h>
+#include <ipxe/eap.h>
+
+/** @file
+ *
+ * EAP MD5-Challenge authentication method
+ *
+ */
+
+/**
+ * Handle EAP MD5-Challenge
+ *
+ * @v supplicant       EAP supplicant
+ * @v req              Request type data
+ * @v req_len          Length of request type data
+ * @ret rc             Return status code
+ */
+static int eap_rx_md5 ( struct eap_supplicant *supplicant,
+                       const void *req, size_t req_len ) {
+       struct net_device *netdev = supplicant->netdev;
+       const struct eap_md5 *md5req = req;
+       struct {
+               uint8_t len;
+               uint8_t value[MD5_DIGEST_SIZE];
+       } __attribute__ (( packed )) md5rsp;
+       struct chap_response chap;
+       void *secret;
+       int secret_len;
+       int rc;
+
+       /* Sanity checks */
+       if ( req_len < sizeof ( *md5req ) ) {
+               DBGC ( netdev, "EAP %s underlength MD5-Challenge:\n",
+                      netdev->name );
+               DBGC_HDA ( netdev, 0, req, req_len );
+               rc = -EINVAL;
+               goto err_sanity;
+       }
+       if ( ( req_len - sizeof ( *md5req ) ) < md5req->len ) {
+               DBGC ( netdev, "EAP %s truncated MD5-Challenge:\n",
+                      netdev->name );
+               DBGC_HDA ( netdev, 0, req, req_len );
+               rc = -EINVAL;
+               goto err_sanity;
+       }
+
+       /* Construct response */
+       if ( ( rc = chap_init ( &chap, &md5_algorithm ) ) != 0 ) {
+               DBGC ( netdev, "EAP %s could not initialise CHAP: %s\n",
+                      netdev->name, strerror ( rc ) );
+               goto err_chap;
+       }
+       chap_set_identifier ( &chap, supplicant->id );
+       secret_len = fetch_raw_setting_copy ( netdev_settings ( netdev ),
+                                             &password_setting, &secret );
+       if ( secret_len < 0 ) {
+               rc = secret_len;
+               DBGC ( netdev, "EAP %s has no secret: %s\n",
+                      netdev->name, strerror ( rc ) );
+               goto err_secret;
+       }
+       chap_update ( &chap, secret, secret_len );
+       chap_update ( &chap, md5req->value, md5req->len );
+       chap_respond ( &chap );
+       assert ( chap.response_len == sizeof ( md5rsp.value ) );
+       md5rsp.len = sizeof ( md5rsp.value );
+       memcpy ( md5rsp.value, chap.response, sizeof ( md5rsp.value ) );
+
+       /* Transmit response */
+       if ( ( rc = eap_tx_response ( supplicant, &md5rsp,
+                                     sizeof ( md5rsp ) ) ) != 0 )
+               goto err_tx;
+
+ err_tx:
+       free ( secret );
+ err_secret:
+       chap_finish ( &chap );
+ err_chap:
+ err_sanity:
+       return rc;
+}
+
+/** EAP MD5-Challenge method */
+struct eap_method eap_md5_method __eap_method = {
+       .type = EAP_TYPE_MD5,
+       .rx = eap_rx_md5,
+};