]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Introduce the interface for external authentication
authorSunil Dutt <usdutt@codeaurora.org>
Thu, 1 Feb 2018 07:15:41 +0000 (12:45 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 2 Feb 2018 16:51:04 +0000 (18:51 +0200)
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>
src/drivers/driver.h
src/drivers/driver_common.c
src/drivers/driver_nl80211.c
src/drivers/driver_nl80211_event.c

index f28bd2b2c4c6f8b5288b93f25b10a74aef0da79c..d9c6fd9f5f6979913679950b665ebeb3dee2c141 100644 (file)
@@ -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;
 };
 
 /**
index 04643043e9e502a3957586a192389b48c9594498..33a6db346738a432be7f0a4f65b75e71f7418e35 100644 (file)
@@ -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";
index 9b3bde278cdebc15284c51c6cac4e99c86806593..d6bf12160b679153aa9f68b50854c7a67092c6d8 100644 (file)
@@ -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,
 };
index 1b5be97c43fdbdeb44c7208a5c46edcb3fff5cc5..5591cebe81fafb2c0ca071bcb2e788b4b96bceab 100644 (file)
@@ -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);