mirror of
				https://github.com/max-moser/network-manager-wireguard.git
				synced 2025-11-04 09:03:49 +03:00 
			
		
		
		
	Implement import/export and connection editor UI
This commit is contained in:
		
							parent
							
								
									3209433372
								
							
						
					
					
						commit
						94046d0b8c
					
				
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -65,30 +65,56 @@ typedef struct {
 | 
			
		||||
#define COL_AUTH_PAGE 1
 | 
			
		||||
#define COL_AUTH_TYPE 2
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
is_empty(const char *str)
 | 
			
		||||
{
 | 
			
		||||
	gboolean empty = FALSE;
 | 
			
		||||
	gchar *tmp = g_strdup(str);
 | 
			
		||||
	tmp = g_strstrip(tmp);
 | 
			
		||||
 | 
			
		||||
	if(!tmp || !tmp[0]){
 | 
			
		||||
		empty = TRUE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	g_free(tmp);
 | 
			
		||||
	return empty;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
check_interface_ip4_entry(const char *str)
 | 
			
		||||
{
 | 
			
		||||
	gs_free char *str_clone = NULL;
 | 
			
		||||
	char *str_iter;
 | 
			
		||||
	const char *tok;
 | 
			
		||||
	int count = 0;
 | 
			
		||||
	return is_ip4((char *)str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	if(!str || !str[0]) {
 | 
			
		||||
		return FALSE;
 | 
			
		||||
static gboolean
 | 
			
		||||
check_interface_ip6_entry(const char *str)
 | 
			
		||||
{
 | 
			
		||||
	return is_ip6((char *)str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
check_interface_dns_entry(const char *str)
 | 
			
		||||
{
 | 
			
		||||
	if(is_empty(str)){
 | 
			
		||||
		return TRUE;
 | 
			
		||||
	}
 | 
			
		||||
	else if(is_ip4(str)){
 | 
			
		||||
		return TRUE;
 | 
			
		||||
	}
 | 
			
		||||
	else if(is_ip6(str)){
 | 
			
		||||
		return TRUE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	// an IP4 consists of 4 segments
 | 
			
		||||
	if(count != 4){
 | 
			
		||||
static gboolean
 | 
			
		||||
check_interface_mtu_entry(const char *str)
 | 
			
		||||
{
 | 
			
		||||
	if(is_empty(str)){
 | 
			
		||||
		return TRUE;
 | 
			
		||||
	}
 | 
			
		||||
	else if(!g_ascii_string_to_unsigned(str, 10, 0, 1500, NULL, NULL)){
 | 
			
		||||
		return FALSE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -98,11 +124,7 @@ check_interface_ip4_entry(const char *str)
 | 
			
		||||
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)){
 | 
			
		||||
	if(is_empty(str)){
 | 
			
		||||
		return FALSE;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
@ -113,10 +135,7 @@ check_interface_private_key(const char *str)
 | 
			
		||||
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)){
 | 
			
		||||
	if(!g_ascii_string_to_unsigned(str, 10, 0, 65535, NULL, NULL)){
 | 
			
		||||
		return FALSE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -124,58 +143,54 @@ check_interface_listen_port(const char *str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
check_peer_public_key(const char *str)
 | 
			
		||||
{
 | 
			
		||||
	// TODO
 | 
			
		||||
check_peer_public_key(const char *str){
 | 
			
		||||
	return check_interface_private_key(str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
check_peer_allowed_ips(const char *str)
 | 
			
		||||
{
 | 
			
		||||
	// TODO
 | 
			
		||||
	return check_interface_ip4_entry(str);
 | 
			
		||||
	gchar **ips;
 | 
			
		||||
	int idx = 0;
 | 
			
		||||
	gboolean success = TRUE;
 | 
			
		||||
 | 
			
		||||
	ips = g_strsplit_set(str, ", \t", 0);
 | 
			
		||||
 | 
			
		||||
	while(ips && ips[idx]){
 | 
			
		||||
 | 
			
		||||
		if(is_empty(ips[idx])){
 | 
			
		||||
			idx++;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// there should not be any trailing commas, etc. anymore
 | 
			
		||||
		// -> if any of the items is not a valid IPv4 or IPv6 address: error!
 | 
			
		||||
		if(!is_ip4(ips[idx]) && !is_ip6(ips[idx])){
 | 
			
		||||
			success = FALSE;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		idx++;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	g_strfreev(ips);
 | 
			
		||||
	return success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
check_peer_endpoint(const char *str)
 | 
			
		||||
{
 | 
			
		||||
	// TODO
 | 
			
		||||
	return check_interface_ip4_entry(str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
check_gateway_entry (const char *str)
 | 
			
		||||
{
 | 
			
		||||
	gs_free char *str_clone = NULL;
 | 
			
		||||
	char *str_iter;
 | 
			
		||||
	const char *tok;
 | 
			
		||||
	gboolean success = FALSE;
 | 
			
		||||
 | 
			
		||||
	if (!str || !str[0])
 | 
			
		||||
		return FALSE;
 | 
			
		||||
 | 
			
		||||
	str_clone = g_strdup (str);
 | 
			
		||||
	str_iter = str_clone;
 | 
			
		||||
	while ((tok = strsep (&str_iter, " \t,"))) {
 | 
			
		||||
		if (   tok[0]
 | 
			
		||||
		    && (nmovpn_remote_parse (tok,
 | 
			
		||||
		                             NULL,
 | 
			
		||||
		                             NULL,
 | 
			
		||||
		                             NULL,
 | 
			
		||||
		                             NULL,
 | 
			
		||||
		                             NULL) != -1))
 | 
			
		||||
		   return FALSE;
 | 
			
		||||
		success = TRUE;
 | 
			
		||||
	}
 | 
			
		||||
	return success;
 | 
			
		||||
	return is_ip4((char *)str) || is_ip6((char *)str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
check (OpenvpnEditorPrivate *priv,
 | 
			
		||||
		char *widget_name,
 | 
			
		||||
		CheckFunc chk, const char *key,
 | 
			
		||||
		gboolean set_error,
 | 
			
		||||
		GError **error)
 | 
			
		||||
{
 | 
			
		||||
	const char *str;
 | 
			
		||||
	GtkWidget *widget;
 | 
			
		||||
@ -186,11 +201,11 @@ check (OpenvpnEditorPrivate *priv, char *widget_name, CheckFunc chk, GError **er
 | 
			
		||||
	else {
 | 
			
		||||
		gtk_style_context_add_class (gtk_widget_get_style_context (widget), "error");
 | 
			
		||||
		// only set the error if it's NULL
 | 
			
		||||
		if(error == NULL){
 | 
			
		||||
		if(error == NULL && set_error){
 | 
			
		||||
			g_set_error (error,
 | 
			
		||||
						NMV_EDITOR_PLUGIN_ERROR,
 | 
			
		||||
						NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
 | 
			
		||||
						NM_WG_KEY_ADDR_IP4);
 | 
			
		||||
						key);
 | 
			
		||||
		}
 | 
			
		||||
		return FALSE;
 | 
			
		||||
	}
 | 
			
		||||
@ -198,6 +213,28 @@ check (OpenvpnEditorPrivate *priv, char *widget_name, CheckFunc chk, GError **er
 | 
			
		||||
	return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_error_class(OpenvpnEditorPrivate *priv, char *widget_name, gboolean error)
 | 
			
		||||
{
 | 
			
		||||
	GtkWidget *widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, widget_name));
 | 
			
		||||
	if(error){
 | 
			
		||||
		gtk_style_context_add_class (gtk_widget_get_style_context (widget), "error");
 | 
			
		||||
	}
 | 
			
		||||
	else{
 | 
			
		||||
		gtk_style_context_remove_class (gtk_widget_get_style_context (widget), "error");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
is_filled_out(OpenvpnEditorPrivate *priv, char *widget_name)
 | 
			
		||||
{
 | 
			
		||||
	const char *str;
 | 
			
		||||
	GtkWidget *widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, widget_name));
 | 
			
		||||
	str = gtk_entry_get_text(GTK_ENTRY (widget));
 | 
			
		||||
 | 
			
		||||
	return !is_empty(str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
check_validity (OpenvpnEditor *self, GError **error)
 | 
			
		||||
{
 | 
			
		||||
@ -206,27 +243,73 @@ check_validity (OpenvpnEditor *self, GError **error)
 | 
			
		||||
	GtkTreeModel *model;
 | 
			
		||||
	GtkTreeIter iter;
 | 
			
		||||
	const char *contype = NULL;
 | 
			
		||||
	gboolean success;
 | 
			
		||||
	gboolean success = TRUE;
 | 
			
		||||
	gboolean ip4_ok = TRUE;
 | 
			
		||||
	gboolean ip6_ok = TRUE;
 | 
			
		||||
 | 
			
		||||
	// check the various input fields for errors
 | 
			
		||||
	if(!check(priv, "interface_ip4_entry", check_interface_ip4_entry, error)){
 | 
			
		||||
	if(!check(priv, "interface_ip4_entry", check_interface_ip4_entry, NM_WG_KEY_ADDR_IP4, FALSE, error)){
 | 
			
		||||
		ip4_ok = FALSE;
 | 
			
		||||
	}
 | 
			
		||||
	if(!check(priv, "interface_ip6_entry", check_interface_ip6_entry, NM_WG_KEY_ADDR_IP6, FALSE, error)){
 | 
			
		||||
		ip6_ok = FALSE;
 | 
			
		||||
	}
 | 
			
		||||
	if(!check(priv, "interface_private_key_entry", check_interface_private_key, NM_WG_KEY_PRIVATE_KEY, TRUE, error)){
 | 
			
		||||
		success = FALSE;
 | 
			
		||||
	}
 | 
			
		||||
	if(!check(priv, "interface_private_key_entry", check_interface_private_key, error)){
 | 
			
		||||
	if(!check(priv, "interface_port_entry", check_interface_listen_port, NM_WG_KEY_LISTEN_PORT, TRUE, error)){
 | 
			
		||||
		success = FALSE;
 | 
			
		||||
	}
 | 
			
		||||
	if(!check(priv, "interface_port_entry", check_interface_listen_port, error)){
 | 
			
		||||
	if(!check(priv, "interface_dns_entry", check_interface_dns_entry, NM_WG_KEY_DNS, TRUE, error)){
 | 
			
		||||
		success = FALSE;
 | 
			
		||||
	}
 | 
			
		||||
	if(!check(priv, "peer_public_key_entry", check_peer_public_key, error)){
 | 
			
		||||
	if(!check(priv, "interface_mtu_entry", check_interface_mtu_entry, NM_WG_KEY_MTU, TRUE, error)){
 | 
			
		||||
		success = FALSE;
 | 
			
		||||
	}
 | 
			
		||||
	if(!check(priv, "peer_allowed_ips_entry", check_peer_allowed_ips, error)){
 | 
			
		||||
	if(!check(priv, "peer_public_key_entry", check_peer_public_key, NM_WG_KEY_PUBLIC_KEY, TRUE, error)){
 | 
			
		||||
		success = FALSE;
 | 
			
		||||
	}
 | 
			
		||||
	if(!check(priv, "peer_endpoint_entry", check_peer_endpoint, error)){
 | 
			
		||||
	if(!check(priv, "peer_allowed_ips_entry", check_peer_allowed_ips, NM_WG_KEY_ALLOWED_IPS, TRUE, error)){
 | 
			
		||||
		success = FALSE;
 | 
			
		||||
	}
 | 
			
		||||
	if(!check(priv, "peer_endpoint_entry", check_peer_endpoint, NM_WG_KEY_ENDPOINT, TRUE, error)){
 | 
			
		||||
		success = FALSE;
 | 
			
		||||
	}
 | 
			
		||||
	// pre-up, post-up, pre-down, post-down are scripts and don't get validated
 | 
			
		||||
 | 
			
		||||
	if(ip4_ok && ip6_ok){
 | 
			
		||||
		set_error_class(priv, "interface_ip4_entry", FALSE);
 | 
			
		||||
		set_error_class(priv, "interface_ip6_entry", FALSE);
 | 
			
		||||
		// this should be fine, actually
 | 
			
		||||
	}
 | 
			
		||||
	else if(ip4_ok){
 | 
			
		||||
		// IP6 is filled out but not ok
 | 
			
		||||
		if(is_filled_out(priv, "interface_ip6_entry")){
 | 
			
		||||
			success = FALSE;
 | 
			
		||||
			g_set_error (error,
 | 
			
		||||
						NMV_EDITOR_PLUGIN_ERROR,
 | 
			
		||||
						NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
 | 
			
		||||
						NM_WG_KEY_ADDR_IP6);
 | 
			
		||||
		}
 | 
			
		||||
		else{
 | 
			
		||||
			set_error_class(priv, "interface_ip4_entry", FALSE);
 | 
			
		||||
			set_error_class(priv, "interface_ip6_entry", FALSE);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else if(ip6_ok){
 | 
			
		||||
		// IP4 is filled out but not ok
 | 
			
		||||
		if(is_filled_out(priv, "interface_ip4_entry")){
 | 
			
		||||
			success = FALSE;
 | 
			
		||||
			g_set_error (error,
 | 
			
		||||
						NMV_EDITOR_PLUGIN_ERROR,
 | 
			
		||||
						NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
 | 
			
		||||
						NM_WG_KEY_ADDR_IP4);
 | 
			
		||||
		}
 | 
			
		||||
		else{
 | 
			
		||||
			set_error_class(priv, "interface_ip4_entry", FALSE);
 | 
			
		||||
			set_error_class(priv, "interface_ip6_entry", FALSE);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "auth_combo"));
 | 
			
		||||
@ -367,11 +450,41 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection, GError **erro
 | 
			
		||||
	}
 | 
			
		||||
	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
 | 
			
		||||
 | 
			
		||||
	// Local IPv6 address
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_ip6_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_IP6);
 | 
			
		||||
		if (value)
 | 
			
		||||
			gtk_entry_set_text (GTK_ENTRY (widget), value);
 | 
			
		||||
	}
 | 
			
		||||
	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
 | 
			
		||||
 | 
			
		||||
	// DNS
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_dns_entry"));
 | 
			
		||||
	g_return_val_if_fail (widget != NULL, FALSE);
 | 
			
		||||
	if (s_vpn) {
 | 
			
		||||
		value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_DNS);
 | 
			
		||||
		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_mtu_entry"));
 | 
			
		||||
	g_return_val_if_fail (widget != NULL, FALSE);
 | 
			
		||||
	if (s_vpn) {
 | 
			
		||||
		value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_MTU);
 | 
			
		||||
		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);
 | 
			
		||||
		value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_PRIVATE_KEY);
 | 
			
		||||
		if (value)
 | 
			
		||||
			gtk_entry_set_text (GTK_ENTRY (widget), value);
 | 
			
		||||
	}
 | 
			
		||||
@ -381,7 +494,57 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection, GError **erro
 | 
			
		||||
	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);
 | 
			
		||||
		value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_LISTEN_PORT);
 | 
			
		||||
		if (value)
 | 
			
		||||
			gtk_entry_set_text (GTK_ENTRY (widget), value);
 | 
			
		||||
	}
 | 
			
		||||
	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
 | 
			
		||||
 | 
			
		||||
	// Interface Pre Up
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_pre_up_entry"));
 | 
			
		||||
	g_return_val_if_fail (widget != NULL, FALSE);
 | 
			
		||||
	if (s_vpn) {
 | 
			
		||||
		value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_PRE_UP);
 | 
			
		||||
		if (value)
 | 
			
		||||
			gtk_entry_set_text (GTK_ENTRY (widget), value);
 | 
			
		||||
	}
 | 
			
		||||
	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
 | 
			
		||||
 | 
			
		||||
	// Interface Post Up
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_post_up_entry"));
 | 
			
		||||
	g_return_val_if_fail (widget != NULL, FALSE);
 | 
			
		||||
	if (s_vpn) {
 | 
			
		||||
		value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_POST_UP);
 | 
			
		||||
		if (value)
 | 
			
		||||
			gtk_entry_set_text (GTK_ENTRY (widget), value);
 | 
			
		||||
	}
 | 
			
		||||
	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
 | 
			
		||||
 | 
			
		||||
	// Interface Pre Down
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_pre_down_entry"));
 | 
			
		||||
	g_return_val_if_fail (widget != NULL, FALSE);
 | 
			
		||||
	if (s_vpn) {
 | 
			
		||||
		value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_PRE_DOWN);
 | 
			
		||||
		if (value)
 | 
			
		||||
			gtk_entry_set_text (GTK_ENTRY (widget), value);
 | 
			
		||||
	}
 | 
			
		||||
	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
 | 
			
		||||
 | 
			
		||||
	// Interface Post Down
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_post_down_entry"));
 | 
			
		||||
	g_return_val_if_fail (widget != NULL, FALSE);
 | 
			
		||||
	if (s_vpn) {
 | 
			
		||||
		value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_POST_DOWN);
 | 
			
		||||
		if (value)
 | 
			
		||||
			gtk_entry_set_text (GTK_ENTRY (widget), value);
 | 
			
		||||
	}
 | 
			
		||||
	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
 | 
			
		||||
 | 
			
		||||
	// Interface Preshared Key
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_psk_entry"));
 | 
			
		||||
	g_return_val_if_fail (widget != NULL, FALSE);
 | 
			
		||||
	if (s_vpn) {
 | 
			
		||||
		value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_PRESHARED_KEY);
 | 
			
		||||
		if (value)
 | 
			
		||||
			gtk_entry_set_text (GTK_ENTRY (widget), value);
 | 
			
		||||
	}
 | 
			
		||||
@ -392,7 +555,7 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection, GError **erro
 | 
			
		||||
	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);
 | 
			
		||||
		value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_PUBLIC_KEY);
 | 
			
		||||
		if (value)
 | 
			
		||||
			gtk_entry_set_text (GTK_ENTRY (widget), value);
 | 
			
		||||
	}
 | 
			
		||||
@ -402,7 +565,7 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection, GError **erro
 | 
			
		||||
	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);
 | 
			
		||||
		value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_ALLOWED_IPS);
 | 
			
		||||
		if (value)
 | 
			
		||||
			gtk_entry_set_text (GTK_ENTRY (widget), value);
 | 
			
		||||
	}
 | 
			
		||||
@ -412,7 +575,7 @@ init_editor_plugin (OpenvpnEditor *self, NMConnection *connection, GError **erro
 | 
			
		||||
	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);
 | 
			
		||||
		value = nm_setting_vpn_get_data_item (s_vpn, NM_WG_KEY_ENDPOINT);
 | 
			
		||||
		if (value)
 | 
			
		||||
			gtk_entry_set_text (GTK_ENTRY (widget), value);
 | 
			
		||||
	}
 | 
			
		||||
@ -576,18 +739,66 @@ update_connection (NMVpnEditor *iface,
 | 
			
		||||
	if (str && str[0])
 | 
			
		||||
		nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_ADDR_IP4, str);
 | 
			
		||||
 | 
			
		||||
	// local ip6
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_ip6_entry"));
 | 
			
		||||
	str = gtk_entry_get_text (GTK_ENTRY (widget));
 | 
			
		||||
	if (str && str[0])
 | 
			
		||||
		nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_ADDR_IP6, 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);
 | 
			
		||||
 | 
			
		||||
	// dns
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_dns_entry"));
 | 
			
		||||
	str = gtk_entry_get_text (GTK_ENTRY (widget));
 | 
			
		||||
	if (str && str[0])
 | 
			
		||||
		nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_DNS, str);
 | 
			
		||||
 | 
			
		||||
	// mtu
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_mtu_entry"));
 | 
			
		||||
	str = gtk_entry_get_text (GTK_ENTRY (widget));
 | 
			
		||||
	if (str && str[0])
 | 
			
		||||
		nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_MTU, 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);
 | 
			
		||||
 | 
			
		||||
	// pre up script
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_pre_up_entry"));
 | 
			
		||||
	str = gtk_entry_get_text (GTK_ENTRY (widget));
 | 
			
		||||
	if (str && str[0])
 | 
			
		||||
		nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_PRE_UP, str);
 | 
			
		||||
 | 
			
		||||
	// post up script
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_post_up_entry"));
 | 
			
		||||
	str = gtk_entry_get_text (GTK_ENTRY (widget));
 | 
			
		||||
	if (str && str[0])
 | 
			
		||||
		nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_POST_UP, str);
 | 
			
		||||
 | 
			
		||||
	// pre up script
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_pre_down_entry"));
 | 
			
		||||
	str = gtk_entry_get_text (GTK_ENTRY (widget));
 | 
			
		||||
	if (str && str[0])
 | 
			
		||||
		nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_PRE_DOWN, str);
 | 
			
		||||
 | 
			
		||||
	// post down script
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_post_down_entry"));
 | 
			
		||||
	str = gtk_entry_get_text (GTK_ENTRY (widget));
 | 
			
		||||
	if (str && str[0])
 | 
			
		||||
		nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_POST_DOWN, str);
 | 
			
		||||
 | 
			
		||||
	// preshared key
 | 
			
		||||
	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_psk_entry"));
 | 
			
		||||
	str = gtk_entry_get_text (GTK_ENTRY (widget));
 | 
			
		||||
	if (str && str[0])
 | 
			
		||||
		nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_PRESHARED_KEY, 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));
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										196
									
								
								shared/utils.c
									
									
									
									
									
								
							
							
						
						
									
										196
									
								
								shared/utils.c
									
									
									
									
									
								
							@ -248,3 +248,199 @@ out_fail:
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*****************************************************************************/
 | 
			
		||||
 | 
			
		||||
// check if the given string looks like an IPv4 address
 | 
			
		||||
// that is, four segments of numbers (0-255), separated by dots
 | 
			
		||||
// additionally, there may be a port suffix (separated from the address by a colon; 0 - 65535)
 | 
			
		||||
// and/or a subnet (separated by the rest by a slash; 0 - 32)
 | 
			
		||||
gboolean
 | 
			
		||||
is_ip4(char *addr)
 | 
			
		||||
{
 | 
			
		||||
	int idx = 0;
 | 
			
		||||
	int dots = 0;
 | 
			
		||||
	gchar **parts;
 | 
			
		||||
	gchar **tmp;
 | 
			
		||||
	gchar **tmp2;
 | 
			
		||||
	gchar *lastpart;
 | 
			
		||||
	gboolean success = TRUE;
 | 
			
		||||
 | 
			
		||||
	if(!addr){
 | 
			
		||||
		return FALSE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while(addr && addr[idx]){
 | 
			
		||||
		if(addr[idx] == '.'){
 | 
			
		||||
			dots++;
 | 
			
		||||
		}
 | 
			
		||||
		idx++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if(dots != 3){
 | 
			
		||||
		return FALSE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parts = g_strsplit(addr, ".", 0);
 | 
			
		||||
 | 
			
		||||
	// iterate over the first three parts, which cannot be anything else than numbers
 | 
			
		||||
	for(idx = 0; idx < 3; idx++){
 | 
			
		||||
		if(!g_ascii_string_to_unsigned(parts[idx], 10, 0, 255, NULL, NULL)){
 | 
			
		||||
			success = FALSE;
 | 
			
		||||
			goto ip4end;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// if the last part is a number, we're fine
 | 
			
		||||
	lastpart = parts[3];
 | 
			
		||||
	if(g_ascii_string_to_unsigned(lastpart, 10, 0, 255, NULL, NULL)){
 | 
			
		||||
		success = TRUE;
 | 
			
		||||
		goto ip4end;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// might have a subnet suffix after a slash (e.g. 192.168.1.254/24)
 | 
			
		||||
	// might have a port suffix after a colon (e.g. 192.168.1.254:8080)
 | 
			
		||||
	if(g_strrstr(lastpart, ":") && g_strrstr(lastpart, "/")){
 | 
			
		||||
		tmp = g_strsplit(lastpart, ":", 2);
 | 
			
		||||
		tmp2 = g_strsplit(tmp[1], "/", 2);
 | 
			
		||||
 | 
			
		||||
		if(!g_ascii_string_to_unsigned(tmp[0], 10, 0, 255, NULL, NULL)){
 | 
			
		||||
			// the last part of the IP
 | 
			
		||||
			success = FALSE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if(!g_ascii_string_to_unsigned(tmp2[0], 10, 0, 65535, NULL, NULL)){
 | 
			
		||||
			// the port
 | 
			
		||||
			success = FALSE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if(!g_ascii_string_to_unsigned(tmp2[1], 10, 0, 32, NULL, NULL)){
 | 
			
		||||
			// the subnet portion
 | 
			
		||||
			success = FALSE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		g_strfreev(tmp);
 | 
			
		||||
		g_strfreev(tmp2);
 | 
			
		||||
	}
 | 
			
		||||
	else if(g_strrstr(lastpart, "/")){
 | 
			
		||||
		tmp = g_strsplit(lastpart, "/", 2);
 | 
			
		||||
 | 
			
		||||
		if(!g_ascii_string_to_unsigned(tmp[0], 10, 0, 255, NULL, NULL)){
 | 
			
		||||
			// the last part of the IP
 | 
			
		||||
			success = FALSE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if(!g_ascii_string_to_unsigned(tmp[1], 10, 0, 32, NULL, NULL)){
 | 
			
		||||
			// the subnet portion
 | 
			
		||||
			success = FALSE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		g_strfreev(tmp);
 | 
			
		||||
	}
 | 
			
		||||
	else if(g_strrstr(lastpart, ":")){
 | 
			
		||||
		tmp = g_strsplit(lastpart, ":", 2);
 | 
			
		||||
 | 
			
		||||
		if(!g_ascii_string_to_unsigned(tmp[0], 10, 0, 255, NULL, NULL)){
 | 
			
		||||
			// the last part of the IP
 | 
			
		||||
			success = FALSE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if(!g_ascii_string_to_unsigned(tmp[1], 10, 0, 65535, NULL, NULL)){
 | 
			
		||||
			// the port
 | 
			
		||||
			success = FALSE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		g_strfreev(tmp);
 | 
			
		||||
	}
 | 
			
		||||
	else{
 | 
			
		||||
		// we have neither a port nor a subnet suffix, but it's not a number either
 | 
			
		||||
		success = FALSE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
ip4end:
 | 
			
		||||
	g_strfreev(parts);
 | 
			
		||||
	return success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// check if the given string looks like an IPv6 address
 | 
			
		||||
// that is, several segments of up to 4 hexadecimal digits
 | 
			
		||||
// separated by colons, possibly followed by a slash and a subnet (0 - 128)
 | 
			
		||||
//
 | 
			
		||||
// if there are several zeroes in adjacent segments,
 | 
			
		||||
// those segments may be omitted
 | 
			
		||||
gboolean
 | 
			
		||||
is_ip6(char *addr)
 | 
			
		||||
{
 | 
			
		||||
	gchar **parts;
 | 
			
		||||
	gchar **tmp;
 | 
			
		||||
	gchar *lastpart;
 | 
			
		||||
	int len = 0;
 | 
			
		||||
	int i = 0;
 | 
			
		||||
	int num_empty = 0;
 | 
			
		||||
	int num_colons = 0;
 | 
			
		||||
	gboolean success = TRUE;
 | 
			
		||||
 | 
			
		||||
	if(!addr){
 | 
			
		||||
		return FALSE;
 | 
			
		||||
	}
 | 
			
		||||
	else if(!g_strrstr(addr, ":")){
 | 
			
		||||
		return FALSE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while(addr && addr[i]){
 | 
			
		||||
		if(addr[i] == ':'){
 | 
			
		||||
			num_colons++;
 | 
			
		||||
		}
 | 
			
		||||
		i++;
 | 
			
		||||
	}
 | 
			
		||||
	if(num_colons < 2){
 | 
			
		||||
		// an IPv6 has to contain at least two colons
 | 
			
		||||
		return FALSE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parts = g_strsplit(addr, ":", 0);
 | 
			
		||||
	while(parts && parts[len]){
 | 
			
		||||
		len++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	num_empty = 0;
 | 
			
		||||
	for(i = 0; i < (len-1); i++){
 | 
			
		||||
		if((i == 0) && (!g_strcmp0("", parts[i]))){
 | 
			
		||||
			// the beginning may be empty (e.g. in "::1")
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if(!g_strcmp0("", parts[i]) && (num_empty < 1)){
 | 
			
		||||
			// there may be one "skipped" part in the IP6
 | 
			
		||||
			num_empty++;
 | 
			
		||||
		}
 | 
			
		||||
		else if(!g_ascii_string_to_unsigned(parts[i], 16, 0, 65536, NULL, NULL)){
 | 
			
		||||
			// the rest of the parts have to be numerals between 0 and 16^4 in hex
 | 
			
		||||
			success = FALSE;
 | 
			
		||||
			goto ip6end;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lastpart = parts[len-1];
 | 
			
		||||
	if(g_strrstr(lastpart, "/")){
 | 
			
		||||
		// we have a subnet portion
 | 
			
		||||
		tmp = g_strsplit(lastpart, "/", 2);
 | 
			
		||||
 | 
			
		||||
		if(g_strcmp0("", tmp[0]) && !g_ascii_string_to_unsigned(tmp[0], 16, 0, 65536, NULL, NULL)){
 | 
			
		||||
			success = FALSE;
 | 
			
		||||
		}
 | 
			
		||||
		else if(!g_ascii_string_to_unsigned(tmp[1], 10, 0, 128, NULL, NULL)){
 | 
			
		||||
			success = FALSE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		g_strfreev(tmp);
 | 
			
		||||
	}
 | 
			
		||||
	else{
 | 
			
		||||
		// there is only a number, or an empty string (e.g. in the case of "::")
 | 
			
		||||
		if(g_strcmp0("", lastpart) && !g_ascii_string_to_unsigned(lastpart, 16, 0, 65536, NULL, NULL)){
 | 
			
		||||
			success = FALSE;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
ip6end:
 | 
			
		||||
	g_strfreev(parts);
 | 
			
		||||
	return success;
 | 
			
		||||
}
 | 
			
		||||
@ -26,7 +26,11 @@
 | 
			
		||||
#define NMV_WG_TAG_PRIVATE_KEY			"PrivateKey"
 | 
			
		||||
#define NMV_WG_TAG_LISTEN_PORT			"ListenPort"
 | 
			
		||||
#define NMV_WG_TAG_ADDRESS				"Address"
 | 
			
		||||
#define NMV_WG_TAG_DNS                  "DNS"
 | 
			
		||||
#define NMV_WG_TAG_MTU                  "MTU"
 | 
			
		||||
#define NMV_WG_TAG_PRE_UP               "PreUp"
 | 
			
		||||
#define NMV_WG_TAG_POST_UP				"PostUp"
 | 
			
		||||
#define NMV_WG_TAG_PRE_DOWN             "PreDown"
 | 
			
		||||
#define NMV_WG_TAG_POST_DOWN			"PostDown"
 | 
			
		||||
#define NMV_WG_TAG_PRESHARED_KEY		"PresharedKey"
 | 
			
		||||
#define NMV_WG_TAG_PEER					"[Peer]"
 | 
			
		||||
@ -92,6 +96,10 @@ gboolean is_pkcs12 (const char *filepath);
 | 
			
		||||
 | 
			
		||||
gboolean is_encrypted (const char *filename);
 | 
			
		||||
 | 
			
		||||
gboolean is_ip4 (char *addr);
 | 
			
		||||
 | 
			
		||||
gboolean is_ip6 (char *addr);
 | 
			
		||||
 | 
			
		||||
#define NMOVPN_PROTCOL_TYPES \
 | 
			
		||||
	"udp", \
 | 
			
		||||
	"udp4", \
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user