wpa_priv: Add authentication command and event
These are needed to work with nl80211 driver interface. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
06f52b12f9
commit
6ebe816be0
3 changed files with 198 additions and 0 deletions
|
@ -26,6 +26,25 @@ enum privsep_cmd {
|
||||||
PRIVSEP_CMD_L2_NOTIFY_AUTH_START,
|
PRIVSEP_CMD_L2_NOTIFY_AUTH_START,
|
||||||
PRIVSEP_CMD_L2_SEND,
|
PRIVSEP_CMD_L2_SEND,
|
||||||
PRIVSEP_CMD_SET_COUNTRY,
|
PRIVSEP_CMD_SET_COUNTRY,
|
||||||
|
PRIVSEP_CMD_AUTHENTICATE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct privsep_cmd_authenticate
|
||||||
|
{
|
||||||
|
int freq;
|
||||||
|
u8 bssid[ETH_ALEN];
|
||||||
|
u8 ssid[SSID_MAX_LEN];
|
||||||
|
size_t ssid_len;
|
||||||
|
int auth_alg;
|
||||||
|
size_t ie_len;
|
||||||
|
u8 wep_key[4][16];
|
||||||
|
size_t wep_key_len[4];
|
||||||
|
int wep_tx_keyidx;
|
||||||
|
int local_state_change;
|
||||||
|
int p2p;
|
||||||
|
size_t sae_data_len;
|
||||||
|
/* followed by ie_len bytes of ie */
|
||||||
|
/* followed by sae_data_len bytes of sae_data */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct privsep_cmd_associate
|
struct privsep_cmd_associate
|
||||||
|
@ -69,6 +88,17 @@ enum privsep_event {
|
||||||
PRIVSEP_EVENT_FT_RESPONSE,
|
PRIVSEP_EVENT_FT_RESPONSE,
|
||||||
PRIVSEP_EVENT_RX_EAPOL,
|
PRIVSEP_EVENT_RX_EAPOL,
|
||||||
PRIVSEP_EVENT_SCAN_STARTED,
|
PRIVSEP_EVENT_SCAN_STARTED,
|
||||||
|
PRIVSEP_EVENT_AUTH,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct privsep_event_auth {
|
||||||
|
u8 peer[ETH_ALEN];
|
||||||
|
u8 bssid[ETH_ALEN];
|
||||||
|
u16 auth_type;
|
||||||
|
u16 auth_transaction;
|
||||||
|
u16 status_code;
|
||||||
|
size_t ies_len;
|
||||||
|
/* followed by ies_len bytes of ies */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PRIVSEP_COMMANDS_H */
|
#endif /* PRIVSEP_COMMANDS_H */
|
||||||
|
|
|
@ -220,6 +220,56 @@ static int wpa_driver_privsep_set_key(const char *ifname, void *priv,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_driver_privsep_authenticate(
|
||||||
|
void *priv, struct wpa_driver_auth_params *params)
|
||||||
|
{
|
||||||
|
struct wpa_driver_privsep_data *drv = priv;
|
||||||
|
struct privsep_cmd_authenticate *data;
|
||||||
|
int i, res;
|
||||||
|
size_t buflen;
|
||||||
|
u8 *pos;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d bssid=" MACSTR
|
||||||
|
" auth_alg=%d local_state_change=%d p2p=%d",
|
||||||
|
__func__, priv, params->freq, MAC2STR(params->bssid),
|
||||||
|
params->auth_alg, params->local_state_change, params->p2p);
|
||||||
|
|
||||||
|
buflen = sizeof(*data) + params->ie_len + params->sae_data_len;
|
||||||
|
data = os_zalloc(buflen);
|
||||||
|
if (data == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
data->freq = params->freq;
|
||||||
|
os_memcpy(data->bssid, params->bssid, ETH_ALEN);
|
||||||
|
os_memcpy(data->ssid, params->ssid, params->ssid_len);
|
||||||
|
data->ssid_len = params->ssid_len;
|
||||||
|
data->auth_alg = params->auth_alg;
|
||||||
|
data->ie_len = params->ie_len;
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
if (params->wep_key[i])
|
||||||
|
os_memcpy(data->wep_key[i], params->wep_key[i],
|
||||||
|
params->wep_key_len[i]);
|
||||||
|
data->wep_key_len[i] = params->wep_key_len[i];
|
||||||
|
}
|
||||||
|
data->wep_tx_keyidx = params->wep_tx_keyidx;
|
||||||
|
data->local_state_change = params->local_state_change;
|
||||||
|
data->p2p = params->p2p;
|
||||||
|
pos = (u8 *) (data + 1);
|
||||||
|
if (params->ie_len) {
|
||||||
|
os_memcpy(pos, params->ie, params->ie_len);
|
||||||
|
pos += params->ie_len;
|
||||||
|
}
|
||||||
|
if (params->sae_data_len)
|
||||||
|
os_memcpy(pos, params->sae_data, params->sae_data_len);
|
||||||
|
|
||||||
|
res = wpa_priv_cmd(drv, PRIVSEP_CMD_AUTHENTICATE, data, buflen,
|
||||||
|
NULL, NULL);
|
||||||
|
os_free(data);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpa_driver_privsep_associate(
|
static int wpa_driver_privsep_associate(
|
||||||
void *priv, struct wpa_driver_associate_params *params)
|
void *priv, struct wpa_driver_associate_params *params)
|
||||||
{
|
{
|
||||||
|
@ -309,6 +359,32 @@ static int wpa_driver_privsep_deauthenticate(void *priv, const u8 *addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpa_driver_privsep_event_auth(void *ctx, u8 *buf, size_t len)
|
||||||
|
{
|
||||||
|
union wpa_event_data data;
|
||||||
|
struct privsep_event_auth *auth;
|
||||||
|
|
||||||
|
os_memset(&data, 0, sizeof(data));
|
||||||
|
if (len < sizeof(*auth))
|
||||||
|
return;
|
||||||
|
auth = (struct privsep_event_auth *) buf;
|
||||||
|
if (len < sizeof(*auth) + auth->ies_len)
|
||||||
|
return;
|
||||||
|
|
||||||
|
os_memcpy(data.auth.peer, auth->peer, ETH_ALEN);
|
||||||
|
os_memcpy(data.auth.bssid, auth->bssid, ETH_ALEN);
|
||||||
|
data.auth.auth_type = auth->auth_type;
|
||||||
|
data.auth.auth_transaction = auth->auth_transaction;
|
||||||
|
data.auth.status_code = auth->status_code;
|
||||||
|
if (auth->ies_len) {
|
||||||
|
data.auth.ies = (u8 *) (auth + 1);
|
||||||
|
data.auth.ies_len = auth->ies_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_supplicant_event(ctx, EVENT_AUTH, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wpa_driver_privsep_event_assoc(void *ctx,
|
static void wpa_driver_privsep_event_assoc(void *ctx,
|
||||||
enum wpa_event_type event,
|
enum wpa_event_type event,
|
||||||
u8 *buf, size_t len)
|
u8 *buf, size_t len)
|
||||||
|
@ -506,6 +582,9 @@ static void wpa_driver_privsep_receive(int sock, void *eloop_ctx,
|
||||||
wpa_driver_privsep_event_rx_eapol(drv->ctx, event_buf,
|
wpa_driver_privsep_event_rx_eapol(drv->ctx, event_buf,
|
||||||
event_len);
|
event_len);
|
||||||
break;
|
break;
|
||||||
|
case PRIVSEP_EVENT_AUTH:
|
||||||
|
wpa_driver_privsep_event_auth(drv->ctx, event_buf, event_len);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
os_free(buf);
|
os_free(buf);
|
||||||
|
@ -742,6 +821,7 @@ struct wpa_driver_ops wpa_driver_privsep_ops = {
|
||||||
.set_param = wpa_driver_privsep_set_param,
|
.set_param = wpa_driver_privsep_set_param,
|
||||||
.scan2 = wpa_driver_privsep_scan,
|
.scan2 = wpa_driver_privsep_scan,
|
||||||
.deauthenticate = wpa_driver_privsep_deauthenticate,
|
.deauthenticate = wpa_driver_privsep_deauthenticate,
|
||||||
|
.authenticate = wpa_driver_privsep_authenticate,
|
||||||
.associate = wpa_driver_privsep_associate,
|
.associate = wpa_driver_privsep_associate,
|
||||||
.get_capa = wpa_driver_privsep_get_capa,
|
.get_capa = wpa_driver_privsep_get_capa,
|
||||||
.get_mac_addr = wpa_driver_privsep_get_mac_addr,
|
.get_mac_addr = wpa_driver_privsep_get_mac_addr,
|
||||||
|
|
|
@ -195,6 +195,58 @@ static void wpa_priv_cmd_get_scan_results(struct wpa_priv_interface *iface,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpa_priv_cmd_authenticate(struct wpa_priv_interface *iface,
|
||||||
|
void *buf, size_t len)
|
||||||
|
{
|
||||||
|
struct wpa_driver_auth_params params;
|
||||||
|
struct privsep_cmd_authenticate *auth;
|
||||||
|
int res, i;
|
||||||
|
|
||||||
|
if (iface->drv_priv == NULL || iface->driver->authenticate == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (len < sizeof(*auth)) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Invalid authentication request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auth = buf;
|
||||||
|
if (sizeof(*auth) + auth->ie_len + auth->sae_data_len > len) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Authentication request overflow");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
os_memset(¶ms, 0, sizeof(params));
|
||||||
|
params.freq = auth->freq;
|
||||||
|
params.bssid = auth->bssid;
|
||||||
|
params.ssid = auth->ssid;
|
||||||
|
if (auth->ssid_len > SSID_MAX_LEN)
|
||||||
|
return;
|
||||||
|
params.ssid_len = auth->ssid_len;
|
||||||
|
params.auth_alg = auth->auth_alg;
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
if (auth->wep_key_len[i]) {
|
||||||
|
params.wep_key[i] = auth->wep_key[i];
|
||||||
|
params.wep_key_len[i] = auth->wep_key_len[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
params.wep_tx_keyidx = auth->wep_tx_keyidx;
|
||||||
|
params.local_state_change = auth->local_state_change;
|
||||||
|
params.p2p = auth->p2p;
|
||||||
|
if (auth->ie_len) {
|
||||||
|
params.ie = (u8 *) (auth + 1);
|
||||||
|
params.ie_len = auth->ie_len;
|
||||||
|
}
|
||||||
|
if (auth->sae_data_len) {
|
||||||
|
params.sae_data = ((u8 *) (auth + 1)) + auth->ie_len;
|
||||||
|
params.sae_data_len = auth->sae_data_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = iface->driver->authenticate(iface->drv_priv, ¶ms);
|
||||||
|
wpa_printf(MSG_DEBUG, "drv->authenticate: res=%d", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wpa_priv_cmd_associate(struct wpa_priv_interface *iface,
|
static void wpa_priv_cmd_associate(struct wpa_priv_interface *iface,
|
||||||
void *buf, size_t len)
|
void *buf, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -557,6 +609,9 @@ static void wpa_priv_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
||||||
pos[cmd_len] = '\0';
|
pos[cmd_len] = '\0';
|
||||||
wpa_priv_cmd_set_country(iface, pos);
|
wpa_priv_cmd_set_country(iface, pos);
|
||||||
break;
|
break;
|
||||||
|
case PRIVSEP_CMD_AUTHENTICATE:
|
||||||
|
wpa_priv_cmd_authenticate(iface, cmd_buf, cmd_len);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,6 +781,36 @@ static int wpa_priv_send_event(struct wpa_priv_interface *iface, int event,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpa_priv_send_auth(struct wpa_priv_interface *iface,
|
||||||
|
union wpa_event_data *data)
|
||||||
|
{
|
||||||
|
size_t buflen = sizeof(struct privsep_event_auth) + data->auth.ies_len;
|
||||||
|
struct privsep_event_auth *auth;
|
||||||
|
u8 *buf, *pos;
|
||||||
|
|
||||||
|
buf = os_malloc(buflen);
|
||||||
|
if (buf == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auth = (struct privsep_event_auth *) buf;
|
||||||
|
pos = (u8 *) (auth + 1);
|
||||||
|
|
||||||
|
os_memcpy(auth->peer, data->auth.peer, ETH_ALEN);
|
||||||
|
os_memcpy(auth->bssid, data->auth.bssid, ETH_ALEN);
|
||||||
|
auth->auth_type = data->auth.auth_type;
|
||||||
|
auth->auth_transaction = data->auth.auth_transaction;
|
||||||
|
auth->status_code = data->auth.status_code;
|
||||||
|
if (data->auth.ies) {
|
||||||
|
os_memcpy(pos, data->auth.ies, data->auth.ies_len);
|
||||||
|
auth->ies_len = data->auth.ies_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_priv_send_event(iface, PRIVSEP_EVENT_AUTH, buf, buflen);
|
||||||
|
|
||||||
|
os_free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wpa_priv_send_assoc(struct wpa_priv_interface *iface, int event,
|
static void wpa_priv_send_assoc(struct wpa_priv_interface *iface, int event,
|
||||||
union wpa_event_data *data)
|
union wpa_event_data *data)
|
||||||
{
|
{
|
||||||
|
@ -906,6 +991,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
case EVENT_FT_RESPONSE:
|
case EVENT_FT_RESPONSE:
|
||||||
wpa_priv_send_ft_response(iface, data);
|
wpa_priv_send_ft_response(iface, data);
|
||||||
break;
|
break;
|
||||||
|
case EVENT_AUTH:
|
||||||
|
wpa_priv_send_auth(iface, data);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
wpa_printf(MSG_DEBUG, "Unsupported driver event %d (%s) - TODO",
|
wpa_printf(MSG_DEBUG, "Unsupported driver event %d (%s) - TODO",
|
||||||
event, event_to_string(event));
|
event, event_to_string(event));
|
||||||
|
|
Loading…
Reference in a new issue