]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[eap] Add support for the MD5-Challenge authentication type
authorMichael Brown <mcb30@ipxe.org>
Wed, 10 Jan 2024 15:23:07 +0000 (15:23 +0000)
committerMichael Brown <mcb30@ipxe.org>
Wed, 10 Jan 2024 16:22:32 +0000 (16:22 +0000)
RFC 3748 states that support for MD5-Challenge is mandatory for EAP
implementations.  The MD5 and CHAP code is already included in the
default build since it is required by iSCSI, and so this does not
substantially increase the binary size.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/eap.h
src/net/eap.c

index bbae517da4a8b10116327ab90f4163fbc9117ab6..cf1c7c00d52c7cbece2f3dce8c70a59ea9622893 100644 (file)
@@ -49,6 +49,17 @@ struct eap_message {
 /** EAP NAK */
 #define EAP_TYPE_NAK 3
 
+/** EAP MD5 challenge request/response */
+#define EAP_TYPE_MD5 4
+
+/** EAP MD5 challenge request/response type data */
+struct eap_md5 {
+       /** Value length */
+       uint8_t len;
+       /** Value */
+       uint8_t value[0];
+} __attribute__ (( packed ));
+
 /** EAP success */
 #define EAP_CODE_SUCCESS 3
 
index fe01f136ef034ac2048e581e0b28e36325529b9b..79b060aa6bdc32ab4631e1c7149e1cc14e353973 100644 (file)
@@ -28,6 +28,8 @@ 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
@@ -157,6 +159,84 @@ 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
  *