summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrinivas Dasari <dasaris@qti.qualcomm.com>2018-01-25 10:13:38 -0500
committerJohannes Berg <johannes.berg@intel.com>2018-01-31 06:56:52 -0500
commit40cbfa90218bc570a7959b436b9d48a18c361041 (patch)
tree875d9606ce484261a21a2ff1b17055af42cbc3af
parent5037a00992e5fcb3d8509964313565a3dab6697c (diff)
cfg80211/nl80211: Optional authentication offload to userspace
This interface allows the host driver to offload the authentication to user space. This is exclusively defined for host drivers that do not define separate commands for authentication and association, but rely on userspace SME (e.g., in wpa_supplicant for the ~WPA_DRIVER_FLAGS_SME case) for the authentication to happen. This can be used to implement SAE without full implementation in the kernel/firmware while still being able to use NL80211_CMD_CONNECT with driver-based BSS selection. Host driver sends NL80211_CMD_EXTERNAL_AUTH event to start/abort authentication to the port on which connect is triggered and status of authentication is further indicated by user space to host driver through the same command response interface. User space entities advertise this capability through the NL80211_ATTR_EXTERNAL_AUTH_SUPP flag in the NL80211_CMD_CONNECT request. Host drivers shall look at this capability to offload the authentication. Signed-off-by: Srinivas Dasari <dasaris@qti.qualcomm.com> Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com> [add socket connection ownership check] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/cfg80211.h54
-rw-r--r--include/uapi/linux/nl80211.h47
-rw-r--r--net/wireless/nl80211.c94
-rw-r--r--net/wireless/rdev-ops.h15
-rw-r--r--net/wireless/trace.h23
5 files changed, 230 insertions, 3 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 81174f9b8d14..68def3e5b013 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1905,11 +1905,16 @@ struct cfg80211_auth_request {
1905 * @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n) 1905 * @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n)
1906 * @ASSOC_REQ_DISABLE_VHT: Disable VHT 1906 * @ASSOC_REQ_DISABLE_VHT: Disable VHT
1907 * @ASSOC_REQ_USE_RRM: Declare RRM capability in this association 1907 * @ASSOC_REQ_USE_RRM: Declare RRM capability in this association
1908 * @CONNECT_REQ_EXTERNAL_AUTH_SUPPORT: User space indicates external
1909 * authentication capability. Drivers can offload authentication to
1910 * userspace if this flag is set. Only applicable for cfg80211_connect()
1911 * request (connect callback).
1908 */ 1912 */
1909enum cfg80211_assoc_req_flags { 1913enum cfg80211_assoc_req_flags {
1910 ASSOC_REQ_DISABLE_HT = BIT(0), 1914 ASSOC_REQ_DISABLE_HT = BIT(0),
1911 ASSOC_REQ_DISABLE_VHT = BIT(1), 1915 ASSOC_REQ_DISABLE_VHT = BIT(1),
1912 ASSOC_REQ_USE_RRM = BIT(2), 1916 ASSOC_REQ_USE_RRM = BIT(2),
1917 CONNECT_REQ_EXTERNAL_AUTH_SUPPORT = BIT(3),
1913}; 1918};
1914 1919
1915/** 1920/**
@@ -2601,6 +2606,33 @@ struct cfg80211_pmk_conf {
2601}; 2606};
2602 2607
2603/** 2608/**
2609 * struct cfg80211_external_auth_params - Trigger External authentication.
2610 *
2611 * Commonly used across the external auth request and event interfaces.
2612 *
2613 * @action: action type / trigger for external authentication. Only significant
2614 * for the authentication request event interface (driver to user space).
2615 * @bssid: BSSID of the peer with which the authentication has
2616 * to happen. Used by both the authentication request event and
2617 * authentication response command interface.
2618 * @ssid: SSID of the AP. Used by both the authentication request event and
2619 * authentication response command interface.
2620 * @key_mgmt_suite: AKM suite of the respective authentication. Used by the
2621 * authentication request event interface.
2622 * @status: status code, %WLAN_STATUS_SUCCESS for successful authentication,
2623 * use %WLAN_STATUS_UNSPECIFIED_FAILURE if user space cannot give you
2624 * the real status code for failures. Used only for the authentication
2625 * response command interface (user space to driver).
2626 */
2627struct cfg80211_external_auth_params {
2628 enum nl80211_external_auth_action action;
2629 u8 bssid[ETH_ALEN] __aligned(2);
2630 struct cfg80211_ssid ssid;
2631 unsigned int key_mgmt_suite;
2632 u16 status;
2633};
2634
2635/**
2604 * struct cfg80211_ops - backend description for wireless configuration 2636 * struct cfg80211_ops - backend description for wireless configuration
2605 * 2637 *
2606 * This struct is registered by fullmac card drivers and/or wireless stacks 2638 * This struct is registered by fullmac card drivers and/or wireless stacks
@@ -2923,6 +2955,9 @@ struct cfg80211_pmk_conf {
2923 * (invoked with the wireless_dev mutex held) 2955 * (invoked with the wireless_dev mutex held)
2924 * @del_pmk: delete the previously configured PMK for the given authenticator. 2956 * @del_pmk: delete the previously configured PMK for the given authenticator.
2925 * (invoked with the wireless_dev mutex held) 2957 * (invoked with the wireless_dev mutex held)
2958 *
2959 * @external_auth: indicates result of offloaded authentication processing from
2960 * user space
2926 */ 2961 */
2927struct cfg80211_ops { 2962struct cfg80211_ops {
2928 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); 2963 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3216,6 +3251,8 @@ struct cfg80211_ops {
3216 const struct cfg80211_pmk_conf *conf); 3251 const struct cfg80211_pmk_conf *conf);
3217 int (*del_pmk)(struct wiphy *wiphy, struct net_device *dev, 3252 int (*del_pmk)(struct wiphy *wiphy, struct net_device *dev,
3218 const u8 *aa); 3253 const u8 *aa);
3254 int (*external_auth)(struct wiphy *wiphy, struct net_device *dev,
3255 struct cfg80211_external_auth_params *params);
3219}; 3256};
3220 3257
3221/* 3258/*
@@ -6202,6 +6239,17 @@ void cfg80211_nan_func_terminated(struct wireless_dev *wdev,
6202/* ethtool helper */ 6239/* ethtool helper */
6203void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info); 6240void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info);
6204 6241
6242/**
6243 * cfg80211_external_auth_request - userspace request for authentication
6244 * @netdev: network device
6245 * @params: External authentication parameters
6246 * @gfp: allocation flags
6247 * Returns: 0 on success, < 0 on error
6248 */
6249int cfg80211_external_auth_request(struct net_device *netdev,
6250 struct cfg80211_external_auth_params *params,
6251 gfp_t gfp);
6252
6205/* Logging, debugging and troubleshooting/diagnostic helpers. */ 6253/* Logging, debugging and troubleshooting/diagnostic helpers. */
6206 6254
6207/* wiphy_printk helpers, similar to dev_printk */ 6255/* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 6f60503fa617..c2342456cf16 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -992,6 +992,27 @@
992 * 992 *
993 * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded. 993 * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded.
994 * 994 *
995 * @NL80211_CMD_EXTERNAL_AUTH: This interface is exclusively defined for host
996 * drivers that do not define separate commands for authentication and
997 * association, but rely on user space for the authentication to happen.
998 * This interface acts both as the event request (driver to user space)
999 * to trigger the authentication and command response (userspace to
1000 * driver) to indicate the authentication status.
1001 *
1002 * User space uses the %NL80211_CMD_CONNECT command to the host driver to
1003 * trigger a connection. The host driver selects a BSS and further uses
1004 * this interface to offload only the authentication part to the user
1005 * space. Authentication frames are passed between the driver and user
1006 * space through the %NL80211_CMD_FRAME interface. Host driver proceeds
1007 * further with the association after getting successful authentication
1008 * status. User space indicates the authentication status through
1009 * %NL80211_ATTR_STATUS_CODE attribute in %NL80211_CMD_EXTERNAL_AUTH
1010 * command interface.
1011 *
1012 * Host driver reports this status on an authentication failure to the
1013 * user space through the connect result as the user space would have
1014 * initiated the connection through the connect request.
1015 *
995 * @NL80211_CMD_MAX: highest used command number 1016 * @NL80211_CMD_MAX: highest used command number
996 * @__NL80211_CMD_AFTER_LAST: internal use 1017 * @__NL80211_CMD_AFTER_LAST: internal use
997 */ 1018 */
@@ -1198,6 +1219,8 @@ enum nl80211_commands {
1198 1219
1199 NL80211_CMD_RELOAD_REGDB, 1220 NL80211_CMD_RELOAD_REGDB,
1200 1221
1222 NL80211_CMD_EXTERNAL_AUTH,
1223
1201 /* add new commands above here */ 1224 /* add new commands above here */
1202 1225
1203 /* used to define NL80211_CMD_MAX below */ 1226 /* used to define NL80211_CMD_MAX below */
@@ -2153,6 +2176,16 @@ enum nl80211_commands {
2153 * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT. 2176 * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT.
2154 * @NL80211_ATTR_PORT_AUTHORIZED: (reserved) 2177 * @NL80211_ATTR_PORT_AUTHORIZED: (reserved)
2155 * 2178 *
2179 * @NL80211_ATTR_EXTERNAL_AUTH_ACTION: Identify the requested external
2180 * authentication operation (u32 attribute with an
2181 * &enum nl80211_external_auth_action value). This is used with the
2182 * &NL80211_CMD_EXTERNAL_AUTH request event.
2183 * @NL80211_ATTR_EXTERNAL_AUTH_SUPPORT: Flag attribute indicating that the user
2184 * space supports external authentication. This attribute shall be used
2185 * only with %NL80211_CMD_CONNECT request. The driver may offload
2186 * authentication processing to user space if this capability is indicated
2187 * in NL80211_CMD_CONNECT requests from the user space.
2188 *
2156 * @NUM_NL80211_ATTR: total number of nl80211_attrs available 2189 * @NUM_NL80211_ATTR: total number of nl80211_attrs available
2157 * @NL80211_ATTR_MAX: highest attribute number currently defined 2190 * @NL80211_ATTR_MAX: highest attribute number currently defined
2158 * @__NL80211_ATTR_AFTER_LAST: internal use 2191 * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2579,6 +2612,9 @@ enum nl80211_attrs {
2579 NL80211_ATTR_PMKR0_NAME, 2612 NL80211_ATTR_PMKR0_NAME,
2580 NL80211_ATTR_PORT_AUTHORIZED, 2613 NL80211_ATTR_PORT_AUTHORIZED,
2581 2614
2615 NL80211_ATTR_EXTERNAL_AUTH_ACTION,
2616 NL80211_ATTR_EXTERNAL_AUTH_SUPPORT,
2617
2582 /* add attributes here, update the policy in nl80211.c */ 2618 /* add attributes here, update the policy in nl80211.c */
2583 2619
2584 __NL80211_ATTR_AFTER_LAST, 2620 __NL80211_ATTR_AFTER_LAST,
@@ -5495,4 +5531,15 @@ enum nl80211_nan_match_attributes {
5495 NL80211_NAN_MATCH_ATTR_MAX = NUM_NL80211_NAN_MATCH_ATTR - 1 5531 NL80211_NAN_MATCH_ATTR_MAX = NUM_NL80211_NAN_MATCH_ATTR - 1
5496}; 5532};
5497 5533
5534/**
5535 * nl80211_external_auth_action - Action to perform with external
5536 * authentication request. Used by NL80211_ATTR_EXTERNAL_AUTH_ACTION.
5537 * @NL80211_EXTERNAL_AUTH_START: Start the authentication.
5538 * @NL80211_EXTERNAL_AUTH_ABORT: Abort the ongoing authentication.
5539 */
5540enum nl80211_external_auth_action {
5541 NL80211_EXTERNAL_AUTH_START,
5542 NL80211_EXTERNAL_AUTH_ABORT,
5543};
5544
5498#endif /* __LINUX_NL80211_H */ 5545#endif /* __LINUX_NL80211_H */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index dd249ec9f228..aa6b64069c80 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -420,6 +420,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
420 [NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 }, 420 [NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 },
421 [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN }, 421 [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
422 [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG }, 422 [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
423 [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
423}; 424};
424 425
425/* policy for the key attributes */ 426/* policy for the key attributes */
@@ -9161,6 +9162,15 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
9161 return -EINVAL; 9162 return -EINVAL;
9162 } 9163 }
9163 9164
9165 if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) {
9166 if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
9167 GENL_SET_ERR_MSG(info,
9168 "external auth requires connection ownership");
9169 return -EINVAL;
9170 }
9171 connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;
9172 }
9173
9164 wdev_lock(dev->ieee80211_ptr); 9174 wdev_lock(dev->ieee80211_ptr);
9165 9175
9166 err = cfg80211_connect(rdev, dev, &connect, connkeys, 9176 err = cfg80211_connect(rdev, dev, &connect, connkeys,
@@ -12469,6 +12479,41 @@ static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info)
12469 return ret; 12479 return ret;
12470} 12480}
12471 12481
12482static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)
12483{
12484 struct cfg80211_registered_device *rdev = info->user_ptr[0];
12485 struct net_device *dev = info->user_ptr[1];
12486 struct cfg80211_external_auth_params params;
12487
12488 if (rdev->ops->external_auth)
12489 return -EOPNOTSUPP;
12490
12491 if (!info->attrs[NL80211_ATTR_SSID])
12492 return -EINVAL;
12493
12494 if (!info->attrs[NL80211_ATTR_BSSID])
12495 return -EINVAL;
12496
12497 if (!info->attrs[NL80211_ATTR_STATUS_CODE])
12498 return -EINVAL;
12499
12500 memset(&params, 0, sizeof(params));
12501
12502 params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
12503 if (params.ssid.ssid_len == 0 ||
12504 params.ssid.ssid_len > IEEE80211_MAX_SSID_LEN)
12505 return -EINVAL;
12506 memcpy(params.ssid.ssid, nla_data(info->attrs[NL80211_ATTR_SSID]),
12507 params.ssid.ssid_len);
12508
12509 memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]),
12510 ETH_ALEN);
12511
12512 params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
12513
12514 return rdev_external_auth(rdev, dev, &params);
12515}
12516
12472#define NL80211_FLAG_NEED_WIPHY 0x01 12517#define NL80211_FLAG_NEED_WIPHY 0x01
12473#define NL80211_FLAG_NEED_NETDEV 0x02 12518#define NL80211_FLAG_NEED_NETDEV 0x02
12474#define NL80211_FLAG_NEED_RTNL 0x04 12519#define NL80211_FLAG_NEED_RTNL 0x04
@@ -13364,6 +13409,14 @@ static const struct genl_ops nl80211_ops[] = {
13364 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 13409 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
13365 NL80211_FLAG_NEED_RTNL, 13410 NL80211_FLAG_NEED_RTNL,
13366 }, 13411 },
13412 {
13413 .cmd = NL80211_CMD_EXTERNAL_AUTH,
13414 .doit = nl80211_external_auth,
13415 .policy = nl80211_policy,
13416 .flags = GENL_ADMIN_PERM,
13417 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
13418 NL80211_FLAG_NEED_RTNL,
13419 },
13367 13420
13368}; 13421};
13369 13422
@@ -15375,6 +15428,47 @@ void nl80211_send_ap_stopped(struct wireless_dev *wdev)
15375 nlmsg_free(msg); 15428 nlmsg_free(msg);
15376} 15429}
15377 15430
15431int cfg80211_external_auth_request(struct net_device *dev,
15432 struct cfg80211_external_auth_params *params,
15433 gfp_t gfp)
15434{
15435 struct wireless_dev *wdev = dev->ieee80211_ptr;
15436 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
15437 struct sk_buff *msg;
15438 void *hdr;
15439
15440 if (!wdev->conn_owner_nlportid)
15441 return -EINVAL;
15442
15443 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
15444 if (!msg)
15445 return -ENOMEM;
15446
15447 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH);
15448 if (!hdr)
15449 goto nla_put_failure;
15450
15451 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
15452 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
15453 nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) ||
15454 nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION,
15455 params->action) ||
15456 nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) ||
15457 nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len,
15458 params->ssid.ssid))
15459 goto nla_put_failure;
15460
15461 genlmsg_end(msg, hdr);
15462 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
15463 wdev->conn_owner_nlportid);
15464 return 0;
15465
15466 nla_put_failure:
15467 nlmsg_free(msg);
15468 return -ENOBUFS;
15469}
15470EXPORT_SYMBOL(cfg80211_external_auth_request);
15471
15378/* initialisation/exit functions */ 15472/* initialisation/exit functions */
15379 15473
15380int __init nl80211_init(void) 15474int __init nl80211_init(void)
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 0c06240d25af..84f23ae015fc 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1190,4 +1190,19 @@ static inline int rdev_del_pmk(struct cfg80211_registered_device *rdev,
1190 trace_rdev_return_int(&rdev->wiphy, ret); 1190 trace_rdev_return_int(&rdev->wiphy, ret);
1191 return ret; 1191 return ret;
1192} 1192}
1193
1194static inline int
1195rdev_external_auth(struct cfg80211_registered_device *rdev,
1196 struct net_device *dev,
1197 struct cfg80211_external_auth_params *params)
1198{
1199 int ret = -EOPNOTSUPP;
1200
1201 trace_rdev_external_auth(&rdev->wiphy, dev, params);
1202 if (rdev->ops->external_auth)
1203 ret = rdev->ops->external_auth(&rdev->wiphy, dev, params);
1204 trace_rdev_return_int(&rdev->wiphy, ret);
1205 return ret;
1206}
1207
1193#endif /* __CFG80211_RDEV_OPS */ 1208#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index bcfedd39e7a3..5152938b358d 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2319,6 +2319,29 @@ TRACE_EVENT(rdev_del_pmk,
2319 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(aa)) 2319 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(aa))
2320); 2320);
2321 2321
2322TRACE_EVENT(rdev_external_auth,
2323 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
2324 struct cfg80211_external_auth_params *params),
2325 TP_ARGS(wiphy, netdev, params),
2326 TP_STRUCT__entry(WIPHY_ENTRY
2327 NETDEV_ENTRY
2328 MAC_ENTRY(bssid)
2329 __array(u8, ssid, IEEE80211_MAX_SSID_LEN + 1)
2330 __field(u16, status)
2331 ),
2332 TP_fast_assign(WIPHY_ASSIGN;
2333 NETDEV_ASSIGN;
2334 MAC_ASSIGN(bssid, params->bssid);
2335 memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1);
2336 memcpy(__entry->ssid, params->ssid.ssid,
2337 params->ssid.ssid_len);
2338 __entry->status = params->status;
2339 ),
2340 TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
2341 ", ssid: %s, status: %u", WIPHY_PR_ARG, NETDEV_PR_ARG,
2342 __entry->bssid, __entry->ssid, __entry->status)
2343);
2344
2322/************************************************************* 2345/*************************************************************
2323 * cfg80211 exported functions traces * 2346 * cfg80211 exported functions traces *
2324 *************************************************************/ 2347 *************************************************************/