$search
00001 /* 00002 * Wi-Fi Protected Setup 00003 * Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "crypto/dh_group5.h" 00019 #include "common/ieee802_11_defs.h" 00020 #include "wps_i.h" 00021 #include "wps_dev_attr.h" 00022 00023 00034 struct wps_data * wps_init(const struct wps_config *cfg) 00035 { 00036 struct wps_data *data = os_zalloc(sizeof(*data)); 00037 if (data == NULL) 00038 return NULL; 00039 data->wps = cfg->wps; 00040 data->registrar = cfg->registrar; 00041 if (cfg->registrar) { 00042 os_memcpy(data->uuid_r, cfg->wps->uuid, WPS_UUID_LEN); 00043 } else { 00044 os_memcpy(data->mac_addr_e, cfg->wps->dev.mac_addr, ETH_ALEN); 00045 os_memcpy(data->uuid_e, cfg->wps->uuid, WPS_UUID_LEN); 00046 } 00047 if (cfg->pin) { 00048 data->dev_pw_id = data->wps->oob_dev_pw_id == 0 ? 00049 DEV_PW_DEFAULT : data->wps->oob_dev_pw_id; 00050 data->dev_password = os_malloc(cfg->pin_len); 00051 if (data->dev_password == NULL) { 00052 os_free(data); 00053 return NULL; 00054 } 00055 os_memcpy(data->dev_password, cfg->pin, cfg->pin_len); 00056 data->dev_password_len = cfg->pin_len; 00057 } 00058 00059 data->pbc = cfg->pbc; 00060 if (cfg->pbc) { 00061 /* Use special PIN '00000000' for PBC */ 00062 data->dev_pw_id = DEV_PW_PUSHBUTTON; 00063 os_free(data->dev_password); 00064 data->dev_password = os_malloc(8); 00065 if (data->dev_password == NULL) { 00066 os_free(data); 00067 return NULL; 00068 } 00069 os_memset(data->dev_password, '0', 8); 00070 data->dev_password_len = 8; 00071 } 00072 00073 data->state = data->registrar ? RECV_M1 : SEND_M1; 00074 00075 if (cfg->assoc_wps_ie) { 00076 struct wps_parse_attr attr; 00077 wpa_hexdump_buf(MSG_DEBUG, "WPS: WPS IE from (Re)AssocReq", 00078 cfg->assoc_wps_ie); 00079 if (wps_parse_msg(cfg->assoc_wps_ie, &attr) < 0) { 00080 wpa_printf(MSG_DEBUG, "WPS: Failed to parse WPS IE " 00081 "from (Re)AssocReq"); 00082 } else if (attr.request_type == NULL) { 00083 wpa_printf(MSG_DEBUG, "WPS: No Request Type attribute " 00084 "in (Re)AssocReq WPS IE"); 00085 } else { 00086 wpa_printf(MSG_DEBUG, "WPS: Request Type (from WPS IE " 00087 "in (Re)AssocReq WPS IE): %d", 00088 *attr.request_type); 00089 data->request_type = *attr.request_type; 00090 } 00091 } 00092 00093 if (cfg->new_ap_settings) { 00094 data->new_ap_settings = 00095 os_malloc(sizeof(*data->new_ap_settings)); 00096 if (data->new_ap_settings == NULL) { 00097 os_free(data); 00098 return NULL; 00099 } 00100 os_memcpy(data->new_ap_settings, cfg->new_ap_settings, 00101 sizeof(*data->new_ap_settings)); 00102 } 00103 00104 if (cfg->peer_addr) 00105 os_memcpy(data->peer_dev.mac_addr, cfg->peer_addr, ETH_ALEN); 00106 00107 data->use_psk_key = cfg->use_psk_key; 00108 00109 return data; 00110 } 00111 00112 00117 void wps_deinit(struct wps_data *data) 00118 { 00119 if (data->wps_pin_revealed) { 00120 wpa_printf(MSG_DEBUG, "WPS: Full PIN information revealed and " 00121 "negotiation failed"); 00122 if (data->registrar) 00123 wps_registrar_invalidate_pin(data->wps->registrar, 00124 data->uuid_e); 00125 } else if (data->registrar) 00126 wps_registrar_unlock_pin(data->wps->registrar, data->uuid_e); 00127 00128 wpabuf_free(data->dh_privkey); 00129 wpabuf_free(data->dh_pubkey_e); 00130 wpabuf_free(data->dh_pubkey_r); 00131 wpabuf_free(data->last_msg); 00132 os_free(data->dev_password); 00133 os_free(data->new_psk); 00134 wps_device_data_free(&data->peer_dev); 00135 os_free(data->new_ap_settings); 00136 dh5_free(data->dh_ctx); 00137 os_free(data); 00138 } 00139 00140 00153 enum wps_process_res wps_process_msg(struct wps_data *wps, 00154 enum wsc_op_code op_code, 00155 const struct wpabuf *msg) 00156 { 00157 if (wps->registrar) 00158 return wps_registrar_process_msg(wps, op_code, msg); 00159 else 00160 return wps_enrollee_process_msg(wps, op_code, msg); 00161 } 00162 00163 00173 struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code) 00174 { 00175 if (wps->registrar) 00176 return wps_registrar_get_msg(wps, op_code); 00177 else 00178 return wps_enrollee_get_msg(wps, op_code); 00179 } 00180 00181 00187 int wps_is_selected_pbc_registrar(const struct wpabuf *msg) 00188 { 00189 struct wps_parse_attr attr; 00190 00191 /* 00192 * In theory, this could also verify that attr.sel_reg_config_methods 00193 * includes WPS_CONFIG_PUSHBUTTON, but some deployed AP implementations 00194 * do not set Selected Registrar Config Methods attribute properly, so 00195 * it is safer to just use Device Password ID here. 00196 */ 00197 00198 if (wps_parse_msg(msg, &attr) < 0 || 00199 !attr.selected_registrar || *attr.selected_registrar == 0 || 00200 !attr.dev_password_id || 00201 WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON) 00202 return 0; 00203 00204 return 1; 00205 } 00206 00207 00213 int wps_is_selected_pin_registrar(const struct wpabuf *msg) 00214 { 00215 struct wps_parse_attr attr; 00216 00217 /* 00218 * In theory, this could also verify that attr.sel_reg_config_methods 00219 * includes WPS_CONFIG_LABEL, WPS_CONFIG_DISPLAY, or WPS_CONFIG_KEYPAD, 00220 * but some deployed AP implementations do not set Selected Registrar 00221 * Config Methods attribute properly, so it is safer to just use 00222 * Device Password ID here. 00223 */ 00224 00225 if (wps_parse_msg(msg, &attr) < 0) 00226 return 0; 00227 00228 if (!attr.selected_registrar || *attr.selected_registrar == 0) 00229 return 0; 00230 00231 if (attr.dev_password_id != NULL && 00232 WPA_GET_BE16(attr.dev_password_id) == DEV_PW_PUSHBUTTON) 00233 return 0; 00234 00235 return 1; 00236 } 00237 00238 00247 const u8 * wps_get_uuid_e(const struct wpabuf *msg) 00248 { 00249 struct wps_parse_attr attr; 00250 00251 if (wps_parse_msg(msg, &attr) < 0) 00252 return NULL; 00253 return attr.uuid_e; 00254 } 00255 00256 00264 struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type) 00265 { 00266 struct wpabuf *ie; 00267 u8 *len; 00268 00269 wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association " 00270 "Request"); 00271 ie = wpabuf_alloc(100); 00272 if (ie == NULL) 00273 return NULL; 00274 00275 wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); 00276 len = wpabuf_put(ie, 1); 00277 wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); 00278 00279 if (wps_build_version(ie) || 00280 wps_build_req_type(ie, req_type)) { 00281 wpabuf_free(ie); 00282 return NULL; 00283 } 00284 00285 *len = wpabuf_len(ie) - 2; 00286 00287 return ie; 00288 } 00289 00290 00301 struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, 00302 const u8 *uuid, 00303 enum wps_request_type req_type) 00304 { 00305 struct wpabuf *ie; 00306 u8 *len; 00307 u16 methods; 00308 00309 wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request"); 00310 00311 ie = wpabuf_alloc(200); 00312 if (ie == NULL) 00313 return NULL; 00314 00315 wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); 00316 len = wpabuf_put(ie, 1); 00317 wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); 00318 00319 if (pbc) 00320 methods = WPS_CONFIG_PUSHBUTTON; 00321 else { 00322 methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | 00323 WPS_CONFIG_KEYPAD; 00324 #ifdef CONFIG_WPS_UFD 00325 methods |= WPS_CONFIG_USBA; 00326 #endif /* CONFIG_WPS_UFD */ 00327 #ifdef CONFIG_WPS_NFC 00328 methods |= WPS_CONFIG_NFC_INTERFACE; 00329 #endif /* CONFIG_WPS_NFC */ 00330 } 00331 00332 if (wps_build_version(ie) || 00333 wps_build_req_type(ie, req_type) || 00334 wps_build_config_methods(ie, methods) || 00335 wps_build_uuid_e(ie, uuid) || 00336 wps_build_primary_dev_type(dev, ie) || 00337 wps_build_rf_bands(dev, ie) || 00338 wps_build_assoc_state(NULL, ie) || 00339 wps_build_config_error(ie, WPS_CFG_NO_ERROR) || 00340 wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON : 00341 DEV_PW_DEFAULT)) { 00342 wpabuf_free(ie); 00343 return NULL; 00344 } 00345 00346 *len = wpabuf_len(ie) - 2; 00347 00348 return ie; 00349 } 00350 00351 00352 void wps_free_pending_msgs(struct upnp_pending_message *msgs) 00353 { 00354 struct upnp_pending_message *p, *prev; 00355 p = msgs; 00356 while (p) { 00357 prev = p; 00358 p = p->next; 00359 wpabuf_free(prev->msg); 00360 os_free(prev); 00361 } 00362 } 00363 00364 00365 int wps_attr_text(struct wpabuf *data, char *buf, char *end) 00366 { 00367 struct wps_parse_attr attr; 00368 char *pos = buf; 00369 int ret; 00370 00371 if (wps_parse_msg(data, &attr) < 0) 00372 return -1; 00373 00374 if (attr.wps_state) { 00375 if (*attr.wps_state == WPS_STATE_NOT_CONFIGURED) 00376 ret = os_snprintf(pos, end - pos, 00377 "wps_state=unconfigured\n"); 00378 else if (*attr.wps_state == WPS_STATE_CONFIGURED) 00379 ret = os_snprintf(pos, end - pos, 00380 "wps_state=configured\n"); 00381 else 00382 ret = 0; 00383 if (ret < 0 || ret >= end - pos) 00384 return pos - buf; 00385 pos += ret; 00386 } 00387 00388 if (attr.ap_setup_locked && *attr.ap_setup_locked) { 00389 ret = os_snprintf(pos, end - pos, 00390 "wps_ap_setup_locked=1\n"); 00391 if (ret < 0 || ret >= end - pos) 00392 return pos - buf; 00393 pos += ret; 00394 } 00395 00396 if (attr.selected_registrar && *attr.selected_registrar) { 00397 ret = os_snprintf(pos, end - pos, 00398 "wps_selected_registrar=1\n"); 00399 if (ret < 0 || ret >= end - pos) 00400 return pos - buf; 00401 pos += ret; 00402 } 00403 00404 if (attr.dev_password_id) { 00405 ret = os_snprintf(pos, end - pos, 00406 "wps_device_password_id=%u\n", 00407 WPA_GET_BE16(attr.dev_password_id)); 00408 if (ret < 0 || ret >= end - pos) 00409 return pos - buf; 00410 pos += ret; 00411 } 00412 00413 if (attr.sel_reg_config_methods) { 00414 ret = os_snprintf(pos, end - pos, 00415 "wps_selected_registrar_config_methods=" 00416 "0x%04x\n", 00417 WPA_GET_BE16(attr.sel_reg_config_methods)); 00418 if (ret < 0 || ret >= end - pos) 00419 return pos - buf; 00420 pos += ret; 00421 } 00422 00423 if (attr.primary_dev_type) { 00424 char devtype[WPS_DEV_TYPE_BUFSIZE]; 00425 ret = os_snprintf(pos, end - pos, 00426 "wps_primary_device_type=%s\n", 00427 wps_dev_type_bin2str(attr.primary_dev_type, 00428 devtype, 00429 sizeof(devtype))); 00430 if (ret < 0 || ret >= end - pos) 00431 return pos - buf; 00432 pos += ret; 00433 } 00434 00435 if (attr.dev_name) { 00436 char *str = os_malloc(attr.dev_name_len + 1); 00437 size_t i; 00438 if (str == NULL) 00439 return pos - buf; 00440 for (i = 0; i < attr.dev_name_len; i++) { 00441 if (attr.dev_name[i] < 32) 00442 str[i] = '_'; 00443 else 00444 str[i] = attr.dev_name[i]; 00445 } 00446 str[i] = '\0'; 00447 ret = os_snprintf(pos, end - pos, "wps_device_name=%s\n", str); 00448 os_free(str); 00449 if (ret < 0 || ret >= end - pos) 00450 return pos - buf; 00451 pos += ret; 00452 } 00453 00454 if (attr.config_methods) { 00455 ret = os_snprintf(pos, end - pos, 00456 "wps_config_methods=0x%04x\n", 00457 WPA_GET_BE16(attr.config_methods)); 00458 if (ret < 0 || ret >= end - pos) 00459 return pos - buf; 00460 pos += ret; 00461 } 00462 00463 return pos - buf; 00464 }