Пример #1
0
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;
}
Пример #2
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;
}
Пример #4
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);
}
Пример #5
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;
}
Пример #7
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;
}
Пример #8
0
/**
 * 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;
}
Пример #12
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;
}
Пример #13
0
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;
}
Пример #15
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;
}
Пример #17
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);
}
Пример #18
0
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;
}
Пример #19
0
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;
}
Пример #20
0
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;
}
Пример #22
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;
}
Пример #23
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;
}
Пример #24
0
/**
 * 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;
}
Пример #26
0
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;
}
Пример #27
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;
}
Пример #30
0
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;
	}
}