mirror of https://github.com/ipxe/ipxe.git
[eap] Allow MD5-Challenge authentication method to be disabled
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>pull/1163/head
parent
834f319f87
commit
25ffcd79bf
|
@ -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
|
|
@ -91,6 +91,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
#define CRYPTO_80211_WPA /* WPA Personal, authenticating with passphrase */
|
#define CRYPTO_80211_WPA /* WPA Personal, authenticating with passphrase */
|
||||||
#define CRYPTO_80211_WPA2 /* Add support for stronger WPA cryptography */
|
#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
|
* Name resolution modules
|
||||||
*
|
*
|
||||||
|
|
|
@ -166,6 +166,8 @@ struct eap_method {
|
||||||
/** Declare an EAP method */
|
/** Declare an EAP method */
|
||||||
#define __eap_method __table_entry ( EAP_METHODS, 01 )
|
#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,
|
extern int eap_rx ( struct eap_supplicant *supplicant,
|
||||||
const void *data, size_t len );
|
const void *data, size_t len );
|
||||||
|
|
||||||
|
|
|
@ -297,6 +297,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
#define ERRFILE_httpntlm ( ERRFILE_NET | 0x004a0000 )
|
#define ERRFILE_httpntlm ( ERRFILE_NET | 0x004a0000 )
|
||||||
#define ERRFILE_eap ( ERRFILE_NET | 0x004b0000 )
|
#define ERRFILE_eap ( ERRFILE_NET | 0x004b0000 )
|
||||||
#define ERRFILE_lldp ( ERRFILE_NET | 0x004c0000 )
|
#define ERRFILE_lldp ( ERRFILE_NET | 0x004c0000 )
|
||||||
|
#define ERRFILE_eap_md5 ( ERRFILE_NET | 0x004d0000 )
|
||||||
|
|
||||||
#define ERRFILE_image ( ERRFILE_IMAGE | 0x00000000 )
|
#define ERRFILE_image ( ERRFILE_IMAGE | 0x00000000 )
|
||||||
#define ERRFILE_elf ( ERRFILE_IMAGE | 0x00010000 )
|
#define ERRFILE_elf ( ERRFILE_IMAGE | 0x00010000 )
|
||||||
|
|
|
@ -28,8 +28,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <byteswap.h>
|
#include <byteswap.h>
|
||||||
#include <ipxe/netdevice.h>
|
#include <ipxe/netdevice.h>
|
||||||
#include <ipxe/md5.h>
|
|
||||||
#include <ipxe/chap.h>
|
|
||||||
#include <ipxe/eap.h>
|
#include <ipxe/eap.h>
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
@ -46,8 +44,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
* @v rsp_len Length of response type data
|
* @v rsp_len Length of response type data
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int eap_tx_response ( struct eap_supplicant *supplicant,
|
int eap_tx_response ( struct eap_supplicant *supplicant,
|
||||||
const void *rsp, size_t rsp_len ) {
|
const void *rsp, size_t rsp_len ) {
|
||||||
struct net_device *netdev = supplicant->netdev;
|
struct net_device *netdev = supplicant->netdev;
|
||||||
struct eap_message *msg;
|
struct eap_message *msg;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
@ -167,84 +165,6 @@ struct eap_method eap_identity_method __eap_method = {
|
||||||
.rx = eap_rx_identity,
|
.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
|
* Handle EAP Request
|
||||||
*
|
*
|
||||||
|
@ -370,3 +290,9 @@ int eap_rx ( struct eap_supplicant *supplicant, const void *data,
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Drag in objects via eap_rx() */
|
||||||
|
REQUIRING_SYMBOL ( eap_rx );
|
||||||
|
|
||||||
|
/* Drag in EAP configuration */
|
||||||
|
REQUIRE_OBJECT ( config_eap );
|
||||||
|
|
|
@ -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,
|
||||||
|
};
|
Loading…
Reference in New Issue