static int wps_parse_oob_cred(struct wps_context *wps, struct wpabuf *data) { struct wpabuf msg; struct wps_parse_attr attr; size_t i; if (wps_parse_msg(data, &attr) < 0 || attr.num_cred <= 0) { wpa_printf(MSG_ERROR, "WPS: OOB credential not found"); return -1; } for (i = 0; i < attr.num_cred; i++) { struct wps_credential local_cred; struct wps_parse_attr cattr; os_memset(&local_cred, 0, sizeof(local_cred)); wpabuf_set(&msg, attr.cred[i], attr.cred_len[i]); if (wps_parse_msg(&msg, &cattr) < 0 || wps_process_cred(&cattr, &local_cred)) { wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB " "credential"); return -1; } wps->cred_cb(wps->cb_ctx, &local_cred); } return 0; }
/** * wps_get_uuid_e - Get UUID-E from WPS IE * @msg: WPS IE contents from Beacon or Probe Response frame * Returns: Pointer to UUID-E or %NULL if not included * * The returned pointer is to the msg contents and it remains valid only as * long as the msg buffer is valid. */ const u8 * wps_get_uuid_e(const struct wpabuf *msg) { struct wps_parse_attr attr; if (wps_parse_msg(msg, &attr) < 0) return NULL; return attr.uuid_e; }
int wps_validate_m8(const struct wpabuf *tlvs) { struct wps_parse_attr attr; int wps2; if (tlvs == NULL) { wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M8"); return -1; } if (wps_parse_msg(tlvs, &attr) < 0) { wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " "in M8"); return -1; } wps2 = attr.version2 != NULL; if (wps_validate_version(attr.version, 1) || wps_validate_msg_type(attr.msg_type, 1) || wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) || wps_validate_encr_settings(attr.encr_settings, attr.encr_settings_len, 1) || wps_validate_version2(attr.version2, wps2) || wps_validate_authenticator(attr.authenticator, 1)) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M8"); #ifdef WPS_STRICT_WPS2 if (wps2) return -1; #else /* WPS_STRICT_WPS2 */ return -1; #endif /* WPS_STRICT_WPS2 */ } return 0; }
static void wps_er_process_wlanevent_probe_req(struct wps_er_ap *ap, const u8 *addr, struct wpabuf *msg) { struct wps_parse_attr attr; wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - Probe Request - from " MACSTR, MAC2STR(addr)); wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message " "(TLVs from Probe Request)", msg); if (wps_validate_probe_req(msg, addr) < 0) { wpa_printf(MSG_INFO, "WPS-STRICT: ER: Ignore invalid proxied " "Probe Request frame from " MACSTR, MAC2STR(addr)); return; } if (wps_parse_msg(msg, &attr) < 0) { wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in " "WLANEvent message"); return; } wps_er_add_sta_data(ap, addr, &attr, 1); wps_registrar_probe_req_rx(ap->er->wps->registrar, addr, msg, 0); }
static int wps_process_cred_e(struct wps_data *wps, const u8 *cred, size_t cred_len, int wps2) { struct wps_parse_attr attr; struct wpabuf msg; wpa_printf(MSG_DEBUG, "WPS: Received Credential"); os_memset(&wps->cred, 0, sizeof(wps->cred)); wpabuf_set(&msg, cred, cred_len); if (wps_parse_msg(&msg, &attr) < 0 || wps_process_cred(&attr, &wps->cred)) return -1; if (os_memcmp(wps->cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: MAC Address in the Credential (" MACSTR ") does not match with own address (" MACSTR ")", MAC2STR(wps->cred.mac_addr), MAC2STR(wps->wps->dev.mac_addr)); /* * In theory, this could be consider fatal error, but there are * number of deployed implementations using other address here * due to unclarity in the specification. For interoperability * reasons, allow this to be processed since we do not really * use the MAC Address information for anything. */ #ifdef CONFIG_WPS_STRICT if (wps2) { wpa_printf(MSG_INFO, "WPS: Do not accept incorrect " "MAC Address in AP Settings"); return -1; } #endif /* CONFIG_WPS_STRICT */ } #ifdef CONFIG_WPS2 if (!(wps->cred.encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP | WPS_ENCR_AES))) { if (wps->cred.encr_type & WPS_ENCR_WEP) { wpa_printf(MSG_INFO, "WPS: Reject Credential " "due to WEP configuration"); return -2; } wpa_printf(MSG_INFO, "WPS: Reject Credential due to " "invalid encr_type 0x%x", wps->cred.encr_type); return -1; } #endif /* CONFIG_WPS2 */ if (wps->wps->cred_cb) { wps->cred.cred_attr = cred - 4; wps->cred.cred_attr_len = cred_len + 4; wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred); wps->cred.cred_attr = NULL; wps->cred.cred_attr_len = 0; } return 0; }
static int wps_validate_cred(const u8 *cred, size_t len) { struct wps_parse_attr attr; struct wpabuf buf; if (cred == NULL) return -1; wpabuf_set(&buf, cred, len); if (wps_parse_msg(&buf, &attr) < 0) { wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse Credential"); return -1; } if (wps_validate_network_idx(attr.network_idx, 1) || wps_validate_ssid(attr.ssid, attr.ssid_len, 1) || wps_validate_auth_type(attr.auth_type, 1) || wps_validate_encr_type(attr.encr_type, 1) || wps_validate_network_key_index(attr.network_key_idx, 0) || wps_validate_network_key(attr.network_key, attr.network_key_len, attr.encr_type, 1) || wps_validate_mac_addr(attr.mac_addr, 1) || wps_validate_network_key_shareable(attr.network_key_shareable, 0)) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Credential"); return -1; } return 0; }
/** * wps_init - Initialize WPS Registration protocol data * @cfg: WPS configuration * Returns: Pointer to allocated data or %NULL on failure * * This function is used to initialize WPS data for a registration protocol * instance (i.e., each run of registration protocol as a Registrar of * Enrollee. The caller is responsible for freeing this data after the * registration run has been completed by calling wps_deinit(). */ struct wps_data * wps_init(const struct wps_config *cfg) { struct wps_data *data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; data->wps = cfg->wps; data->registrar = cfg->registrar; if (cfg->registrar) { os_memcpy(data->uuid_r, cfg->wps->uuid, WPS_UUID_LEN); } else { os_memcpy(data->mac_addr_e, cfg->wps->dev.mac_addr, ETH_ALEN); os_memcpy(data->uuid_e, cfg->wps->uuid, WPS_UUID_LEN); } if (cfg->pin) { data->dev_pw_id = DEV_PW_DEFAULT; data->dev_password = os_malloc(cfg->pin_len); if (data->dev_password == NULL) { os_free(data); return NULL; } os_memcpy(data->dev_password, cfg->pin, cfg->pin_len); data->dev_password_len = cfg->pin_len; } data->pbc = cfg->pbc; if (cfg->pbc) { /* Use special PIN '00000000' for PBC */ data->dev_pw_id = DEV_PW_PUSHBUTTON; os_free(data->dev_password); data->dev_password = os_malloc(8); if (data->dev_password == NULL) { os_free(data); return NULL; } os_memset(data->dev_password, '0', 8); data->dev_password_len = 8; } data->state = data->registrar ? RECV_M1 : SEND_M1; if (cfg->assoc_wps_ie) { struct wps_parse_attr attr; wpa_hexdump_buf(MSG_DEBUG, "WPS: WPS IE from (Re)AssocReq", cfg->assoc_wps_ie); if (wps_parse_msg(cfg->assoc_wps_ie, &attr) < 0) { wpa_printf(MSG_DEBUG, "WPS: Failed to parse WPS IE " "from (Re)AssocReq"); } else if (attr.request_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Request Type attribute " "in (Re)AssocReq WPS IE"); } else { wpa_printf(MSG_DEBUG, "WPS: Request Type (from WPS IE " "in (Re)AssocReq WPS IE): %d", *attr.request_type); data->request_type = *attr.request_type; } } return data; }
/** * wps_is_addr_authorized - Check whether WPS IE authorizes MAC address * @msg: WPS IE contents from Beacon or Probe Response frame * @addr: MAC address to search for * @ver1_compat: Whether to use version 1 compatibility mode * Returns: 2 if the specified address is explicit authorized, 1 if address is * authorized (broadcast), 0 if not */ int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr, int ver1_compat) { struct wps_parse_attr attr; unsigned int i; const u8 *pos; const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; if (wps_parse_msg(msg, &attr) < 0) return 0; if (!attr.version2 && ver1_compat) { /* * Version 1.0 AP - AuthorizedMACs not used, so revert back to * old mechanism of using SelectedRegistrar. */ return is_selected_pin_registrar(&attr); } if (!attr.authorized_macs) return 0; pos = attr.authorized_macs; for (i = 0; i < attr.authorized_macs_len / ETH_ALEN; i++) { if (os_memcmp(pos, addr, ETH_ALEN) == 0) return 2; if (os_memcmp(pos, bcast, ETH_ALEN) == 0) return 1; pos += ETH_ALEN; } return 0; }
int wps_validate_m8_encr(const struct wpabuf *tlvs, int ap, int wps2) { struct wps_parse_attr attr; if (tlvs == NULL) { wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M8 encrypted " "settings"); return -1; } if (wps_parse_msg(tlvs, &attr) < 0) { wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " "in M8 encrypted settings"); return -1; } if (wps_validate_ssid(attr.ssid, attr.ssid_len, ap) || wps_validate_auth_type(attr.auth_type, ap) || wps_validate_encr_type(attr.encr_type, ap) || wps_validate_network_key_index(attr.network_key_idx, 0) || wps_validate_mac_addr(attr.mac_addr, ap) || wps_validate_credential(attr.cred, attr.cred_len, attr.num_cred, !ap) || wps_validate_key_wrap_auth(attr.key_wrap_auth, 1)) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M8 encrypted " "settings"); #ifdef WPS_STRICT_WPS2 if (wps2) return -1; #else /* WPS_STRICT_WPS2 */ return -1; #endif /* WPS_STRICT_WPS2 */ } return 0; }
int wps_validate_assoc_resp(const struct wpabuf *wps_ie) { struct wps_parse_attr attr; int wps2; if (wps_ie == NULL) { wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in " "(Re)Association Response frame"); return -1; } if (wps_parse_msg(wps_ie, &attr) < 0) { wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in " "(Re)Association Response frame"); return -1; } wps2 = attr.version2 != NULL; if (wps_validate_version(attr.version, 1) || wps_validate_response_type(attr.response_type, 1) || wps_validate_version2(attr.version2, wps2)) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid (Re)Association " "Response frame"); return -1; } return 0; }
int wps_validate_m6_encr(const struct wpabuf *tlvs, int wps2) { struct wps_parse_attr attr; if (tlvs == NULL) { wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M6 encrypted " "settings"); return -1; } if (wps_parse_msg(tlvs, &attr) < 0) { wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " "in M6 encrypted settings"); return -1; } if (wps_validate_r_snonce2(attr.r_snonce2, 1) || wps_validate_key_wrap_auth(attr.key_wrap_auth, 1)) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M6 encrypted " "settings"); #ifdef WPS_STRICT_WPS2 if (wps2) return -1; #else /* WPS_STRICT_WPS2 */ return -1; #endif /* WPS_STRICT_WPS2 */ } return 0; }
/** * wps_is_selected_pbc_registrar - Check whether WPS IE indicates active PBC * @msg: WPS IE contents from Beacon or Probe Response frame * Returns: 1 if PBC Registrar is active, 0 if not */ int wps_is_selected_pbc_registrar(const struct wpabuf *msg) { struct wps_parse_attr attr; /* * In theory, this could also verify that attr.sel_reg_config_methods * includes WPS_CONFIG_PUSHBUTTON, but some deployed AP implementations * do not set Selected Registrar Config Methods attribute properly, so * it is safer to just use Device Password ID here. */ if (wps_parse_msg(msg, &attr) < 0 || !attr.selected_registrar || *attr.selected_registrar == 0 || !attr.dev_password_id || WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON) return 0; #ifdef CONFIG_WPS_STRICT if (!attr.sel_reg_config_methods || !(WPA_GET_BE16(attr.sel_reg_config_methods) & WPS_CONFIG_PUSHBUTTON)) return 0; #endif /* CONFIG_WPS_STRICT */ return 1; }
static int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg) { struct wps_parse_attr attr; wpa_printf(MSG_DEBUG, "P2P: Parsing WPS IE"); if (wps_parse_msg(buf, &attr)) return -1; if (attr.dev_name && attr.dev_name_len < sizeof(msg->device_name) && !msg->device_name[0]) os_memcpy(msg->device_name, attr.dev_name, attr.dev_name_len); if (attr.config_methods) { msg->wps_config_methods = WPA_GET_BE16(attr.config_methods); wpa_printf(MSG_DEBUG, "P2P: Config Methods (WPS): 0x%x", msg->wps_config_methods); } if (attr.dev_password_id) { msg->dev_password_id = WPA_GET_BE16(attr.dev_password_id); wpa_printf(MSG_DEBUG, "P2P: Device Password ID: %d", msg->dev_password_id); } if (attr.primary_dev_type) { char devtype[WPS_DEV_TYPE_BUFSIZE]; msg->wps_pri_dev_type = attr.primary_dev_type; wpa_printf(MSG_DEBUG, "P2P: Primary Device Type (WPS): %s", wps_dev_type_bin2str(msg->wps_pri_dev_type, devtype, sizeof(devtype))); } return 0; }
int wps_validate_wsc_done(const struct wpabuf *tlvs) { struct wps_parse_attr attr; int wps2; if (tlvs == NULL) { wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in WSC_Done"); return -1; } if (wps_parse_msg(tlvs, &attr) < 0) { wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " "in WSC_Done"); return -1; } wps2 = attr.version2 != NULL; if (wps_validate_version(attr.version, 1) || wps_validate_msg_type(attr.msg_type, 1) || wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) || wps_validate_registrar_nonce(attr.registrar_nonce, 1) || wps_validate_version2(attr.version2, wps2)) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC_Done"); #ifdef WPS_STRICT_WPS2 if (wps2) return -1; #else /* WPS_STRICT_WPS2 */ return -1; #endif /* WPS_STRICT_WPS2 */ } return 0; }
/** * wps_is_20 - Check whether WPS attributes claim support for WPS 2.0 */ int wps_is_20(const struct wpabuf *msg) { struct wps_parse_attr attr; if (msg == NULL || wps_parse_msg(msg, &attr) < 0) return 0; return attr.version2 != NULL; }
int wps_validate_beacon_probe_resp(const struct wpabuf *wps_ie, int probe, const u8 *addr) { struct wps_parse_attr attr; int wps2, sel_reg; if (wps_ie == NULL) { wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in " "%sProbe Response frame", probe ? "" : "Beacon/"); return -1; } if (wps_parse_msg(wps_ie, &attr) < 0) { wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in " "%sProbe Response frame", probe ? "" : "Beacon/"); return -1; } wps2 = attr.version2 != NULL; sel_reg = attr.selected_registrar != NULL && *attr.selected_registrar != 0; if (wps_validate_version(attr.version, 1) || wps_validate_wps_state(attr.wps_state, 1) || wps_validate_ap_setup_locked(attr.ap_setup_locked, 0) || wps_validate_selected_registrar(attr.selected_registrar, 0) || wps_validate_dev_password_id(attr.dev_password_id, sel_reg) || wps_validate_sel_reg_config_methods(attr.sel_reg_config_methods, wps2, sel_reg) || wps_validate_response_type(attr.response_type, probe) || wps_validate_uuid_e(attr.uuid_e, probe) || wps_validate_manufacturer(attr.manufacturer, attr.manufacturer_len, probe) || wps_validate_model_name(attr.model_name, attr.model_name_len, probe) || wps_validate_model_number(attr.model_number, attr.model_number_len, probe) || wps_validate_serial_number(attr.serial_number, attr.serial_number_len, probe) || wps_validate_primary_dev_type(attr.primary_dev_type, probe) || wps_validate_dev_name(attr.dev_name, attr.dev_name_len, probe) || wps_validate_ap_config_methods(attr.config_methods, wps2, probe) || wps_validate_rf_bands(attr.rf_bands, 0) || wps_validate_version2(attr.version2, wps2) || wps_validate_authorized_macs(attr.authorized_macs, attr.authorized_macs_len, 0)) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid %sProbe Response " "frame from " MACSTR, probe ? "" : "Beacon/", MAC2STR(addr)); #ifdef WPS_STRICT_WPS2 if (wps2) return -1; #else /* WPS_STRICT_WPS2 */ return -1; #endif /* WPS_STRICT_WPS2 */ } return 0; }
/** * wps_is_selected_pin_registrar - Check whether WPS IE indicates active PIN * @msg: WPS IE contents from Beacon or Probe Response frame * Returns: 1 if PIN Registrar is active, 0 if not */ int wps_is_selected_pin_registrar(const struct wpabuf *msg) { struct wps_parse_attr attr; if (wps_parse_msg(msg, &attr) < 0) return 0; return is_selected_pin_registrar(&attr); }
static enum http_reply_code web_process_put_wlan_response(struct upnp_wps_device_sm *sm, char *data, struct wpabuf **reply, const char **replyname) { struct wpabuf *msg; enum http_reply_code ret; u8 macaddr[ETH_ALEN]; int ev_type; int type; char *val; /* * External UPnP-based Registrar is passing us a message to be proxied * over to a Wi-Fi -based client of ours. */ wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse"); msg = xml_get_base64_item(data, "NewMessage", &ret); if (msg == NULL) return ret; val = xml_get_first_item(data, "NewWLANEventType"); if (val == NULL) { wpabuf_free(msg); return UPNP_ARG_VALUE_INVALID; } ev_type = atol(val); os_free(val); val = xml_get_first_item(data, "NewWLANEventMAC"); if (val == NULL || hwaddr_aton(val, macaddr)) { wpabuf_free(msg); os_free(val); return UPNP_ARG_VALUE_INVALID; } os_free(val); if (ev_type == UPNP_WPS_WLANEVENT_TYPE_EAP) { struct wps_parse_attr attr; if (wps_parse_msg(msg, &attr) < 0 || attr.msg_type == NULL) type = -1; else type = *attr.msg_type; wpa_printf(MSG_DEBUG, "WPS UPnP: Message Type %d", type); } else type = -1; if (!sm->ctx->rx_req_put_wlan_response || sm->ctx->rx_req_put_wlan_response(sm->priv, ev_type, macaddr, msg, type)) { wpa_printf(MSG_INFO, "WPS UPnP: Fail: sm->ctx->" "rx_req_put_wlan_response"); wpabuf_free(msg); return HTTP_INTERNAL_SERVER_ERROR; } wpabuf_free(msg); *replyname = NULL; *reply = NULL; return HTTP_OK; }
static enum wps_process_res wps_process_m6(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { struct wpabuf *decrypted; struct wps_parse_attr eattr; wpa_printf(MSG_DEBUG, "WPS: Received M6"); if (wps->state != RECV_M6) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M6", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || wps_process_authenticator(wps, attr->authenticator, msg)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_validate_m6_encr(decrypted, attr->version2 != NULL) < 0) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, &eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || wps_process_r_snonce2(wps, eattr.r_snonce2)) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpabuf_free(decrypted); if (wps->wps->ap) wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_AP_PIN_SUCCESS, NULL); wps->state = SEND_M7; return WPS_CONTINUE; }
static enum wps_process_res wps_process_m8(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { struct wpabuf *decrypted; struct wps_parse_attr eattr; wpa_printf(MSG_DEBUG, "WPS: Received M8"); if (wps->state != RECV_M8) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M8", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || wps_process_authenticator(wps, attr->authenticator, msg)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_validate_m8_encr(decrypted, wps->wps->ap, attr->version2 != 0) < 0) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, &eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || wps_process_creds(wps, eattr.cred, eattr.cred_len, eattr.num_cred, attr->version2 != NULL) || wps_process_ap_settings_e(wps, &eattr, decrypted, attr->version2 != NULL)) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpabuf_free(decrypted); wps->state = WPS_MSG_DONE; return WPS_CONTINUE; }
int wps_validate_m1(const struct wpabuf *tlvs) { struct wps_parse_attr attr; int wps2; if (tlvs == NULL) { wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M1"); return -1; } if (wps_parse_msg(tlvs, &attr) < 0) { wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " "in M1"); return -1; } wps2 = attr.version2 != NULL; if (wps_validate_version(attr.version, 1) || wps_validate_msg_type(attr.msg_type, 1) || wps_validate_uuid_e(attr.uuid_e, 1) || wps_validate_mac_addr(attr.mac_addr, 1) || wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) || wps_validate_public_key(attr.public_key, attr.public_key_len, 1) || wps_validate_auth_type_flags(attr.auth_type_flags, 1) || wps_validate_encr_type_flags(attr.encr_type_flags, 1) || wps_validate_conn_type_flags(attr.conn_type_flags, 1) || wps_validate_config_methods(attr.config_methods, wps2, 1) || wps_validate_wps_state(attr.wps_state, 1) || wps_validate_manufacturer(attr.manufacturer, attr.manufacturer_len, 1) || wps_validate_model_name(attr.model_name, attr.model_name_len, 1) || wps_validate_model_number(attr.model_number, attr.model_number_len, 1) || wps_validate_serial_number(attr.serial_number, attr.serial_number_len, 1) || wps_validate_primary_dev_type(attr.primary_dev_type, 1) || wps_validate_dev_name(attr.dev_name, attr.dev_name_len, 1) || wps_validate_rf_bands(attr.rf_bands, 1) || wps_validate_assoc_state(attr.assoc_state, 1) || wps_validate_dev_password_id(attr.dev_password_id, 1) || wps_validate_config_error(attr.config_error, 1) || wps_validate_os_version(attr.os_version, 1) || wps_validate_version2(attr.version2, wps2) || wps_validate_request_to_enroll(attr.request_to_enroll, 0)) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M1"); #ifdef WPS_STRICT_WPS2 if (wps2) return -1; #else /* WPS_STRICT_WPS2 */ return -1; #endif /* WPS_STRICT_WPS2 */ } return 0; }
static int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg) { struct wps_parse_attr attr; int i; wpa_printf(MSG_DEBUG, "P2P: Parsing WPS IE"); if (wps_parse_msg(buf, &attr)) return -1; if (attr.dev_name && attr.dev_name_len < sizeof(msg->device_name) && !msg->device_name[0]) os_memcpy(msg->device_name, attr.dev_name, attr.dev_name_len); if (attr.config_methods) { msg->wps_config_methods = WPA_GET_BE16(attr.config_methods); wpa_printf(MSG_DEBUG, "P2P: Config Methods (WPS): 0x%x", msg->wps_config_methods); } if (attr.dev_password_id) { msg->dev_password_id = WPA_GET_BE16(attr.dev_password_id); wpa_printf(MSG_DEBUG, "P2P: Device Password ID: %d", msg->dev_password_id); msg->dev_password_id_present = 1; } if (attr.primary_dev_type) { char devtype[WPS_DEV_TYPE_BUFSIZE]; msg->wps_pri_dev_type = attr.primary_dev_type; wpa_printf(MSG_DEBUG, "P2P: Primary Device Type (WPS): %s", wps_dev_type_bin2str(msg->wps_pri_dev_type, devtype, sizeof(devtype))); } if (attr.sec_dev_type_list) { msg->wps_sec_dev_type_list = attr.sec_dev_type_list; msg->wps_sec_dev_type_list_len = attr.sec_dev_type_list_len; } for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { msg->wps_vendor_ext[i] = attr.vendor_ext[i]; msg->wps_vendor_ext_len[i] = attr.vendor_ext_len[i]; } msg->manufacturer = attr.manufacturer; msg->manufacturer_len = attr.manufacturer_len; msg->model_name = attr.model_name; msg->model_name_len = attr.model_name_len; msg->model_number = attr.model_number; msg->model_number_len = attr.model_number_len; msg->serial_number = attr.serial_number; msg->serial_number_len = attr.serial_number_len; msg->oob_dev_password = attr.oob_dev_password; msg->oob_dev_password_len = attr.oob_dev_password_len; return 0; }
static enum wps_process_res wps_process_m4(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { struct wpabuf *decrypted; struct wps_parse_attr eattr; wpa_printf(MSG_DEBUG, "WPS: Received M4"); if (wps->state != RECV_M4) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M4", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || wps_process_authenticator(wps, attr->authenticator, msg) || wps_process_r_hash1(wps, attr->r_hash1) || wps_process_r_hash2(wps, attr->r_hash2)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_validate_m4_encr(decrypted, attr->version2 != NULL) < 0) { wpabuf_clear_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, &eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || wps_process_r_snonce1(wps, eattr.r_snonce1)) { wpabuf_clear_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpabuf_clear_free(decrypted); wps->state = SEND_M5; return WPS_CONTINUE; }
/** * wps_ap_priority_compar - Prioritize WPS IE from two APs * @wps_a: WPS IE contents from Beacon or Probe Response frame * @wps_b: WPS IE contents from Beacon or Probe Response frame * Returns: 1 if wps_b is considered more likely selection for WPS * provisioning, -1 if wps_a is considered more like, or 0 if no preference */ int wps_ap_priority_compar(const struct wpabuf *wps_a, const struct wpabuf *wps_b) { struct wps_parse_attr attr_a, attr_b; int sel_a, sel_b; if (wps_a == NULL || wps_parse_msg(wps_a, &attr_a) < 0) return 1; if (wps_b == NULL || wps_parse_msg(wps_b, &attr_b) < 0) return -1; sel_a = attr_a.selected_registrar && *attr_a.selected_registrar != 0; sel_b = attr_b.selected_registrar && *attr_b.selected_registrar != 0; if (sel_a && !sel_b) return -1; if (!sel_a && sel_b) return 1; return 0; }
static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK"); if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", attr.version ? *attr.version : 0); return WPS_FAILURE; } if (attr.msg_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_WSC_ACK) { wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", *attr.msg_type); return WPS_FAILURE; } if (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0)) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); return WPS_FAILURE; } if (wps->state == RECV_ACK && wps->wps->ap) { wpa_printf(MSG_DEBUG, "WPS: External Registrar registration " "completed successfully"); wps_success_event(wps->wps); wps->state = WPS_FINISHED; return WPS_DONE; } return WPS_FAILURE; }
int upnp_er_set_selected_registrar(struct wps_registrar *reg, struct subscription *s, const struct wpabuf *msg) { struct wps_parse_attr attr; wpa_hexdump_buf(MSG_MSGDUMP, "WPS: SetSelectedRegistrar attributes", msg); if (wps_validate_upnp_set_selected_registrar(msg) < 0) return -1; if (wps_parse_msg(msg, &attr) < 0) return -1; s->reg = reg; eloop_cancel_timeout(upnp_er_set_selected_timeout, s, NULL); os_memset(s->authorized_macs, 0, sizeof(s->authorized_macs)); if (attr.selected_registrar == NULL || *attr.selected_registrar == 0) { wpa_printf(MSG_DEBUG, "WPS: SetSelectedRegistrar: Disable " "Selected Registrar"); s->selected_registrar = 0; } else { s->selected_registrar = 1; s->dev_password_id = attr.dev_password_id ? WPA_GET_BE16(attr.dev_password_id) : DEV_PW_DEFAULT; s->config_methods = attr.sel_reg_config_methods ? WPA_GET_BE16(attr.sel_reg_config_methods) : -1; if (attr.authorized_macs) { int count = attr.authorized_macs_len / ETH_ALEN; if (count > WPS_MAX_AUTHORIZED_MACS) count = WPS_MAX_AUTHORIZED_MACS; os_memcpy(s->authorized_macs, attr.authorized_macs, count * ETH_ALEN); } else if (!attr.version2) { #ifdef CONFIG_WPS2 wpa_printf(MSG_DEBUG, "WPS: Add broadcast " "AuthorizedMACs for WPS 1.0 ER"); os_memset(s->authorized_macs, 0xff, ETH_ALEN); #endif /* CONFIG_WPS2 */ } eloop_register_timeout(WPS_PBC_WALK_TIME, 0, upnp_er_set_selected_timeout, s, NULL); } wps_registrar_selected_registrar_changed(reg); return 0; }
static void wps_er_ap_get_m1(struct wps_er_ap *ap, struct wpabuf *m1) { struct wps_parse_attr attr; if (wps_parse_msg(m1, &attr) < 0) { wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse M1"); return; } if (attr.primary_dev_type) os_memcpy(ap->pri_dev_type, attr.primary_dev_type, 8); if (attr.wps_state) ap->wps_state = *attr.wps_state; if (attr.mac_addr) os_memcpy(ap->mac_addr, attr.mac_addr, ETH_ALEN); wps_er_subscribe(ap); }
int wps_validate_probe_req(const struct wpabuf *wps_ie, const u8 *addr) { struct wps_parse_attr attr; int wps2; if (wps_ie == NULL) { wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in " "Probe Request frame"); return -1; } if (wps_parse_msg(wps_ie, &attr) < 0) { wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in " "Probe Request frame"); return -1; } wps2 = attr.version2 != NULL; if (wps_validate_version(attr.version, 1) || wps_validate_request_type(attr.request_type, 1) || wps_validate_config_methods(attr.config_methods, wps2, 1) || wps_validate_uuid_e(attr.uuid_e, attr.uuid_r == NULL) || wps_validate_uuid_r(attr.uuid_r, attr.uuid_e == NULL) || wps_validate_primary_dev_type(attr.primary_dev_type, 1) || wps_validate_rf_bands(attr.rf_bands, 1) || wps_validate_assoc_state(attr.assoc_state, 1) || wps_validate_config_error(attr.config_error, 1) || wps_validate_dev_password_id(attr.dev_password_id, 1) || wps_validate_version2(attr.version2, wps2) || wps_validate_manufacturer(attr.manufacturer, attr.manufacturer_len, wps2) || wps_validate_model_name(attr.model_name, attr.model_name_len, wps2) || wps_validate_model_number(attr.model_number, attr.model_number_len, wps2) || wps_validate_dev_name(attr.dev_name, attr.dev_name_len, wps2) || wps_validate_request_to_enroll(attr.request_to_enroll, 0) || wps_validate_req_dev_type(attr.req_dev_type, attr.num_req_dev_type, 0)) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Probe Request " "frame from " MACSTR, MAC2STR(addr)); return -1; } return 0; }
static int hostapd_wps_nfc_tag_process(struct hostapd_data *hapd, const struct wpabuf *wps) { struct wps_parse_attr attr; wpa_hexdump_buf(MSG_DEBUG, "WPS: Received NFC tag payload", wps); if (wps_parse_msg(wps, &attr)) { wpa_printf(MSG_DEBUG, "WPS: Ignore invalid data from NFC tag"); return -1; } if (attr.oob_dev_password) return hostapd_wps_add_nfc_password_token(hapd, &attr); wpa_printf(MSG_DEBUG, "WPS: Ignore unrecognized NFC tag"); return -1; }
static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg) { enum wps_process_res res; struct wps_parse_attr attr; enum wsc_op_code op_code; op_code = WSC_MSG; if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) { switch (*attr.msg_type) { case WPS_WSC_ACK: op_code = WSC_ACK; break; case WPS_WSC_NACK: op_code = WSC_NACK; break; case WPS_WSC_DONE: op_code = WSC_Done; break; } } res = wps_process_msg(ap->wps, op_code, msg); if (res == WPS_CONTINUE) { struct wpabuf *next = wps_get_msg(ap->wps, &op_code); if (next) { wps_er_ap_put_message(ap, next); wpabuf_free(next); } else { wpa_printf(MSG_DEBUG, "WPS ER: Failed to build " "message"); wps_deinit(ap->wps); ap->wps = NULL; } } else if (res == WPS_DONE) { wpa_printf(MSG_DEBUG, "WPS ER: Protocol run done"); wps_deinit(ap->wps); ap->wps = NULL; } else { wpa_printf(MSG_DEBUG, "WPS ER: Failed to process message from " "AP (res=%d)", res); wps_deinit(ap->wps); ap->wps = NULL; } }