nl80211: Introduce the interface for external authentication
This command/event interface can be used by host drivers that do not define separate commands for authentication and association but rely on wpa_supplicant for the authentication (SAE) processing. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
8678b14faa
commit
ba71cb821a
4 changed files with 143 additions and 1 deletions
|
@ -2051,6 +2051,36 @@ enum wpa_drv_update_connect_params_mask {
|
|||
WPA_DRV_UPDATE_AUTH_TYPE = BIT(2),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct external_auth - External authentication trigger parameters
|
||||
*
|
||||
* These are used across the external authentication request and event
|
||||
* interfaces.
|
||||
* @action: Action type / trigger for external authentication. Only significant
|
||||
* for the event interface.
|
||||
* @bssid: BSSID of the peer with which the authentication has to happen. Used
|
||||
* by both the request and event interface.
|
||||
* @ssid: SSID of the AP. Used by both the request and event interface.
|
||||
* @ssid_len: SSID length in octets.
|
||||
* @key_mgmt_suite: AKM suite of the respective authentication. Optional for
|
||||
* the request interface.
|
||||
* @status: Status code, %WLAN_STATUS_SUCCESS for successful authentication,
|
||||
* use %WLAN_STATUS_UNSPECIFIED_FAILURE if wpa_supplicant cannot give
|
||||
* the real status code for failures. Used only for the request interface
|
||||
* from user space to the driver.
|
||||
*/
|
||||
struct external_auth {
|
||||
enum {
|
||||
EXT_AUTH_START,
|
||||
EXT_AUTH_ABORT,
|
||||
} action;
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 ssid[SSID_MAX_LEN];
|
||||
size_t ssid_len;
|
||||
unsigned int key_mgmt_suite;
|
||||
u16 status;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wpa_driver_ops - Driver interface API definition
|
||||
*
|
||||
|
@ -4012,6 +4042,16 @@ struct wpa_driver_ops {
|
|||
int (*update_connect_params)(
|
||||
void *priv, struct wpa_driver_associate_params *params,
|
||||
enum wpa_drv_update_connect_params_mask mask);
|
||||
|
||||
/**
|
||||
* send_external_auth_status - Indicate the status of external
|
||||
* authentication processing to the host driver.
|
||||
* @priv: Private driver interface data
|
||||
* @params: Status of authentication processing.
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int (*send_external_auth_status)(void *priv,
|
||||
struct external_auth *params);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -4507,6 +4547,16 @@ enum wpa_event_type {
|
|||
* performed before start operating on this channel.
|
||||
*/
|
||||
EVENT_DFS_PRE_CAC_EXPIRED,
|
||||
|
||||
/**
|
||||
* EVENT_EXTERNAL_AUTH - This event interface is used by host drivers
|
||||
* that do not define separate commands for authentication and
|
||||
* association (~WPA_DRIVER_FLAGS_SME) but offload the 802.11
|
||||
* authentication to wpa_supplicant. This event carries all the
|
||||
* necessary information from the host driver for the authentication to
|
||||
* happen.
|
||||
*/
|
||||
EVENT_EXTERNAL_AUTH,
|
||||
};
|
||||
|
||||
|
||||
|
@ -5309,6 +5359,9 @@ union wpa_event_data {
|
|||
P2P_LO_STOPPED_REASON_NOT_SUPPORTED,
|
||||
} reason_code;
|
||||
} p2p_lo_stop;
|
||||
|
||||
/* For EVENT_EXTERNAL_AUTH */
|
||||
struct external_auth external_auth;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -82,6 +82,7 @@ const char * event_to_string(enum wpa_event_type event)
|
|||
E2S(P2P_LO_STOP);
|
||||
E2S(BEACON_LOSS);
|
||||
E2S(DFS_PRE_CAC_EXPIRED);
|
||||
E2S(EXTERNAL_AUTH);
|
||||
}
|
||||
|
||||
return "UNKNOWN";
|
||||
|
|
|
@ -2020,7 +2020,9 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
|
|||
wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP "
|
||||
"handle %p", bss->nl_mgmt);
|
||||
|
||||
if (drv->nlmode == NL80211_IFTYPE_ADHOC) {
|
||||
if (drv->nlmode == NL80211_IFTYPE_ADHOC ||
|
||||
((drv->capa.flags & WPA_DRIVER_FLAGS_SAE) &&
|
||||
!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))) {
|
||||
u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4);
|
||||
|
||||
/* register for any AUTH message */
|
||||
|
@ -5368,6 +5370,11 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
|
|||
nl80211_put_fils_connect_params(drv, params, msg) != 0)
|
||||
return -1;
|
||||
|
||||
if ((params->auth_alg & WPA_AUTH_ALG_SAE) &&
|
||||
(!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) &&
|
||||
nla_put_flag(msg, NL80211_ATTR_EXTERNAL_AUTH_SUPPORT))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -10377,6 +10384,38 @@ fail:
|
|||
}
|
||||
|
||||
|
||||
static int nl80211_send_external_auth_status(void *priv,
|
||||
struct external_auth *params)
|
||||
{
|
||||
struct i802_bss *bss = priv;
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
struct nl_msg *msg = NULL;
|
||||
int ret = -1;
|
||||
|
||||
wpa_dbg(drv->ctx, MSG_DEBUG,
|
||||
"nl80211: External auth status: %u", params->status);
|
||||
|
||||
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_EXTERNAL_AUTH);
|
||||
if (!msg ||
|
||||
nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, params->status) ||
|
||||
nla_put(msg, NL80211_ATTR_SSID, params->ssid_len,
|
||||
params->ssid) ||
|
||||
nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid))
|
||||
goto fail;
|
||||
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||
msg = NULL;
|
||||
if (ret) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: External Auth status update failed: ret=%d (%s)",
|
||||
ret, strerror(-ret));
|
||||
goto fail;
|
||||
}
|
||||
fail:
|
||||
nlmsg_free(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||
.name = "nl80211",
|
||||
.desc = "Linux nl80211/cfg80211",
|
||||
|
@ -10504,4 +10543,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
|||
.configure_data_frame_filters = nl80211_configure_data_frame_filters,
|
||||
.get_ext_capab = nl80211_get_ext_capab,
|
||||
.update_connect_params = nl80211_update_connection_params,
|
||||
.send_external_auth_status = nl80211_send_external_auth_status,
|
||||
};
|
||||
|
|
|
@ -131,6 +131,7 @@ static const char * nl80211_command_to_string(enum nl80211_commands cmd)
|
|||
C2S(NL80211_CMD_SET_QOS_MAP)
|
||||
C2S(NL80211_CMD_ADD_TX_TS)
|
||||
C2S(NL80211_CMD_DEL_TX_TS)
|
||||
C2S(NL80211_CMD_EXTERNAL_AUTH)
|
||||
default:
|
||||
return "NL80211_CMD_UNKNOWN";
|
||||
}
|
||||
|
@ -2175,6 +2176,50 @@ static void nl80211_reg_change_event(struct wpa_driver_nl80211_data *drv,
|
|||
}
|
||||
|
||||
|
||||
static void nl80211_external_auth(struct wpa_driver_nl80211_data *drv,
|
||||
struct nlattr **tb)
|
||||
{
|
||||
union wpa_event_data event;
|
||||
enum nl80211_external_auth_action act;
|
||||
|
||||
if (!tb[NL80211_ATTR_AKM_SUITES] ||
|
||||
!tb[NL80211_ATTR_EXTERNAL_AUTH_ACTION] ||
|
||||
!tb[NL80211_ATTR_BSSID] ||
|
||||
!tb[NL80211_ATTR_SSID])
|
||||
return;
|
||||
|
||||
os_memset(&event, 0, sizeof(event));
|
||||
act = nla_get_u32(tb[NL80211_ATTR_EXTERNAL_AUTH_ACTION]);
|
||||
switch (act) {
|
||||
case NL80211_EXTERNAL_AUTH_START:
|
||||
event.external_auth.action = EXT_AUTH_START;
|
||||
break;
|
||||
case NL80211_EXTERNAL_AUTH_ABORT:
|
||||
event.external_auth.action = EXT_AUTH_ABORT;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
event.external_auth.key_mgmt_suite =
|
||||
nla_get_u32(tb[NL80211_ATTR_AKM_SUITES]);
|
||||
|
||||
event.external_auth.ssid_len = nla_len(tb[NL80211_ATTR_SSID]);
|
||||
if (event.external_auth.ssid_len > SSID_MAX_LEN)
|
||||
return;
|
||||
os_memcpy(event.external_auth.ssid, nla_data(tb[NL80211_ATTR_SSID]),
|
||||
event.external_auth.ssid_len);
|
||||
|
||||
os_memcpy(event.external_auth.bssid, nla_data(tb[NL80211_ATTR_BSSID]),
|
||||
ETH_ALEN);
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: External auth action: %u, AKM: 0x%x",
|
||||
event.external_auth.action,
|
||||
event.external_auth.key_mgmt_suite);
|
||||
wpa_supplicant_event(drv->ctx, EVENT_EXTERNAL_AUTH, &event);
|
||||
}
|
||||
|
||||
static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
||||
struct nlattr **tb)
|
||||
{
|
||||
|
@ -2373,6 +2418,9 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
|||
case NL80211_CMD_NEW_PEER_CANDIDATE:
|
||||
nl80211_new_peer_candidate(drv, tb);
|
||||
break;
|
||||
case NL80211_CMD_EXTERNAL_AUTH:
|
||||
nl80211_external_auth(drv, tb);
|
||||
break;
|
||||
default:
|
||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
|
||||
"(cmd=%d)", cmd);
|
||||
|
|
Loading…
Reference in a new issue