Merge branch 'master' into nm-gtk-devel_missing

pull/22/head
Druco 2018-11-23 18:02:36 -08:00
commit 41e4873cc5
6 changed files with 125 additions and 11 deletions

View File

@ -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

View File

@ -2323,6 +2323,45 @@ config: http-proxy-retry or socks-proxy-retry</property>
<property name="position">4</property> <property name="position">4</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkBox" id="persistent-keep-alive">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Persis. Keepalive:</property>
<property name="width_chars">15</property>
<property name="max_width_chars">15</property>
<attributes>
<attribute name="underline" value="True"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="peer_persistent_keep_alive_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>

View File

@ -98,6 +98,19 @@ check_interface_mtu_entry(const char *str)
return TRUE; return TRUE;
} }
static gboolean
check_peer_persistent_keep_alive_entry(const char *str)
{
if(is_empty(str)){
return TRUE;
}
else if(!g_ascii_string_to_unsigned(str, 10, 0, 450, NULL, NULL)){
return FALSE;
}
return TRUE;
}
static gboolean static gboolean
check_peer_preshared_key(const char *str) check_peer_preshared_key(const char *str)
{ {
@ -274,6 +287,9 @@ check_validity (WireguardEditor *self, GError **error)
if(!check(priv, "peer_psk_entry", check_peer_preshared_key, NM_WG_KEY_PRESHARED_KEY, TRUE, error)){ if(!check(priv, "peer_psk_entry", check_peer_preshared_key, NM_WG_KEY_PRESHARED_KEY, TRUE, error)){
success = FALSE; success = FALSE;
} }
if(!check(priv, "peer_persistent_keep_alive_entry", check_peer_persistent_keep_alive_entry, NM_WG_KEY_PERSISTENT_KEEP_ALIVE, TRUE, error)){
success = FALSE;
}
// pre-up, post-up, pre-down, post-down are scripts and don't get validated // pre-up, post-up, pre-down, post-down are scripts and don't get validated
if(ip4_ok && ip6_ok){ if(ip4_ok && ip6_ok){
@ -364,7 +380,7 @@ init_editor_plugin (WireguardEditor *self, NMConnection *connection, GError **er
} }
g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self); g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
// Interface Private Key // Interface MTU
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_mtu_entry")); widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_mtu_entry"));
g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (widget != NULL, FALSE);
if (s_vpn) { if (s_vpn) {
@ -444,6 +460,15 @@ init_editor_plugin (WireguardEditor *self, NMConnection *connection, GError **er
} }
g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self); g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
// Peer Persistent Keep Alive
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "peer_persistent_keep_alive_entry"));
g_return_val_if_fail (widget != NULL, FALSE);
if (s_vpn) {
value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_PERSISTENT_KEEP_ALIVE);
if (value)
gtk_entry_set_text (GTK_ENTRY (widget), value);
}
g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
// Peer Public Key // Peer Public Key
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "peer_public_key_entry")); widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "peer_public_key_entry"));
@ -607,6 +632,13 @@ update_connection (NMVpnEditor *iface,
if (str && str[0]){ if (str && str[0]){
nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_ENDPOINT, str); nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_ENDPOINT, str);
} }
// persistent keep alive
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "peer_persistent_keep_alive_entry"));
str = gtk_entry_get_text (GTK_ENTRY (widget));
if (str && str[0]){
nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_PERSISTENT_KEEP_ALIVE, str);
}
nm_connection_add_setting (connection, NM_SETTING (s_vpn)); nm_connection_add_setting (connection, NM_SETTING (s_vpn));
valid = TRUE; valid = TRUE;

View File

@ -567,6 +567,30 @@ parse_mtu(const char **line, guint64 *mtu, char **out_error)
return success; return success;
} }
// parse Persistent Keep Alive value (max 0-5min? (450))
static gboolean
parse_persistent_keep_alive(const char **line, guint64 *pka, char **out_error)
{
int idx = 0;
char *tmp = NULL;
gboolean success = TRUE;
if(!_parse_common(line, &idx, out_error)){
return FALSE;
}
tmp = g_strdup(line[idx]);
if(!g_ascii_string_to_unsigned(tmp, 10, 0, 450, pka, NULL)){
*out_error = g_strdup_printf("'%s' is not a valid Persistent Keep Alive assignment! (max '%d')", tmp, 450);
*pka = -1;
success = FALSE;
}
g_free(tmp);
return success;
}
// parse the line and check if there were any IP4 and IP6 included // parse the line and check if there were any IP4 and IP6 included
// (if there are more than just one IP4, the later take precedence; same for IP6) // (if there are more than just one IP4, the later take precedence; same for IP6)
// //
@ -876,7 +900,7 @@ do_import (const char *path, const char *contents, gsize contents_len, GError **
} }
setting_vpn_add_data_item_int64(s_vpn, NM_WG_KEY_MTU, mtu); setting_vpn_add_data_item_int64(s_vpn, NM_WG_KEY_MTU, mtu);
printf("%s = %ld\n", NM_WG_KEY_DNS, mtu); printf("%s = %ld\n", NMV_WG_TAG_MTU, mtu);
continue; continue;
} }
@ -1005,6 +1029,17 @@ do_import (const char *path, const char *contents, gsize contents_len, GError **
printf("%s = %s\n", NMV_WG_TAG_PRESHARED_KEY, psk); printf("%s = %s\n", NMV_WG_TAG_PRESHARED_KEY, psk);
continue; continue;
} }
if (NM_IN_STRSET (params[0], NMV_WG_TAG_PERSISTENT_KEEP_ALIVE)){
guint64 pka = 0;
if(!parse_persistent_keep_alive(params, &pka, &line_error)){
goto handle_line_error;
}
setting_vpn_add_data_item_int64(s_vpn, NM_WG_KEY_PERSISTENT_KEEP_ALIVE, pka);
printf("%s = %lu\n", NMV_WG_TAG_PERSISTENT_KEEP_ALIVE, pka);
continue;
}
/* currently we ignore any unknown options and skip over them. */ /* currently we ignore any unknown options and skip over them. */
continue; continue;
@ -1111,6 +1146,7 @@ create_config_string (NMConnection *connection, GError **error)
const char *allowed_ips; const char *allowed_ips;
const char *endpoint; const char *endpoint;
const char *psk; const char *psk;
const char *pka;
const char *dns; const char *dns;
char *value = NULL; char *value = NULL;
char **ip_list, **ip_iter; char **ip_list, **ip_iter;
@ -1137,6 +1173,7 @@ create_config_string (NMConnection *connection, GError **error)
allowed_ips = _arg_is_set(nm_setting_vpn_get_data_item(s_vpn, NM_WG_KEY_ALLOWED_IPS)); allowed_ips = _arg_is_set(nm_setting_vpn_get_data_item(s_vpn, NM_WG_KEY_ALLOWED_IPS));
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));
dns = _arg_is_set(nm_setting_vpn_get_data_item(s_vpn, NM_WG_KEY_DNS)); dns = _arg_is_set(nm_setting_vpn_get_data_item(s_vpn, NM_WG_KEY_DNS));
if(!ip4 && !ip6){ if(!ip4 && !ip6){
@ -1229,6 +1266,10 @@ create_config_string (NMConnection *connection, GError **error)
if(psk){ if(psk){
args_write_line(f, NMV_WG_TAG_PRESHARED_KEY, "=", psk); args_write_line(f, NMV_WG_TAG_PRESHARED_KEY, "=", psk);
} }
if(pka && *pka > 0){
args_write_line(f, NMV_WG_TAG_PERSISTENT_KEEP_ALIVE, "=", pka);
}
return g_steal_pointer (&f); return g_steal_pointer (&f);
} }

View File

@ -42,6 +42,7 @@
#define NM_WG_KEY_ALLOWED_IPS "peer-allowed-ips" #define NM_WG_KEY_ALLOWED_IPS "peer-allowed-ips"
#define NM_WG_KEY_ENDPOINT "peer-endpoint" #define NM_WG_KEY_ENDPOINT "peer-endpoint"
#define NM_WG_KEY_PRESHARED_KEY "peer-preshared-key" #define NM_WG_KEY_PRESHARED_KEY "peer-preshared-key"
#define NM_WG_KEY_PERSISTENT_KEEP_ALIVE "peer-persistent-keep-alive"
#define NM_OPENVPN_KEY_AUTH "auth" #define NM_OPENVPN_KEY_AUTH "auth"
#define NM_OPENVPN_KEY_CA "ca" #define NM_OPENVPN_KEY_CA "ca"

View File

@ -37,6 +37,7 @@
#define NMV_WG_TAG_PUBLIC_KEY "PublicKey" #define NMV_WG_TAG_PUBLIC_KEY "PublicKey"
#define NMV_WG_TAG_ALLOWED_IPS "AllowedIPs" #define NMV_WG_TAG_ALLOWED_IPS "AllowedIPs"
#define NMV_WG_TAG_ENDPOINT "Endpoint" #define NMV_WG_TAG_ENDPOINT "Endpoint"
#define NMV_WG_TAG_PERSISTENT_KEEP_ALIVE "PersistentKeepalive"
#define NMV_OVPN_TAG_AUTH "auth" #define NMV_OVPN_TAG_AUTH "auth"
#define NMV_OVPN_TAG_AUTH_NOCACHE "auth-nocache" #define NMV_OVPN_TAG_AUTH_NOCACHE "auth-nocache"