Example #1
0
static void eapol_test_set_anon_id(void *ctx, const u8 *id, size_t len)
{
	struct eapol_test_data *e = ctx;
	struct wpa_supplicant *wpa_s = e->wpa_s;
	char *str;
	int res;

	wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity",
			  id, len);

	if (wpa_s->current_ssid == NULL)
		return;

	if (id == NULL) {
		if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
				   "NULL", 0) < 0)
			return;
	} else {
		str = os_malloc(len * 2 + 1);
		if (str == NULL)
			return;
		wpa_snprintf_hex(str, len * 2 + 1, id, len);
		res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
				     str, 0);
		os_free(str);
		if (res < 0)
			return;
	}
}
Example #2
0
static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s,
					      int registrar, const u8 *bssid)
{
	struct wpa_ssid *ssid;

	ssid = wpa_config_add_network(wpa_s->conf);
	if (ssid == NULL)
		return NULL;
	wpas_notify_network_added(wpa_s, ssid);
	wpa_config_set_network_defaults(ssid);
	if (wpa_config_set(ssid, "key_mgmt", "WPS", 0) < 0 ||
	    wpa_config_set(ssid, "eap", "WSC", 0) < 0 ||
	    wpa_config_set(ssid, "identity", registrar ?
			   "\"" WSC_ID_REGISTRAR "\"" :
			   "\"" WSC_ID_ENROLLEE "\"", 0) < 0) {
		wpas_notify_network_removed(wpa_s, ssid);
		wpa_config_remove_network(wpa_s->conf, ssid->id);
		return NULL;
	}

	if (bssid) {
		struct wpa_bss *bss;
		int count = 0;

		os_memcpy(ssid->bssid, bssid, ETH_ALEN);
		ssid->bssid_set = 1;

		dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
			if (os_memcmp(bssid, bss->bssid, ETH_ALEN) != 0)
				continue;

			os_free(ssid->ssid);
			ssid->ssid = os_malloc(bss->ssid_len);
			if (ssid->ssid == NULL)
				break;
			os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
			ssid->ssid_len = bss->ssid_len;
			wpa_hexdump_ascii(MSG_DEBUG, "WPS: Picked SSID from "
					  "scan results",
					  ssid->ssid, ssid->ssid_len);
			count++;
		}

		if (count > 1) {
			wpa_printf(MSG_DEBUG, "WPS: More than one SSID found "
				   "for the AP; use wildcard");
			os_free(ssid->ssid);
			ssid->ssid = NULL;
			ssid->ssid_len = 0;
		}
	}

	return ssid;
}
Example #3
0
static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s,
					      int registrar, const u8 *bssid)
{
	struct wpa_ssid *ssid;

	ssid = wpa_config_add_network(wpa_s->conf);
	if (ssid == NULL)
		return NULL;
	wpa_config_set_network_defaults(ssid);
	if (wpa_config_set(ssid, "key_mgmt", "WPS", 0) < 0 ||
	    wpa_config_set(ssid, "eap", "WSC", 0) < 0 ||
	    wpa_config_set(ssid, "identity", registrar ?
			   "\"" WSC_ID_REGISTRAR "\"" :
			   "\"" WSC_ID_ENROLLEE "\"", 0) < 0) {
		wpa_config_remove_network(wpa_s->conf, ssid->id);
		return NULL;
	}

	if (bssid) {
		size_t i;
		struct wpa_scan_res *res;

		os_memcpy(ssid->bssid, bssid, ETH_ALEN);
		ssid->bssid_set = 1;

		/* Try to get SSID from scan results */
		if (wpa_s->scan_res == NULL &&
		    wpa_supplicant_get_scan_results(wpa_s) < 0)
			return ssid; /* Could not find any scan results */

		for (i = 0; i < wpa_s->scan_res->num; i++) {
			const u8 *ie;

			res = wpa_s->scan_res->res[i];
			if (os_memcmp(bssid, res->bssid, ETH_ALEN) != 0)
				continue;

			ie = wpa_scan_get_ie(res, WLAN_EID_SSID);
			if (ie == NULL)
				break;
			os_free(ssid->ssid);
			ssid->ssid = os_malloc(ie[1]);
			if (ssid->ssid == NULL)
				break;
			os_memcpy(ssid->ssid, ie + 2, ie[1]);
			ssid->ssid_len = ie[1];
			break;
		}
	}

	return ssid;
}
Example #4
0
int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
		       int p2p_group)
{
	struct wpa_ssid *ssid;
	wpas_clear_wps(wpa_s);
	ssid = wpas_wps_add_network(wpa_s, 0, bssid);
	if (ssid == NULL)
		return -1;
	ssid->temporary = 1;
	ssid->p2p_group = p2p_group;
#ifdef CONFIG_P2P
	if (p2p_group && wpa_s->go_params && wpa_s->go_params->ssid_len) {
		ssid->ssid = os_zalloc(wpa_s->go_params->ssid_len + 1);
		if (ssid->ssid) {
			ssid->ssid_len = wpa_s->go_params->ssid_len;
			os_memcpy(ssid->ssid, wpa_s->go_params->ssid,
				  ssid->ssid_len);
			wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP "
					  "SSID", ssid->ssid, ssid->ssid_len);
		}
	}
#endif /* CONFIG_P2P */
	wpa_config_set(ssid, "phase1", "\"pbc=1\"", 0);
	if (wpa_s->wps_fragment_size)
		ssid->eap.fragment_size = wpa_s->wps_fragment_size;
	eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
			       wpa_s, NULL);
	wpas_wps_reassoc(wpa_s, ssid, bssid);
	return 0;
}
Example #5
0
static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id)
{
	struct wpa_ssid *ssid;
	int errors = 0, end = 0;
	char buf[2000], *pos, *pos2;

	wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block",
		   *line);
	ssid = os_zalloc(sizeof(*ssid));
	if (ssid == NULL)
		return NULL;
	dl_list_init(&ssid->psk_list);
	ssid->id = id;

	wpa_config_set_network_defaults(ssid);

	while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) {
		if (os_strcmp(pos, "}") == 0) {
			end = 1;
			break;
		}

		pos2 = os_strchr(pos, '=');
		if (pos2 == NULL) {
			wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line "
				   "'%s'.", *line, pos);
			errors++;
			continue;
		}

		*pos2++ = '\0';
		if (*pos2 == '"') {
			if (os_strchr(pos2 + 1, '"') == NULL) {
				wpa_printf(MSG_ERROR, "Line %d: invalid "
					   "quotation '%s'.", *line, pos2);
				errors++;
				continue;
			}
		}

		if (wpa_config_set(ssid, pos, pos2, *line) < 0)
			errors++;
	}

	if (!end) {
		wpa_printf(MSG_ERROR, "Line %d: network block was not "
			   "terminated properly.", *line);
		errors++;
	}

	errors += wpa_config_validate_network(ssid, *line);

	if (errors) {
		wpa_config_free_ssid(ssid);
		ssid = NULL;
	}

	return ssid;
}
Example #6
0
static int wpa_supplicant_ctrl_iface_set_network(
	struct wpa_supplicant *wpa_s, char *cmd)
{
	int id;
	struct wpa_ssid *ssid;
	char *name, *value;

	/* cmd: "<network id> <variable name> <value>" */
	name = os_strchr(cmd, ' ');
	if (name == NULL)
		return -1;
	*name++ = '\0';

	value = os_strchr(name, ' ');
	if (value == NULL)
		return -1;
	*value++ = '\0';

	id = atoi(cmd);
	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
		   id, name);
	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
			      (u8 *) value, os_strlen(value));

	ssid = wpa_config_get_network(wpa_s->conf, id);
	if (ssid == NULL) {
		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
			   "id=%d", id);
		return -1;
	}

	if (wpa_config_set(ssid, name, value, 0) < 0) {
		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
			   "variable '%s'", name);
		return -1;
	} else {
		if (os_strcmp(name, "priority") == 0) {
			wpa_config_update_prio_list(wpa_s->conf);
		}
	}

	if (wpa_s->current_ssid == ssid) {
		/*
		 * Invalidate the EAP session cache if anything in the current
		 * configuration changes.
		 */
		eapol_sm_invalidate_cached_session(wpa_s->eapol);
	}

	if ((os_strcmp(name, "psk") == 0 &&
	     value[0] == '"' && ssid->ssid_len) ||
	    (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
		wpa_config_update_psk(ssid);

	return 0;
}
Example #7
0
int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid)
{
	struct wpa_ssid *ssid;
	wpas_clear_wps(wpa_s);
	ssid = wpas_wps_add_network(wpa_s, 0, bssid);
	if (ssid == NULL)
		return -1;
	wpa_config_set(ssid, "phase1", "\"pbc=1\"", 0);
	eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
			       wpa_s, NULL);
	wpas_wps_reassoc(wpa_s, ssid);
	return 0;
}
Example #8
0
static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len)
{
	struct wpa_supplicant *wpa_s = ctx;
	char *str;
	int res;

	wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity",
			  id, len);

	if (wpa_s->current_ssid == NULL)
		return;

	if (id == NULL) {
		if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
				   "NULL", 0) < 0)
			return;
	} else {
		str = os_malloc(len * 2 + 1);
		if (str == NULL)
			return;
		wpa_snprintf_hex(str, len * 2 + 1, id, len);
		res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
				     str, 0);
		os_free(str);
		if (res < 0)
			return;
	}

	if (wpa_s->conf->update_config) {
		res = wpa_config_write(wpa_s->confname, wpa_s->conf);
		if (res) {
			wpa_printf(MSG_DEBUG, "Failed to update config after "
				   "anonymous_id update");
		}
	}
}
Example #9
0
int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
		       const char *pin)
{
	struct wpa_ssid *ssid;
	char val[30];

	if (!pin)
		return -1;
	wpas_clear_wps(wpa_s);
	ssid = wpas_wps_add_network(wpa_s, 1, bssid);
	if (ssid == NULL)
		return -1;
	os_snprintf(val, sizeof(val), "\"pin=%s\"", pin);
	wpa_config_set(ssid, "phase1", val, 0);
	eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
			       wpa_s, NULL);
	wpas_wps_reassoc(wpa_s, ssid);
	return 0;
}
Example #10
0
int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
		       const char *pin, struct wps_new_ap_settings *settings)
{
	struct wpa_ssid *ssid;
	char val[200];
	char *pos, *end;
	int res;

	if (!pin)
		return -1;
	wpas_clear_wps(wpa_s);
	ssid = wpas_wps_add_network(wpa_s, 1, bssid);
	if (ssid == NULL)
		return -1;
	ssid->temporary = 1;
	pos = val;
	end = pos + sizeof(val);
	res = os_snprintf(pos, end - pos, "\"pin=%s", pin);
	if (res < 0 || res >= end - pos)
		return -1;
	pos += res;
	if (settings) {
		res = os_snprintf(pos, end - pos, " new_ssid=%s new_auth=%s "
				  "new_encr=%s new_key=%s",
				  settings->ssid_hex, settings->auth,
				  settings->encr, settings->key_hex);
		if (res < 0 || res >= end - pos)
			return -1;
		pos += res;
	}
	res = os_snprintf(pos, end - pos, "\"");
	if (res < 0 || res >= end - pos)
		return -1;
	wpa_config_set(ssid, "phase1", val, 0);
	if (wpa_s->wps_fragment_size)
		ssid->eap.fragment_size = wpa_s->wps_fragment_size;
	eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
			       wpa_s, NULL);
	wpas_wps_reassoc(wpa_s, ssid, bssid);
	return 0;
}
Example #11
0
int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
		       const char *pin, int p2p_group, u16 dev_pw_id)
{
	struct wpa_ssid *ssid;
	char val[128];
	unsigned int rpin = 0;

	wpas_clear_wps(wpa_s);
	ssid = wpas_wps_add_network(wpa_s, 0, bssid);
	if (ssid == NULL)
		return -1;
	ssid->temporary = 1;
	ssid->p2p_group = p2p_group;
#ifdef CONFIG_P2P
	if (p2p_group && wpa_s->go_params && wpa_s->go_params->ssid_len) {
		ssid->ssid = os_zalloc(wpa_s->go_params->ssid_len + 1);
		if (ssid->ssid) {
			ssid->ssid_len = wpa_s->go_params->ssid_len;
			os_memcpy(ssid->ssid, wpa_s->go_params->ssid,
				  ssid->ssid_len);
			wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP "
					  "SSID", ssid->ssid, ssid->ssid_len);
		}
	}
#endif /* CONFIG_P2P */
	if (pin)
		os_snprintf(val, sizeof(val), "\"pin=%s dev_pw_id=%u\"",
			    pin, dev_pw_id);
	else {
		rpin = wps_generate_pin();
		os_snprintf(val, sizeof(val), "\"pin=%08d dev_pw_id=%u\"",
			    rpin, dev_pw_id);
	}
	wpa_config_set(ssid, "phase1", val, 0);
	if (wpa_s->wps_fragment_size)
		ssid->eap.fragment_size = wpa_s->wps_fragment_size;
	eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
			       wpa_s, NULL);
	wpas_wps_reassoc(wpa_s, ssid, bssid);
	return rpin;
}
Example #12
0
int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
		       const char *pin)
{
	struct wpa_ssid *ssid;
	char val[128];
	unsigned int rpin = 0;

	wpas_clear_wps(wpa_s);
	ssid = wpas_wps_add_network(wpa_s, 0, bssid);
	if (ssid == NULL)
		return -1;
	if (pin)
		os_snprintf(val, sizeof(val), "\"pin=%s\"", pin);
	else {
		rpin = wps_generate_pin();
		os_snprintf(val, sizeof(val), "\"pin=%08d\"", rpin);
	}
	wpa_config_set(ssid, "phase1", val, 0);
	eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
			       wpa_s, NULL);
	wpas_wps_reassoc(wpa_s, ssid);
	return rpin;
}
status_t
WPASupplicantApp::_JoinNetwork(BMessage *message)
{
	const char *interfaceName = NULL;
	status_t status = message->FindString("device", &interfaceName);
	if (status != B_OK)
		return status;

	// Check if we already registered this interface.
	wpa_supplicant *interface = wpa_supplicant_get_iface(fWPAGlobal,
		interfaceName);
	if (interface == NULL) {
		wpa_interface interfaceOptions;
		memset(&interfaceOptions, 0, sizeof(wpa_interface));

		interfaceOptions.ifname = interfaceName;

		interface = wpa_supplicant_add_iface(fWPAGlobal, &interfaceOptions);
		if (interface == NULL)
			return B_NO_MEMORY;
	} else {
		// Disable everything
		wpa_supplicant_disable_network(interface, NULL);

		// Try to remove any existing network
		while (true) {
			wpa_ssid *network = wpa_config_get_network(interface->conf, 0);
			if (network == NULL)
				break;

			wpas_notify_network_removed(interface, network);
			wpa_config_remove_network(interface->conf, network->id);
		}
	}

	const char *networkName = NULL;
	status = message->FindString("name", &networkName);
	if (status != B_OK)
		return status;

	uint32 authMode = B_NETWORK_AUTHENTICATION_NONE;
	status = message->FindUInt32("authentication", &authMode);
	if (status != B_OK)
		return status;

	uint32 encapMode = B_NETWORK_EAP_ENCAPSULATION_NONE;
	if (authMode == B_NETWORK_AUTHENTICATION_EAP)
		message->FindUInt32("encapsulation", &encapMode);

	const char *username = NULL;
	if (encapMode > B_NETWORK_EAP_ENCAPSULATION_NONE) {
		status = message->FindString("username", &username);
		if (status != B_OK)
			return status;
	}

	const char *password = NULL;
	if (authMode > B_NETWORK_AUTHENTICATION_NONE) {
		status = message->FindString("password", &password);
		if (status != B_OK)
			return status;
	}

	wpa_ssid *network = wpa_config_add_network(interface->conf);
	if (network == NULL)
		return B_NO_MEMORY;

	wpas_notify_network_added(interface, network);

	network->disabled = 1;
	wpa_config_set_network_defaults(network);

	// Fill in the info from the join request

	// The format includes the quotes
	BString value;
	value = "\"";
	value += networkName;
	value += "\"";
	int result = wpa_config_set(network, "ssid", value.String(), 0);

	if (result == 0)
		result = wpa_config_set(network, "scan_ssid", "1", 1);

	if (authMode >= B_NETWORK_AUTHENTICATION_WPA) {
		if (result == 0)
			result = wpa_config_set(network, "proto", "WPA RSN", 2);
		if (result == 0) {
			switch (authMode) {
				case B_NETWORK_AUTHENTICATION_WPA:
				case B_NETWORK_AUTHENTICATION_WPA2:
				default:
					result = wpa_config_set(network, "key_mgmt", "WPA-PSK", 3);
					break;
				case B_NETWORK_AUTHENTICATION_EAP:
					result = wpa_config_set(network, "key_mgmt", "WPA-EAP", 3);
					break;
			}
		}
		if (result == 0)
			result = wpa_config_set(network, "pairwise", "CCMP TKIP NONE", 4);
		if (result == 0) {
			result = wpa_config_set(network, "group",
				"CCMP TKIP WEP104 WEP40", 5);
		}
		if (result == 0) {
			if (encapMode > B_NETWORK_EAP_ENCAPSULATION_NONE) {
				switch (encapMode) {
					case B_NETWORK_EAP_ENCAPSULATION_PEAP:
						result = wpa_config_set(network, "eap", "PEAP", 6);
						break;
					case B_NETWORK_EAP_ENCAPSULATION_TLS:
						result = wpa_config_set(network, "eap", "TLS", 6);
						break;
				}
			}
		}
	} else {
		// Open or WEP.
		if (result == 0)
			result = wpa_config_set(network, "key_mgmt", "NONE", 6);
	}

	if (result == 0) {
		if (authMode == B_NETWORK_AUTHENTICATION_WEP) {
			if (strncmp("0x", password, 2) == 0) {
				// interpret as hex key
				// TODO: make this non-ambiguous
				result = wpa_config_set(network, "wep_key0", password + 2, 7);
			} else {
				value = "\"";
				value += password;
				value += "\"";
				result = wpa_config_set(network, "wep_key0", value.String(), 8);
			}

			if (result == 0)
				result = wpa_config_set(network, "wep_tx_keyidx", "0", 9);
		} else if (authMode == B_NETWORK_AUTHENTICATION_EAP) {
			// EAP
			value = "\"";
			value += password;
			value += "\"";
			result = wpa_config_set(network, "password", value.String(), 10);
			if (encapMode > B_NETWORK_EAP_ENCAPSULATION_NONE) {
				value = "\"";
				value += username;
				value += "\"";
				result = wpa_config_set(network, "identity",
					value.String(), 11);
			}
			// TODO: Does EAP need the same thing?
			#if 0
			if (result == 0) {
				// We need to actually "apply" the PSK
				wpa_config_update_psk(network);
			}
			#endif
		} else if (authMode >= B_NETWORK_AUTHENTICATION_WPA) {
			// WPA/WPA2
			value = "\"";
			value += password;
			value += "\"";
			result = wpa_config_set(network, "psk", value.String(), 10);

			if (result == 0) {
				// We need to actually "apply" the PSK
				wpa_config_update_psk(network);
			}
		}

		if (result != 0) {
			// The key format is invalid, we need to ask for another password.
			BMessage newJoinRequest = *message;
			newJoinRequest.RemoveName("password");
			newJoinRequest.AddString("error", "Password format invalid");
			newJoinRequest.AddBool("forceDialog", true);
			PostMessage(&newJoinRequest);
		}
	}

	if (result != 0) {
		wpas_notify_network_removed(interface, network);
		wpa_config_remove_network(interface->conf, network->id);
		return B_ERROR;
	}

	// Set up watching for the completion event
	_StartWatchingInterfaceChanges(interface, _InterfaceStateChangeCallback,
		message);

	// Now attempt to connect
	wpa_supplicant_select_network(interface, network);

	// Use a message runner to return a timeout and stop watching after a while
	BMessage timeout(kMsgJoinTimeout);
	timeout.AddPointer("interface", interface);

	BMessageRunner::StartSending(be_app_messenger, &timeout,
		15 * 1000 * 1000, 1);
		// Note that we don't need to cancel this. If joining works before the
		// timeout happens, it will take the StateChangeWatchingEntry with it
		// and the timeout message won't match anything and be discarded.

	return B_OK;
}
Example #14
0
static struct wpa_ssid * wpa_config_read_network(HKEY hk, const TCHAR *netw,
						 int id)
{
	HKEY nhk;
	LONG ret;
	DWORD i;
	struct wpa_ssid *ssid;
	int errors = 0;

	ret = RegOpenKeyEx(hk, netw, 0, KEY_QUERY_VALUE, &nhk);
	if (ret != ERROR_SUCCESS) {
		wpa_printf(MSG_DEBUG, "Could not open wpa_supplicant config "
			   "network '" TSTR "'", netw);
		return NULL;
	}

	wpa_printf(MSG_MSGDUMP, "Start of a new network '" TSTR "'", netw);
	ssid = os_zalloc(sizeof(*ssid));
	if (ssid == NULL) {
		RegCloseKey(nhk);
		return NULL;
	}
	dl_list_init(&ssid->psk_list);
	ssid->id = id;

	wpa_config_set_network_defaults(ssid);

	for (i = 0; ; i++) {
		TCHAR name[255], data[1024];
		DWORD namelen, datalen, type;

		namelen = 255;
		datalen = sizeof(data);
		ret = RegEnumValue(nhk, i, name, &namelen, NULL, &type,
				   (LPBYTE) data, &datalen);

		if (ret == ERROR_NO_MORE_ITEMS)
			break;

		if (ret != ERROR_SUCCESS) {
			wpa_printf(MSG_ERROR, "RegEnumValue failed: 0x%x",
				   (unsigned int) ret);
			break;
		}

		if (namelen >= 255)
			namelen = 255 - 1;
		name[namelen] = TEXT('\0');

		if (datalen >= 1024)
			datalen = 1024 - 1;
		data[datalen] = TEXT('\0');

		wpa_unicode2ascii_inplace(name);
		wpa_unicode2ascii_inplace(data);
		if (wpa_config_set(ssid, (char *) name, (char *) data, 0) < 0)
			errors++;
	}

	RegCloseKey(nhk);

	if (ssid->passphrase) {
		if (ssid->psk_set) {
			wpa_printf(MSG_ERROR, "Both PSK and passphrase "
				   "configured for network '" TSTR "'.", netw);
			errors++;
		}
		wpa_config_update_psk(ssid);
	}

	if ((ssid->group_cipher & WPA_CIPHER_CCMP) &&
	    !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) &&
	    !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) {
		/* Group cipher cannot be stronger than the pairwise cipher. */
		wpa_printf(MSG_DEBUG, "Removed CCMP from group cipher "
			   "list since it was not allowed for pairwise "
			   "cipher for network '" TSTR "'.", netw);
		ssid->group_cipher &= ~WPA_CIPHER_CCMP;
	}

	if (errors) {
		wpa_config_free_ssid(ssid);
		ssid = NULL;
	}

	return ssid;
}
Example #15
0
/*
 * This installs received WPS configuration into a new network configuration.
 * It is optional that the new network configuration be saved to the
 * original configuration file.
 */
int wps_set_supplicant_ssid_configuration(void *ctx, u8 *buf, size_t len)
{
	int ret = -1;
	struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)ctx;
	struct wpa_ssid *ssid = 0;
	struct wps_data *wps = 0;
	u8 str_ssid[33];
	size_t ssid_length;
	u16 auth, encr;
	u8 nwKeyIdx;
	u8 *nwKey = 0;
	size_t nwKey_length;
	u8 macAddr[6];
	char *eapType = 0;
	char *eapIdentity = 0;
	Boolean keyProvideAuto;
	Boolean enabled8021X;
	Boolean passphrase = 0;
	size_t length;
	char *var, *value;

	do {
		if (!wpa_s)
			break;

                /* Optionally share new configuration with other software,
                 * e.g. with hostapd.
                 */
                wps_new_configuration_share(wpa_s, buf, len);

		ssid = wpa_config_add_network(wpa_s->conf);
		if (!ssid)
			break;
		wpa_config_set_network_defaults(ssid);

		if (wps_create_wps_data(&wps))
			break;

		if(wps_parse_wps_data(buf, len, wps))
			break;

		/* SSID */
		ssid_length = sizeof(str_ssid);
		if(wps_get_value(wps, WPS_TYPE_SSID, str_ssid, &ssid_length))
			break;
		str_ssid[ssid_length] = 0;

		/* Authentication Type */
		if (wps_get_value(wps, WPS_TYPE_AUTH_TYPE, &auth, NULL))
			break;

		/* Encryption Type */
		if (wps_get_value(wps, WPS_TYPE_ENCR_TYPE, &encr, NULL))
			break;

		/* Network Key Index (Option) */
		if(wps_get_value(wps, WPS_TYPE_NW_KEY_INDEX, &nwKeyIdx, NULL))
			nwKeyIdx = 1;
		if ((1 > nwKeyIdx) || (4 < nwKeyIdx)) { /* warning */
			wpa_printf(MSG_WARNING, "Network Key Index is fixed. %d -> 1\n", nwKeyIdx);
			nwKeyIdx = 1;
		}

		/* Network Key */
		nwKey_length = 0;
		(void)wps_get_value(wps, WPS_TYPE_NW_KEY, NULL, &nwKey_length);
		if (nwKey_length) {
			nwKey = (u8 *)calloc(1, nwKey_length + 1);
			if (!nwKey)
				break;
			if (wps_get_value(wps, WPS_TYPE_NW_KEY, nwKey, &nwKey_length)) {
				break;
			}
			nwKey[nwKey_length] = 0;
		}

		/* MAC Address */
		length = sizeof(macAddr);
		if(wps_get_value(wps, WPS_TYPE_MAC_ADDR, macAddr, &length))
			break;

		/* EAP Type (Option) */
		length = 0;
		(void)wps_get_value(wps, WPS_TYPE_EAP_TYPE, NULL, &length);
		if (length) {
			eapType = (char *)calloc(1, length + 1);
			if (!eapType)
				break;
			if (wps_get_value(wps, WPS_TYPE_EAP_TYPE, eapType, &length)) {
				break;
			}
			eapType[length] = 0;
		}

		/* EAP Identity (Option) */
		length = 0;
		(void)wps_get_value(wps, WPS_TYPE_EAP_IDENTITY, NULL, &length);
		if (length) {
			eapIdentity = (char *)calloc(1, length + 1);
			if (!eapIdentity)
				break;
			if (wps_get_value(wps, WPS_TYPE_EAP_IDENTITY, eapIdentity, &length)) {
				break;
			}
			eapIdentity[length] = 0;
		}

		/* Key Provided Automaticaly (Option) */
		if(wps_get_value(wps, WPS_TYPE_KEY_PROVIDED_AUTO, &keyProvideAuto, NULL))
			keyProvideAuto = 0;

		/* 802.1X Enabled (Option) */
		if(wps_get_value(wps, WPS_TYPE_8021X_ENABLED, &enabled8021X, NULL))
			enabled8021X = 0;

		/* Set Configuration */
                /* %%%%%% Sony set disabled to 1... why? */
		ssid->disabled = 0;
		/* ssid */
		var = "ssid";
		value = (char *)os_malloc(os_strlen((char *)str_ssid) + 3);
		if (!value)
			break;
		os_snprintf(value, os_strlen((char *)str_ssid) + 3, "\"%s\"", str_ssid);
		if (wpa_config_set(ssid, var, value, 0))
			break;
		free(value);

		/* auth_alg */
		var = "auth_alg";
		if (WPS_AUTHTYPE_SHARED == auth)
			value = "SHARED";
		else
			value = "OPEN";
		if (wpa_config_set(ssid, var, value, 0))
			break;

		/* key_mgmt */
		var = "key_mgmt";
		switch (auth) {
		case WPS_AUTHTYPE_OPEN:
		case WPS_AUTHTYPE_SHARED:
			if (enabled8021X)
				value = "IEEE8021X";
			else
				value = "NONE";
			break;
		case WPS_AUTHTYPE_WPAPSK:
		case WPS_AUTHTYPE_WPA2PSK:
			if (enabled8021X)
				value = "WPA-PSK IEEE8021X";
			else
				value = "WPA-PSK";
			break;
		case WPS_AUTHTYPE_WPA:
		case WPS_AUTHTYPE_WPA2:
			if (enabled8021X)
				value = "WPA-EAP IEEE8021X";
			else
				value = "WPA-EAP";
			break;
		default:
			value = 0;
			break;
		}
		if (!value | wpa_config_set(ssid, var, value, 0))
			break;

		/* proto */
		var = "proto";
		switch (auth) {
		case WPS_AUTHTYPE_WPA:
		case WPS_AUTHTYPE_WPAPSK:
			value = "WPA";
			break;
		case WPS_AUTHTYPE_WPA2:
		case WPS_AUTHTYPE_WPA2PSK:
			value = "RSN";
			break;
		default:
			ssid->proto = 0;
			value = 0;
			break;
		}
		if (value && wpa_config_set(ssid, var, value, 0))
			break;

		/* pariwise */
		var = "pairwise";
		switch (encr) {
		case WPS_ENCRTYPE_NONE:
			ssid->pairwise_cipher = WPA_CIPHER_NONE;
			value = 0;
			break;
		case WPS_ENCRTYPE_TKIP:
			value = "TKIP";
			break;
		case WPS_ENCRTYPE_AES:
			value = "CCMP";
			break;
		default:
			value = 0;
			break;
		}
		if (value && wpa_config_set(ssid, var, value, 0))
			break;

		/* group */
		var = "group";
		switch (encr) {
		case WPS_ENCRTYPE_NONE:
			ssid->group_cipher = WPA_CIPHER_NONE;
			value = 0;
			break;
		case WPS_ENCRTYPE_WEP:
			value = "WEP104 WEP40";
			break;
		case WPS_ENCRTYPE_TKIP:
			value = "TKIP";
			break;
		case WPS_ENCRTYPE_AES:
                        #if 0   /* original */
			value = "CCMP";
                        #else   /* HACK! */
                        /* It is not uncommon for group cipher to be
                         * TKIP whereas the pairwise is CCMP, but 
                         * WPS makes no distinction.
                         * Workaround by configuring both in this case.
                         */
			value = "TKIP CCMP";
                        #endif
			break;
		default:
			value = 0;
			break;
		}
		if (value && wpa_config_set(ssid, var, value, 0))
			break;

		/* wep_tx_keyidx */
		var = "wep_tx_keyidx";
		switch (encr) {
		case WPS_ENCRTYPE_WEP:
			value = (char *)os_malloc(2);
			if (!value)
				break;
			os_snprintf(value, 2, "%d", nwKeyIdx - 1);
			break;
		default:
			value = 0;
			break;
		}
		if (value && wpa_config_set(ssid, var, value, 0)) {
			free(value);
			break;
		} else if (value)
			free(value);
		if (!value && (WPS_ENCRTYPE_WEP == encr))
			break;

		/* wep_keyn */
		switch (encr) {
		case WPS_ENCRTYPE_WEP:
			var = (char *)os_malloc(9);
			if (!var)
				break;
			os_snprintf(var, 9, "wep_key%d", nwKeyIdx - 1);
			if (is_hex(nwKey, nwKey_length)) {
				value = (char *)os_malloc(nwKey_length * 2 + 1);
				if (!value)
					break;
				wpa_snprintf_hex_uppercase(value, nwKey_length * 2 + 1,
										   nwKey, nwKey_length);
				value[nwKey_length * 2] = 0;
			} else if ((5 == nwKey_length) || (13 == nwKey_length)) {
				value = (char *)os_malloc(nwKey_length + 3);
				if (!value)
					break;
				os_snprintf(value, nwKey_length + 3, "\"%s\"", nwKey);
			} else if ((nwKey_length) || (13 == nwKey_length)) {
				value = (char *)os_malloc(nwKey_length + 1);
				if (!value)
					break;
				os_memcpy(value, nwKey, nwKey_length);
				value[nwKey_length] = 0;
			}
			break;
		default:
			var = 0;
			value = 0;
			break;
		}
		if (var && value && wpa_config_set(ssid, var, value, 0))
			break;
		if (var)
			free(var);
		if (value)
			free(value);
		if ((!var || !value) && (WPS_ENCRTYPE_WEP == encr))
			break;

		/* psk */
		var = "psk";
		switch (auth) {
		case WPS_AUTHTYPE_WPA:
		case WPS_AUTHTYPE_WPA2:
		case WPS_AUTHTYPE_WPAPSK:
		case WPS_AUTHTYPE_WPA2PSK:
			if (nwKey_length) {
				value = (char *)os_malloc(nwKey_length + 3);
				if (!value)
					break;
				if (64 > nwKey_length) {
					os_snprintf(value, nwKey_length + 3, "\"%s\"", nwKey);
					passphrase = 1;
				} else if (64 == nwKey_length) {
					os_memcpy(value, nwKey, nwKey_length);
					value[nwKey_length] = 0;
				} else {
					free(value);
					value = 0;
					break;
				}
			} else
				value = 0;
			break;
		default:
			value = 0;
			break;
		}
		if (value && wpa_config_set(ssid, var, value, 0)) {
			free(value);
			break;
		} else if (value)
			free(value);
		if (nwKey_length && !value &&
			((WPS_AUTHTYPE_WPA == auth) ||
			 (WPS_AUTHTYPE_WPA2 == auth) ||
			 (WPS_AUTHTYPE_WPAPSK == auth) ||
			 (WPS_AUTHTYPE_WPA2PSK == auth)))
			break;
		
		/* eap */
		if (eapType && os_strlen(eapType)) {
			var = "eap";
			value = (char *)eapType;
			if (wpa_config_set(ssid, var, value, 0))
				break;
		}

		/* identity */
		if (eapIdentity && os_strlen(eapIdentity)) {
			var = "identity";
			value = (char *)eapIdentity;
			if (wpa_config_set(ssid, var, value, 0))
				break;
		}

		ret = 0;
	} while (0);

	(void)wps_destroy_wps_data(&wps);

	if (ret) {
		if (ssid)
			(void)wpa_config_remove_network(wpa_s->conf, ssid->id);
	} else {
		if (passphrase)
			wpa_config_update_psk(ssid);
	}

	if (nwKey)
		free(nwKey);
	if (eapType)
		free(eapType);
	if (eapIdentity)
		free(eapIdentity);

	return ret?ret:ssid->id;
}
Example #16
0
static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id)
{
	struct wpa_ssid *ssid;
	int errors = 0, end = 0;
	char buf[256], *pos, *pos2;

	wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block",
		   *line);
	ssid = (struct wpa_ssid *) malloc(sizeof(*ssid));
	if (ssid == NULL)
		return NULL;
	memset(ssid, 0, sizeof(*ssid));
	ssid->id = id;

	ssid->proto = WPA_PROTO_WPA | WPA_PROTO_RSN;
	ssid->pairwise_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP;
	ssid->group_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP |
		WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40;
	ssid->key_mgmt = WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X;
	ssid->eapol_flags = EAPOL_FLAG_REQUIRE_KEY_UNICAST |
		EAPOL_FLAG_REQUIRE_KEY_BROADCAST;
	ssid->eap_workaround = (unsigned int) -1;

	while ((pos = wpa_config_get_line(buf, sizeof(buf), f, line))) {
		if (strcmp(pos, "}") == 0) {
			end = 1;
			break;
		}

		pos2 = strchr(pos, '=');
		if (pos2 == NULL) {
			wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line "
				   "'%s'.", *line, pos);
			errors++;
			continue;
		}

		*pos2++ = '\0';
		if (*pos2 == '"') {
			if (strchr(pos2 + 1, '"') == NULL) {
				wpa_printf(MSG_ERROR, "Line %d: invalid "
					   "quotation '%s'.", *line, pos2);
				errors++;
				continue;
			}
		}

		if (wpa_config_set(ssid, pos, pos2, *line) < 0)
			errors++;
	}

	if (!end) {
		wpa_printf(MSG_ERROR, "Line %d: network block was not "
			   "terminated properly.", *line);
		errors++;
	}

	if (ssid->passphrase) {
		if (ssid->psk_set) {
			wpa_printf(MSG_ERROR, "Line %d: both PSK and "
				   "passphrase configured.", *line);
			errors++;
		}
		wpa_config_update_psk(ssid);
	}

	if ((ssid->key_mgmt & WPA_KEY_MGMT_PSK) && !ssid->psk_set) {
		wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key "
			   "management, but no PSK configured.", *line);
		errors++;
	}

	if ((ssid->group_cipher & WPA_CIPHER_CCMP) &&
	    !(ssid->pairwise_cipher & WPA_CIPHER_CCMP)) {
		/* Group cipher cannot be stronger than the pairwise cipher. */
		wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher"
			   " list since it was not allowed for pairwise "
			   "cipher", *line);
		ssid->group_cipher &= ~WPA_CIPHER_CCMP;
	}

	if (errors) {
		free(ssid);
		ssid = NULL;
	}

	return ssid;
}
Example #17
0
struct wpa_scan_result *wps_select_ssid(struct wpa_supplicant *wpa_s,
		struct wpa_scan_result *results,
		int num, struct wpa_ssid **ssid)
{
	struct wpa_scan_result *bss;
	struct wpa_scan_result *selected = 0;
	int num_good;
	struct wpa_scan_result *maybe = 0;
        int num_maybe;
	struct wpa_ssid *tmp;
	int ret = -1;
	char *var, *value;
	struct wps_data *data = 0;
	char bssid_str[18+1];
	char ssid_str[32+3];
    u8 uuidSel[SIZE_UUID];
    u8 uuidBss[SIZE_UUID];
    size_t length;
	struct wps_config *wps;
	int i;
        int is_push_button;

	do {
		if (!wpa_s || !wpa_s->conf || !results || !num || !ssid)
			break;

		wps = wpa_s->conf->wps;
                is_push_button = (wps->dev_pwd_len == 8 && 
                        memcmp(wps->dev_pwd, "00000000", 8) == 0);

		if (wps->nwid_trying_wps != -1) {
			(void)wpa_config_remove_network(wpa_s->conf, wps->nwid_trying_wps);
			wps->nwid_trying_wps = -1;
		}

		*ssid = 0;

		num_good = 0;
		num_maybe = 0;
		for (i = 0; i < num; i++) {
			bss = &results[i];
            if (wps->filter_bssid_flag && memcmp(
                        wps->filter_bssid, bss->bssid, 6) != 0) {
                continue;
            }
            if (wps->filter_ssid_length > 0 && memcmp(
                        wps->filter_ssid, bss->ssid, 
                        wps->filter_ssid_length) != 0) {
                continue;
            }
			if (bss->wps_ie_len) {
				u16 dev_pwd_id;

				do {
					if (wps_create_wps_data(&data))
						break;

					if (wps_parse_wps_ie(bss->wps_ie, bss->wps_ie_len, data))
						break;

		            length = sizeof(uuidBss);
                    /* selected bss UUID-E */
		            if (wps_get_value(data, WPS_TYPE_UUID_E, uuidBss, &length))
			            break;

					if (wps_get_value(data, WPS_TYPE_DEVICE_PWD_ID, &dev_pwd_id, 0))
						break;

                    if (is_push_button) {
                        if (WPS_DEVICEPWDID_PUSH_BTN != dev_pwd_id) 
                            break;
                    } else {        /* PIN mode */
                        if (WPS_DEVICEPWDID_DEFAULT != dev_pwd_id) {
                            break;
                        }
                    }
                    
                    /* In the case of a dual-band AP and a dual-band station,
                     * the station may discover more than one Registrar in PBC mode.
                     * If the dual-band station does discover more than one Registrar
                     * in PBC mode, one each RF band, and the UUID in the Beacon and
                     * Probe-Response are the same for all RF bands, then the station 
                     * shall not consider this to be a session overlap.
                     */
					if (num_good) {
					    /* check dual-band concurrent AP case */
					    if (((selected->freq >= 4000) && (bss->freq <= 3000)) ||
					        ((selected->freq <= 3000) && (bss->freq >= 4000)))
					    {
                    		/* one is 2.4GHz and another is 5GHz */
                    		if (memcmp(uuidSel, uuidBss, length) == 0)
                    		{
                    		    /* UUID-E of them are totally the same */
                    		    /* Select the 5GHz one */
                    		    if (bss->freq >= 4000)
					                selected = bss;
                    		    break;
                    		}
					    }
					}
				    selected = bss;
            		memcpy(&uuidSel, &uuidBss, length);
					num_good++;
				} while (0);

				(void)wps_destroy_wps_data(&data);

                /* If we have WPS at all then it's a maybe
                 * for PIN
                 */
                if (!is_push_button) {
                    num_maybe++;
					if ((!maybe) || (bss->qual > maybe->qual)) {
						maybe = bss;
					}
                }
			} else {
                /* No WPS IE */
                /* If in open mode, it may support WPS...
                 * (some microsoft products)
                 * take it as a maybe
                 */
                if ((bss->caps & IEEE80211_CAP_PRIVACY) == 0) {
                    num_maybe++;
                    if ((!maybe) || (bss->qual > maybe->qual)) {
                        maybe = bss;
                    }
                }
            }
		}

        /* Push button mode must have exact explicit match.
         * For PIN mode, due to greater security, we are willing
         * to be more lenient; and due to the ambiguity of the WPS
         * standard, it is not actually required that the AP
         * advertise it's PIN mode (as versus PB mode
         * which requires such advertisement).
         * But we want either one good match, or if no good match,
         * then just one maybe... otherwise the user should have
         * done pre-filtering.... 
         * for best results, the user should do pre-filtering!
         */
        if (is_push_button) {
		    if (num_good > 1) {
		        wpa_msg(wpa_s, MSG_INFO, 
                        "Must be only one AP enabled WPS-PBC");
                break;
            } else if (num_good == 1) {
                /* good */
            } else if (num_good == 0) {
		        wpa_msg(wpa_s, MSG_INFO, 
                        "There are no APs which are enabled WPS-PBC");
                break;
            }
		} else { /* PIN mode */
		    if (num_good > 1) {
			    wpa_msg(wpa_s, MSG_INFO, 
                        "Must be only one AP enabled WPS-PIN");
                break;
            } else if (num_good == 1) {
                /* good */
            } else if (num_maybe > 1) {
			    wpa_msg(wpa_s, MSG_INFO, 
                        "There are no APs which are enabled WPS-PIN"
                        " but attaching WPS IE, concern some microsoft products,"
                        " try to connect strongest RSSI one");
				selected = maybe;
            } else if (num_maybe == 1) {
                /* select this one */
                selected = maybe;
            } else {
			    wpa_msg(wpa_s, MSG_INFO, 
                        "There are no APs available for WPS");
                break;
            }
        }

		if (!selected)
			break;

		*ssid = wpa_config_add_network(wpa_s->conf);
		if (!*ssid)
			break;
		wpa_config_set_network_defaults(*ssid);
		(*ssid)->disabled = 1;

		/* bssid */
		var = "bssid";
		os_snprintf(bssid_str, sizeof(bssid_str), "%02X:%02X:%02X:%02X:%02X:%02X",
					selected->bssid[0], selected->bssid[1],
					selected->bssid[2], selected->bssid[3],
					selected->bssid[4], selected->bssid[5]);
		bssid_str[18] = 0;
		if (wpa_config_set(*ssid, var, bssid_str, 0))
			break;

		/* ssid */
		var = "ssid";
		ssid_str[0] = '"';
		os_memcpy(ssid_str + 1, selected->ssid, selected->ssid_len);
		ssid_str[selected->ssid_len + 1] = '"';
		ssid_str[selected->ssid_len + 2] = 0;
		if (wpa_config_set(*ssid, var, ssid_str, 0))
			break;

		/* auth_alg */
		var = "auth_alg";
		value = "OPEN";
		if (wpa_config_set(*ssid, var, value, 0))
			break;

		/* key_mgmt */
		var = "key_mgmt";
		value = "IEEE8021X";
		if (wpa_config_set(*ssid, var, value, 0))
			break;

		/* eap */
		var = "eap";
		value = "WPS";
		if (wpa_config_set(*ssid, var, value, 0))
			break;

		/* identity */
		var = "identity";
		free((*ssid)->identity);
		switch (wps->reg_mode) {
		case WPS_SUPPLICANT_REGMODE_NONE:
			value = WPS_IDENTITY_ENROLLEE;
			break;
		default:
			value = WPS_IDENTITY_REGISTRAR;
			break;
		}
		(*ssid)->identity = (u8 *)os_strdup(value);
		(*ssid)->identity_len = os_strlen(value);

		ret = 0;
	} while (0);

	if (ret) {
		if (*ssid)
			(void)wpa_config_remove_network(wpa_s->conf, (*ssid)->id);
		selected = 0;
	} else {
		wpa_msg(wpa_s, MSG_INFO, "Found AP for WPS [%*s]", (*ssid)->ssid_len,(*ssid)->ssid);

		switch (wps->reg_mode) {
		case WPS_SUPPLICANT_REGMODE_NONE:
			if (wps->config) {
				free(wps->config);
				wps->config = 0;
				wps->config_len = 0;
			}
			break;
		case WPS_SUPPLICANT_REGMODE_CONFIGURE_AP:
			break;
		case WPS_SUPPLICANT_REGMODE_REGISTER_AP:
		case WPS_SUPPLICANT_REGMODE_REGISTER_STA:
			if (wps->config) {
				free(wps->config);
				wps->config = 0;
				wps->config_len = 0;
			}

			(void)wps_get_supplicant_ssid_configuration(wpa_s, (*ssid)->id, &wps->config, &wps->config_len);
			break;
		default:
			break;
		}

		if (wpa_s->current_ssid)
			wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);

		tmp = wpa_s->conf->ssid;
		while (tmp) {
                        #if 0   /* original from Sony */
			tmp->disabled = (*ssid)->id != tmp->id;
                        #else
                        /* Set bit 1 of disabled as "temporary WPS bit" */
			tmp->disabled = ((*ssid)->id != tmp->id) << 1;
                        #endif
			tmp = tmp->next;
		}

		wps->nwid_trying_wps = (*ssid)->id;

		wpa_s->reassociate = 1;
		wpa_supplicant_req_scan(wpa_s, 0, 0);
	}

	return selected;
}
Example #18
0
int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
{
	struct wpa_ssid *ssid;
	struct nai_realm *realm;
	struct nai_realm_eap *eap = NULL;
	u16 count, i;
	char buf[100];
	const u8 *ie;

	if (bss == NULL)
		return -1;
	ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
	if (ie == NULL || ie[1] == 0) {
		wpa_printf(MSG_DEBUG, "Interworking: No SSID known for "
			   MACSTR, MAC2STR(bss->bssid));
		return -1;
	}

	realm = nai_realm_parse(bss->anqp_nai_realm, &count);
	if (realm == NULL) {
		wpa_printf(MSG_DEBUG, "Interworking: Could not parse NAI "
			   "Realm list from " MACSTR, MAC2STR(bss->bssid));
		count = 0;
	}

	for (i = 0; i < count; i++) {
		if (!nai_realm_match(&realm[i], wpa_s->conf->home_realm))
			continue;
		eap = nai_realm_find_eap(wpa_s, &realm[i]);
		if (eap)
			break;
	}

	if (!eap) {
		if (interworking_connect_3gpp(wpa_s, bss) == 0) {
			if (realm)
				nai_realm_free(realm, count);
			return 0;
		}

		wpa_printf(MSG_DEBUG, "Interworking: No matching credentials "
			   "and EAP method found for " MACSTR,
			   MAC2STR(bss->bssid));
		nai_realm_free(realm, count);
		return -1;
	}

	wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR,
		   MAC2STR(bss->bssid));

	ssid = wpa_config_add_network(wpa_s->conf);
	if (ssid == NULL) {
		nai_realm_free(realm, count);
		return -1;
	}
	wpas_notify_network_added(wpa_s, ssid);
	wpa_config_set_network_defaults(ssid);
	ssid->temporary = 1;
	ssid->ssid = os_zalloc(ie[1] + 1);
	if (ssid->ssid == NULL)
		goto fail;
	os_memcpy(ssid->ssid, ie + 2, ie[1]);
	ssid->ssid_len = ie[1];

	if (wpa_config_set(ssid, "eap", eap_get_name(EAP_VENDOR_IETF,
						     eap->method), 0) < 0)
		goto fail;

	if (wpa_s->conf->home_username && wpa_s->conf->home_username[0] &&
	    wpa_config_set_quoted(ssid, "identity",
				  wpa_s->conf->home_username) < 0)
		goto fail;

	if (wpa_s->conf->home_password && wpa_s->conf->home_password[0] &&
	    wpa_config_set_quoted(ssid, "password", wpa_s->conf->home_password)
	    < 0)
		goto fail;

	switch (eap->method) {
	case EAP_TYPE_TTLS:
		if (eap->inner_method) {
			os_snprintf(buf, sizeof(buf), "\"autheap=%s\"",
				    eap_get_name(EAP_VENDOR_IETF,
						 eap->inner_method));
			if (wpa_config_set(ssid, "phase2", buf, 0) < 0)
				goto fail;
			break;
		}
		switch (eap->inner_non_eap) {
		case NAI_REALM_INNER_NON_EAP_PAP:
			if (wpa_config_set(ssid, "phase2", "\"auth=PAP\"", 0) <
			    0)
				goto fail;
			break;
		case NAI_REALM_INNER_NON_EAP_CHAP:
			if (wpa_config_set(ssid, "phase2", "\"auth=CHAP\"", 0)
			    < 0)
				goto fail;
			break;
		case NAI_REALM_INNER_NON_EAP_MSCHAP:
			if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAP\"",
					   0) < 0)
				goto fail;
			break;
		case NAI_REALM_INNER_NON_EAP_MSCHAPV2:
			if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAPV2\"",
					   0) < 0)
				goto fail;
			break;
		}
		break;
	case EAP_TYPE_PEAP:
		os_snprintf(buf, sizeof(buf), "\"auth=%s\"",
			    eap_get_name(EAP_VENDOR_IETF, eap->inner_method));
		if (wpa_config_set(ssid, "phase2", buf, 0) < 0)
			goto fail;
		break;
	}

	if (wpa_s->conf->home_ca_cert && wpa_s->conf->home_ca_cert[0] &&
	    wpa_config_set_quoted(ssid, "ca_cert", wpa_s->conf->home_ca_cert) <
	    0)
		goto fail;

	nai_realm_free(realm, count);

	wpa_supplicant_select_network(wpa_s, ssid);

	return 0;

fail:
	wpas_notify_network_removed(wpa_s, ssid);
	wpa_config_remove_network(wpa_s->conf, ssid->id);
	nai_realm_free(realm, count);
	return -1;
}
Example #19
0
static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s,
				     struct wpa_bss *bss)
{
#ifdef INTERWORKING_3GPP
	struct wpa_ssid *ssid;
	const u8 *ie;

	ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
	if (ie == NULL)
		return -1;
	wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR " (3GPP)",
		   MAC2STR(bss->bssid));

	ssid = wpa_config_add_network(wpa_s->conf);
	if (ssid == NULL)
		return -1;

	wpas_notify_network_added(wpa_s, ssid);
	wpa_config_set_network_defaults(ssid);
	ssid->temporary = 1;
	ssid->ssid = os_zalloc(ie[1] + 1);
	if (ssid->ssid == NULL)
		goto fail;
	os_memcpy(ssid->ssid, ie + 2, ie[1]);
	ssid->ssid_len = ie[1];

	/* TODO: figure out whether to use EAP-SIM, EAP-AKA, or EAP-AKA' */
	if (wpa_config_set(ssid, "eap", "SIM", 0) < 0) {
		wpa_printf(MSG_DEBUG, "EAP-SIM not supported");
		goto fail;
	}
	if (set_root_nai(ssid, wpa_s->conf->home_imsi, '1') < 0) {
		wpa_printf(MSG_DEBUG, "Failed to set Root NAI");
		goto fail;
	}

	if (wpa_s->conf->home_milenage && wpa_s->conf->home_milenage[0]) {
		if (wpa_config_set_quoted(ssid, "password",
					  wpa_s->conf->home_milenage) < 0)
			goto fail;
	} else {
		/* TODO: PIN */
		if (wpa_config_set_quoted(ssid, "pcsc", "") < 0)
			goto fail;
	}

	if (wpa_s->conf->home_password && wpa_s->conf->home_password[0] &&
	    wpa_config_set_quoted(ssid, "password", wpa_s->conf->home_password)
	    < 0)
		goto fail;

	wpa_supplicant_select_network(wpa_s, ssid);

	return 0;

fail:
	wpas_notify_network_removed(wpa_s, ssid);
	wpa_config_remove_network(wpa_s->conf, ssid->id);
#endif /* INTERWORKING_3GPP */
	return -1;
}
Example #20
0
/**
 * wpas_dbus_iface_set_network - Set options for a configured network
 * @message: Pointer to incoming dbus message
 * @wpa_s: wpa_supplicant structure for a network interface
 * @ssid: wpa_ssid structure for a configured network
 * Returns: a dbus message containing a UINT32 indicating success (1) or
 *          failure (0)
 *
 * Handler function for "set" method call of a configured network.
 */
DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message,
					  struct wpa_supplicant *wpa_s,
					  struct wpa_ssid *ssid)
{
	DBusMessage *reply = NULL;
	struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
	DBusMessageIter	iter, iter_dict;

	dbus_message_iter_init(message, &iter);

	if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) {
		reply = wpas_dbus_new_invalid_opts_error(message, NULL);
		goto out;
	}

	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
		char *value = NULL;
		size_t size = 50;
		int ret;

		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
			reply = wpas_dbus_new_invalid_opts_error(message,
								 NULL);
			goto out;
		}

		/* Type conversions, since wpa_supplicant wants strings */
		if (entry.type == DBUS_TYPE_ARRAY &&
		    entry.array_type == DBUS_TYPE_BYTE) {
			if (entry.array_len <= 0)
				goto error;

			size = entry.array_len * 2 + 1;
			value = os_zalloc(size);
			if (value == NULL)
				goto error;
			ret = wpa_snprintf_hex(value, size,
					       (u8 *) entry.bytearray_value,
					       entry.array_len);
			if (ret <= 0)
				goto error;
		} else if (entry.type == DBUS_TYPE_STRING) {
			if (should_quote_opt(entry.key)) {
				size = os_strlen(entry.str_value);
				/* Zero-length option check */
				if (size <= 0)
					goto error;
				size += 3;  /* For quotes and terminator */
				value = os_zalloc(size);
				if (value == NULL)
					goto error;
				ret = os_snprintf(value, size, "\"%s\"",
						  entry.str_value);
				if (ret < 0 || (size_t) ret != (size - 1))
					goto error;
			} else {
				value = os_strdup(entry.str_value);
				if (value == NULL)
					goto error;
			}
		} else if (entry.type == DBUS_TYPE_UINT32) {
			value = os_zalloc(size);
			if (value == NULL)
				goto error;
			ret = os_snprintf(value, size, "%u",
					  entry.uint32_value);
			if (ret <= 0)
				goto error;
		} else if (entry.type == DBUS_TYPE_INT32) {
			value = os_zalloc(size);
			if (value == NULL)
				goto error;
			ret = os_snprintf(value, size, "%d",
					  entry.int32_value);
			if (ret <= 0)
				goto error;
		} else
			goto error;

		if (wpa_config_set(ssid, entry.key, value, 0) < 0)
			goto error;

		if ((os_strcmp(entry.key, "psk") == 0 &&
		     value[0] == '"' && ssid->ssid_len) ||
		    (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
			wpa_config_update_psk(ssid);
		else if (os_strcmp(entry.key, "priority") == 0)
			wpa_config_update_prio_list(wpa_s->conf);

		os_free(value);
		wpa_dbus_dict_entry_clear(&entry);
		continue;

	error:
		os_free(value);
		reply = wpas_dbus_new_invalid_opts_error(message, entry.key);
		wpa_dbus_dict_entry_clear(&entry);
		break;
	}

	if (!reply)
		reply = wpas_dbus_new_success_reply(message);

out:
	return reply;
}
Example #21
0
static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s,
					      int registrar, const u8 *bssid)
{
	struct wpa_ssid *ssid;

	ssid = wpa_config_add_network(wpa_s->conf);
	if (ssid == NULL)
		return NULL;
	wpas_notify_network_added(wpa_s, ssid);
	wpa_config_set_network_defaults(ssid);
	ssid->temporary = 1;
	if (wpa_config_set(ssid, "key_mgmt", "WPS", 0) < 0 ||
	    wpa_config_set(ssid, "eap", "WSC", 0) < 0 ||
	    wpa_config_set(ssid, "identity", registrar ?
			   "\"" WSC_ID_REGISTRAR "\"" :
			   "\"" WSC_ID_ENROLLEE "\"", 0) < 0) {
		wpas_notify_network_removed(wpa_s, ssid);
		wpa_config_remove_network(wpa_s->conf, ssid->id);
		return NULL;
	}

	if (bssid) {
#ifndef CONFIG_P2P
		struct wpa_bss *bss;
		int count = 0;
#endif /* CONFIG_P2P */

		os_memcpy(ssid->bssid, bssid, ETH_ALEN);
		ssid->bssid_set = 1;

		/*
		 * Note: With P2P, the SSID may change at the time the WPS
		 * provisioning is started, so better not filter the AP based
		 * on the current SSID in the scan results.
		 */
#ifndef CONFIG_P2P
		dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
			if (os_memcmp(bssid, bss->bssid, ETH_ALEN) != 0)
				continue;

			os_free(ssid->ssid);
			ssid->ssid = os_malloc(bss->ssid_len);
			if (ssid->ssid == NULL)
				break;
			os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
			ssid->ssid_len = bss->ssid_len;
			wpa_hexdump_ascii(MSG_DEBUG, "WPS: Picked SSID from "
					  "scan results",
					  ssid->ssid, ssid->ssid_len);
			count++;
		}

		if (count > 1) {
			wpa_printf(MSG_DEBUG, "WPS: More than one SSID found "
				   "for the AP; use wildcard");
			os_free(ssid->ssid);
			ssid->ssid = NULL;
			ssid->ssid_len = 0;
		}
#endif /* CONFIG_P2P */
	}

	return ssid;
}