mirror of
				https://github.com/max-moser/network-manager-wireguard.git
				synced 2025-11-04 00:53:49 +03:00 
			
		
		
		
	Merge branch 'master' into master
This commit is contained in:
		
						commit
						0c23f17362
					
				
							
								
								
									
										18
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								README.md
									
									
									
									
									
								
							@ -26,7 +26,7 @@ Once the installation is completed, the Plugin can be used per NetworkManager (u
 | 
				
			|||||||
When a new WireGuard connection is created and configured via the NetworkManager GUI (can also be called via `nm-connection-editor`), it is the Connection Editor Plugin which is executed.
 | 
					When a new WireGuard connection is created and configured via the NetworkManager GUI (can also be called via `nm-connection-editor`), it is the Connection Editor Plugin which is executed.
 | 
				
			||||||
When the connection is activated, it is the service plugin that is being called.
 | 
					When the connection is activated, it is the service plugin that is being called.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
A very basic testing suite is provided in the form of the Python script `examples/dbus/dbus.py`, which looks up the Plugin via name on D-BUS and sends it a Connect() instruction. More or less the same thing (and more) can however be achieved by just using NetworkManager after installing the package, so there should not be a need for this - except for the fact that the script is easily modifiable.
 | 
					A very basic testing suite is provided in the form of the Python script `examples/dbus/dbus.py`, which looks up the Plugin via name on D-Bus and sends it a Connect() instruction. More or less the same thing (and more) can however be achieved by just using NetworkManager after installing the package, so there should not be a need for this - except for the fact that the script is easily modifiable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Viewing Logs
 | 
					### Viewing Logs
 | 
				
			||||||
@ -41,18 +41,18 @@ The logs that are created by NetworkManager can be viewed with `journalctl -u Ne
 | 
				
			|||||||
Over the course of the project, I created some files that are not required for the project itself, but rather for its development.  
 | 
					Over the course of the project, I created some files that are not required for the project itself, but rather for its development.  
 | 
				
			||||||
Here is a brief overview over some of them:
 | 
					Here is a brief overview over some of them:
 | 
				
			||||||
* `includes2strings.py`: Searches the input for `-I` flags (useful for extracting the include dirs from a Makefile)
 | 
					* `includes2strings.py`: Searches the input for `-I` flags (useful for extracting the include dirs from a Makefile)
 | 
				
			||||||
* `examples/dbus/dbus.py`: A small script that tests the availability of the Plugin and its responsiveness to D-BUS messages
 | 
					* `examples/dbus/dbus.py`: A small script that tests the availability of the Plugin and its responsiveness to D-Bus messages
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Configuration
 | 
					### Configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### D-BUS Allowance
 | 
					#### D-Bus Allowance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
D-BUS does not allow just anybody to own any D-BUS service name they like. Thus, it may be necessary to tell D-BUS that it is not forbidden to use the name `org.freedesktop.NetworkManager.wireguard`.  
 | 
					D-Bus does not allow just anybody to own any D-Bus service name they like. Thus, it may be necessary to tell D-Bus that it is not forbidden to use the name `org.freedesktop.NetworkManager.wireguard`.  
 | 
				
			||||||
This can be achieved by placing an appropriate file (like `nm-wireguard-service.conf`) inside the directory `/etc/dbus-1/system.d` or similar.
 | 
					This can be achieved by placing an appropriate file (like `nm-wireguard-service.conf`) inside the directory `/etc/dbus-1/system.d` or similar.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The following is an example for the content of such a file:
 | 
					The following is an example for the content of such a file:
 | 
				
			||||||
~~~~
 | 
					~~~~xml
 | 
				
			||||||
<!DOCTYPE busconfig PUBLIC
 | 
					<!DOCTYPE busconfig PUBLIC
 | 
				
			||||||
 "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 | 
					 "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 | 
				
			||||||
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
 | 
					 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
 | 
				
			||||||
@ -72,7 +72,7 @@ The following is an example for the content of such a file:
 | 
				
			|||||||
NetworkManager has to be told where the plugins live in order to be able to call them. This is done via `service.name` files, which usually reside in `/etc/NetworkManager/VPN` or `/usr/lib/NetworkManager/VPN` (e.g. `/usr/lib/NetworkManager/VPN/nm-wireguard-service.name`).
 | 
					NetworkManager has to be told where the plugins live in order to be able to call them. This is done via `service.name` files, which usually reside in `/etc/NetworkManager/VPN` or `/usr/lib/NetworkManager/VPN` (e.g. `/usr/lib/NetworkManager/VPN/nm-wireguard-service.name`).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
An example for the content of these files would be:
 | 
					An example for the content of these files would be:
 | 
				
			||||||
~~~~
 | 
					~~~~ini
 | 
				
			||||||
# This file is obsoleted by a file in /usr/local/lib/NetworkManager/VPN
 | 
					# This file is obsoleted by a file in /usr/local/lib/NetworkManager/VPN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[VPN Connection]
 | 
					[VPN Connection]
 | 
				
			||||||
@ -98,10 +98,10 @@ supports-hints=false
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### Service (the Plugin itself)
 | 
					### Service (the Plugin itself)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The service is responsible for setting up a VPN connection with the supplied parameters. For this, it has to implement a [D-BUS interface](https://developer.gnome.org/NetworkManager/stable/gdbus-org.freedesktop.NetworkManager.VPN.Plugin.html) and listen to incoming requests, which will be sent by NetworkManager in due time (i.e. when the user tells NM to set up the appropriate VPN connection).  
 | 
					The service is responsible for setting up a VPN connection with the supplied parameters. For this, it has to implement a [D-Bus interface](https://developer.gnome.org/NetworkManager/stable/gdbus-org.freedesktop.NetworkManager.VPN.Plugin.html) and listen to incoming requests, which will be sent by NetworkManager in due time (i.e. when the user tells NM to set up the appropriate VPN connection).  
 | 
				
			||||||
If the binary service is not running at the time when NM wants to set up the connection, it will try to start the binary ad hoc.
 | 
					If the binary service is not running at the time when NM wants to set up the connection, it will try to start the binary ad hoc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In principle, this piece of software can be written in any language, but in order to make the implementation sane, there should at least exist convenient D-BUS bindings for the language. Further, there are parts of the code already implemented in C, which might make it more convenient to just stick to that.
 | 
					In principle, this piece of software can be written in any language, but in order to make the implementation sane, there should at least exist convenient D-Bus bindings for the language. Further, there are parts of the code already implemented in C, which might make it more convenient to just stick to that.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Auth-Dialog
 | 
					### Auth-Dialog
 | 
				
			||||||
@ -157,7 +157,7 @@ Saved connections are stored in `/etc/NetworkManager/system-connections`, with o
 | 
				
			|||||||
This guarantees that nobody can have a look at the saved system-wide connections (and their stored secrets) that isn't supposed to.
 | 
					This guarantees that nobody can have a look at the saved system-wide connections (and their stored secrets) that isn't supposed to.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
An example of such a system-connection file would be (one can see that the user-input data is stored as key-value pairs with internally used keys in the vpn section):
 | 
					An example of such a system-connection file would be (one can see that the user-input data is stored as key-value pairs with internally used keys in the vpn section):
 | 
				
			||||||
~~~~
 | 
					~~~~ini
 | 
				
			||||||
[connection]
 | 
					[connection]
 | 
				
			||||||
id=wiretest
 | 
					id=wiretest
 | 
				
			||||||
uuid=8298d5ea-73d5-499b-9376-57409a7a2331
 | 
					uuid=8298d5ea-73d5-499b-9376-57409a7a2331
 | 
				
			||||||
 | 
				
			|||||||
@ -140,6 +140,11 @@ check_peer_public_key(const char *str){
 | 
				
			|||||||
static gboolean
 | 
					static gboolean
 | 
				
			||||||
check_interface_listen_port(const char *str)
 | 
					check_interface_listen_port(const char *str)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						// Listen port is not a required field according to man wg
 | 
				
			||||||
 | 
						if(is_empty(str)){
 | 
				
			||||||
 | 
							return TRUE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(!g_ascii_string_to_unsigned(str, 10, 0, 65535, NULL, NULL)){
 | 
						if(!g_ascii_string_to_unsigned(str, 10, 0, 65535, NULL, NULL)){
 | 
				
			||||||
		return FALSE;
 | 
							return FALSE;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -1064,13 +1064,6 @@ handle_line_error:
 | 
				
			|||||||
		goto out_error;
 | 
							goto out_error;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(!have_listen_port){
 | 
					 | 
				
			||||||
		g_set_error_literal(error, NMV_EDITOR_PLUGIN_ERROR, NMV_EDITOR_PLUGIN_ERROR_FAILED,
 | 
					 | 
				
			||||||
							"The file to import wasn't a valid Wireguard configuration (no local listen port)");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		goto out_error;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(!have_ip4_addr && !have_ip6_addr){
 | 
						if(!have_ip4_addr && !have_ip6_addr){
 | 
				
			||||||
		g_set_error_literal(error, NMV_EDITOR_PLUGIN_ERROR, NMV_EDITOR_PLUGIN_ERROR_FAILED,
 | 
							g_set_error_literal(error, NMV_EDITOR_PLUGIN_ERROR, NMV_EDITOR_PLUGIN_ERROR_FAILED,
 | 
				
			||||||
							"The file to import wasn't a valid Wireguard configuration (no local IPv4 or IPv6 addresses)");
 | 
												"The file to import wasn't a valid Wireguard configuration (no local IPv4 or IPv6 addresses)");
 | 
				
			||||||
@ -1154,6 +1147,7 @@ create_config_string (NMConnection *connection, GError **error)
 | 
				
			|||||||
	const char *endpoint;
 | 
						const char *endpoint;
 | 
				
			||||||
	const char *psk;
 | 
						const char *psk;
 | 
				
			||||||
	const char *pka;
 | 
						const char *pka;
 | 
				
			||||||
 | 
						const char *dns;
 | 
				
			||||||
	char *value = NULL;
 | 
						char *value = NULL;
 | 
				
			||||||
	char **ip_list, **ip_iter;
 | 
						char **ip_list, **ip_iter;
 | 
				
			||||||
	GArray *ips;
 | 
						GArray *ips;
 | 
				
			||||||
@ -1180,6 +1174,7 @@ create_config_string (NMConnection *connection, GError **error)
 | 
				
			|||||||
	endpoint    = _arg_is_set(nm_setting_vpn_get_data_item(s_vpn, NM_WG_KEY_ENDPOINT));
 | 
						endpoint    = _arg_is_set(nm_setting_vpn_get_data_item(s_vpn, NM_WG_KEY_ENDPOINT));
 | 
				
			||||||
	psk         = _arg_is_set(nm_setting_vpn_get_data_item(s_vpn, NM_WG_KEY_PRESHARED_KEY));
 | 
						psk         = _arg_is_set(nm_setting_vpn_get_data_item(s_vpn, NM_WG_KEY_PRESHARED_KEY));
 | 
				
			||||||
	pka         = _arg_is_set(nm_setting_vpn_get_data_item(s_vpn, NM_WG_KEY_PERSISTENT_KEEP_ALIVE));
 | 
						pka         = _arg_is_set(nm_setting_vpn_get_data_item(s_vpn, NM_WG_KEY_PERSISTENT_KEEP_ALIVE));
 | 
				
			||||||
 | 
						dns         = _arg_is_set(nm_setting_vpn_get_data_item(s_vpn, NM_WG_KEY_DNS));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(!ip4 && !ip6){
 | 
						if(!ip4 && !ip6){
 | 
				
			||||||
		g_set_error_literal(error,
 | 
							g_set_error_literal(error,
 | 
				
			||||||
@ -1189,14 +1184,6 @@ create_config_string (NMConnection *connection, GError **error)
 | 
				
			|||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(!listen_port){
 | 
					 | 
				
			||||||
		g_set_error_literal(error,
 | 
					 | 
				
			||||||
							NMV_EDITOR_PLUGIN_ERROR,
 | 
					 | 
				
			||||||
							NMV_EDITOR_PLUGIN_ERROR_FILE_NOT_VPN,
 | 
					 | 
				
			||||||
							"Connection was incomplete (missing local listen port)");
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(!private_key){
 | 
						if(!private_key){
 | 
				
			||||||
		g_set_error_literal(error,
 | 
							g_set_error_literal(error,
 | 
				
			||||||
							NMV_EDITOR_PLUGIN_ERROR,
 | 
												NMV_EDITOR_PLUGIN_ERROR,
 | 
				
			||||||
@ -1243,7 +1230,10 @@ create_config_string (NMConnection *connection, GError **error)
 | 
				
			|||||||
	args_write_line(f, value);
 | 
						args_write_line(f, value);
 | 
				
			||||||
	g_free(value);
 | 
						g_free(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(listen_port){
 | 
				
			||||||
		args_write_line(f, NMV_WG_TAG_LISTEN_PORT, "=", listen_port);
 | 
							args_write_line(f, NMV_WG_TAG_LISTEN_PORT, "=", listen_port);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(post_up){
 | 
						if(post_up){
 | 
				
			||||||
		args_write_line(f, NMV_WG_TAG_POST_UP, "=", post_up);
 | 
							args_write_line(f, NMV_WG_TAG_POST_UP, "=", post_up);
 | 
				
			||||||
@ -1259,6 +1249,10 @@ create_config_string (NMConnection *connection, GError **error)
 | 
				
			|||||||
	ip_list = g_strsplit_set (allowed_ips, " \t,", 0);
 | 
						ip_list = g_strsplit_set (allowed_ips, " \t,", 0);
 | 
				
			||||||
	ips = g_array_new(TRUE, TRUE, sizeof(char *));
 | 
						ips = g_array_new(TRUE, TRUE, sizeof(char *));
 | 
				
			||||||
	for (ip_iter = ip_list; ip_iter && *ip_iter; ip_iter++) {
 | 
						for (ip_iter = ip_list; ip_iter && *ip_iter; ip_iter++) {
 | 
				
			||||||
 | 
							// Using the g_strsplit_set call above can create zero length array elements if
 | 
				
			||||||
 | 
							// there is multiple separators such as both a comma and a space so we need to
 | 
				
			||||||
 | 
							// ignore any 0 length strings
 | 
				
			||||||
 | 
							if (0 != strlen(*ip_iter))
 | 
				
			||||||
			g_array_append_val(ips, *ip_iter);
 | 
								g_array_append_val(ips, *ip_iter);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -94,6 +94,7 @@ typedef struct _Configs{
 | 
				
			|||||||
	GVariant *config;
 | 
						GVariant *config;
 | 
				
			||||||
	GVariant *ip4config;
 | 
						GVariant *ip4config;
 | 
				
			||||||
	GVariant *ip6config;
 | 
						GVariant *ip6config;
 | 
				
			||||||
 | 
						GVariant *dns_config;
 | 
				
			||||||
} Configs;
 | 
					} Configs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
@ -346,13 +347,15 @@ set_config(NMVpnServicePlugin *plugin, NMConnection *connection)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	NMSettingVpn *s_vpn = nm_connection_get_setting_vpn(connection);
 | 
						NMSettingVpn *s_vpn = nm_connection_get_setting_vpn(connection);
 | 
				
			||||||
	GVariantBuilder builder, ip4builder, ip6builder;
 | 
						GVariantBuilder builder, ip4builder, ip6builder;
 | 
				
			||||||
	GVariant *config, *ip4config, *ip6config;
 | 
						GVariantBuilder dns_builder;
 | 
				
			||||||
 | 
						GVariant *config, *ip4config, *ip6config, *dns_config;
 | 
				
			||||||
	GVariant *val;
 | 
						GVariant *val;
 | 
				
			||||||
	const char *setting;
 | 
						const char *setting;
 | 
				
			||||||
	const gchar *if_name;
 | 
						const gchar *if_name;
 | 
				
			||||||
	guint64 subnet = 24;
 | 
						guint64 subnet = 24;
 | 
				
			||||||
	gboolean has_ip4 = FALSE;
 | 
						gboolean has_ip4 = FALSE;
 | 
				
			||||||
	gboolean has_ip6 = FALSE;
 | 
						gboolean has_ip6 = FALSE;
 | 
				
			||||||
 | 
						gboolean has_dns = FALSE;
 | 
				
			||||||
	Configs *configs = malloc(sizeof(Configs));
 | 
						Configs *configs = malloc(sizeof(Configs));
 | 
				
			||||||
	memset(configs, 0, sizeof(Configs));
 | 
						memset(configs, 0, sizeof(Configs));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -361,6 +364,7 @@ set_config(NMVpnServicePlugin *plugin, NMConnection *connection)
 | 
				
			|||||||
	g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
 | 
						g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
 | 
				
			||||||
	g_variant_builder_init(&ip4builder, G_VARIANT_TYPE_VARDICT);
 | 
						g_variant_builder_init(&ip4builder, G_VARIANT_TYPE_VARDICT);
 | 
				
			||||||
	g_variant_builder_init(&ip6builder, G_VARIANT_TYPE_VARDICT);
 | 
						g_variant_builder_init(&ip6builder, G_VARIANT_TYPE_VARDICT);
 | 
				
			||||||
 | 
						g_variant_builder_init(&dns_builder, G_VARIANT_TYPE_VARDICT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// build the configs
 | 
						// build the configs
 | 
				
			||||||
	setting = get_setting(s_vpn, NM_WG_KEY_ADDR_IP4);
 | 
						setting = get_setting(s_vpn, NM_WG_KEY_ADDR_IP4);
 | 
				
			||||||
@ -387,6 +391,9 @@ set_config(NMVpnServicePlugin *plugin, NMConnection *connection)
 | 
				
			|||||||
	setting = get_setting(s_vpn, NM_WG_KEY_DNS);
 | 
						setting = get_setting(s_vpn, NM_WG_KEY_DNS);
 | 
				
			||||||
	if(setting){
 | 
						if(setting){
 | 
				
			||||||
		// TODO
 | 
							// TODO
 | 
				
			||||||
 | 
							val = g_variant_new_string(setting);
 | 
				
			||||||
 | 
							g_variant_builder_add(&dns_builder, "{ss}", NMV_WG_TAG_DNS, val);
 | 
				
			||||||
 | 
							has_dns = TRUE;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setting = get_setting(s_vpn, NM_WG_KEY_ENDPOINT);
 | 
						setting = get_setting(s_vpn, NM_WG_KEY_ENDPOINT);
 | 
				
			||||||
@ -447,10 +454,12 @@ set_config(NMVpnServicePlugin *plugin, NMConnection *connection)
 | 
				
			|||||||
	config = g_variant_builder_end(&builder);
 | 
						config = g_variant_builder_end(&builder);
 | 
				
			||||||
	ip4config = g_variant_builder_end(&ip4builder);
 | 
						ip4config = g_variant_builder_end(&ip4builder);
 | 
				
			||||||
	ip6config = g_variant_builder_end(&ip6builder);
 | 
						ip6config = g_variant_builder_end(&ip6builder);
 | 
				
			||||||
 | 
						dns_config = g_variant_builder_end(&dns_builder);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// populate the configs struct and send the configuration asynchronously
 | 
						// populate the configs struct and send the configuration asynchronously
 | 
				
			||||||
	configs->ip4config = (has_ip4) ? ip4config : NULL;
 | 
						configs->ip4config = (has_ip4) ? ip4config : NULL;
 | 
				
			||||||
	configs->ip6config = (has_ip6) ? ip6config : NULL;
 | 
						configs->ip6config = (has_ip6) ? ip6config : NULL;
 | 
				
			||||||
 | 
						configs->dns_config = (has_dns) ? dns_config : NULL;
 | 
				
			||||||
	configs->plugin    = plugin;
 | 
						configs->plugin    = plugin;
 | 
				
			||||||
	configs->config    = config;
 | 
						configs->config    = config;
 | 
				
			||||||
	g_timeout_add(0, send_config, configs);
 | 
						g_timeout_add(0, send_config, configs);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user