Implement import/export and connection editor UI
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_PAGE 1
|
||||||
#define COL_AUTH_TYPE 2
|
#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
|
static gboolean
|
||||||
check_interface_ip4_entry(const char *str)
|
check_interface_ip4_entry(const char *str)
|
||||||
{
|
{
|
||||||
gs_free char *str_clone = NULL;
|
return is_ip4((char *)str);
|
||||||
char *str_iter;
|
}
|
||||||
const char *tok;
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
if(!str || !str[0]) {
|
static gboolean
|
||||||
return FALSE;
|
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);
|
return FALSE;
|
||||||
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
|
static gboolean
|
||||||
if(count != 4){
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,11 +124,7 @@ check_interface_ip4_entry(const char *str)
|
||||||
static gboolean
|
static gboolean
|
||||||
check_interface_private_key(const char *str)
|
check_interface_private_key(const char *str)
|
||||||
{
|
{
|
||||||
gs_free char *str_clone = NULL;
|
if(is_empty(str)){
|
||||||
str_clone = g_strdup(str);
|
|
||||||
str_clone = g_strstrip(str_clone);
|
|
||||||
|
|
||||||
if(!g_strcmp0("", str_clone)){
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,10 +135,7 @@ check_interface_private_key(const char *str)
|
||||||
static gboolean
|
static gboolean
|
||||||
check_interface_listen_port(const char *str)
|
check_interface_listen_port(const char *str)
|
||||||
{
|
{
|
||||||
gs_free char *str_clone = NULL;
|
if(!g_ascii_string_to_unsigned(str, 10, 0, 65535, NULL, NULL)){
|
||||||
str_clone = g_strdup(str);
|
|
||||||
|
|
||||||
if(!g_ascii_string_to_unsigned(str_clone, 10, 0, 65535, NULL, NULL)){
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,58 +143,54 @@ check_interface_listen_port(const char *str)
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
check_peer_public_key(const char *str)
|
check_peer_public_key(const char *str){
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
return check_interface_private_key(str);
|
return check_interface_private_key(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
check_peer_allowed_ips(const char *str)
|
check_peer_allowed_ips(const char *str)
|
||||||
{
|
{
|
||||||
// TODO
|
gchar **ips;
|
||||||
return check_interface_ip4_entry(str);
|
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
|
static gboolean
|
||||||
check_peer_endpoint(const char *str)
|
check_peer_endpoint(const char *str)
|
||||||
{
|
{
|
||||||
// TODO
|
return is_ip4((char *)str) || is_ip6((char *)str);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef gboolean (*CheckFunc)(const char *str);
|
typedef gboolean (*CheckFunc)(const char *str);
|
||||||
|
|
||||||
// helper function to reduce boilerplate code in 'check_validity()'
|
// helper function to reduce boilerplate code in 'check_validity()'
|
||||||
static gboolean
|
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;
|
const char *str;
|
||||||
GtkWidget *widget;
|
GtkWidget *widget;
|
||||||
|
@ -186,11 +201,11 @@ check (OpenvpnEditorPrivate *priv, char *widget_name, CheckFunc chk, GError **er
|
||||||
else {
|
else {
|
||||||
gtk_style_context_add_class (gtk_widget_get_style_context (widget), "error");
|
gtk_style_context_add_class (gtk_widget_get_style_context (widget), "error");
|
||||||
// only set the error if it's NULL
|
// only set the error if it's NULL
|
||||||
if(error == NULL){
|
if(error == NULL && set_error){
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
NMV_EDITOR_PLUGIN_ERROR,
|
NMV_EDITOR_PLUGIN_ERROR,
|
||||||
NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
|
NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
|
||||||
NM_WG_KEY_ADDR_IP4);
|
key);
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -198,6 +213,28 @@ check (OpenvpnEditorPrivate *priv, char *widget_name, CheckFunc chk, GError **er
|
||||||
return TRUE;
|
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
|
static gboolean
|
||||||
check_validity (OpenvpnEditor *self, GError **error)
|
check_validity (OpenvpnEditor *self, GError **error)
|
||||||
{
|
{
|
||||||
|
@ -206,27 +243,73 @@ check_validity (OpenvpnEditor *self, GError **error)
|
||||||
GtkTreeModel *model;
|
GtkTreeModel *model;
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
const char *contype = NULL;
|
const char *contype = NULL;
|
||||||
gboolean success;
|
gboolean success = TRUE;
|
||||||
|
gboolean ip4_ok = TRUE;
|
||||||
|
gboolean ip6_ok = TRUE;
|
||||||
|
|
||||||
// check the various input fields for errors
|
// 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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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"));
|
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);
|
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
|
// Interface Private Key
|
||||||
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_private_key_entry"));
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_private_key_entry"));
|
||||||
g_return_val_if_fail (widget != NULL, FALSE);
|
g_return_val_if_fail (widget != NULL, FALSE);
|
||||||
if (s_vpn) {
|
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)
|
if (value)
|
||||||
gtk_entry_set_text (GTK_ENTRY (widget), 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"));
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_port_entry"));
|
||||||
g_return_val_if_fail (widget != NULL, FALSE);
|
g_return_val_if_fail (widget != NULL, FALSE);
|
||||||
if (s_vpn) {
|
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)
|
if (value)
|
||||||
gtk_entry_set_text (GTK_ENTRY (widget), 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"));
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "peer_public_key_entry"));
|
||||||
g_return_val_if_fail (widget != NULL, FALSE);
|
g_return_val_if_fail (widget != NULL, FALSE);
|
||||||
if (s_vpn) {
|
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)
|
if (value)
|
||||||
gtk_entry_set_text (GTK_ENTRY (widget), 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"));
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "peer_allowed_ips_entry"));
|
||||||
g_return_val_if_fail (widget != NULL, FALSE);
|
g_return_val_if_fail (widget != NULL, FALSE);
|
||||||
if (s_vpn) {
|
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)
|
if (value)
|
||||||
gtk_entry_set_text (GTK_ENTRY (widget), 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"));
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "peer_endpoint_entry"));
|
||||||
g_return_val_if_fail (widget != NULL, FALSE);
|
g_return_val_if_fail (widget != NULL, FALSE);
|
||||||
if (s_vpn) {
|
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)
|
if (value)
|
||||||
gtk_entry_set_text (GTK_ENTRY (widget), value);
|
gtk_entry_set_text (GTK_ENTRY (widget), value);
|
||||||
}
|
}
|
||||||
|
@ -576,18 +739,66 @@ update_connection (NMVpnEditor *iface,
|
||||||
if (str && str[0])
|
if (str && str[0])
|
||||||
nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_ADDR_IP4, str);
|
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
|
// private key
|
||||||
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_private_key_entry"));
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_private_key_entry"));
|
||||||
str = gtk_entry_get_text (GTK_ENTRY (widget));
|
str = gtk_entry_get_text (GTK_ENTRY (widget));
|
||||||
if (str && str[0])
|
if (str && str[0])
|
||||||
nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_PRIVATE_KEY, str);
|
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
|
// listen port
|
||||||
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_port_entry"));
|
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "interface_port_entry"));
|
||||||
str = gtk_entry_get_text (GTK_ENTRY (widget));
|
str = gtk_entry_get_text (GTK_ENTRY (widget));
|
||||||
if (str && str[0])
|
if (str && str[0])
|
||||||
nm_setting_vpn_add_data_item (s_vpn, NM_WG_KEY_LISTEN_PORT, str);
|
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
|
// 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"));
|
||||||
str = gtk_entry_get_text (GTK_ENTRY (widget));
|
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_PRIVATE_KEY "PrivateKey"
|
||||||
#define NMV_WG_TAG_LISTEN_PORT "ListenPort"
|
#define NMV_WG_TAG_LISTEN_PORT "ListenPort"
|
||||||
#define NMV_WG_TAG_ADDRESS "Address"
|
#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_POST_UP "PostUp"
|
||||||
|
#define NMV_WG_TAG_PRE_DOWN "PreDown"
|
||||||
#define NMV_WG_TAG_POST_DOWN "PostDown"
|
#define NMV_WG_TAG_POST_DOWN "PostDown"
|
||||||
#define NMV_WG_TAG_PRESHARED_KEY "PresharedKey"
|
#define NMV_WG_TAG_PRESHARED_KEY "PresharedKey"
|
||||||
#define NMV_WG_TAG_PEER "[Peer]"
|
#define NMV_WG_TAG_PEER "[Peer]"
|
||||||
|
@ -92,6 +96,10 @@ gboolean is_pkcs12 (const char *filepath);
|
||||||
|
|
||||||
gboolean is_encrypted (const char *filename);
|
gboolean is_encrypted (const char *filename);
|
||||||
|
|
||||||
|
gboolean is_ip4 (char *addr);
|
||||||
|
|
||||||
|
gboolean is_ip6 (char *addr);
|
||||||
|
|
||||||
#define NMOVPN_PROTCOL_TYPES \
|
#define NMOVPN_PROTCOL_TYPES \
|
||||||
"udp", \
|
"udp", \
|
||||||
"udp4", \
|
"udp4", \
|
||||||
|
|
Loading…
Reference in New Issue