Rebase from upstream commit : 3bb9dcf44627ffdd313fe92c563ae454b6ff8aa6
[librecmc/librecmc.git] / package / network / services / hostapd / patches / 557-hostapd-support-Multi-AP-backhaul-STA-onboarding.patch
1 From 8b04a4cddbd6dbadb24279713af7ac677e80d342 Mon Sep 17 00:00:00 2001
2 From: Davina Lu <ylu@quantenna.com>
3 Date: Tue, 2 Oct 2018 18:34:14 -0700
4 Subject: [PATCH] hostapd: support Multi-AP backhaul STA onboarding
5
6 The Wi-Fi Alliance Multi-AP Specification v1.0 allows onboarding of a
7 backhaul STA through WPS. To enable this, the WPS registrar offers a
8 different set of credentials (backhaul credentials instead of fronthaul
9 credentials) when the Multi-AP subelement is present in the WFA vendor
10 extension element of the WSC M1 message.
11
12 Add 3 new configuration options to specify the backhaul credentials for
13 the hostapd internal registrar: multi_ap_backhaul_ssid,
14 multi_ap_backhaul_wpa_psk, multi_ap_backhaul_wpa_passphrase. These are
15 only relevant for a fronthaul SSID, i.e. where multi_ap is set to 2 or
16 3. When these options are set, pass the backhaul credentials instead of
17 the normal credentials when the Multi-AP subelement is present.
18
19 Ignore the Multi-AP subelement if the backhaul config options are not
20 set. Note that for an SSID which is fronthaul and backhaul at the same
21 time (i.e., multi_ap == 3), this results in the correct credentials
22 being sent anyway.
23
24 The security to be used for the backaul BSS is fixed to WPA2PSK. The
25 Multi-AP Specification only allows Open and WPA2PSK networks to be
26 configured. Although not stated explicitly, the backhaul link is
27 intended to be always encrypted, hence WPA2PSK.
28
29 To build the credentials, the credential-building code is essentially
30 copied and simplified. Indeed, the backhaul credentials are always
31 WPA2PSK and never use per-device PSK. All the options set for the
32 fronthaul BSS WPS are simply ignored.
33
34 Signed-off-by: Davina Lu <ylu@quantenna.com>
35 Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
36 Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
37 ---
38 v4: no change
39 ---
40  hostapd/config_file.c    | 47 ++++++++++++++++++++++++++++++++++++++++
41  hostapd/hostapd.conf     |  9 ++++++++
42  src/ap/ap_config.c       |  2 ++
43  src/ap/ap_config.h       |  1 +
44  src/ap/wps_hostapd.c     | 26 ++++++++++++++++++++++
45  src/wps/wps.h            | 32 +++++++++++++++++++++++++++
46  src/wps/wps_attr_parse.c | 11 ++++++++++
47  src/wps/wps_attr_parse.h |  1 +
48  src/wps/wps_dev_attr.c   |  5 +++++
49  src/wps/wps_dev_attr.h   |  1 +
50  src/wps/wps_registrar.c  | 25 ++++++++++++++++++++-
51  11 files changed, 159 insertions(+), 1 deletion(-)
52
53 --- a/hostapd/config_file.c
54 +++ b/hostapd/config_file.c
55 @@ -3479,6 +3479,53 @@ static int hostapd_config_fill(struct ho
56                                    line, pos);
57                         return 1;
58                 }
59 +       } else if (os_strcmp(buf, "multi_ap_backhaul_ssid") == 0) {
60 +               size_t slen;
61 +               char *str = wpa_config_parse_string(pos, &slen);
62 +
63 +               if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
64 +                       wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
65 +                                  line, pos);
66 +                       os_free(str);
67 +                       return 1;
68 +               }
69 +               os_memcpy(bss->multi_ap_backhaul_ssid.ssid, str, slen);
70 +               bss->multi_ap_backhaul_ssid.ssid_len = slen;
71 +               bss->multi_ap_backhaul_ssid.ssid_set = 1;
72 +               os_free(str);
73 +       } else if (os_strcmp(buf, "multi_ap_backhaul_wpa_passphrase") == 0) {
74 +               int len = os_strlen(pos);
75 +
76 +               if (len < 8 || len > 63) {
77 +                       wpa_printf(MSG_ERROR,
78 +                                  "Line %d: invalid WPA passphrase length %d (expected 8..63)",
79 +                                  line, len);
80 +                       return 1;
81 +               }
82 +               os_free(bss->multi_ap_backhaul_ssid.wpa_passphrase);
83 +               bss->multi_ap_backhaul_ssid.wpa_passphrase = os_strdup(pos);
84 +               if (bss->multi_ap_backhaul_ssid.wpa_passphrase) {
85 +                       hostapd_config_clear_wpa_psk(&bss->multi_ap_backhaul_ssid.wpa_psk);
86 +                       bss->multi_ap_backhaul_ssid.wpa_passphrase_set = 1;
87 +               }
88 +       } else if (os_strcmp(buf, "multi_ap_backhaul_wpa_psk") == 0) {
89 +               hostapd_config_clear_wpa_psk(&bss->multi_ap_backhaul_ssid.wpa_psk);
90 +               bss->multi_ap_backhaul_ssid.wpa_psk =
91 +                       os_zalloc(sizeof(struct hostapd_wpa_psk));
92 +               if (bss->multi_ap_backhaul_ssid.wpa_psk == NULL)
93 +                       return 1;
94 +               if (hexstr2bin(pos, bss->multi_ap_backhaul_ssid.wpa_psk->psk,
95 +                              PMK_LEN) ||
96 +                   pos[PMK_LEN * 2] != '\0') {
97 +                       wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
98 +                                  line, pos);
99 +                       hostapd_config_clear_wpa_psk(&bss->multi_ap_backhaul_ssid.wpa_psk);
100 +                       return 1;
101 +               }
102 +               bss->multi_ap_backhaul_ssid.wpa_psk->group = 1;
103 +               os_free(bss->multi_ap_backhaul_ssid.wpa_passphrase);
104 +               bss->multi_ap_backhaul_ssid.wpa_passphrase = NULL;
105 +               bss->multi_ap_backhaul_ssid.wpa_psk_set = 1;
106         } else if (os_strcmp(buf, "upnp_iface") == 0) {
107                 os_free(bss->upnp_iface);
108                 bss->upnp_iface = os_strdup(pos);
109 --- a/hostapd/hostapd.conf
110 +++ b/hostapd/hostapd.conf
111 @@ -1852,6 +1852,15 @@ own_ip_addr=127.0.0.1
112  # attribute.
113  #ap_settings=hostapd.ap_settings
114  
115 +# Multi-AP backhaul BSS config
116 +# Used in WPS when multi_ap=2 or 3. Defines "backhaul BSS" credentials.
117 +# These are passed in WPS M8 instead of the normal (fronthaul) credentials
118 +# if the enrollee has the Multi-AP subelement set. Backhaul SSID is formatted
119 +# like ssid2. The key is set like wpa_psk or wpa_passphrase.
120 +#multi_ap_backhaul_ssid="backhaul"
121 +#multi_ap_backhaul_wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
122 +#multi_ap_backhaul_wpa_passphrase=secret passphrase
123 +
124  # WPS UPnP interface
125  # If set, support for external Registrars is enabled.
126  #upnp_iface=br0
127 --- a/src/ap/ap_config.c
128 +++ b/src/ap/ap_config.c
129 @@ -582,6 +582,8 @@ void hostapd_config_free_bss(struct host
130         os_free(conf->ap_pin);
131         os_free(conf->extra_cred);
132         os_free(conf->ap_settings);
133 +       hostapd_config_clear_wpa_psk(&conf->multi_ap_backhaul_ssid.wpa_psk);
134 +       str_clear_free(conf->multi_ap_backhaul_ssid.wpa_passphrase);
135         os_free(conf->upnp_iface);
136         os_free(conf->friendly_name);
137         os_free(conf->manufacturer_url);
138 --- a/src/ap/ap_config.h
139 +++ b/src/ap/ap_config.h
140 @@ -456,6 +456,7 @@ struct hostapd_bss_config {
141         int force_per_enrollee_psk;
142         u8 *ap_settings;
143         size_t ap_settings_len;
144 +       struct hostapd_ssid multi_ap_backhaul_ssid;
145         char *upnp_iface;
146         char *friendly_name;
147         char *manufacturer_url;
148 --- a/src/ap/wps_hostapd.c
149 +++ b/src/ap/wps_hostapd.c
150 @@ -962,6 +962,7 @@ static void hostapd_free_wps(struct wps_
151                 wpabuf_free(wps->dev.vendor_ext[i]);
152         wps_device_data_free(&wps->dev);
153         os_free(wps->network_key);
154 +       os_free(wps->multi_ap_backhaul_network_key);
155         hostapd_wps_nfc_clear(wps);
156         wpabuf_free(wps->dh_pubkey);
157         wpabuf_free(wps->dh_privkey);
158 @@ -1131,6 +1132,31 @@ int hostapd_init_wps(struct hostapd_data
159                 wps->encr_types_wpa = WPS_ENCR_AES | WPS_ENCR_TKIP;
160         }
161  
162 +       if (hapd->conf->multi_ap & FRONTHAUL_BSS &&
163 +           hapd->conf->multi_ap_backhaul_ssid.ssid_len) {
164 +               wps->multi_ap_backhaul_ssid_len =
165 +                       hapd->conf->multi_ap_backhaul_ssid.ssid_len;
166 +               os_memcpy(wps->multi_ap_backhaul_ssid,
167 +                         hapd->conf->multi_ap_backhaul_ssid.ssid,
168 +                         wps->multi_ap_backhaul_ssid_len);
169 +               if (conf->multi_ap_backhaul_ssid.wpa_passphrase) {
170 +                       wps->multi_ap_backhaul_network_key =
171 +                               (u8 *) os_strdup(conf->multi_ap_backhaul_ssid.wpa_passphrase);
172 +                       wps->multi_ap_backhaul_network_key_len =
173 +                               os_strlen(conf->multi_ap_backhaul_ssid.wpa_passphrase);
174 +               } else if (conf->multi_ap_backhaul_ssid.wpa_psk) {
175 +                       wps->multi_ap_backhaul_network_key =
176 +                               os_malloc(2 * PMK_LEN + 1);
177 +                       if (wps->multi_ap_backhaul_network_key == NULL)
178 +                               goto fail;
179 +                       wpa_snprintf_hex((char *) wps->multi_ap_backhaul_network_key,
180 +                                        2 * PMK_LEN + 1,
181 +                                        conf->multi_ap_backhaul_ssid.wpa_psk->psk,
182 +                                        PMK_LEN);
183 +                       wps->multi_ap_backhaul_network_key_len = 2 * PMK_LEN;
184 +               }
185 +       }
186 +
187         wps->ap_settings = conf->ap_settings;
188         wps->ap_settings_len = conf->ap_settings_len;
189  
190 --- a/src/wps/wps.h
191 +++ b/src/wps/wps.h
192 @@ -100,6 +100,7 @@ struct wps_device_data {
193         struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
194  
195         int p2p;
196 +       u8 multi_ap_ext;
197  };
198  
199  /**
200 @@ -730,6 +731,37 @@ struct wps_context {
201         int psk_set;
202  
203         /**
204 +        * multi_ap_backhaul_ssid - SSID to supply to a Multi-AP backhaul
205 +        * enrollee
206 +        *
207 +        * This SSID is used by the Registrar to fill in information for
208 +        * Credentials when the enrollee advertises it is a Multi-AP backhaul
209 +        * STA.
210 +        */
211 +       u8 multi_ap_backhaul_ssid[SSID_MAX_LEN];
212 +
213 +       /**
214 +        * multi_ap_backhaul_ssid_len - Length of multi_ap_backhaul_ssid in
215 +        * octets
216 +        */
217 +       size_t multi_ap_backhaul_ssid_len;
218 +
219 +       /**
220 +        * multi_ap_backhaul_network_key - The Network Key (PSK) for the
221 +        * Multi-AP backhaul enrollee.
222 +        *
223 +        * This key can be either the ASCII passphrase (8..63 characters) or the
224 +        * 32-octet PSK (64 hex characters).
225 +        */
226 +       u8 *multi_ap_backhaul_network_key;
227 +
228 +       /**
229 +        * multi_ap_backhaul_network_key_len - Length of
230 +        * multi_ap_backhaul_network_key in octets
231 +        */
232 +       size_t multi_ap_backhaul_network_key_len;
233 +
234 +       /**
235          * ap_settings - AP Settings override for M7 (only used at AP)
236          *
237          * If %NULL, AP Settings attributes will be generated based on the
238 --- a/src/wps/wps_attr_parse.c
239 +++ b/src/wps/wps_attr_parse.c
240 @@ -67,6 +67,17 @@ static int wps_set_vendor_ext_wfa_subele
241                 }
242                 attr->registrar_configuration_methods = pos;
243                 break;
244 +       case WFA_ELEM_MULTI_AP:
245 +               if (len != 1) {
246 +                       wpa_printf(MSG_DEBUG,
247 +                                  "WPS: Invalid Multi-AP Extension length %u",
248 +                                  len);
249 +                       return -1;
250 +               }
251 +               attr->multi_ap_ext = *pos;
252 +               wpa_printf(MSG_DEBUG, "WPS: Multi-AP Extension 0x%02x",
253 +                          attr->multi_ap_ext);
254 +               break;
255         default:
256                 wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor "
257                            "Extension subelement %u", id);
258 --- a/src/wps/wps_attr_parse.h
259 +++ b/src/wps/wps_attr_parse.h
260 @@ -97,6 +97,7 @@ struct wps_parse_attr {
261         const u8 *cred[MAX_CRED_COUNT];
262         const u8 *req_dev_type[MAX_REQ_DEV_TYPE_COUNT];
263         const u8 *vendor_ext[MAX_WPS_PARSE_VENDOR_EXT];
264 +       u8 multi_ap_ext;
265  };
266  
267  int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr);
268 --- a/src/wps/wps_dev_attr.c
269 +++ b/src/wps/wps_dev_attr.c
270 @@ -389,6 +389,11 @@ int wps_process_os_version(struct wps_de
271         return 0;
272  }
273  
274 +void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext)
275 +{
276 +       dev->multi_ap_ext = ext;
277 +       wpa_printf(MSG_DEBUG, "WPS: Multi-AP extension value %02x", dev->multi_ap_ext);
278 +}
279  
280  int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands)
281  {
282 --- a/src/wps/wps_dev_attr.h
283 +++ b/src/wps/wps_dev_attr.h
284 @@ -29,6 +29,7 @@ int wps_build_dev_name(struct wps_device
285  int wps_process_device_attrs(struct wps_device_data *dev,
286                              struct wps_parse_attr *attr);
287  int wps_process_os_version(struct wps_device_data *dev, const u8 *ver);
288 +void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext);
289  int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands);
290  void wps_device_data_free(struct wps_device_data *dev);
291  int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg);
292 --- a/src/wps/wps_registrar.c
293 +++ b/src/wps/wps_registrar.c
294 @@ -1588,7 +1588,6 @@ int wps_build_credential_wrap(struct wpa
295         return 0;
296  }
297  
298 -
299  int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
300  {
301         struct wpabuf *cred;
302 @@ -1603,6 +1602,29 @@ int wps_build_cred(struct wps_data *wps,
303         }
304         os_memset(&wps->cred, 0, sizeof(wps->cred));
305  
306 +       if (wps->peer_dev.multi_ap_ext == MULTI_AP_BACKHAUL_STA &&
307 +           wps->wps->multi_ap_backhaul_ssid_len) {
308 +               wpa_printf(MSG_DEBUG, "WPS: Use backhaul STA credentials");
309 +               os_memcpy(wps->cred.ssid, wps->wps->multi_ap_backhaul_ssid,
310 +                         wps->wps->multi_ap_backhaul_ssid_len);
311 +               wps->cred.ssid_len = wps->wps->multi_ap_backhaul_ssid_len;
312 +               /* Backhaul is always WPA2PSK */
313 +               wps->cred.auth_type = WPS_AUTH_WPA2PSK;
314 +               wps->cred.encr_type = WPS_ENCR_AES;
315 +               /* Set MAC address in the Credential to be the Enrollee's MAC
316 +                * address
317 +                */
318 +               os_memcpy(wps->cred.mac_addr, wps->mac_addr_e, ETH_ALEN);
319 +               if (wps->wps->multi_ap_backhaul_network_key) {
320 +                       os_memcpy(wps->cred.key,
321 +                                 wps->wps->multi_ap_backhaul_network_key,
322 +                                 wps->wps->multi_ap_backhaul_network_key_len);
323 +                       wps->cred.key_len =
324 +                               wps->wps->multi_ap_backhaul_network_key_len;
325 +               }
326 +               goto use_provided;
327 +       }
328 +
329         os_memcpy(wps->cred.ssid, wps->wps->ssid, wps->wps->ssid_len);
330         wps->cred.ssid_len = wps->wps->ssid_len;
331  
332 @@ -2705,6 +2727,7 @@ static enum wps_process_res wps_process_
333                 wps->use_psk_key = 1;
334         }
335  #endif /* WPS_WORKAROUNDS */
336 +       wps_process_vendor_ext_m1(&wps->peer_dev, attr->multi_ap_ext);
337  
338         wps->state = SEND_M2;
339         return WPS_CONTINUE;