~ubuntu-branches/ubuntu/precise/wpasupplicant/precise-proposed

« back to all changes in this revision

Viewing changes to .pc/0002-pmkokc-Clear-WPA-and-EAPOL-state-machine-config-pointer-on-.patch/wpa_supplicant/wps_supplicant.c

  • Committer: Package Import Robot
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2013-06-12 15:57:50 UTC
  • Revision ID: package-import@ubuntu.com-20130612155750-go9lgylcef8n3f2f
Tags: 0.7.3-6ubuntu2.2
* Multiple patches to reduce the number of disconnections for WPA Enterprise
  roaming and Opportunistic Key Caching. (LP: #1187524)
* In debian/patches:
  0001-sme-fix-retry-after-auth-assoc-timeout-failure.patch,
  0002-sme-optimize-recovery-from-common-load-balancing-mechanisms.patch,
  0003-sme-blacklist-bss-on-first-failure-if-only-a-*.patch,
  0004-sme-extend-load-balancing-optimization-in-bss-blacklisting.patch,
  0005-sme-optimize-recovery-from-association-command-failures.patch,
  0006-sme-add-timers-for-authentication-and-association.patch,
  0007-sme-nl80211-set-cipher-suites.patch:
  Cherry-pick patches fixing SME (Session Management Entity) for the nl80211
  driver, which works as a basis for the OKC patches.
* In debian/patches:
  0001-pmkokc-Set-portValid-TRUE-on-association-for-driver-based-4.patch,
  0002-pmkokc-Clear-WPA-and-EAPOL-state-machine-config-pointer-on-.patch,
  0003-pmkokc-Clear-driver-PMKSA-cache-entry-on-PMKSA-cache-expira.patch,
  0004-pmkokc-Flush-PMKSA-cache-entries-and-invalidate-EAP-state-o.patch,
  0005-pmkokc-Fix-proactive_key_caching-configuration-to-WPA-code.patch,
  0006-pmkokc-RSN-Add-a-debug-message-when-considing-addition-of-O.patch,
  0007-pmkokc-Clear-OKC-based-PMKSA-caching-entries-if-PMK-is-chan.patch,
  0008-pmkokc-Move-wpa_sm_remove_pmkid-call-to-PMKSA-cache-entry-f.patch,
  0009-pmkokc-Use-PMKSA-cache-entries-with-only-a-single-network-c.patch,
  0010-pmkokc-PMKSA-Do-not-evict-active-cache-entry-when-adding-ne.patch,
  0011-pmkokc-PMKSA-Set-cur_pmksa-pointer-during-initial-associati.patch,
  0012-pmkokc-PMKSA-make-deauthentication-due-to-cache-entry-remov.patch,
  0013-pmkokc-PMKSA-update-current-cache-entry-due-to-association-.patch:
  Cherry-pick patches to properly do OKC (Opportunistic Key Caching) which
  helps maintaining connectivity on networks secured with WPA Enterprise,
  especially on nl80211-based drivers -- these patches require SME, and add
  or fix key caching and handling of the cache entries.
* debian/patches/force-enable-okc.patch: force Opportunistic Key Caching to
  be enabled.
* debian/patches/less-aggressive-roaming.patch: use less aggressive roaming
  settings to avoid switching to another AP unnecessarily, when the actual
  signal level difference is small.
* debian/patches/wpa_supplicant-dbus-null-error.patch: Don't send NULL to
  dbus_message_new_error().
* debian/patches/0001-nl80211-Fix-UNSPEC-signal-quality-reporting.patch: fix
  marking qual as invalid rather than signal level.
* debian/patches/wpa_supplicant-squelch-driver-disconnect-spam.patch: recover
  cleanly from streams of disconnect messages (like on iwl3945).
* debian/patches/wpa_supplicant-assoc-timeout.patch: increase association
  timeouts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * wpa_supplicant / WPS integration
 
3
 * Copyright (c) 2008-2010, Jouni Malinen <j@w1.fi>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License version 2 as
 
7
 * published by the Free Software Foundation.
 
8
 *
 
9
 * Alternatively, this software may be distributed under the terms of BSD
 
10
 * license.
 
11
 *
 
12
 * See README and COPYING for more details.
 
13
 */
 
14
 
 
15
#include "includes.h"
 
16
 
 
17
#include "common.h"
 
18
#include "eloop.h"
 
19
#include "uuid.h"
 
20
#include "crypto/dh_group5.h"
 
21
#include "common/ieee802_11_defs.h"
 
22
#include "common/ieee802_11_common.h"
 
23
#include "common/wpa_common.h"
 
24
#include "common/wpa_ctrl.h"
 
25
#include "eap_common/eap_wsc_common.h"
 
26
#include "eap_peer/eap.h"
 
27
#include "rsn_supp/wpa.h"
 
28
#include "config.h"
 
29
#include "wpa_supplicant_i.h"
 
30
#include "driver_i.h"
 
31
#include "notify.h"
 
32
#include "blacklist.h"
 
33
#include "bss.h"
 
34
#include "scan.h"
 
35
#include "wps_supplicant.h"
 
36
 
 
37
 
 
38
#define WPS_PIN_SCAN_IGNORE_SEL_REG 3
 
39
 
 
40
static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx);
 
41
static void wpas_clear_wps(struct wpa_supplicant *wpa_s);
 
42
 
 
43
 
 
44
int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
 
45
{
 
46
        if (!wpa_s->wps_success &&
 
47
            wpa_s->current_ssid &&
 
48
            eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
 
49
                const u8 *bssid = wpa_s->bssid;
 
50
                if (is_zero_ether_addr(bssid))
 
51
                        bssid = wpa_s->pending_bssid;
 
52
 
 
53
                wpa_printf(MSG_DEBUG, "WPS: PIN registration with " MACSTR
 
54
                           " did not succeed - continue trying to find "
 
55
                           "suitable AP", MAC2STR(bssid));
 
56
                wpa_blacklist_add(wpa_s, bssid);
 
57
 
 
58
                wpa_supplicant_deauthenticate(wpa_s,
 
59
                                              WLAN_REASON_DEAUTH_LEAVING);
 
60
                wpa_s->reassociate = 1;
 
61
                wpa_supplicant_req_scan(wpa_s,
 
62
                                        wpa_s->blacklist_cleared ? 5 : 0, 0);
 
63
                wpa_s->blacklist_cleared = 0;
 
64
                return 1;
 
65
        }
 
66
 
 
67
        eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
 
68
 
 
69
        if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid &&
 
70
            !(wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
 
71
                wpa_printf(MSG_DEBUG, "WPS: Network configuration replaced - "
 
72
                           "try to associate with the received credential");
 
73
                wpa_supplicant_deauthenticate(wpa_s,
 
74
                                              WLAN_REASON_DEAUTH_LEAVING);
 
75
                wpa_s->after_wps = 5;
 
76
                wpa_s->wps_freq = wpa_s->assoc_freq;
 
77
                wpa_s->reassociate = 1;
 
78
                wpa_supplicant_req_scan(wpa_s, 0, 0);
 
79
                return 1;
 
80
        }
 
81
 
 
82
        if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid) {
 
83
                wpa_printf(MSG_DEBUG, "WPS: Registration completed - waiting "
 
84
                           "for external credential processing");
 
85
                wpas_clear_wps(wpa_s);
 
86
                wpa_supplicant_deauthenticate(wpa_s,
 
87
                                              WLAN_REASON_DEAUTH_LEAVING);
 
88
                return 1;
 
89
        }
 
90
 
 
91
        return 0;
 
92
}
 
93
 
 
94
 
 
95
static void wpas_wps_security_workaround(struct wpa_supplicant *wpa_s,
 
96
                                         struct wpa_ssid *ssid,
 
97
                                         const struct wps_credential *cred)
 
98
{
 
99
        struct wpa_driver_capa capa;
 
100
        struct wpa_bss *bss;
 
101
        const u8 *ie;
 
102
        struct wpa_ie_data adv;
 
103
        int wpa2 = 0, ccmp = 0;
 
104
 
 
105
        /*
 
106
         * Many existing WPS APs do not know how to negotiate WPA2 or CCMP in
 
107
         * case they are configured for mixed mode operation (WPA+WPA2 and
 
108
         * TKIP+CCMP). Try to use scan results to figure out whether the AP
 
109
         * actually supports stronger security and select that if the client
 
110
         * has support for it, too.
 
111
         */
 
112
 
 
113
        if (wpa_drv_get_capa(wpa_s, &capa))
 
114
                return; /* Unknown what driver supports */
 
115
 
 
116
        bss = wpa_bss_get(wpa_s, cred->mac_addr, ssid->ssid, ssid->ssid_len);
 
117
        if (bss == NULL) {
 
118
                wpa_printf(MSG_DEBUG, "WPS: The AP was not found from BSS "
 
119
                           "table - use credential as-is");
 
120
                return;
 
121
        }
 
122
 
 
123
        wpa_printf(MSG_DEBUG, "WPS: AP found from BSS table");
 
124
 
 
125
        ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
 
126
        if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &adv) == 0) {
 
127
                wpa2 = 1;
 
128
                if (adv.pairwise_cipher & WPA_CIPHER_CCMP)
 
129
                        ccmp = 1;
 
130
        } else {
 
131
                ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
 
132
                if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &adv) == 0 &&
 
133
                    adv.pairwise_cipher & WPA_CIPHER_CCMP)
 
134
                        ccmp = 1;
 
135
        }
 
136
 
 
137
        if (ie == NULL && (ssid->proto & WPA_PROTO_WPA) &&
 
138
            (ssid->pairwise_cipher & WPA_CIPHER_TKIP)) {
 
139
                /*
 
140
                 * TODO: This could be the initial AP configuration and the
 
141
                 * Beacon contents could change shortly. Should request a new
 
142
                 * scan and delay addition of the network until the updated
 
143
                 * scan results are available.
 
144
                 */
 
145
                wpa_printf(MSG_DEBUG, "WPS: The AP did not yet advertise WPA "
 
146
                           "support - use credential as-is");
 
147
                return;
 
148
        }
 
149
 
 
150
        if (ccmp && !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) &&
 
151
            (ssid->pairwise_cipher & WPA_CIPHER_TKIP) &&
 
152
            (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
 
153
                wpa_printf(MSG_DEBUG, "WPS: Add CCMP into the credential "
 
154
                           "based on scan results");
 
155
                if (wpa_s->conf->ap_scan == 1)
 
156
                        ssid->pairwise_cipher |= WPA_CIPHER_CCMP;
 
157
                else
 
158
                        ssid->pairwise_cipher = WPA_CIPHER_CCMP;
 
159
        }
 
160
 
 
161
        if (wpa2 && !(ssid->proto & WPA_PROTO_RSN) &&
 
162
            (ssid->proto & WPA_PROTO_WPA) &&
 
163
            (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP)) {
 
164
                wpa_printf(MSG_DEBUG, "WPS: Add WPA2 into the credential "
 
165
                           "based on scan results");
 
166
                if (wpa_s->conf->ap_scan == 1)
 
167
                        ssid->proto |= WPA_PROTO_RSN;
 
168
                else
 
169
                        ssid->proto = WPA_PROTO_RSN;
 
170
        }
 
171
}
 
172
 
 
173
 
 
174
static int wpa_supplicant_wps_cred(void *ctx,
 
175
                                   const struct wps_credential *cred)
 
176
{
 
177
        struct wpa_supplicant *wpa_s = ctx;
 
178
        struct wpa_ssid *ssid = wpa_s->current_ssid;
 
179
        u8 key_idx = 0;
 
180
        u16 auth_type;
 
181
 
 
182
        if ((wpa_s->conf->wps_cred_processing == 1 ||
 
183
             wpa_s->conf->wps_cred_processing == 2) && cred->cred_attr) {
 
184
                size_t blen = cred->cred_attr_len * 2 + 1;
 
185
                char *buf = os_malloc(blen);
 
186
                if (buf) {
 
187
                        wpa_snprintf_hex(buf, blen,
 
188
                                         cred->cred_attr, cred->cred_attr_len);
 
189
                        wpa_msg(wpa_s, MSG_INFO, "%s%s",
 
190
                                WPS_EVENT_CRED_RECEIVED, buf);
 
191
                        os_free(buf);
 
192
                }
 
193
 
 
194
                wpas_notify_wps_credential(wpa_s, cred);
 
195
        } else
 
196
                wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_CRED_RECEIVED);
 
197
 
 
198
        wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
 
199
                        cred->cred_attr, cred->cred_attr_len);
 
200
 
 
201
        if (wpa_s->conf->wps_cred_processing == 1)
 
202
                return 0;
 
203
 
 
204
        wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", cred->ssid, cred->ssid_len);
 
205
        wpa_printf(MSG_DEBUG, "WPS: Authentication Type 0x%x",
 
206
                   cred->auth_type);
 
207
        wpa_printf(MSG_DEBUG, "WPS: Encryption Type 0x%x", cred->encr_type);
 
208
        wpa_printf(MSG_DEBUG, "WPS: Network Key Index %d", cred->key_idx);
 
209
        wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key",
 
210
                        cred->key, cred->key_len);
 
211
        wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR,
 
212
                   MAC2STR(cred->mac_addr));
 
213
 
 
214
        auth_type = cred->auth_type;
 
215
        if (auth_type == (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
 
216
                wpa_printf(MSG_DEBUG, "WPS: Workaround - convert mixed-mode "
 
217
                           "auth_type into WPA2PSK");
 
218
                auth_type = WPS_AUTH_WPA2PSK;
 
219
        }
 
220
 
 
221
        if (auth_type != WPS_AUTH_OPEN &&
 
222
            auth_type != WPS_AUTH_SHARED &&
 
223
            auth_type != WPS_AUTH_WPAPSK &&
 
224
            auth_type != WPS_AUTH_WPA2PSK) {
 
225
                wpa_printf(MSG_DEBUG, "WPS: Ignored credentials for "
 
226
                           "unsupported authentication type 0x%x",
 
227
                           auth_type);
 
228
                return 0;
 
229
        }
 
230
 
 
231
        if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
 
232
                wpa_printf(MSG_DEBUG, "WPS: Replace WPS network block based "
 
233
                           "on the received credential");
 
234
                os_free(ssid->eap.identity);
 
235
                ssid->eap.identity = NULL;
 
236
                ssid->eap.identity_len = 0;
 
237
                os_free(ssid->eap.phase1);
 
238
                ssid->eap.phase1 = NULL;
 
239
                os_free(ssid->eap.eap_methods);
 
240
                ssid->eap.eap_methods = NULL;
 
241
        } else {
 
242
                wpa_printf(MSG_DEBUG, "WPS: Create a new network based on the "
 
243
                           "received credential");
 
244
                ssid = wpa_config_add_network(wpa_s->conf);
 
245
                if (ssid == NULL)
 
246
                        return -1;
 
247
                wpas_notify_network_added(wpa_s, ssid);
 
248
        }
 
249
 
 
250
        wpa_config_set_network_defaults(ssid);
 
251
 
 
252
        os_free(ssid->ssid);
 
253
        ssid->ssid = os_malloc(cred->ssid_len);
 
254
        if (ssid->ssid) {
 
255
                os_memcpy(ssid->ssid, cred->ssid, cred->ssid_len);
 
256
                ssid->ssid_len = cred->ssid_len;
 
257
        }
 
258
 
 
259
        switch (cred->encr_type) {
 
260
        case WPS_ENCR_NONE:
 
261
                break;
 
262
        case WPS_ENCR_WEP:
 
263
                if (cred->key_len <= 0)
 
264
                        break;
 
265
                if (cred->key_len != 5 && cred->key_len != 13 &&
 
266
                    cred->key_len != 10 && cred->key_len != 26) {
 
267
                        wpa_printf(MSG_ERROR, "WPS: Invalid WEP Key length "
 
268
                                   "%lu", (unsigned long) cred->key_len);
 
269
                        return -1;
 
270
                }
 
271
                if (cred->key_idx > NUM_WEP_KEYS) {
 
272
                        wpa_printf(MSG_ERROR, "WPS: Invalid WEP Key index %d",
 
273
                                   cred->key_idx);
 
274
                        return -1;
 
275
                }
 
276
                if (cred->key_idx)
 
277
                        key_idx = cred->key_idx - 1;
 
278
                if (cred->key_len == 10 || cred->key_len == 26) {
 
279
                        if (hexstr2bin((char *) cred->key,
 
280
                                       ssid->wep_key[key_idx],
 
281
                                       cred->key_len / 2) < 0) {
 
282
                                wpa_printf(MSG_ERROR, "WPS: Invalid WEP Key "
 
283
                                           "%d", key_idx);
 
284
                                return -1;
 
285
                        }
 
286
                        ssid->wep_key_len[key_idx] = cred->key_len / 2;
 
287
                } else {
 
288
                        os_memcpy(ssid->wep_key[key_idx], cred->key,
 
289
                                  cred->key_len);
 
290
                        ssid->wep_key_len[key_idx] = cred->key_len;
 
291
                }
 
292
                ssid->wep_tx_keyidx = key_idx;
 
293
                break;
 
294
        case WPS_ENCR_TKIP:
 
295
                ssid->pairwise_cipher = WPA_CIPHER_TKIP;
 
296
                break;
 
297
        case WPS_ENCR_AES:
 
298
                ssid->pairwise_cipher = WPA_CIPHER_CCMP;
 
299
                break;
 
300
        }
 
301
 
 
302
        switch (auth_type) {
 
303
        case WPS_AUTH_OPEN:
 
304
                ssid->auth_alg = WPA_AUTH_ALG_OPEN;
 
305
                ssid->key_mgmt = WPA_KEY_MGMT_NONE;
 
306
                ssid->proto = 0;
 
307
                break;
 
308
        case WPS_AUTH_SHARED:
 
309
                ssid->auth_alg = WPA_AUTH_ALG_SHARED;
 
310
                ssid->key_mgmt = WPA_KEY_MGMT_NONE;
 
311
                ssid->proto = 0;
 
312
                break;
 
313
        case WPS_AUTH_WPAPSK:
 
314
                ssid->auth_alg = WPA_AUTH_ALG_OPEN;
 
315
                ssid->key_mgmt = WPA_KEY_MGMT_PSK;
 
316
                ssid->proto = WPA_PROTO_WPA;
 
317
                break;
 
318
        case WPS_AUTH_WPA:
 
319
                ssid->auth_alg = WPA_AUTH_ALG_OPEN;
 
320
                ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
 
321
                ssid->proto = WPA_PROTO_WPA;
 
322
                break;
 
323
        case WPS_AUTH_WPA2:
 
324
                ssid->auth_alg = WPA_AUTH_ALG_OPEN;
 
325
                ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
 
326
                ssid->proto = WPA_PROTO_RSN;
 
327
                break;
 
328
        case WPS_AUTH_WPA2PSK:
 
329
                ssid->auth_alg = WPA_AUTH_ALG_OPEN;
 
330
                ssid->key_mgmt = WPA_KEY_MGMT_PSK;
 
331
                ssid->proto = WPA_PROTO_RSN;
 
332
                break;
 
333
        }
 
334
 
 
335
        if (ssid->key_mgmt == WPA_KEY_MGMT_PSK) {
 
336
                if (cred->key_len == 2 * PMK_LEN) {
 
337
                        if (hexstr2bin((const char *) cred->key, ssid->psk,
 
338
                                       PMK_LEN)) {
 
339
                                wpa_printf(MSG_ERROR, "WPS: Invalid Network "
 
340
                                           "Key");
 
341
                                return -1;
 
342
                        }
 
343
                        ssid->psk_set = 1;
 
344
                } else if (cred->key_len >= 8 && cred->key_len < 2 * PMK_LEN) {
 
345
                        os_free(ssid->passphrase);
 
346
                        ssid->passphrase = os_malloc(cred->key_len + 1);
 
347
                        if (ssid->passphrase == NULL)
 
348
                                return -1;
 
349
                        os_memcpy(ssid->passphrase, cred->key, cred->key_len);
 
350
                        ssid->passphrase[cred->key_len] = '\0';
 
351
                        wpa_config_update_psk(ssid);
 
352
                } else {
 
353
                        wpa_printf(MSG_ERROR, "WPS: Invalid Network Key "
 
354
                                   "length %lu",
 
355
                                   (unsigned long) cred->key_len);
 
356
                        return -1;
 
357
                }
 
358
        }
 
359
 
 
360
        wpas_wps_security_workaround(wpa_s, ssid, cred);
 
361
 
 
362
#ifndef CONFIG_NO_CONFIG_WRITE
 
363
        if (wpa_s->conf->update_config &&
 
364
            wpa_config_write(wpa_s->confname, wpa_s->conf)) {
 
365
                wpa_printf(MSG_DEBUG, "WPS: Failed to update configuration");
 
366
                return -1;
 
367
        }
 
368
#endif /* CONFIG_NO_CONFIG_WRITE */
 
369
 
 
370
        return 0;
 
371
}
 
372
 
 
373
 
 
374
static void wpa_supplicant_wps_event_m2d(struct wpa_supplicant *wpa_s,
 
375
                                         struct wps_event_m2d *m2d)
 
376
{
 
377
        wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_M2D
 
378
                "dev_password_id=%d config_error=%d",
 
379
                m2d->dev_password_id, m2d->config_error);
 
380
        wpas_notify_wps_event_m2d(wpa_s, m2d);
 
381
}
 
382
 
 
383
 
 
384
static void wpa_supplicant_wps_event_fail(struct wpa_supplicant *wpa_s,
 
385
                                          struct wps_event_fail *fail)
 
386
{
 
387
        wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_FAIL "msg=%d", fail->msg);
 
388
        wpas_clear_wps(wpa_s);
 
389
        wpas_notify_wps_event_fail(wpa_s, fail);
 
390
}
 
391
 
 
392
 
 
393
static void wpa_supplicant_wps_event_success(struct wpa_supplicant *wpa_s)
 
394
{
 
395
        wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_SUCCESS);
 
396
        wpa_s->wps_success = 1;
 
397
        wpas_notify_wps_event_success(wpa_s);
 
398
}
 
399
 
 
400
 
 
401
static void wpa_supplicant_wps_event_er_ap_add(struct wpa_supplicant *wpa_s,
 
402
                                               struct wps_event_er_ap *ap)
 
403
{
 
404
        char uuid_str[100];
 
405
        char dev_type[WPS_DEV_TYPE_BUFSIZE];
 
406
 
 
407
        uuid_bin2str(ap->uuid, uuid_str, sizeof(uuid_str));
 
408
        if (ap->pri_dev_type)
 
409
                wps_dev_type_bin2str(ap->pri_dev_type, dev_type,
 
410
                                     sizeof(dev_type));
 
411
        else
 
412
                dev_type[0] = '\0';
 
413
 
 
414
        wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_AP_ADD "%s " MACSTR
 
415
                " pri_dev_type=%s wps_state=%d |%s|%s|%s|%s|%s|%s|",
 
416
                uuid_str, MAC2STR(ap->mac_addr), dev_type, ap->wps_state,
 
417
                ap->friendly_name ? ap->friendly_name : "",
 
418
                ap->manufacturer ? ap->manufacturer : "",
 
419
                ap->model_description ? ap->model_description : "",
 
420
                ap->model_name ? ap->model_name : "",
 
421
                ap->manufacturer_url ? ap->manufacturer_url : "",
 
422
                ap->model_url ? ap->model_url : "");
 
423
}
 
424
 
 
425
 
 
426
static void wpa_supplicant_wps_event_er_ap_remove(struct wpa_supplicant *wpa_s,
 
427
                                                  struct wps_event_er_ap *ap)
 
428
{
 
429
        char uuid_str[100];
 
430
        uuid_bin2str(ap->uuid, uuid_str, sizeof(uuid_str));
 
431
        wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_AP_REMOVE "%s", uuid_str);
 
432
}
 
433
 
 
434
 
 
435
static void wpa_supplicant_wps_event_er_enrollee_add(
 
436
        struct wpa_supplicant *wpa_s, struct wps_event_er_enrollee *enrollee)
 
437
{
 
438
        char uuid_str[100];
 
439
        char dev_type[WPS_DEV_TYPE_BUFSIZE];
 
440
 
 
441
        uuid_bin2str(enrollee->uuid, uuid_str, sizeof(uuid_str));
 
442
        if (enrollee->pri_dev_type)
 
443
                wps_dev_type_bin2str(enrollee->pri_dev_type, dev_type,
 
444
                                     sizeof(dev_type));
 
445
        else
 
446
                dev_type[0] = '\0';
 
447
 
 
448
        wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_ENROLLEE_ADD "%s " MACSTR
 
449
                " M1=%d config_methods=0x%x dev_passwd_id=%d pri_dev_type=%s "
 
450
                "|%s|%s|%s|%s|%s|",
 
451
                uuid_str, MAC2STR(enrollee->mac_addr), enrollee->m1_received,
 
452
                enrollee->config_methods, enrollee->dev_passwd_id, dev_type,
 
453
                enrollee->dev_name ? enrollee->dev_name : "",
 
454
                enrollee->manufacturer ? enrollee->manufacturer : "",
 
455
                enrollee->model_name ? enrollee->model_name : "",
 
456
                enrollee->model_number ? enrollee->model_number : "",
 
457
                enrollee->serial_number ? enrollee->serial_number : "");
 
458
}
 
459
 
 
460
 
 
461
static void wpa_supplicant_wps_event_er_enrollee_remove(
 
462
        struct wpa_supplicant *wpa_s, struct wps_event_er_enrollee *enrollee)
 
463
{
 
464
        char uuid_str[100];
 
465
        uuid_bin2str(enrollee->uuid, uuid_str, sizeof(uuid_str));
 
466
        wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_ENROLLEE_REMOVE "%s " MACSTR,
 
467
                uuid_str, MAC2STR(enrollee->mac_addr));
 
468
}
 
469
 
 
470
 
 
471
static void wpa_supplicant_wps_event(void *ctx, enum wps_event event,
 
472
                                     union wps_event_data *data)
 
473
{
 
474
        struct wpa_supplicant *wpa_s = ctx;
 
475
        switch (event) {
 
476
        case WPS_EV_M2D:
 
477
                wpa_supplicant_wps_event_m2d(wpa_s, &data->m2d);
 
478
                break;
 
479
        case WPS_EV_FAIL:
 
480
                wpa_supplicant_wps_event_fail(wpa_s, &data->fail);
 
481
                break;
 
482
        case WPS_EV_SUCCESS:
 
483
                wpa_supplicant_wps_event_success(wpa_s);
 
484
                break;
 
485
        case WPS_EV_PWD_AUTH_FAIL:
 
486
                break;
 
487
        case WPS_EV_PBC_OVERLAP:
 
488
                break;
 
489
        case WPS_EV_PBC_TIMEOUT:
 
490
                break;
 
491
        case WPS_EV_ER_AP_ADD:
 
492
                wpa_supplicant_wps_event_er_ap_add(wpa_s, &data->ap);
 
493
                break;
 
494
        case WPS_EV_ER_AP_REMOVE:
 
495
                wpa_supplicant_wps_event_er_ap_remove(wpa_s, &data->ap);
 
496
                break;
 
497
        case WPS_EV_ER_ENROLLEE_ADD:
 
498
                wpa_supplicant_wps_event_er_enrollee_add(wpa_s,
 
499
                                                         &data->enrollee);
 
500
                break;
 
501
        case WPS_EV_ER_ENROLLEE_REMOVE:
 
502
                wpa_supplicant_wps_event_er_enrollee_remove(wpa_s,
 
503
                                                            &data->enrollee);
 
504
                break;
 
505
        }
 
506
}
 
507
 
 
508
 
 
509
enum wps_request_type wpas_wps_get_req_type(struct wpa_ssid *ssid)
 
510
{
 
511
        if (eap_is_wps_pbc_enrollee(&ssid->eap) ||
 
512
            eap_is_wps_pin_enrollee(&ssid->eap))
 
513
                return WPS_REQ_ENROLLEE;
 
514
        else
 
515
                return WPS_REQ_REGISTRAR;
 
516
}
 
517
 
 
518
 
 
519
static void wpas_clear_wps(struct wpa_supplicant *wpa_s)
 
520
{
 
521
        int id;
 
522
        struct wpa_ssid *ssid, *remove_ssid = NULL;
 
523
 
 
524
        eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
 
525
 
 
526
        /* Remove any existing WPS network from configuration */
 
527
        ssid = wpa_s->conf->ssid;
 
528
        while (ssid) {
 
529
                if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
 
530
                        if (ssid == wpa_s->current_ssid) {
 
531
                                wpa_s->current_ssid = NULL;
 
532
                                if (ssid != NULL)
 
533
                                        wpas_notify_network_changed(wpa_s);
 
534
                        }
 
535
                        id = ssid->id;
 
536
                        remove_ssid = ssid;
 
537
                } else
 
538
                        id = -1;
 
539
                ssid = ssid->next;
 
540
                if (id >= 0) {
 
541
                        wpas_notify_network_removed(wpa_s, remove_ssid);
 
542
                        wpa_config_remove_network(wpa_s->conf, id);
 
543
                }
 
544
        }
 
545
}
 
546
 
 
547
 
 
548
static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx)
 
549
{
 
550
        struct wpa_supplicant *wpa_s = eloop_ctx;
 
551
        wpa_printf(MSG_INFO, WPS_EVENT_TIMEOUT "Requested operation timed "
 
552
                   "out");
 
553
        wpas_clear_wps(wpa_s);
 
554
}
 
555
 
 
556
 
 
557
static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s,
 
558
                                              int registrar, const u8 *bssid)
 
559
{
 
560
        struct wpa_ssid *ssid;
 
561
 
 
562
        ssid = wpa_config_add_network(wpa_s->conf);
 
563
        if (ssid == NULL)
 
564
                return NULL;
 
565
        wpas_notify_network_added(wpa_s, ssid);
 
566
        wpa_config_set_network_defaults(ssid);
 
567
        if (wpa_config_set(ssid, "key_mgmt", "WPS", 0) < 0 ||
 
568
            wpa_config_set(ssid, "eap", "WSC", 0) < 0 ||
 
569
            wpa_config_set(ssid, "identity", registrar ?
 
570
                           "\"" WSC_ID_REGISTRAR "\"" :
 
571
                           "\"" WSC_ID_ENROLLEE "\"", 0) < 0) {
 
572
                wpas_notify_network_removed(wpa_s, ssid);
 
573
                wpa_config_remove_network(wpa_s->conf, ssid->id);
 
574
                return NULL;
 
575
        }
 
576
 
 
577
        if (bssid) {
 
578
                struct wpa_bss *bss;
 
579
                int count = 0;
 
580
 
 
581
                os_memcpy(ssid->bssid, bssid, ETH_ALEN);
 
582
                ssid->bssid_set = 1;
 
583
 
 
584
                dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
 
585
                        if (os_memcmp(bssid, bss->bssid, ETH_ALEN) != 0)
 
586
                                continue;
 
587
 
 
588
                        os_free(ssid->ssid);
 
589
                        ssid->ssid = os_malloc(bss->ssid_len);
 
590
                        if (ssid->ssid == NULL)
 
591
                                break;
 
592
                        os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
 
593
                        ssid->ssid_len = bss->ssid_len;
 
594
                        wpa_hexdump_ascii(MSG_DEBUG, "WPS: Picked SSID from "
 
595
                                          "scan results",
 
596
                                          ssid->ssid, ssid->ssid_len);
 
597
                        count++;
 
598
                }
 
599
 
 
600
                if (count > 1) {
 
601
                        wpa_printf(MSG_DEBUG, "WPS: More than one SSID found "
 
602
                                   "for the AP; use wildcard");
 
603
                        os_free(ssid->ssid);
 
604
                        ssid->ssid = NULL;
 
605
                        ssid->ssid_len = 0;
 
606
                }
 
607
        }
 
608
 
 
609
        return ssid;
 
610
}
 
611
 
 
612
 
 
613
static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s,
 
614
                             struct wpa_ssid *selected)
 
615
{
 
616
        struct wpa_ssid *ssid;
 
617
 
 
618
        /* Mark all other networks disabled and trigger reassociation */
 
619
        ssid = wpa_s->conf->ssid;
 
620
        while (ssid) {
 
621
                int was_disabled = ssid->disabled;
 
622
                ssid->disabled = ssid != selected;
 
623
                if (was_disabled != ssid->disabled)
 
624
                        wpas_notify_network_enabled_changed(wpa_s, ssid);
 
625
                ssid = ssid->next;
 
626
        }
 
627
        wpa_s->disconnected = 0;
 
628
        wpa_s->reassociate = 1;
 
629
        wpa_s->scan_runs = 0;
 
630
        wpa_s->wps_success = 0;
 
631
        wpa_s->blacklist_cleared = 0;
 
632
        wpa_supplicant_req_scan(wpa_s, 0, 0);
 
633
}
 
634
 
 
635
 
 
636
int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid)
 
637
{
 
638
        struct wpa_ssid *ssid;
 
639
        wpas_clear_wps(wpa_s);
 
640
        ssid = wpas_wps_add_network(wpa_s, 0, bssid);
 
641
        if (ssid == NULL)
 
642
                return -1;
 
643
        wpa_config_set(ssid, "phase1", "\"pbc=1\"", 0);
 
644
        eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
 
645
                               wpa_s, NULL);
 
646
        wpas_wps_reassoc(wpa_s, ssid);
 
647
        return 0;
 
648
}
 
649
 
 
650
 
 
651
int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
 
652
                       const char *pin)
 
653
{
 
654
        struct wpa_ssid *ssid;
 
655
        char val[128];
 
656
        unsigned int rpin = 0;
 
657
 
 
658
        wpas_clear_wps(wpa_s);
 
659
        ssid = wpas_wps_add_network(wpa_s, 0, bssid);
 
660
        if (ssid == NULL)
 
661
                return -1;
 
662
        if (pin)
 
663
                os_snprintf(val, sizeof(val), "\"pin=%s\"", pin);
 
664
        else {
 
665
                rpin = wps_generate_pin();
 
666
                os_snprintf(val, sizeof(val), "\"pin=%08d\"", rpin);
 
667
        }
 
668
        wpa_config_set(ssid, "phase1", val, 0);
 
669
        eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
 
670
                               wpa_s, NULL);
 
671
        wpas_wps_reassoc(wpa_s, ssid);
 
672
        return rpin;
 
673
}
 
674
 
 
675
 
 
676
#ifdef CONFIG_WPS_OOB
 
677
int wpas_wps_start_oob(struct wpa_supplicant *wpa_s, char *device_type,
 
678
                       char *path, char *method, char *name)
 
679
{
 
680
        struct wps_context *wps = wpa_s->wps;
 
681
        struct oob_device_data *oob_dev;
 
682
 
 
683
        oob_dev = wps_get_oob_device(device_type);
 
684
        if (oob_dev == NULL)
 
685
                return -1;
 
686
        oob_dev->device_path = path;
 
687
        oob_dev->device_name = name;
 
688
        wps->oob_conf.oob_method = wps_get_oob_method(method);
 
689
 
 
690
        if (wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E) {
 
691
                /*
 
692
                 * Use pre-configured DH keys in order to be able to write the
 
693
                 * key hash into the OOB file.
 
694
                 */
 
695
                wpabuf_free(wps->dh_pubkey);
 
696
                wpabuf_free(wps->dh_privkey);
 
697
                wps->dh_privkey = NULL;
 
698
                wps->dh_pubkey = NULL;
 
699
                dh5_free(wps->dh_ctx);
 
700
                wps->dh_ctx = dh5_init(&wps->dh_privkey, &wps->dh_pubkey);
 
701
                wps->dh_pubkey = wpabuf_zeropad(wps->dh_pubkey, 192);
 
702
                if (wps->dh_ctx == NULL || wps->dh_pubkey == NULL) {
 
703
                        wpa_printf(MSG_ERROR, "WPS: Failed to initialize "
 
704
                                   "Diffie-Hellman handshake");
 
705
                        return -1;
 
706
                }
 
707
        }
 
708
 
 
709
        if (wps->oob_conf.oob_method == OOB_METHOD_CRED)
 
710
                wpas_clear_wps(wpa_s);
 
711
 
 
712
        if (wps_process_oob(wps, oob_dev, 0) < 0)
 
713
                return -1;
 
714
 
 
715
        if ((wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ||
 
716
             wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) &&
 
717
            wpas_wps_start_pin(wpa_s, NULL,
 
718
                               wpabuf_head(wps->oob_conf.dev_password)) < 0)
 
719
                        return -1;
 
720
 
 
721
        return 0;
 
722
}
 
723
#endif /* CONFIG_WPS_OOB */
 
724
 
 
725
 
 
726
int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
 
727
                       const char *pin, struct wps_new_ap_settings *settings)
 
728
{
 
729
        struct wpa_ssid *ssid;
 
730
        char val[200];
 
731
        char *pos, *end;
 
732
        int res;
 
733
 
 
734
        if (!pin)
 
735
                return -1;
 
736
        wpas_clear_wps(wpa_s);
 
737
        ssid = wpas_wps_add_network(wpa_s, 1, bssid);
 
738
        if (ssid == NULL)
 
739
                return -1;
 
740
        pos = val;
 
741
        end = pos + sizeof(val);
 
742
        res = os_snprintf(pos, end - pos, "\"pin=%s", pin);
 
743
        if (res < 0 || res >= end - pos)
 
744
                return -1;
 
745
        pos += res;
 
746
        if (settings) {
 
747
                res = os_snprintf(pos, end - pos, " new_ssid=%s new_auth=%s "
 
748
                                  "new_encr=%s new_key=%s",
 
749
                                  settings->ssid_hex, settings->auth,
 
750
                                  settings->encr, settings->key_hex);
 
751
                if (res < 0 || res >= end - pos)
 
752
                        return -1;
 
753
                pos += res;
 
754
        }
 
755
        res = os_snprintf(pos, end - pos, "\"");
 
756
        if (res < 0 || res >= end - pos)
 
757
                return -1;
 
758
        wpa_config_set(ssid, "phase1", val, 0);
 
759
        eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
 
760
                               wpa_s, NULL);
 
761
        wpas_wps_reassoc(wpa_s, ssid);
 
762
        return 0;
 
763
}
 
764
 
 
765
 
 
766
static int wpas_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk,
 
767
                               size_t psk_len)
 
768
{
 
769
        wpa_printf(MSG_DEBUG, "WPS: Received new WPA/WPA2-PSK from WPS for "
 
770
                   "STA " MACSTR, MAC2STR(mac_addr));
 
771
        wpa_hexdump_key(MSG_DEBUG, "Per-device PSK", psk, psk_len);
 
772
 
 
773
        /* TODO */
 
774
 
 
775
        return 0;
 
776
}
 
777
 
 
778
 
 
779
static void wpas_wps_pin_needed_cb(void *ctx, const u8 *uuid_e,
 
780
                                   const struct wps_device_data *dev)
 
781
{
 
782
        char uuid[40], txt[400];
 
783
        int len;
 
784
        char devtype[WPS_DEV_TYPE_BUFSIZE];
 
785
        if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
 
786
                return;
 
787
        wpa_printf(MSG_DEBUG, "WPS: PIN needed for UUID-E %s", uuid);
 
788
        len = os_snprintf(txt, sizeof(txt), "WPS-EVENT-PIN-NEEDED %s " MACSTR
 
789
                          " [%s|%s|%s|%s|%s|%s]",
 
790
                          uuid, MAC2STR(dev->mac_addr), dev->device_name,
 
791
                          dev->manufacturer, dev->model_name,
 
792
                          dev->model_number, dev->serial_number,
 
793
                          wps_dev_type_bin2str(dev->pri_dev_type, devtype,
 
794
                                               sizeof(devtype)));
 
795
        if (len > 0 && len < (int) sizeof(txt))
 
796
                wpa_printf(MSG_INFO, "%s", txt);
 
797
}
 
798
 
 
799
 
 
800
static void wpas_wps_set_sel_reg_cb(void *ctx, int sel_reg, u16 dev_passwd_id,
 
801
                                    u16 sel_reg_config_methods)
 
802
{
 
803
#ifdef CONFIG_WPS_ER
 
804
        struct wpa_supplicant *wpa_s = ctx;
 
805
 
 
806
        if (wpa_s->wps_er == NULL)
 
807
                return;
 
808
        wps_er_set_sel_reg(wpa_s->wps_er, sel_reg, dev_passwd_id,
 
809
                           sel_reg_config_methods);
 
810
#endif /* CONFIG_WPS_ER */
 
811
}
 
812
 
 
813
 
 
814
int wpas_wps_init(struct wpa_supplicant *wpa_s)
 
815
{
 
816
        struct wps_context *wps;
 
817
        struct wps_registrar_config rcfg;
 
818
 
 
819
        wps = os_zalloc(sizeof(*wps));
 
820
        if (wps == NULL)
 
821
                return -1;
 
822
 
 
823
        wps->cred_cb = wpa_supplicant_wps_cred;
 
824
        wps->event_cb = wpa_supplicant_wps_event;
 
825
        wps->cb_ctx = wpa_s;
 
826
 
 
827
        wps->dev.device_name = wpa_s->conf->device_name;
 
828
        wps->dev.manufacturer = wpa_s->conf->manufacturer;
 
829
        wps->dev.model_name = wpa_s->conf->model_name;
 
830
        wps->dev.model_number = wpa_s->conf->model_number;
 
831
        wps->dev.serial_number = wpa_s->conf->serial_number;
 
832
        wps->config_methods =
 
833
                wps_config_methods_str2bin(wpa_s->conf->config_methods);
 
834
        if (wpa_s->conf->device_type &&
 
835
            wps_dev_type_str2bin(wpa_s->conf->device_type,
 
836
                                 wps->dev.pri_dev_type) < 0) {
 
837
                wpa_printf(MSG_ERROR, "WPS: Invalid device_type");
 
838
                os_free(wps);
 
839
                return -1;
 
840
        }
 
841
        wps->dev.os_version = WPA_GET_BE32(wpa_s->conf->os_version);
 
842
        wps->dev.rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ; /* TODO: config */
 
843
        os_memcpy(wps->dev.mac_addr, wpa_s->own_addr, ETH_ALEN);
 
844
        if (is_nil_uuid(wpa_s->conf->uuid)) {
 
845
                uuid_gen_mac_addr(wpa_s->own_addr, wps->uuid);
 
846
                wpa_hexdump(MSG_DEBUG, "WPS: UUID based on MAC address",
 
847
                            wps->uuid, WPS_UUID_LEN);
 
848
        } else
 
849
                os_memcpy(wps->uuid, wpa_s->conf->uuid, WPS_UUID_LEN);
 
850
 
 
851
        wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
 
852
        wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP;
 
853
 
 
854
        os_memset(&rcfg, 0, sizeof(rcfg));
 
855
        rcfg.new_psk_cb = wpas_wps_new_psk_cb;
 
856
        rcfg.pin_needed_cb = wpas_wps_pin_needed_cb;
 
857
        rcfg.set_sel_reg_cb = wpas_wps_set_sel_reg_cb;
 
858
        rcfg.cb_ctx = wpa_s;
 
859
 
 
860
        wps->registrar = wps_registrar_init(wps, &rcfg);
 
861
        if (wps->registrar == NULL) {
 
862
                wpa_printf(MSG_DEBUG, "Failed to initialize WPS Registrar");
 
863
                os_free(wps);
 
864
                return -1;
 
865
        }
 
866
 
 
867
        wpa_s->wps = wps;
 
868
 
 
869
        return 0;
 
870
}
 
871
 
 
872
 
 
873
void wpas_wps_deinit(struct wpa_supplicant *wpa_s)
 
874
{
 
875
        eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
 
876
 
 
877
        if (wpa_s->wps == NULL)
 
878
                return;
 
879
 
 
880
#ifdef CONFIG_WPS_ER
 
881
        wps_er_deinit(wpa_s->wps_er, NULL, NULL);
 
882
        wpa_s->wps_er = NULL;
 
883
#endif /* CONFIG_WPS_ER */
 
884
 
 
885
        wps_registrar_deinit(wpa_s->wps->registrar);
 
886
        wpabuf_free(wpa_s->wps->dh_pubkey);
 
887
        wpabuf_free(wpa_s->wps->dh_privkey);
 
888
        wpabuf_free(wpa_s->wps->oob_conf.pubkey_hash);
 
889
        wpabuf_free(wpa_s->wps->oob_conf.dev_password);
 
890
        os_free(wpa_s->wps->network_key);
 
891
        os_free(wpa_s->wps);
 
892
        wpa_s->wps = NULL;
 
893
}
 
894
 
 
895
 
 
896
int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
 
897
                            struct wpa_ssid *ssid, struct wpa_scan_res *bss)
 
898
{
 
899
        struct wpabuf *wps_ie;
 
900
 
 
901
        if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
 
902
                return -1;
 
903
 
 
904
        wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
 
905
        if (eap_is_wps_pbc_enrollee(&ssid->eap)) {
 
906
                if (!wps_ie) {
 
907
                        wpa_printf(MSG_DEBUG, "   skip - non-WPS AP");
 
908
                        return 0;
 
909
                }
 
910
 
 
911
                if (!wps_is_selected_pbc_registrar(wps_ie)) {
 
912
                        wpa_printf(MSG_DEBUG, "   skip - WPS AP "
 
913
                                   "without active PBC Registrar");
 
914
                        wpabuf_free(wps_ie);
 
915
                        return 0;
 
916
                }
 
917
 
 
918
                /* TODO: overlap detection */
 
919
                wpa_printf(MSG_DEBUG, "   selected based on WPS IE "
 
920
                           "(Active PBC)");
 
921
                wpabuf_free(wps_ie);
 
922
                return 1;
 
923
        }
 
924
 
 
925
        if (eap_is_wps_pin_enrollee(&ssid->eap)) {
 
926
                if (!wps_ie) {
 
927
                        wpa_printf(MSG_DEBUG, "   skip - non-WPS AP");
 
928
                        return 0;
 
929
                }
 
930
 
 
931
                /*
 
932
                 * Start with WPS APs that advertise active PIN Registrar and
 
933
                 * allow any WPS AP after third scan since some APs do not set
 
934
                 * Selected Registrar attribute properly when using external
 
935
                 * Registrar.
 
936
                 */
 
937
                if (!wps_is_selected_pin_registrar(wps_ie)) {
 
938
                        if (wpa_s->scan_runs < WPS_PIN_SCAN_IGNORE_SEL_REG) {
 
939
                                wpa_printf(MSG_DEBUG, "   skip - WPS AP "
 
940
                                           "without active PIN Registrar");
 
941
                                wpabuf_free(wps_ie);
 
942
                                return 0;
 
943
                        }
 
944
                        wpa_printf(MSG_DEBUG, "   selected based on WPS IE");
 
945
                } else {
 
946
                        wpa_printf(MSG_DEBUG, "   selected based on WPS IE "
 
947
                                   "(Active PIN)");
 
948
                }
 
949
                wpabuf_free(wps_ie);
 
950
                return 1;
 
951
        }
 
952
 
 
953
        if (wps_ie) {
 
954
                wpa_printf(MSG_DEBUG, "   selected based on WPS IE");
 
955
                wpabuf_free(wps_ie);
 
956
                return 1;
 
957
        }
 
958
 
 
959
        return -1;
 
960
}
 
961
 
 
962
 
 
963
int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s,
 
964
                              struct wpa_ssid *ssid,
 
965
                              struct wpa_scan_res *bss)
 
966
{
 
967
        struct wpabuf *wps_ie = NULL;
 
968
        int ret = 0;
 
969
 
 
970
        if (eap_is_wps_pbc_enrollee(&ssid->eap)) {
 
971
                wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
 
972
                if (wps_ie && wps_is_selected_pbc_registrar(wps_ie)) {
 
973
                        /* allow wildcard SSID for WPS PBC */
 
974
                        ret = 1;
 
975
                }
 
976
        } else if (eap_is_wps_pin_enrollee(&ssid->eap)) {
 
977
                wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
 
978
                if (wps_ie &&
 
979
                    (wps_is_selected_pin_registrar(wps_ie) ||
 
980
                     wpa_s->scan_runs >= WPS_PIN_SCAN_IGNORE_SEL_REG)) {
 
981
                        /* allow wildcard SSID for WPS PIN */
 
982
                        ret = 1;
 
983
                }
 
984
        }
 
985
 
 
986
        if (!ret && ssid->bssid_set &&
 
987
            os_memcmp(ssid->bssid, bss->bssid, ETH_ALEN) == 0) {
 
988
                /* allow wildcard SSID due to hardcoded BSSID match */
 
989
                ret = 1;
 
990
        }
 
991
 
 
992
        wpabuf_free(wps_ie);
 
993
 
 
994
        return ret;
 
995
}
 
996
 
 
997
 
 
998
int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s,
 
999
                              struct wpa_bss *selected, struct wpa_ssid *ssid)
 
1000
{
 
1001
        const u8 *sel_uuid, *uuid;
 
1002
        struct wpabuf *wps_ie;
 
1003
        int ret = 0;
 
1004
        struct wpa_bss *bss;
 
1005
 
 
1006
        if (!eap_is_wps_pbc_enrollee(&ssid->eap))
 
1007
                return 0;
 
1008
 
 
1009
        /* Make sure that only one AP is in active PBC mode */
 
1010
        wps_ie = wpa_bss_get_vendor_ie_multi(selected, WPS_IE_VENDOR_TYPE);
 
1011
        if (wps_ie)
 
1012
                sel_uuid = wps_get_uuid_e(wps_ie);
 
1013
        else
 
1014
                sel_uuid = NULL;
 
1015
 
 
1016
        dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
 
1017
                struct wpabuf *ie;
 
1018
                if (bss == selected)
 
1019
                        continue;
 
1020
                ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
 
1021
                if (!ie)
 
1022
                        continue;
 
1023
                if (!wps_is_selected_pbc_registrar(ie)) {
 
1024
                        wpabuf_free(ie);
 
1025
                        continue;
 
1026
                }
 
1027
                uuid = wps_get_uuid_e(ie);
 
1028
                if (sel_uuid == NULL || uuid == NULL ||
 
1029
                    os_memcmp(sel_uuid, uuid, 16) != 0) {
 
1030
                        ret = 1; /* PBC overlap */
 
1031
                        wpabuf_free(ie);
 
1032
                        break;
 
1033
                }
 
1034
 
 
1035
                /* TODO: verify that this is reasonable dual-band situation */
 
1036
 
 
1037
                wpabuf_free(ie);
 
1038
        }
 
1039
 
 
1040
        wpabuf_free(wps_ie);
 
1041
 
 
1042
        return ret;
 
1043
}
 
1044
 
 
1045
 
 
1046
void wpas_wps_notify_scan_results(struct wpa_supplicant *wpa_s)
 
1047
{
 
1048
        struct wpa_bss *bss;
 
1049
 
 
1050
        if (wpa_s->disconnected || wpa_s->wpa_state >= WPA_ASSOCIATED)
 
1051
                return;
 
1052
 
 
1053
        dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
 
1054
                struct wpabuf *ie;
 
1055
                ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
 
1056
                if (!ie)
 
1057
                        continue;
 
1058
                if (wps_is_selected_pbc_registrar(ie))
 
1059
                        wpa_msg_ctrl(wpa_s, MSG_INFO,
 
1060
                                     WPS_EVENT_AP_AVAILABLE_PBC);
 
1061
                else if (wps_is_selected_pin_registrar(ie))
 
1062
                        wpa_msg_ctrl(wpa_s, MSG_INFO,
 
1063
                                     WPS_EVENT_AP_AVAILABLE_PIN);
 
1064
                else
 
1065
                        wpa_msg_ctrl(wpa_s, MSG_INFO,
 
1066
                                     WPS_EVENT_AP_AVAILABLE);
 
1067
                wpabuf_free(ie);
 
1068
                break;
 
1069
        }
 
1070
}
 
1071
 
 
1072
 
 
1073
int wpas_wps_searching(struct wpa_supplicant *wpa_s)
 
1074
{
 
1075
        struct wpa_ssid *ssid;
 
1076
 
 
1077
        for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
 
1078
                if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && !ssid->disabled)
 
1079
                        return 1;
 
1080
        }
 
1081
 
 
1082
        return 0;
 
1083
}
 
1084
 
 
1085
 
 
1086
int wpas_wps_scan_result_text(const u8 *ies, size_t ies_len, char *buf,
 
1087
                              char *end)
 
1088
{
 
1089
        struct wpabuf *wps_ie;
 
1090
        int ret;
 
1091
 
 
1092
        wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len, WPS_DEV_OUI_WFA);
 
1093
        if (wps_ie == NULL)
 
1094
                return 0;
 
1095
 
 
1096
        ret = wps_attr_text(wps_ie, buf, end);
 
1097
        wpabuf_free(wps_ie);
 
1098
        return ret;
 
1099
}
 
1100
 
 
1101
 
 
1102
int wpas_wps_er_start(struct wpa_supplicant *wpa_s)
 
1103
{
 
1104
#ifdef CONFIG_WPS_ER
 
1105
        if (wpa_s->wps_er) {
 
1106
                wps_er_refresh(wpa_s->wps_er);
 
1107
                return 0;
 
1108
        }
 
1109
        wpa_s->wps_er = wps_er_init(wpa_s->wps, wpa_s->ifname);
 
1110
        if (wpa_s->wps_er == NULL)
 
1111
                return -1;
 
1112
        return 0;
 
1113
#else /* CONFIG_WPS_ER */
 
1114
        return 0;
 
1115
#endif /* CONFIG_WPS_ER */
 
1116
}
 
1117
 
 
1118
 
 
1119
int wpas_wps_er_stop(struct wpa_supplicant *wpa_s)
 
1120
{
 
1121
#ifdef CONFIG_WPS_ER
 
1122
        wps_er_deinit(wpa_s->wps_er, NULL, NULL);
 
1123
        wpa_s->wps_er = NULL;
 
1124
#endif /* CONFIG_WPS_ER */
 
1125
        return 0;
 
1126
}
 
1127
 
 
1128
 
 
1129
#ifdef CONFIG_WPS_ER
 
1130
int wpas_wps_er_add_pin(struct wpa_supplicant *wpa_s, const char *uuid,
 
1131
                        const char *pin)
 
1132
{
 
1133
        u8 u[UUID_LEN];
 
1134
        int any = 0;
 
1135
 
 
1136
        if (os_strcmp(uuid, "any") == 0)
 
1137
                any = 1;
 
1138
        else if (uuid_str2bin(uuid, u))
 
1139
                return -1;
 
1140
        return wps_registrar_add_pin(wpa_s->wps->registrar, any ? NULL : u,
 
1141
                                     (const u8 *) pin, os_strlen(pin), 300);
 
1142
}
 
1143
 
 
1144
 
 
1145
int wpas_wps_er_pbc(struct wpa_supplicant *wpa_s, const char *uuid)
 
1146
{
 
1147
        u8 u[UUID_LEN];
 
1148
 
 
1149
        if (uuid_str2bin(uuid, u))
 
1150
                return -1;
 
1151
        return wps_er_pbc(wpa_s->wps_er, u);
 
1152
}
 
1153
 
 
1154
 
 
1155
int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid,
 
1156
                      const char *pin)
 
1157
{
 
1158
        u8 u[UUID_LEN];
 
1159
 
 
1160
        if (uuid_str2bin(uuid, u))
 
1161
                return -1;
 
1162
        return wps_er_learn(wpa_s->wps_er, u, (const u8 *) pin,
 
1163
                            os_strlen(pin));
 
1164
}
 
1165
 
 
1166
 
 
1167
static void wpas_wps_terminate_cb(void *ctx)
 
1168
{
 
1169
        wpa_printf(MSG_DEBUG, "WPS ER: Terminated");
 
1170
        eloop_terminate();
 
1171
}
 
1172
#endif /* CONFIG_WPS_ER */
 
1173
 
 
1174
 
 
1175
int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s)
 
1176
{
 
1177
#ifdef CONFIG_WPS_ER
 
1178
        if (wpa_s->wps_er) {
 
1179
                wps_er_deinit(wpa_s->wps_er, wpas_wps_terminate_cb, wpa_s);
 
1180
                wpa_s->wps_er = NULL;
 
1181
                return 1;
 
1182
        }
 
1183
#endif /* CONFIG_WPS_ER */
 
1184
        return 0;
 
1185
}