Add EAPOL_TX command to extend ext_eapol_frame_io possibilities

This makes it convenient for an external test script to use
ext_eapol_frame_io=1 to delay and/or modify transmission of EAPOL-Key
msg 1/4 without having to use separate frame injection mechanisms.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2021-02-01 16:57:14 +02:00 committed by Jouni Malinen
parent 7f0a2e4225
commit 1c5aa2579d
6 changed files with 102 additions and 5 deletions

View file

@ -1946,6 +1946,52 @@ static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd)
}
static int hostapd_ctrl_iface_eapol_tx(struct hostapd_data *hapd, char *cmd)
{
char *pos, *pos2;
u8 dst[ETH_ALEN], *buf;
int used, ret;
size_t len;
unsigned int prev;
int encrypt = 0;
wpa_printf(MSG_DEBUG, "External EAPOL TX: %s", cmd);
pos = cmd;
used = hwaddr_aton2(pos, dst);
if (used < 0)
return -1;
pos += used;
while (*pos == ' ')
pos++;
pos2 = os_strchr(pos, ' ');
if (pos2) {
len = pos2 - pos;
encrypt = os_strstr(pos2, "encrypt=1") != NULL;
} else {
len = os_strlen(pos);
}
if (len & 1)
return -1;
len /= 2;
buf = os_malloc(len);
if (!buf || hexstr2bin(pos, buf, len) < 0) {
os_free(buf);
return -1;
}
prev = hapd->ext_eapol_frame_io;
hapd->ext_eapol_frame_io = 0;
ret = hostapd_wpa_auth_send_eapol(hapd, dst, buf, len, encrypt);
hapd->ext_eapol_frame_io = prev;
os_free(buf);
return ret;
}
static u16 ipv4_hdr_checksum(const void *buf, size_t len)
{
size_t i;
@ -3651,6 +3697,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "EAPOL_TX ", 9) == 0) {
if (hostapd_ctrl_iface_eapol_tx(hapd, buf + 9) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
reply_len = -1;

View file

@ -556,6 +556,9 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
int wpa_auth_rekey_ptk(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm);
int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth);
int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
const u8 *data, size_t data_len,
int encrypt);
void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm);
void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val);

View file

@ -505,9 +505,9 @@ static int hostapd_wpa_auth_get_seqnum(void *ctx, const u8 *addr, int idx,
}
static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
const u8 *data, size_t data_len,
int encrypt)
int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
const u8 *data, size_t data_len,
int encrypt)
{
struct hostapd_data *hapd = ctx;
struct sta_info *sta;

View file

@ -39,6 +39,7 @@
#include "driver_i.h"
#include "wps_supplicant.h"
#include "ibss_rsn.h"
#include "wpas_glue.h"
#include "ap.h"
#include "p2p_supplicant.h"
#include "p2p/p2p.h"
@ -9519,6 +9520,45 @@ static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd)
}
static int wpas_ctrl_iface_eapol_tx(struct wpa_supplicant *wpa_s, char *cmd)
{
char *pos;
u8 dst[ETH_ALEN], *buf;
int used, ret;
size_t len;
unsigned int prev;
wpa_printf(MSG_DEBUG, "External EAPOL TX: %s", cmd);
pos = cmd;
used = hwaddr_aton2(pos, dst);
if (used < 0)
return -1;
pos += used;
while (*pos == ' ')
pos++;
len = os_strlen(pos);
if (len & 1)
return -1;
len /= 2;
buf = os_malloc(len);
if (!buf || hexstr2bin(pos, buf, len) < 0) {
os_free(buf);
return -1;
}
prev = wpa_s->ext_eapol_frame_io;
wpa_s->ext_eapol_frame_io = 0;
ret = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, buf, len);
wpa_s->ext_eapol_frame_io = prev;
os_free(buf);
return ret;
}
static u16 ipv4_hdr_checksum(const void *buf, size_t len)
{
size_t i;
@ -11514,6 +11554,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "EAPOL_TX ", 9) == 0) {
if (wpas_ctrl_iface_eapol_tx(wpa_s, buf + 9) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0)
reply_len = -1;

View file

@ -95,8 +95,8 @@ static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type,
* @len: Frame payload length
* Returns: >=0 on success, <0 on failure
*/
static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
u16 proto, const u8 *buf, size_t len)
int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
u16 proto, const u8 *buf, size_t len)
{
#ifdef CONFIG_TESTING_OPTIONS
if (wpa_s->ext_eapol_frame_io && proto == ETH_P_EAPOL) {

View file

@ -15,6 +15,8 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s);
int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s);
void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
u16 proto, const u8 *buf, size_t len);
const char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field,
const char *default_txt,