1 /* 2 * hostapd / 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 "utils/includes.h" 16 17 #include "utils/common.h" 18 #include "utils/eloop.h" 19 #include "utils/uuid.h" 20 #include "crypto/dh_groups.h" 21 #include "common/wpa_ctrl.h" 22 #include "common/ieee802_11_defs.h" 23 #include "common/ieee802_11_common.h" 24 #include "eapol_auth/eapol_auth_sm.h" 25 #include "eapol_auth/eapol_auth_sm_i.h" 26 #include "wps/wps.h" 27 #include "wps/wps_defs.h" 28 #include "wps/wps_dev_attr.h" 29 #include "hostapd.h" 30 #include "ap_config.h" 31 #include "beacon.h" 32 #include "sta_info.h" 33 #include "wps_hostapd.h" 34 35 36 #ifdef CONFIG_WPS_UPNP 37 #include "wps/wps_upnp.h" 38 static int hostapd_wps_upnp_init(struct hostapd_data *hapd, 39 struct wps_context *wps); 40 static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd); 41 #endif /* CONFIG_WPS_UPNP */ 42 43 static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, 44 const u8 *ie, size_t ie_len); 45 static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx); 46 47 48 static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk, 49 size_t psk_len) 50 { 51 struct hostapd_data *hapd = ctx; 52 struct hostapd_wpa_psk *p; 53 struct hostapd_ssid *ssid = &hapd->conf->ssid; 54 55 wpa_printf(MSG_DEBUG, "Received new WPA/WPA2-PSK from WPS for STA " 56 MACSTR, MAC2STR(mac_addr)); 57 wpa_hexdump_key(MSG_DEBUG, "Per-device PSK", psk, psk_len); 58 59 if (psk_len != PMK_LEN) { 60 wpa_printf(MSG_DEBUG, "Unexpected PSK length %lu", 61 (unsigned long) psk_len); 62 return -1; 63 } 64 65 /* Add the new PSK to runtime PSK list */ 66 p = os_zalloc(sizeof(*p)); 67 if (p == NULL) 68 return -1; 69 os_memcpy(p->addr, mac_addr, ETH_ALEN); 70 os_memcpy(p->psk, psk, PMK_LEN); 71 72 p->next = ssid->wpa_psk; 73 ssid->wpa_psk = p; 74 75 if (ssid->wpa_psk_file) { 76 FILE *f; 77 char hex[PMK_LEN * 2 + 1]; 78 /* Add the new PSK to PSK list file */ 79 f = fopen(ssid->wpa_psk_file, "a"); 80 if (f == NULL) { 81 wpa_printf(MSG_DEBUG, "Failed to add the PSK to " 82 "'%s'", ssid->wpa_psk_file); 83 return -1; 84 } 85 86 wpa_snprintf_hex(hex, sizeof(hex), psk, psk_len); 87 fprintf(f, MACSTR " %s\n", MAC2STR(mac_addr), hex); 88 fclose(f); 89 } 90 91 return 0; 92 } 93 94 95 static int hostapd_wps_set_ie_cb(void *ctx, struct wpabuf *beacon_ie, 96 struct wpabuf *probe_resp_ie) 97 { 98 struct hostapd_data *hapd = ctx; 99 wpabuf_free(hapd->wps_beacon_ie); 100 hapd->wps_beacon_ie = beacon_ie; 101 wpabuf_free(hapd->wps_probe_resp_ie); 102 hapd->wps_probe_resp_ie = probe_resp_ie; 103 ieee802_11_set_beacon(hapd); 104 return hapd->drv.set_ap_wps_ie(hapd); 105 } 106 107 108 static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e, 109 const struct wps_device_data *dev) 110 { 111 struct hostapd_data *hapd = ctx; 112 char uuid[40], txt[400]; 113 int len; 114 char devtype[WPS_DEV_TYPE_BUFSIZE]; 115 if (uuid_bin2str(uuid_e, uuid, sizeof(uuid))) 116 return; 117 wpa_printf(MSG_DEBUG, "WPS: PIN needed for E-UUID %s", uuid); 118 len = os_snprintf(txt, sizeof(txt), WPS_EVENT_PIN_NEEDED 119 "%s " MACSTR " [%s|%s|%s|%s|%s|%s]", 120 uuid, MAC2STR(dev->mac_addr), dev->device_name, 121 dev->manufacturer, dev->model_name, 122 dev->model_number, dev->serial_number, 123 wps_dev_type_bin2str(dev->pri_dev_type, devtype, 124 sizeof(devtype))); 125 if (len > 0 && len < (int) sizeof(txt)) 126 wpa_msg(hapd->msg_ctx, MSG_INFO, "%s", txt); 127 128 if (hapd->conf->wps_pin_requests) { 129 FILE *f; 130 struct os_time t; 131 f = fopen(hapd->conf->wps_pin_requests, "a"); 132 if (f == NULL) 133 return; 134 os_get_time(&t); 135 fprintf(f, "%ld\t%s\t" MACSTR "\t%s\t%s\t%s\t%s\t%s" 136 "\t%s\n", 137 t.sec, uuid, MAC2STR(dev->mac_addr), dev->device_name, 138 dev->manufacturer, dev->model_name, dev->model_number, 139 dev->serial_number, 140 wps_dev_type_bin2str(dev->pri_dev_type, devtype, 141 sizeof(devtype))); 142 fclose(f); 143 } 144 } 145 146 147 static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr, 148 const u8 *uuid_e) 149 { 150 struct hostapd_data *hapd = ctx; 151 char uuid[40]; 152 if (uuid_bin2str(uuid_e, uuid, sizeof(uuid))) 153 return; 154 wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_REG_SUCCESS MACSTR " %s", 155 MAC2STR(mac_addr), uuid); 156 if (hapd->wps_reg_success_cb) 157 hapd->wps_reg_success_cb(hapd->wps_reg_success_cb_ctx, 158 mac_addr, uuid_e); 159 } 160 161 162 static void hostapd_wps_enrollee_seen_cb(void *ctx, const u8 *addr, 163 const u8 *uuid_e, 164 const u8 *pri_dev_type, 165 u16 config_methods, 166 u16 dev_password_id, u8 request_type, 167 const char *dev_name) 168 { 169 struct hostapd_data *hapd = ctx; 170 char uuid[40]; 171 char devtype[WPS_DEV_TYPE_BUFSIZE]; 172 if (uuid_bin2str(uuid_e, uuid, sizeof(uuid))) 173 return; 174 if (dev_name == NULL) 175 dev_name = ""; 176 wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, WPS_EVENT_ENROLLEE_SEEN MACSTR 177 " %s %s 0x%x %u %u [%s]", 178 MAC2STR(addr), uuid, 179 wps_dev_type_bin2str(pri_dev_type, devtype, 180 sizeof(devtype)), 181 config_methods, dev_password_id, request_type, dev_name); 182 } 183 184 185 static int str_starts(const char *str, const char *start) 186 { 187 return os_strncmp(str, start, os_strlen(start)) == 0; 188 } 189 190 191 static void wps_reload_config(void *eloop_data, void *user_ctx) 192 { 193 struct hostapd_iface *iface = eloop_data; 194 195 wpa_printf(MSG_DEBUG, "WPS: Reload configuration data"); 196 if (iface->reload_config(iface) < 0) { 197 wpa_printf(MSG_WARNING, "WPS: Failed to reload the updated " 198 "configuration"); 199 } 200 } 201 202 203 static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred) 204 { 205 struct hostapd_data *hapd = ctx; 206 FILE *oconf, *nconf; 207 size_t len, i; 208 char *tmp_fname; 209 char buf[1024]; 210 int multi_bss; 211 int wpa; 212 213 wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute", 214 cred->cred_attr, cred->cred_attr_len); 215 216 wpa_printf(MSG_DEBUG, "WPS: Received new AP Settings"); 217 wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", cred->ssid, cred->ssid_len); 218 wpa_printf(MSG_DEBUG, "WPS: Authentication Type 0x%x", 219 cred->auth_type); 220 wpa_printf(MSG_DEBUG, "WPS: Encryption Type 0x%x", cred->encr_type); 221 wpa_printf(MSG_DEBUG, "WPS: Network Key Index %d", cred->key_idx); 222 wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", 223 cred->key, cred->key_len); 224 wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, 225 MAC2STR(cred->mac_addr)); 226 227 if ((hapd->conf->wps_cred_processing == 1 || 228 hapd->conf->wps_cred_processing == 2) && cred->cred_attr) { 229 size_t blen = cred->cred_attr_len * 2 + 1; 230 char *_buf = os_malloc(blen); 231 if (_buf) { 232 wpa_snprintf_hex(_buf, blen, 233 cred->cred_attr, cred->cred_attr_len); 234 wpa_msg(hapd->msg_ctx, MSG_INFO, "%s%s", 235 WPS_EVENT_NEW_AP_SETTINGS, _buf); 236 os_free(_buf); 237 } 238 } else 239 wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_NEW_AP_SETTINGS); 240 241 if (hapd->conf->wps_cred_processing == 1) 242 return 0; 243 244 os_memcpy(hapd->wps->ssid, cred->ssid, cred->ssid_len); 245 hapd->wps->ssid_len = cred->ssid_len; 246 hapd->wps->encr_types = cred->encr_type; 247 hapd->wps->auth_types = cred->auth_type; 248 if (cred->key_len == 0) { 249 os_free(hapd->wps->network_key); 250 hapd->wps->network_key = NULL; 251 hapd->wps->network_key_len = 0; 252 } else { 253 if (hapd->wps->network_key == NULL || 254 hapd->wps->network_key_len < cred->key_len) { 255 hapd->wps->network_key_len = 0; 256 os_free(hapd->wps->network_key); 257 hapd->wps->network_key = os_malloc(cred->key_len); 258 if (hapd->wps->network_key == NULL) 259 return -1; 260 } 261 hapd->wps->network_key_len = cred->key_len; 262 os_memcpy(hapd->wps->network_key, cred->key, cred->key_len); 263 } 264 hapd->wps->wps_state = WPS_STATE_CONFIGURED; 265 266 len = os_strlen(hapd->iface->config_fname) + 5; 267 tmp_fname = os_malloc(len); 268 if (tmp_fname == NULL) 269 return -1; 270 os_snprintf(tmp_fname, len, "%s-new", hapd->iface->config_fname); 271 272 oconf = fopen(hapd->iface->config_fname, "r"); 273 if (oconf == NULL) { 274 wpa_printf(MSG_WARNING, "WPS: Could not open current " 275 "configuration file"); 276 os_free(tmp_fname); 277 return -1; 278 } 279 280 nconf = fopen(tmp_fname, "w"); 281 if (nconf == NULL) { 282 wpa_printf(MSG_WARNING, "WPS: Could not write updated " 283 "configuration file"); 284 os_free(tmp_fname); 285 fclose(oconf); 286 return -1; 287 } 288 289 fprintf(nconf, "# WPS configuration - START\n"); 290 291 fprintf(nconf, "wps_state=2\n"); 292 293 fprintf(nconf, "ssid="); 294 for (i = 0; i < cred->ssid_len; i++) 295 fputc(cred->ssid[i], nconf); 296 fprintf(nconf, "\n"); 297 298 if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) && 299 (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK))) 300 wpa = 3; 301 else if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) 302 wpa = 2; 303 else if (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)) 304 wpa = 1; 305 else 306 wpa = 0; 307 308 if (wpa) { 309 char *prefix; 310 fprintf(nconf, "wpa=%d\n", wpa); 311 312 fprintf(nconf, "wpa_key_mgmt="); 313 prefix = ""; 314 if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA)) { 315 fprintf(nconf, "WPA-EAP"); 316 prefix = " "; 317 } 318 if (cred->auth_type & (WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) 319 fprintf(nconf, "%sWPA-PSK", prefix); 320 fprintf(nconf, "\n"); 321 322 fprintf(nconf, "wpa_pairwise="); 323 prefix = ""; 324 if (cred->encr_type & WPS_ENCR_AES) { 325 fprintf(nconf, "CCMP"); 326 prefix = " "; 327 } 328 if (cred->encr_type & WPS_ENCR_TKIP) { 329 fprintf(nconf, "%sTKIP", prefix); 330 } 331 fprintf(nconf, "\n"); 332 333 if (cred->key_len >= 8 && cred->key_len < 64) { 334 fprintf(nconf, "wpa_passphrase="); 335 for (i = 0; i < cred->key_len; i++) 336 fputc(cred->key[i], nconf); 337 fprintf(nconf, "\n"); 338 } else if (cred->key_len == 64) { 339 fprintf(nconf, "wpa_psk="); 340 for (i = 0; i < cred->key_len; i++) 341 fputc(cred->key[i], nconf); 342 fprintf(nconf, "\n"); 343 } else { 344 wpa_printf(MSG_WARNING, "WPS: Invalid key length %lu " 345 "for WPA/WPA2", 346 (unsigned long) cred->key_len); 347 } 348 349 fprintf(nconf, "auth_algs=1\n"); 350 } else { 351 if ((cred->auth_type & WPS_AUTH_OPEN) && 352 (cred->auth_type & WPS_AUTH_SHARED)) 353 fprintf(nconf, "auth_algs=3\n"); 354 else if (cred->auth_type & WPS_AUTH_SHARED) 355 fprintf(nconf, "auth_algs=2\n"); 356 else 357 fprintf(nconf, "auth_algs=1\n"); 358 359 if (cred->encr_type & WPS_ENCR_WEP && cred->key_idx <= 4) { 360 int key_idx = cred->key_idx; 361 if (key_idx) 362 key_idx--; 363 fprintf(nconf, "wep_default_key=%d\n", key_idx); 364 fprintf(nconf, "wep_key%d=", key_idx); 365 if (cred->key_len == 10 || cred->key_len == 26) { 366 /* WEP key as a hex string */ 367 for (i = 0; i < cred->key_len; i++) 368 fputc(cred->key[i], nconf); 369 } else { 370 /* Raw WEP key; convert to hex */ 371 for (i = 0; i < cred->key_len; i++) 372 fprintf(nconf, "%02x", cred->key[i]); 373 } 374 fprintf(nconf, "\n"); 375 } 376 } 377 378 fprintf(nconf, "# WPS configuration - END\n"); 379 380 multi_bss = 0; 381 while (fgets(buf, sizeof(buf), oconf)) { 382 if (os_strncmp(buf, "bss=", 4) == 0) 383 multi_bss = 1; 384 if (!multi_bss && 385 (str_starts(buf, "ssid=") || 386 str_starts(buf, "auth_algs=") || 387 str_starts(buf, "wps_state=") || 388 str_starts(buf, "wpa=") || 389 str_starts(buf, "wpa_psk=") || 390 str_starts(buf, "wpa_pairwise=") || 391 str_starts(buf, "rsn_pairwise=") || 392 str_starts(buf, "wpa_key_mgmt=") || 393 str_starts(buf, "wpa_passphrase="))) { 394 fprintf(nconf, "#WPS# %s", buf); 395 } else 396 fprintf(nconf, "%s", buf); 397 } 398 399 fclose(nconf); 400 fclose(oconf); 401 402 if (rename(tmp_fname, hapd->iface->config_fname) < 0) { 403 wpa_printf(MSG_WARNING, "WPS: Failed to rename the updated " 404 "configuration file: %s", strerror(errno)); 405 os_free(tmp_fname); 406 return -1; 407 } 408 409 os_free(tmp_fname); 410 411 /* Schedule configuration reload after short period of time to allow 412 * EAP-WSC to be finished. 413 */ 414 eloop_register_timeout(0, 100000, wps_reload_config, hapd->iface, 415 NULL); 416 417 /* TODO: dualband AP may need to update multiple configuration files */ 418 419 wpa_printf(MSG_DEBUG, "WPS: AP configuration updated"); 420 421 return 0; 422 } 423 424 425 static void hostapd_wps_reenable_ap_pin(void *eloop_data, void *user_ctx) 426 { 427 struct hostapd_data *hapd = eloop_data; 428 429 if (hapd->conf->ap_setup_locked) 430 return; 431 432 wpa_printf(MSG_DEBUG, "WPS: Re-enable AP PIN"); 433 wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED); 434 hapd->wps->ap_setup_locked = 0; 435 wps_registrar_update_ie(hapd->wps->registrar); 436 } 437 438 439 static void hostapd_pwd_auth_fail(struct hostapd_data *hapd, 440 struct wps_event_pwd_auth_fail *data) 441 { 442 if (!data->enrollee || hapd->conf->ap_pin == NULL) 443 return; 444 445 /* 446 * Registrar failed to prove its knowledge of the AP PIN. Lock AP setup 447 * for some time if this happens multiple times to slow down brute 448 * force attacks. 449 */ 450 hapd->ap_pin_failures++; 451 wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u", 452 hapd->ap_pin_failures); 453 if (hapd->ap_pin_failures < 3) 454 return; 455 456 wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED); 457 hapd->wps->ap_setup_locked = 1; 458 459 wps_registrar_update_ie(hapd->wps->registrar); 460 461 if (!hapd->conf->ap_setup_locked) { 462 if (hapd->ap_pin_lockout_time == 0) 463 hapd->ap_pin_lockout_time = 60; 464 else if (hapd->ap_pin_lockout_time < 365 * 24 * 60 * 60 && 465 (hapd->ap_pin_failures % 3) == 0) 466 hapd->ap_pin_lockout_time *= 2; 467 468 wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN for %u seconds", 469 hapd->ap_pin_lockout_time); 470 eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL); 471 eloop_register_timeout(hapd->ap_pin_lockout_time, 0, 472 hostapd_wps_reenable_ap_pin, hapd, 473 NULL); 474 } 475 476 /* TODO: dualband AP may need to update other interfaces */ 477 } 478 479 480 static void hostapd_wps_event_cb(void *ctx, enum wps_event event, 481 union wps_event_data *data) 482 { 483 struct hostapd_data *hapd = ctx; 484 485 if (event == WPS_EV_PWD_AUTH_FAIL) 486 hostapd_pwd_auth_fail(hapd, &data->pwd_auth_fail); 487 } 488 489 490 static void hostapd_wps_clear_ies(struct hostapd_data *hapd) 491 { 492 wpabuf_free(hapd->wps_beacon_ie); 493 hapd->wps_beacon_ie = NULL; 494 495 wpabuf_free(hapd->wps_probe_resp_ie); 496 hapd->wps_probe_resp_ie = NULL; 497 498 hapd->drv.set_ap_wps_ie(hapd); 499 } 500 501 502 int hostapd_init_wps(struct hostapd_data *hapd, 503 struct hostapd_bss_config *conf) 504 { 505 struct wps_context *wps; 506 struct wps_registrar_config cfg; 507 508 if (conf->wps_state == 0) { 509 hostapd_wps_clear_ies(hapd); 510 return 0; 511 } 512 513 wps = os_zalloc(sizeof(*wps)); 514 if (wps == NULL) 515 return -1; 516 517 wps->cred_cb = hostapd_wps_cred_cb; 518 wps->event_cb = hostapd_wps_event_cb; 519 wps->cb_ctx = hapd; 520 521 os_memset(&cfg, 0, sizeof(cfg)); 522 wps->wps_state = hapd->conf->wps_state; 523 wps->ap_setup_locked = hapd->conf->ap_setup_locked; 524 if (is_nil_uuid(hapd->conf->uuid)) { 525 uuid_gen_mac_addr(hapd->own_addr, wps->uuid); 526 wpa_hexdump(MSG_DEBUG, "WPS: UUID based on MAC address", 527 wps->uuid, UUID_LEN); 528 } else 529 os_memcpy(wps->uuid, hapd->conf->uuid, UUID_LEN); 530 wps->ssid_len = hapd->conf->ssid.ssid_len; 531 os_memcpy(wps->ssid, hapd->conf->ssid.ssid, wps->ssid_len); 532 wps->ap = 1; 533 os_memcpy(wps->dev.mac_addr, hapd->own_addr, ETH_ALEN); 534 wps->dev.device_name = hapd->conf->device_name ? 535 os_strdup(hapd->conf->device_name) : NULL; 536 wps->dev.manufacturer = hapd->conf->manufacturer ? 537 os_strdup(hapd->conf->manufacturer) : NULL; 538 wps->dev.model_name = hapd->conf->model_name ? 539 os_strdup(hapd->conf->model_name) : NULL; 540 wps->dev.model_number = hapd->conf->model_number ? 541 os_strdup(hapd->conf->model_number) : NULL; 542 wps->dev.serial_number = hapd->conf->serial_number ? 543 os_strdup(hapd->conf->serial_number) : NULL; 544 wps->config_methods = 545 wps_config_methods_str2bin(hapd->conf->config_methods); 546 if (hapd->conf->device_type && 547 wps_dev_type_str2bin(hapd->conf->device_type, 548 wps->dev.pri_dev_type) < 0) { 549 wpa_printf(MSG_ERROR, "WPS: Invalid device_type"); 550 os_free(wps); 551 return -1; 552 } 553 wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version); 554 wps->dev.rf_bands = hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ? 555 WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */ 556 557 if (conf->wpa & WPA_PROTO_RSN) { 558 if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) 559 wps->auth_types |= WPS_AUTH_WPA2PSK; 560 if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) 561 wps->auth_types |= WPS_AUTH_WPA2; 562 563 if (conf->rsn_pairwise & WPA_CIPHER_CCMP) 564 wps->encr_types |= WPS_ENCR_AES; 565 if (conf->rsn_pairwise & WPA_CIPHER_TKIP) 566 wps->encr_types |= WPS_ENCR_TKIP; 567 } 568 569 if (conf->wpa & WPA_PROTO_WPA) { 570 if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) 571 wps->auth_types |= WPS_AUTH_WPAPSK; 572 if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) 573 wps->auth_types |= WPS_AUTH_WPA; 574 575 if (conf->wpa_pairwise & WPA_CIPHER_CCMP) 576 wps->encr_types |= WPS_ENCR_AES; 577 if (conf->wpa_pairwise & WPA_CIPHER_TKIP) 578 wps->encr_types |= WPS_ENCR_TKIP; 579 } 580 581 if (conf->ssid.security_policy == SECURITY_PLAINTEXT) { 582 wps->encr_types |= WPS_ENCR_NONE; 583 wps->auth_types |= WPS_AUTH_OPEN; 584 } else if (conf->ssid.security_policy == SECURITY_STATIC_WEP) { 585 wps->encr_types |= WPS_ENCR_WEP; 586 if (conf->auth_algs & WPA_AUTH_ALG_OPEN) 587 wps->auth_types |= WPS_AUTH_OPEN; 588 if (conf->auth_algs & WPA_AUTH_ALG_SHARED) 589 wps->auth_types |= WPS_AUTH_SHARED; 590 } else if (conf->ssid.security_policy == SECURITY_IEEE_802_1X) { 591 wps->auth_types |= WPS_AUTH_OPEN; 592 if (conf->default_wep_key_len) 593 wps->encr_types |= WPS_ENCR_WEP; 594 else 595 wps->encr_types |= WPS_ENCR_NONE; 596 } 597 598 if (conf->ssid.wpa_psk_file) { 599 /* Use per-device PSKs */ 600 } else if (conf->ssid.wpa_passphrase) { 601 wps->network_key = (u8 *) os_strdup(conf->ssid.wpa_passphrase); 602 wps->network_key_len = os_strlen(conf->ssid.wpa_passphrase); 603 } else if (conf->ssid.wpa_psk) { 604 wps->network_key = os_malloc(2 * PMK_LEN + 1); 605 if (wps->network_key == NULL) { 606 os_free(wps); 607 return -1; 608 } 609 wpa_snprintf_hex((char *) wps->network_key, 2 * PMK_LEN + 1, 610 conf->ssid.wpa_psk->psk, PMK_LEN); 611 wps->network_key_len = 2 * PMK_LEN; 612 } else if (conf->ssid.wep.keys_set && conf->ssid.wep.key[0]) { 613 wps->network_key = os_malloc(conf->ssid.wep.len[0]); 614 if (wps->network_key == NULL) { 615 os_free(wps); 616 return -1; 617 } 618 os_memcpy(wps->network_key, conf->ssid.wep.key[0], 619 conf->ssid.wep.len[0]); 620 wps->network_key_len = conf->ssid.wep.len[0]; 621 } 622 623 if (conf->ssid.wpa_psk) { 624 os_memcpy(wps->psk, conf->ssid.wpa_psk->psk, PMK_LEN); 625 wps->psk_set = 1; 626 } 627 628 if (conf->wps_state == WPS_STATE_NOT_CONFIGURED) { 629 /* Override parameters to enable security by default */ 630 wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK; 631 wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP; 632 } 633 634 wps->ap_settings = conf->ap_settings; 635 wps->ap_settings_len = conf->ap_settings_len; 636 637 cfg.new_psk_cb = hostapd_wps_new_psk_cb; 638 cfg.set_ie_cb = hostapd_wps_set_ie_cb; 639 cfg.pin_needed_cb = hostapd_wps_pin_needed_cb; 640 cfg.reg_success_cb = hostapd_wps_reg_success_cb; 641 cfg.enrollee_seen_cb = hostapd_wps_enrollee_seen_cb; 642 cfg.cb_ctx = hapd; 643 cfg.skip_cred_build = conf->skip_cred_build; 644 cfg.extra_cred = conf->extra_cred; 645 cfg.extra_cred_len = conf->extra_cred_len; 646 cfg.disable_auto_conf = (hapd->conf->wps_cred_processing == 1) && 647 conf->skip_cred_build; 648 if (conf->ssid.security_policy == SECURITY_STATIC_WEP) 649 cfg.static_wep_only = 1; 650 651 wps->registrar = wps_registrar_init(wps, &cfg); 652 if (wps->registrar == NULL) { 653 printf("Failed to initialize WPS Registrar\n"); 654 os_free(wps->network_key); 655 os_free(wps); 656 return -1; 657 } 658 659 #ifdef CONFIG_WPS_UPNP 660 wps->friendly_name = hapd->conf->friendly_name; 661 wps->manufacturer_url = hapd->conf->manufacturer_url; 662 wps->model_description = hapd->conf->model_description; 663 wps->model_url = hapd->conf->model_url; 664 wps->upc = hapd->conf->upc; 665 666 if (hostapd_wps_upnp_init(hapd, wps) < 0) { 667 wpa_printf(MSG_ERROR, "Failed to initialize WPS UPnP"); 668 wps_registrar_deinit(wps->registrar); 669 os_free(wps->network_key); 670 os_free(wps); 671 return -1; 672 } 673 #endif /* CONFIG_WPS_UPNP */ 674 675 hostapd_register_probereq_cb(hapd, hostapd_wps_probe_req_rx, hapd); 676 677 hapd->wps = wps; 678 679 return 0; 680 } 681 682 683 void hostapd_deinit_wps(struct hostapd_data *hapd) 684 { 685 eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL); 686 eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL); 687 if (hapd->wps == NULL) 688 return; 689 #ifdef CONFIG_WPS_UPNP 690 hostapd_wps_upnp_deinit(hapd); 691 #endif /* CONFIG_WPS_UPNP */ 692 wps_registrar_deinit(hapd->wps->registrar); 693 os_free(hapd->wps->network_key); 694 wps_device_data_free(&hapd->wps->dev); 695 wpabuf_free(hapd->wps->dh_pubkey); 696 wpabuf_free(hapd->wps->dh_privkey); 697 wpabuf_free(hapd->wps->oob_conf.pubkey_hash); 698 wpabuf_free(hapd->wps->oob_conf.dev_password); 699 wps_free_pending_msgs(hapd->wps->upnp_msgs); 700 os_free(hapd->wps); 701 hapd->wps = NULL; 702 hostapd_wps_clear_ies(hapd); 703 } 704 705 706 void hostapd_update_wps(struct hostapd_data *hapd) 707 { 708 if (hapd->wps == NULL) 709 return; 710 if (hapd->conf->wps_state) 711 wps_registrar_update_ie(hapd->wps->registrar); 712 else 713 hostapd_deinit_wps(hapd); 714 } 715 716 717 int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid, 718 const char *pin, int timeout) 719 { 720 u8 u[UUID_LEN]; 721 int any = 0; 722 723 if (hapd->wps == NULL) 724 return -1; 725 if (os_strcmp(uuid, "any") == 0) 726 any = 1; 727 else if (uuid_str2bin(uuid, u)) 728 return -1; 729 return wps_registrar_add_pin(hapd->wps->registrar, any ? NULL : u, 730 (const u8 *) pin, os_strlen(pin), 731 timeout); 732 } 733 734 735 int hostapd_wps_button_pushed(struct hostapd_data *hapd) 736 { 737 if (hapd->wps == NULL) 738 return -1; 739 return wps_registrar_button_pushed(hapd->wps->registrar); 740 } 741 742 743 #ifdef CONFIG_WPS_OOB 744 int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type, 745 char *path, char *method, char *name) 746 { 747 struct wps_context *wps = hapd->wps; 748 struct oob_device_data *oob_dev; 749 750 oob_dev = wps_get_oob_device(device_type); 751 if (oob_dev == NULL) 752 return -1; 753 oob_dev->device_path = path; 754 oob_dev->device_name = name; 755 wps->oob_conf.oob_method = wps_get_oob_method(method); 756 757 if (wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) { 758 /* 759 * Use pre-configured DH keys in order to be able to write the 760 * key hash into the OOB file. 761 */ 762 wpabuf_free(wps->dh_pubkey); 763 wpabuf_free(wps->dh_privkey); 764 wps->dh_privkey = NULL; 765 wps->dh_pubkey = dh_init(dh_groups_get(WPS_DH_GROUP), 766 &wps->dh_privkey); 767 wps->dh_pubkey = wpabuf_zeropad(wps->dh_pubkey, 192); 768 if (wps->dh_pubkey == NULL) { 769 wpa_printf(MSG_ERROR, "WPS: Failed to initialize " 770 "Diffie-Hellman handshake"); 771 return -1; 772 } 773 } 774 775 if (wps_process_oob(wps, oob_dev, 1) < 0) 776 goto error; 777 778 if ((wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E || 779 wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) && 780 hostapd_wps_add_pin(hapd, "any", 781 wpabuf_head(wps->oob_conf.dev_password), 0) < 782 0) 783 goto error; 784 785 return 0; 786 787 error: 788 wpabuf_free(wps->dh_pubkey); 789 wps->dh_pubkey = NULL; 790 wpabuf_free(wps->dh_privkey); 791 wps->dh_privkey = NULL; 792 return -1; 793 } 794 #endif /* CONFIG_WPS_OOB */ 795 796 797 static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, 798 const u8 *ie, size_t ie_len) 799 { 800 struct hostapd_data *hapd = ctx; 801 struct wpabuf *wps_ie; 802 struct ieee802_11_elems elems; 803 804 if (hapd->wps == NULL) 805 return 0; 806 807 if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) { 808 wpa_printf(MSG_DEBUG, "WPS: Could not parse ProbeReq from " 809 MACSTR, MAC2STR(addr)); 810 return 0; 811 } 812 813 if (elems.ssid && elems.ssid_len > 0 && 814 (elems.ssid_len != hapd->conf->ssid.ssid_len || 815 os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) != 816 0)) 817 return 0; /* Not for us */ 818 819 wps_ie = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA); 820 if (wps_ie == NULL) 821 return 0; 822 823 if (wpabuf_len(wps_ie) > 0) { 824 wps_registrar_probe_req_rx(hapd->wps->registrar, addr, wps_ie); 825 #ifdef CONFIG_WPS_UPNP 826 /* FIX: what exactly should be included in the WLANEvent? 827 * WPS attributes? Full ProbeReq frame? */ 828 upnp_wps_device_send_wlan_event(hapd->wps_upnp, addr, 829 UPNP_WPS_WLANEVENT_TYPE_PROBE, 830 wps_ie); 831 #endif /* CONFIG_WPS_UPNP */ 832 } 833 834 wpabuf_free(wps_ie); 835 836 return 0; 837 } 838 839 840 #ifdef CONFIG_WPS_UPNP 841 842 static int hostapd_rx_req_put_wlan_response( 843 void *priv, enum upnp_wps_wlanevent_type ev_type, 844 const u8 *mac_addr, const struct wpabuf *msg, 845 enum wps_msg_type msg_type) 846 { 847 struct hostapd_data *hapd = priv; 848 struct sta_info *sta; 849 struct upnp_pending_message *p; 850 851 wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse ev_type=%d mac_addr=" 852 MACSTR, ev_type, MAC2STR(mac_addr)); 853 wpa_hexdump(MSG_MSGDUMP, "WPS UPnP: PutWLANResponse NewMessage", 854 wpabuf_head(msg), wpabuf_len(msg)); 855 if (ev_type != UPNP_WPS_WLANEVENT_TYPE_EAP) { 856 wpa_printf(MSG_DEBUG, "WPS UPnP: Ignored unexpected " 857 "PutWLANResponse WLANEventType %d", ev_type); 858 return -1; 859 } 860 861 /* 862 * EAP response to ongoing to WPS Registration. Send it to EAP-WSC 863 * server implementation for delivery to the peer. 864 */ 865 866 sta = ap_get_sta(hapd, mac_addr); 867 if (!sta) { 868 /* 869 * Workaround - Intel wsccmd uses bogus NewWLANEventMAC: 870 * Pick STA that is in an ongoing WPS registration without 871 * checking the MAC address. 872 */ 873 wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found based " 874 "on NewWLANEventMAC; try wildcard match"); 875 for (sta = hapd->sta_list; sta; sta = sta->next) { 876 if (sta->eapol_sm && (sta->flags & WLAN_STA_WPS)) 877 break; 878 } 879 } 880 881 if (!sta) { 882 wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found"); 883 return 0; 884 } 885 886 p = os_zalloc(sizeof(*p)); 887 if (p == NULL) 888 return -1; 889 os_memcpy(p->addr, sta->addr, ETH_ALEN); 890 p->msg = wpabuf_dup(msg); 891 p->type = msg_type; 892 p->next = hapd->wps->upnp_msgs; 893 hapd->wps->upnp_msgs = p; 894 895 return eapol_auth_eap_pending_cb(sta->eapol_sm, sta->eapol_sm->eap); 896 } 897 898 899 static int hostapd_wps_upnp_init(struct hostapd_data *hapd, 900 struct wps_context *wps) 901 { 902 struct upnp_wps_device_ctx *ctx; 903 904 if (!hapd->conf->upnp_iface) 905 return 0; 906 ctx = os_zalloc(sizeof(*ctx)); 907 if (ctx == NULL) 908 return -1; 909 910 ctx->rx_req_put_wlan_response = hostapd_rx_req_put_wlan_response; 911 if (hapd->conf->ap_pin) 912 ctx->ap_pin = os_strdup(hapd->conf->ap_pin); 913 914 hapd->wps_upnp = upnp_wps_device_init(ctx, wps, hapd); 915 if (hapd->wps_upnp == NULL) { 916 os_free(ctx); 917 return -1; 918 } 919 wps->wps_upnp = hapd->wps_upnp; 920 921 if (upnp_wps_device_start(hapd->wps_upnp, hapd->conf->upnp_iface)) { 922 upnp_wps_device_deinit(hapd->wps_upnp); 923 hapd->wps_upnp = NULL; 924 return -1; 925 } 926 927 return 0; 928 } 929 930 931 static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd) 932 { 933 upnp_wps_device_deinit(hapd->wps_upnp); 934 } 935 936 #endif /* CONFIG_WPS_UPNP */ 937 938 939 int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr, 940 char *buf, size_t buflen) 941 { 942 if (hapd->wps == NULL) 943 return 0; 944 return wps_registrar_get_info(hapd->wps->registrar, addr, buf, buflen); 945 } 946 947 948 static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx) 949 { 950 struct hostapd_data *hapd = eloop_data; 951 wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out"); 952 hostapd_wps_ap_pin_disable(hapd); 953 } 954 955 956 static void hostapd_wps_ap_pin_enable(struct hostapd_data *hapd, int timeout) 957 { 958 wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout); 959 hapd->ap_pin_failures = 0; 960 hapd->conf->ap_setup_locked = 0; 961 if (hapd->wps->ap_setup_locked) { 962 wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED); 963 hapd->wps->ap_setup_locked = 0; 964 wps_registrar_update_ie(hapd->wps->registrar); 965 } 966 eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL); 967 if (timeout > 0) 968 eloop_register_timeout(timeout, 0, 969 hostapd_wps_ap_pin_timeout, hapd, NULL); 970 } 971 972 973 void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd) 974 { 975 wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN"); 976 os_free(hapd->conf->ap_pin); 977 hapd->conf->ap_pin = NULL; 978 #ifdef CONFIG_WPS_UPNP 979 upnp_wps_set_ap_pin(hapd->wps_upnp, NULL); 980 #endif /* CONFIG_WPS_UPNP */ 981 eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL); 982 } 983 984 985 const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout) 986 { 987 unsigned int pin; 988 char pin_txt[9]; 989 990 pin = wps_generate_pin(); 991 os_snprintf(pin_txt, sizeof(pin_txt), "%u", pin); 992 os_free(hapd->conf->ap_pin); 993 hapd->conf->ap_pin = os_strdup(pin_txt); 994 #ifdef CONFIG_WPS_UPNP 995 upnp_wps_set_ap_pin(hapd->wps_upnp, pin_txt); 996 #endif /* CONFIG_WPS_UPNP */ 997 hostapd_wps_ap_pin_enable(hapd, timeout); 998 return hapd->conf->ap_pin; 999 } 1000 1001 1002 const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd) 1003 { 1004 return hapd->conf->ap_pin; 1005 } 1006 1007 1008 int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin, 1009 int timeout) 1010 { 1011 os_free(hapd->conf->ap_pin); 1012 hapd->conf->ap_pin = os_strdup(pin); 1013 if (hapd->conf->ap_pin == NULL) 1014 return -1; 1015 #ifdef CONFIG_WPS_UPNP 1016 upnp_wps_set_ap_pin(hapd->wps_upnp, hapd->conf->ap_pin); 1017 #endif /* CONFIG_WPS_UPNP */ 1018 hostapd_wps_ap_pin_enable(hapd, timeout); 1019 return 0; 1020 } 1021