/**
 * wpas_dbus_global_get_interface - Get the object path for an interface name
 * @message: Pointer to incoming dbus message
 * @global: %wpa_supplicant global data structure
 * Returns: The object path of the interface object,
 *          or a dbus error message with more information
 *
 * Handler function for "getInterface" method call. Handles requests
 * by dbus clients for the object path of an specific network interface.
 */
DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message,
					     struct wpa_global *global)
{
	DBusMessage *reply = NULL;
	const char *ifname;
	const char *path;
	struct wpa_supplicant *wpa_s;

	if (!dbus_message_get_args(message, NULL,
	                           DBUS_TYPE_STRING, &ifname,
	                           DBUS_TYPE_INVALID)) {
		reply = wpas_dbus_new_invalid_opts_error(message, NULL);
		goto out;
	}

	wpa_s = wpa_supplicant_get_iface(global, ifname);
	if (wpa_s == NULL) {
		reply = wpas_dbus_new_invalid_iface_error(message);
		goto out;
	}

	path = wpa_s->dbus_path;
	reply = dbus_message_new_method_return(message);
	dbus_message_append_args(reply,
	                         DBUS_TYPE_OBJECT_PATH, &path,
	                         DBUS_TYPE_INVALID);

out:
	return reply;
}
status_t
WPASupplicantApp::_NotifyNetworkEvent(BMessage *message)
{
	// Verify that the interface is still there.
	BString interfaceName;
	if (message->FindString("interface", &interfaceName) != B_OK)
		return B_ERROR;

	interfaceName.Prepend("/dev/");
	wpa_supplicant *interface = wpa_supplicant_get_iface(fWPAGlobal,
		interfaceName.String());
	if (interface == NULL)
		return B_ENTRY_NOT_FOUND;

	void (*callback)(void *context, void *data, int opcode) = NULL;
	status_t result = message->FindPointer("callback", (void **)&callback);
	if (result != B_OK)
		return result;

	void *context = NULL;
	result = message->FindPointer("context", &context);
	if (result != B_OK)
		return result;

	void *data = NULL;
	message->FindPointer("data", &data);

	callback(context, data, message->FindInt32("opcode"));
	return B_OK;
}
Beispiel #3
0
static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
					      char *cmd)
{
	struct wpa_supplicant *wpa_s;

	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);

	wpa_s = wpa_supplicant_get_iface(global, cmd);
	if (wpa_s == NULL)
		return -1;
	return wpa_supplicant_remove_iface(global, wpa_s);
}
status_t
WPASupplicantApp::_LeaveNetwork(BMessage *message)
{
	const char *interfaceName = NULL;
	status_t status = message->FindString("device", &interfaceName);
	if (status != B_OK)
		return status;

	wpa_supplicant *interface = wpa_supplicant_get_iface(fWPAGlobal,
		interfaceName);
	if (interface == NULL)
		return B_ENTRY_NOT_FOUND;

	if (wpa_supplicant_remove_iface(fWPAGlobal, interface, 0) != 0)
		return B_ERROR;

	return B_OK;
}
Beispiel #5
0
static int wpa_supplicant_global_iface_add(struct wpa_global *global,
					   char *cmd)
{
	struct wpa_interface iface;
	char *pos;

	/*
	 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
	 * TAB<bridge_ifname>
	 */
	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);

	os_memset(&iface, 0, sizeof(iface));

	do {
		iface.ifname = pos = cmd;
		pos = os_strchr(pos, '\t');
		if (pos)
			*pos++ = '\0';
		if (iface.ifname[0] == '\0')
			return -1;
		if (pos == NULL)
			break;

		iface.confname = pos;
		pos = os_strchr(pos, '\t');
		if (pos)
			*pos++ = '\0';
		if (iface.confname[0] == '\0')
			iface.confname = NULL;
		if (pos == NULL)
			break;

		iface.driver = pos;
		pos = os_strchr(pos, '\t');
		if (pos)
			*pos++ = '\0';
		if (iface.driver[0] == '\0')
			iface.driver = NULL;
		if (pos == NULL)
			break;

		iface.ctrl_interface = pos;
		pos = os_strchr(pos, '\t');
		if (pos)
			*pos++ = '\0';
		if (iface.ctrl_interface[0] == '\0')
			iface.ctrl_interface = NULL;
		if (pos == NULL)
			break;

		iface.driver_param = pos;
		pos = os_strchr(pos, '\t');
		if (pos)
			*pos++ = '\0';
		if (iface.driver_param[0] == '\0')
			iface.driver_param = NULL;
		if (pos == NULL)
			break;

		iface.bridge_ifname = pos;
		pos = os_strchr(pos, '\t');
		if (pos)
			*pos++ = '\0';
		if (iface.bridge_ifname[0] == '\0')
			iface.bridge_ifname = NULL;
		if (pos == NULL)
			break;
	} while (0);

	if (wpa_supplicant_get_iface(global, iface.ifname))
		return -1;

	return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
}
/**
 * wpas_dbus_global_add_interface - Request registration of a network interface
 * @message: Pointer to incoming dbus message
 * @global: %wpa_supplicant global data structure
 * Returns: The object path of the new interface object,
 *          or a dbus error message with more information
 *
 * Handler function for "addInterface" method call. Handles requests
 * by dbus clients to register a network interface that wpa_supplicant
 * will manage.
 */
DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message,
					     struct wpa_global *global)
{
	char *ifname = NULL;
	char *driver = NULL;
	char *driver_param = NULL;
	char *confname = NULL;
	char *bridge_ifname = NULL;
	DBusMessage *reply = NULL;
	DBusMessageIter iter;

	dbus_message_iter_init(message, &iter);

	/* First argument: interface name (DBUS_TYPE_STRING)
	 *    Required; must be non-zero length
	 */
	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
		goto error;
	dbus_message_iter_get_basic(&iter, &ifname);
	if (!os_strlen(ifname))
		goto error;

	/* Second argument: dict of options */
	if (dbus_message_iter_next(&iter)) {
		DBusMessageIter iter_dict;
		struct wpa_dbus_dict_entry entry;

		if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
			goto error;
		while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
			if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
				goto error;
			if (!strcmp(entry.key, "driver") &&
			    (entry.type == DBUS_TYPE_STRING)) {
				driver = os_strdup(entry.str_value);
				wpa_dbus_dict_entry_clear(&entry);
				if (driver == NULL)
					goto error;
			} else if (!strcmp(entry.key, "driver-params") &&
				   (entry.type == DBUS_TYPE_STRING)) {
				driver_param = os_strdup(entry.str_value);
				wpa_dbus_dict_entry_clear(&entry);
				if (driver_param == NULL)
					goto error;
			} else if (!strcmp(entry.key, "config-file") &&
				   (entry.type == DBUS_TYPE_STRING)) {
				confname = os_strdup(entry.str_value);
				wpa_dbus_dict_entry_clear(&entry);
				if (confname == NULL)
					goto error;
			} else if (!strcmp(entry.key, "bridge-ifname") &&
				   (entry.type == DBUS_TYPE_STRING)) {
				bridge_ifname = os_strdup(entry.str_value);
				wpa_dbus_dict_entry_clear(&entry);
				if (bridge_ifname == NULL)
					goto error;
			} else {
				wpa_dbus_dict_entry_clear(&entry);
				goto error;
			}
		}
	}

	/*
	 * Try to get the wpa_supplicant record for this iface, return
	 * an error if we already control it.
	 */
	if (wpa_supplicant_get_iface(global, ifname) != NULL) {
		reply = dbus_message_new_error(message,
					       WPAS_ERROR_EXISTS_ERROR,
					       "wpa_supplicant already "
					       "controls this interface.");
	} else {
		struct wpa_supplicant *wpa_s;
		struct wpa_interface iface;
		os_memset(&iface, 0, sizeof(iface));
		iface.ifname = ifname;
		iface.driver = driver;
		iface.driver_param = driver_param;
		iface.confname = confname;
		iface.bridge_ifname = bridge_ifname;
		/* Otherwise, have wpa_supplicant attach to it. */
		if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
			const char *path = wpa_s->dbus_path;
			reply = dbus_message_new_method_return(message);
			dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
			                         &path, DBUS_TYPE_INVALID);
		} else {
			reply = dbus_message_new_error(message,
						       WPAS_ERROR_ADD_ERROR,
						       "wpa_supplicant "
						       "couldn't grab this "
						       "interface.");
		}
	}

out:
	os_free(driver);
	os_free(driver_param);
	os_free(confname);
	os_free(bridge_ifname);
	return reply;

error:
	reply = wpas_dbus_new_invalid_opts_error(message, NULL);
	goto out;
}
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;
}