From 3bb3c292bb683f9e439cf7009fc563e51b69f865 Mon Sep 17 00:00:00 2001 From: Max Moser Date: Wed, 7 Feb 2018 21:05:54 +0100 Subject: [PATCH] Change Editor UI for Wireguard --- properties/nm-openvpn-dialog.ui | 1291 ++++++++----------------------- properties/nm-openvpn-editor.c | 255 +++++- 2 files changed, 565 insertions(+), 981 deletions(-) diff --git a/properties/nm-openvpn-dialog.ui b/properties/nm-openvpn-dialog.ui index 85fe5f6..6a7ad91 100644 --- a/properties/nm-openvpn-dialog.ui +++ b/properties/nm-openvpn-dialog.ui @@ -117,922 +117,6 @@ - - True - False - 12 - vertical - 16 - - - True - False - vertical - 6 - - - True - False - General - 0 - - - - - - False - False - 0 - - - - - True - False - 12 - - - True - False - 6 - 12 - - - True - False - _Gateway: - True - 0 - - - 0 - 0 - - - - - True - True - Remote gateway(s), with optional port and protocol (e.g. ovpn.corp.com:1234:tcp). You can specify multiple hosts for redundancy (use commas or spaces as delimiters). -config: remote - True - - - 1 - 0 - - - - - - - True - True - 1 - - - - - False - True - 0 - - - - - True - False - vertical - 6 - - - True - False - Authentication - 0 - - - - - - False - False - 0 - - - - - True - False - 12 - - - True - False - 6 - 12 - - - True - False - False - False - - - True - False - start - vertical - 6 - - - True - False - CA - 5 - - - False - True - 0 - - - - - True - False - User - 4 - - - False - True - 1 - - - - - - - True - False - page 1 - - - False - - - - - True - False - start - vertical - 6 - - - True - False - 6 - 12 - - - True - False - Password: - 0 - - - 0 - 1 - - - - - True - False - User name: - 0 - - - 0 - 0 - - - - - True - True - Password passed to OpenVPN when prompted for it. -config: auth-user-pass - True - False - - - 1 - 1 - 2 - - - - - True - True - Username passed to OpenVPN when prompted for it. -config: auth-user-pass - True - - - 1 - 0 - 2 - - - - - False - True - 0 - - - - - True - False - CA - 5 - - - False - True - 1 - - - - - 1 - - - - - True - False - page 2 - - - 1 - False - - - - - True - False - start - vertical - 6 - - - True - False - 6 - 12 - - - True - False - Password: - 0 - - - 0 - 1 - - - - - True - False - User name: - 0 - - - 0 - 0 - - - - - True - True - Password passed to OpenVPN when prompted for it. -config: auth-user-pass - True - False - - - 1 - 1 - 2 - - - - - True - True - Username passed to OpenVPN when prompted for it. -config: auth-user-pass - True - - - 1 - 0 - 2 - - - - - False - True - 0 - - - - - True - False - CA - 5 - - - False - True - 1 - - - - - True - False - User - 4 - - - False - True - 2 - - - - - 2 - - - - - True - False - page 3 - - - 2 - False - - - - - True - False - 6 - 12 - - - True - False - Remote IP Address: - right - 0 - - - 0 - 3 - - - - - True - False - Local IP Address: - right - 0 - - - 0 - 4 - - - - - True - False - Key Direction: - 0 - - - 0 - 1 - - - - - True - False - Static Key: - 0 - - - 0 - 0 - - - - - True - False - Pre-shared file for Static Key encryption mode (non-TLS). -config: static <file> - - - 1 - 0 - - - - - True - True - IP address of the remote VPN endpoint. -config: ifconfig <l> <rn> - True - - - 1 - 3 - - - - - True - True - IP address of the local VPN endpoint. -config: ifconfig <l> <rn> - True - - - 1 - 4 - - - - - True - False - Direction for Static Key encryption mode (non-TLS). -If key direction is used, it must be the opposite of that used on the VPN peer. For example, if the peer uses “1”, this connection must use “0”. If you are unsure what value to use, contact your system administrator. -config: static <file> [direction] - model1 - - - - 0 - - - - - 1 - 1 - - - - - - - - - - - 3 - - - - - True - False - page 4 - - - 3 - False - - - - - 0 - 1 - 2 - - - - - True - False - Type: - 0 - - - 0 - 0 - - - - - True - False - Select an authentication mode. - True - model2 - - - - 0 - - - - - 1 - 0 - - - - - - - False - False - 1 - - - - - False - False - 1 - - - - - True - False - vertical - 5 - - - True - False - Interface - 0 - - - - - - False - True - 0 - - - - - True - False - - - True - False - Address (IPv4): - 15 - 15 - - - False - False - 0 - - - - - True - True - - - True - True - 1 - - - - - False - True - 1 - - - - - True - False - - - True - False - Private Key: - 15 - 15 - - - False - False - 0 - - - - - True - True - - - True - True - 1 - - - - - False - True - 2 - - - - - True - False - - - True - False - Listen Port: - 15 - 15 - - - False - False - 0 - - - - - True - True - - - True - True - 1 - - - - - False - True - 3 - - - - - False - True - 2 - - - - - True - False - 1 - 0 - - - False - True - True - False - - - True - False - 6 - - - True - False - gtk-preferences - - - False - False - 0 - - - - - True - False - Ad_vanced… - True - - - False - False - 1 - - - - - - - - - False - False - end - 3 - - - - - True - False - vertical - 5 - - - True - False - Peer - 0 - - - - - - False - True - 0 - - - - - True - False - - - True - False - Public Key: - 15 - 15 - - - False - False - 0 - - - - - True - True - - - True - True - 1 - - - - - False - True - 1 - - - - - True - False - - - True - False - Allowed IPs: - 15 - 15 - - - False - False - 0 - - - - - True - True - - - True - True - 1 - - - - - False - True - 2 - - - - - True - False - - - True - False - Endpoint: - 15 - 15 - - - False - False - 0 - - - - - True - True - - - True - True - 1 - - - - - False - True - 3 - - - - - False - True - 4 - - - - - True - - - - - - - - - - - - - @@ -1574,53 +658,6 @@ config: tun-ipv6 9 - - - True - False - 6 - - - Specify pin_g interval: - False - True - True - False - Ping remote over the TCP/UDP control channel if no packets have been sent for at least n seconds. -config: ping <n> - True - 0.5 - True - - - False - True - 0 - - - - - True - True - Ping remote over the TCP/UDP control channel if no packets have been sent for at least n seconds. -config: ping <n> - adjustment7 - 1 - True - - - False - False - 1 - - - - - False - True - 10 - - True @@ -1688,6 +725,53 @@ config: ping-exit | ping-restart <n> 10 + + + True + False + 6 + + + Specify pin_g interval: + False + True + True + False + Ping remote over the TCP/UDP control channel if no packets have been sent for at least n seconds. +config: ping <n> + True + 0.5 + True + + + False + True + 0 + + + + + True + True + Ping remote over the TCP/UDP control channel if no packets have been sent for at least n seconds. +config: ping <n> + adjustment7 + 1 + True + + + False + False + 1 + + + + + False + True + 10 + + Accept authenticated packets from any address (F_loat) @@ -2640,4 +1724,285 @@ config: http-proxy-retry or socks-proxy-retry + + True + False + 12 + vertical + 16 + + + True + False + vertical + 5 + + + True + False + Interface + 0 + + + + + + False + True + 0 + + + + + True + False + + + True + False + Address (IPv4): + 15 + 15 + + + False + False + 0 + + + + + True + True + + + True + True + 1 + + + + + False + True + 1 + + + + + True + False + + + True + False + Private Key: + 15 + 15 + + + False + False + 0 + + + + + True + True + + + True + True + 1 + + + + + False + True + 2 + + + + + True + False + + + True + False + Listen Port: + 15 + 15 + + + False + False + 0 + + + + + True + True + + + True + True + 1 + + + + + False + True + 3 + + + + + False + True + 2 + + + + + True + False + vertical + 5 + + + True + False + Peer + 0 + + + + + + False + True + 0 + + + + + True + False + + + True + False + Public Key: + 15 + 15 + + + False + False + 0 + + + + + True + True + + + True + True + 1 + + + + + False + True + 1 + + + + + True + False + + + True + False + Allowed IPs: + 15 + 15 + + + False + False + 0 + + + + + True + True + + + True + True + 1 + + + + + False + True + 2 + + + + + True + False + + + True + False + Endpoint: + 15 + 15 + + + False + False + 0 + + + + + True + True + + + True + True + 1 + + + + + False + True + 3 + + + + + False + True + 4 + + + diff --git a/properties/nm-openvpn-editor.c b/properties/nm-openvpn-editor.c index 81dcdfa..f35dec7 100644 --- a/properties/nm-openvpn-editor.c +++ b/properties/nm-openvpn-editor.c @@ -65,6 +65,85 @@ typedef struct { #define COL_AUTH_PAGE 1 #define COL_AUTH_TYPE 2 +static gboolean +check_interface_ip4_entry(const char *str) +{ + gs_free char *str_clone = NULL; + char *str_iter; + const char *tok; + int count = 0; + + if(!str || !str[0]) { + return FALSE; + } + + str_clone = g_strdup(str); + str_iter = str_clone; + while((tok = strsep(&str_iter, "."))){ + count ++; + // each number in an IP4 must be: 0 <= X <= 255 + if(!g_ascii_string_to_unsigned(tok, 10, 0, 255, NULL, NULL)){ + return FALSE; + } + } + + // an IP4 consists of 4 segments + if(count != 4){ + return FALSE; + } + + return TRUE; +} + +static gboolean +check_interface_private_key(const char *str) +{ + gs_free char *str_clone = NULL; + str_clone = g_strdup(str); + str_clone = g_strstrip(str_clone); + + if(!g_strcmp0("", str_clone)){ + return FALSE; + } + + // TODO + return TRUE; +} + +static gboolean +check_interface_listen_port(const char *str) +{ + gs_free char *str_clone = NULL; + str_clone = g_strdup(str); + + if(!g_ascii_string_to_unsigned(str_clone, 10, 0, 65535, NULL, NULL)){ + return FALSE; + } + + return TRUE; +} + +static gboolean +check_peer_public_key(const char *str) +{ + // TODO + return check_interface_private_key(str); +} + +static gboolean +check_peer_allowed_ips(const char *str) +{ + // TODO + return check_interface_ip4_entry(str); +} + +static gboolean +check_peer_endpoint(const char *str) +{ + // TODO + return check_interface_ip4_entry(str); +} + static gboolean check_gateway_entry (const char *str) { @@ -92,30 +171,64 @@ check_gateway_entry (const char *str) return success; } +typedef gboolean (*CheckFunc)(const char *str); + +// helper function to reduce boilerplate code in 'check_validity()' +static gboolean +check (OpenvpnEditorPrivate *priv, char *widget_name, CheckFunc chk, GError **error) +{ + const char *str; + GtkWidget *widget; + widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, widget_name)); + str = gtk_entry_get_text (GTK_ENTRY (widget)); + if (str && chk(str)) + gtk_style_context_remove_class (gtk_widget_get_style_context (widget), "error"); + else { + gtk_style_context_add_class (gtk_widget_get_style_context (widget), "error"); + // only set the error if it's NULL + if(error == NULL){ + g_set_error (error, + NMV_EDITOR_PLUGIN_ERROR, + NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY, + NM_WG_KEY_ADDR_IP4); + } + return FALSE; + } + + return TRUE; +} + static gboolean check_validity (OpenvpnEditor *self, GError **error) { OpenvpnEditorPrivate *priv = OPENVPN_EDITOR_GET_PRIVATE (self); - GtkWidget *widget; const char *str; GtkTreeModel *model; GtkTreeIter iter; const char *contype = NULL; gboolean success; - widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "gateway_entry")); - str = gtk_entry_get_text (GTK_ENTRY (widget)); - if (str && check_gateway_entry (str)) - gtk_style_context_remove_class (gtk_widget_get_style_context (widget), "error"); - else { - gtk_style_context_add_class (gtk_widget_get_style_context (widget), "error"); - g_set_error (error, - NMV_EDITOR_PLUGIN_ERROR, - NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY, - NM_OPENVPN_KEY_REMOTE); - return FALSE; + // check the various input fields for errors + if(!check(priv, "interface_ip4_entry", check_interface_ip4_entry, error)){ + success = FALSE; + } + if(!check(priv, "interface_private_key_entry", check_interface_private_key, error)){ + success = FALSE; + } + if(!check(priv, "interface_port_entry", check_interface_listen_port, error)){ + success = FALSE; + } + if(!check(priv, "peer_public_key_entry", check_peer_public_key, error)){ + success = FALSE; + } + if(!check(priv, "peer_allowed_ips_entry", check_peer_allowed_ips, error)){ + success = FALSE; + } + if(!check(priv, "peer_endpoint_entry", check_peer_endpoint, error)){ + success = FALSE; } + /* widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "auth_combo")); model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget)); g_return_val_if_fail (model, FALSE); @@ -124,8 +237,9 @@ check_validity (OpenvpnEditor *self, GError **error) gtk_tree_model_get (model, &iter, COL_AUTH_TYPE, &contype, -1); if (!auth_widget_check_validity (priv->builder, contype, error)) return FALSE; + */ - return TRUE; + return success; } static void @@ -243,20 +357,76 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection, GError **erro s_vpn = nm_connection_get_setting_vpn (connection); - widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "gateway_entry")); + // Local IPv4 address + widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_ip4_entry")); g_return_val_if_fail (widget != NULL, FALSE); if (s_vpn) { - value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_REMOTE); + value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_ADDR_IP4); if (value) gtk_entry_set_text (GTK_ENTRY (widget), value); } g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self); + // Interface Private Key + widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_private_key_entry")); + g_return_val_if_fail (widget != NULL, FALSE); + if (s_vpn) { + value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_ADDR_IP4); + if (value) + gtk_entry_set_text (GTK_ENTRY (widget), value); + } + g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self); + + // Interface Listening Port + widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_port_entry")); + g_return_val_if_fail (widget != NULL, FALSE); + if (s_vpn) { + value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_ADDR_IP4); + 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 + widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "peer_public_key_entry")); + g_return_val_if_fail (widget != NULL, FALSE); + if (s_vpn) { + value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_ADDR_IP4); + if (value) + gtk_entry_set_text (GTK_ENTRY (widget), value); + } + g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self); + + // Peer Allowed IPs + widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "peer_allowed_ips_entry")); + g_return_val_if_fail (widget != NULL, FALSE); + if (s_vpn) { + value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_ADDR_IP4); + if (value) + gtk_entry_set_text (GTK_ENTRY (widget), value); + } + g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self); + + // Peer Endpoint + widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "peer_endpoint_entry")); + g_return_val_if_fail (widget != NULL, FALSE); + if (s_vpn) { + value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_ADDR_IP4); + if (value) + gtk_entry_set_text (GTK_ENTRY (widget), value); + } + g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self); + + + /* widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "auth_combo")); g_return_val_if_fail (widget != NULL, FALSE); store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING); + */ + /* if (s_vpn) { contype = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE); if (contype) { @@ -268,8 +438,10 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection, GError **erro } else contype = NM_OPENVPN_CONTYPE_TLS; } + */ /* TLS auth widget */ + /* tls_pw_init_auth_widget (priv->builder, s_vpn, NM_OPENVPN_CONTYPE_TLS, "tls", stuff_changed_cb, self); @@ -279,8 +451,10 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection, GError **erro COL_AUTH_PAGE, 0, COL_AUTH_TYPE, NM_OPENVPN_CONTYPE_TLS, -1); + */ /* Password auth widget */ + /* tls_pw_init_auth_widget (priv->builder, s_vpn, NM_OPENVPN_CONTYPE_PASSWORD, "pw", stuff_changed_cb, self); @@ -292,8 +466,10 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection, GError **erro -1); if ((active < 0) && !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD)) active = 1; + */ /* Password+TLS auth widget */ + /* tls_pw_init_auth_widget (priv->builder, s_vpn, NM_OPENVPN_CONTYPE_PASSWORD_TLS, "pw_tls", stuff_changed_cb, self); @@ -305,8 +481,10 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection, GError **erro -1); if ((active < 0) && !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)) active = 2; + */ /* Static key auth widget */ + /* sk_init_auth_widget (priv->builder, s_vpn, stuff_changed_cb, self); gtk_list_store_append (store, &iter); @@ -325,6 +503,7 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection, GError **erro widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "advanced_button")); g_signal_connect (G_OBJECT (widget), "clicked", G_CALLBACK (advanced_button_clicked_cb), self); + */ return TRUE; } @@ -391,22 +570,58 @@ update_connection (NMVpnEditor *iface, s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ()); g_object_set (s_vpn, NM_SETTING_VPN_SERVICE_TYPE, NM_VPN_SERVICE_TYPE_OPENVPN, NULL); - widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "gateway_entry")); + // local ip4 + widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_ip4_entry")); str = gtk_entry_get_text (GTK_ENTRY (widget)); if (str && str[0]) - nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_REMOTE, str); + nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_ADDR_IP4, str); + // private key + widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_private_key_entry")); + str = gtk_entry_get_text (GTK_ENTRY (widget)); + if (str && str[0]) + nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_PRIVATE_KEY, str); + + // listen port + widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_port_entry")); + str = gtk_entry_get_text (GTK_ENTRY (widget)); + if (str && str[0]) + nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_LISTEN_PORT, str); + + // peer public key + widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "peer_public_key_entry")); + str = gtk_entry_get_text (GTK_ENTRY (widget)); + if (str && str[0]) + nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_PUBLIC_KEY, str); + + // allowed IPs + widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "peer_allowed_ips_entry")); + str = gtk_entry_get_text (GTK_ENTRY (widget)); + if (str && str[0]) + nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_ALLOWED_IPS, str); + + // endpoint + widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "peer_endpoint_entry")); + str = gtk_entry_get_text (GTK_ENTRY (widget)); + if (str && str[0]) + nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_ENDPOINT, str); + + /* auth_type = get_auth_type (priv->builder); if (auth_type) { nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE, auth_type); auth_widget_update_connection (priv->builder, auth_type, s_vpn); g_free (auth_type); } + */ + /* if (priv->advanced) g_hash_table_foreach (priv->advanced, hash_copy_advanced, s_vpn); + */ /* Default to agent-owned secrets for new connections */ + /* if (priv->new_connection) { if (nm_setting_vpn_get_secret (s_vpn, NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD)) { nm_setting_set_secret_flags (NM_SETTING (s_vpn), @@ -429,6 +644,7 @@ update_connection (NMVpnEditor *iface, NULL); } } + */ nm_connection_add_setting (connection, NM_SETTING (s_vpn)); valid = TRUE; @@ -480,7 +696,7 @@ openvpn_editor_new (NMConnection *connection, GError **error) g_return_val_if_reached (NULL); } - priv->widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "openvpn-vbox")); + priv->widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "wg-vbox")); if (!priv->widget) { g_set_error_literal (error, NMV_EDITOR_PLUGIN_ERROR, 0, _("could not load UI widget")); g_object_unref (object); @@ -491,6 +707,7 @@ openvpn_editor_new (NMConnection *connection, GError **error) priv->window_group = gtk_window_group_new (); s_vpn = nm_connection_get_setting_vpn (connection); + // if there is at least one item to iterate over, the connection can't be new if (s_vpn) nm_setting_vpn_foreach_data_item (s_vpn, is_new_func, &new); priv->new_connection = new; @@ -500,11 +717,13 @@ openvpn_editor_new (NMConnection *connection, GError **error) return NULL; } + /* priv->advanced = advanced_dialog_new_hash_from_connection (connection, error); if (!priv->advanced) { g_object_unref (object); return NULL; } + */ return object; }