implemented NetworkManager certificate/private key authentication using ssh-agent
This commit is contained in:
@@ -6,6 +6,7 @@ nm_strongswan_auth_dialog_CPPFLAGS = \
|
|||||||
$(LIBGNOMEUI_CFLAGS) \
|
$(LIBGNOMEUI_CFLAGS) \
|
||||||
$(GNOMEKEYRING_CFLAGS) \
|
$(GNOMEKEYRING_CFLAGS) \
|
||||||
$(NETWORK_MANAGER_CFLAGS) \
|
$(NETWORK_MANAGER_CFLAGS) \
|
||||||
|
$(NM_UTILS_CFLAGS) \
|
||||||
-DICONDIR=\""$(datadir)/pixmaps"\" \
|
-DICONDIR=\""$(datadir)/pixmaps"\" \
|
||||||
-DGLADEDIR=\""$(gladedir)"\" \
|
-DGLADEDIR=\""$(gladedir)"\" \
|
||||||
-DBINDIR=\""$(bindir)"\" \
|
-DBINDIR=\""$(bindir)"\" \
|
||||||
|
|||||||
@@ -26,10 +26,17 @@
|
|||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <gnome-keyring.h>
|
#include <gnome-keyring.h>
|
||||||
#include <libgnomeui/libgnomeui.h>
|
#include <libgnomeui/libgnomeui.h>
|
||||||
|
#include <gconf/gconf-client.h>
|
||||||
|
#include <nm-vpn-plugin.h>
|
||||||
|
#include <nm-setting-vpn.h>
|
||||||
|
#include <nm-setting-connection.h>
|
||||||
|
|
||||||
#define NM_DBUS_SERVICE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan"
|
#define NM_DBUS_SERVICE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan"
|
||||||
|
|
||||||
static char *lookup(char *name, char *service)
|
/**
|
||||||
|
* lookup a password in the keyring
|
||||||
|
*/
|
||||||
|
static char *lookup_password(char *name, char *service)
|
||||||
{
|
{
|
||||||
GList *list;
|
GList *list;
|
||||||
GList *iter;
|
GList *iter;
|
||||||
@@ -55,6 +62,29 @@ static char *lookup(char *name, char *service)
|
|||||||
return pass;
|
return pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if this connection needs a password
|
||||||
|
*/
|
||||||
|
static gboolean need_password(char *id)
|
||||||
|
{
|
||||||
|
GConfClient *client;
|
||||||
|
char *key, *str;
|
||||||
|
gboolean need_password = FALSE;
|
||||||
|
|
||||||
|
client = gconf_client_get_default();
|
||||||
|
key = g_strdup_printf("/system/networking/connections/%s/%s/%s",
|
||||||
|
id, NM_SETTING_VPN_SETTING_NAME, "method");
|
||||||
|
str = gconf_client_get_string(client, key, NULL);
|
||||||
|
if (str && !strcmp(str, "eap"))
|
||||||
|
{
|
||||||
|
need_password = TRUE;
|
||||||
|
}
|
||||||
|
g_free(str);
|
||||||
|
g_free(key);
|
||||||
|
g_object_unref(client);
|
||||||
|
return need_password;
|
||||||
|
}
|
||||||
|
|
||||||
int main (int argc, char *argv[])
|
int main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
static gboolean retry = FALSE;
|
static gboolean retry = FALSE;
|
||||||
@@ -62,7 +92,7 @@ int main (int argc, char *argv[])
|
|||||||
GOptionContext *context;
|
GOptionContext *context;
|
||||||
GnomeProgram *program = NULL;
|
GnomeProgram *program = NULL;
|
||||||
int exit_status = 1;
|
int exit_status = 1;
|
||||||
char buf;
|
char buf, *agent;
|
||||||
guint32 itemid;
|
guint32 itemid;
|
||||||
GtkWidget *dialog;
|
GtkWidget *dialog;
|
||||||
GOptionEntry entries[] = {
|
GOptionEntry entries[] = {
|
||||||
@@ -91,8 +121,8 @@ int main (int argc, char *argv[])
|
|||||||
fprintf (stderr, "Have to supply ID, name, and service\n");
|
fprintf (stderr, "Have to supply ID, name, and service\n");
|
||||||
g_object_unref (program);
|
g_object_unref (program);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(service, NM_DBUS_SERVICE_STRONGSWAN) != 0)
|
if (strcmp(service, NM_DBUS_SERVICE_STRONGSWAN) != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "This dialog only works with the '%s' service\n",
|
fprintf(stderr, "This dialog only works with the '%s' service\n",
|
||||||
@@ -101,43 +131,66 @@ int main (int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pass = lookup(name, service);
|
if (need_password(id))
|
||||||
if (!pass || retry)
|
|
||||||
{
|
{
|
||||||
dialog = gnome_password_dialog_new(_("VPN password required"),
|
pass = lookup_password(name, service);
|
||||||
_("Password required to establish VPN connection:"),
|
if (!pass || retry)
|
||||||
NULL, NULL, TRUE);
|
|
||||||
gnome_password_dialog_set_show_remember(GNOME_PASSWORD_DIALOG(dialog), TRUE);
|
|
||||||
gnome_password_dialog_set_show_username(GNOME_PASSWORD_DIALOG(dialog), FALSE);
|
|
||||||
if (pass)
|
|
||||||
{
|
{
|
||||||
gnome_password_dialog_set_password(GNOME_PASSWORD_DIALOG(dialog), pass);
|
dialog = gnome_password_dialog_new(_("VPN password required"),
|
||||||
|
_("Password required to establish VPN connection:"),
|
||||||
|
NULL, NULL, TRUE);
|
||||||
|
gnome_password_dialog_set_show_remember(GNOME_PASSWORD_DIALOG(dialog), TRUE);
|
||||||
|
gnome_password_dialog_set_show_username(GNOME_PASSWORD_DIALOG(dialog), FALSE);
|
||||||
|
if (pass)
|
||||||
|
{
|
||||||
|
gnome_password_dialog_set_password(GNOME_PASSWORD_DIALOG(dialog), pass);
|
||||||
|
}
|
||||||
|
if (!gnome_password_dialog_run_and_block(GNOME_PASSWORD_DIALOG(dialog)))
|
||||||
|
{
|
||||||
|
g_object_unref (program);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pass = gnome_password_dialog_get_password(GNOME_PASSWORD_DIALOG(dialog));
|
||||||
|
switch (gnome_password_dialog_get_remember(GNOME_PASSWORD_DIALOG(dialog)))
|
||||||
|
{
|
||||||
|
case GNOME_PASSWORD_DIALOG_REMEMBER_NOTHING:
|
||||||
|
break;
|
||||||
|
case GNOME_PASSWORD_DIALOG_REMEMBER_SESSION:
|
||||||
|
keyring = "session";
|
||||||
|
/* FALL */
|
||||||
|
case GNOME_PASSWORD_DIALOG_REMEMBER_FOREVER:
|
||||||
|
if (gnome_keyring_set_network_password_sync(keyring,
|
||||||
|
g_get_user_name(), NULL, name, "password", service, NULL, 0,
|
||||||
|
pass, &itemid) != GNOME_KEYRING_RESULT_OK)
|
||||||
|
{
|
||||||
|
g_warning ("storing password in keyring failed");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!gnome_password_dialog_run_and_block(GNOME_PASSWORD_DIALOG(dialog)))
|
printf("password\n%s\n", pass);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
agent = getenv("SSH_AUTH_SOCK");
|
||||||
|
if (agent)
|
||||||
{
|
{
|
||||||
g_object_unref (program);
|
printf("agent\n%s\n", agent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GtkWidget *dialog;
|
||||||
|
|
||||||
|
dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR,
|
||||||
|
GTK_BUTTONS_OK,
|
||||||
|
_("Configuration uses ssh-agent for authentication, "
|
||||||
|
"but ssh-agent is not running!"));
|
||||||
|
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||||
|
gtk_widget_destroy (dialog);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pass = gnome_password_dialog_get_password(GNOME_PASSWORD_DIALOG(dialog));
|
|
||||||
switch (gnome_password_dialog_get_remember(GNOME_PASSWORD_DIALOG(dialog)))
|
|
||||||
{
|
|
||||||
case GNOME_PASSWORD_DIALOG_REMEMBER_NOTHING:
|
|
||||||
break;
|
|
||||||
case GNOME_PASSWORD_DIALOG_REMEMBER_SESSION:
|
|
||||||
keyring = "session";
|
|
||||||
/* FALL */
|
|
||||||
case GNOME_PASSWORD_DIALOG_REMEMBER_FOREVER:
|
|
||||||
if (gnome_keyring_set_network_password_sync(keyring,
|
|
||||||
g_get_user_name(), NULL, name, "password", service, NULL, 0,
|
|
||||||
pass, &itemid) != GNOME_KEYRING_RESULT_OK)
|
|
||||||
{
|
|
||||||
g_warning ("storing password in keyring failed");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
printf("password\n%s\n", pass);
|
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
/* flush output, wait for input */
|
/* flush output, wait for input */
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|||||||
@@ -37,14 +37,28 @@
|
|||||||
<property name="column_spacing">6</property>
|
<property name="column_spacing">6</property>
|
||||||
<property name="row_spacing">6</property>
|
<property name="row_spacing">6</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkLabel" id="address-label">
|
<widget class="GtkFileChooserButton" id="certificate-button">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="xalign">0</property>
|
<property name="tooltip_text">Gateway certificate to use for gateway authentication.</property>
|
||||||
<property name="label" translatable="yes">_Address:</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="mnemonic_widget">address-entry</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="right_attach">2</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="bottom_attach">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="certificate-label">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="label" translatable="yes">C_ertificate:</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="mnemonic_widget">certificate-button</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="bottom_attach">2</property>
|
||||||
<property name="x_options">GTK_FILL</property>
|
<property name="x_options">GTK_FILL</property>
|
||||||
<property name="y_options"></property>
|
<property name="y_options"></property>
|
||||||
</packing>
|
</packing>
|
||||||
@@ -63,32 +77,18 @@
|
|||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkLabel" id="certificate-label">
|
<widget class="GtkLabel" id="address-label">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="xalign">0</property>
|
<property name="xalign">0</property>
|
||||||
<property name="label" translatable="yes">_Certificate:</property>
|
<property name="label" translatable="yes">_Address:</property>
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<property name="mnemonic_widget">certificate-button</property>
|
<property name="mnemonic_widget">address-entry</property>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="top_attach">1</property>
|
|
||||||
<property name="bottom_attach">2</property>
|
|
||||||
<property name="x_options">GTK_FILL</property>
|
<property name="x_options">GTK_FILL</property>
|
||||||
<property name="y_options"></property>
|
<property name="y_options"></property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<widget class="GtkFileChooserButton" id="certificate-button">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="tooltip_text">Gateway certificate to use for gateway authentication.</property>
|
|
||||||
</widget>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">1</property>
|
|
||||||
<property name="right_attach">2</property>
|
|
||||||
<property name="top_attach">1</property>
|
|
||||||
<property name="bottom_attach">2</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
@@ -102,14 +102,14 @@
|
|||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkVBox" id="authentication-vbox">
|
<widget class="GtkVBox" id="client-vbox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="spacing">6</property>
|
<property name="spacing">6</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkLabel" id="authentication-label">
|
<widget class="GtkLabel" id="client-label">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="xalign">0</property>
|
<property name="xalign">0</property>
|
||||||
<property name="label" translatable="yes"><b>Authentication</b></property>
|
<property name="label" translatable="yes"><b>Client</b></property>
|
||||||
<property name="use_markup">True</property>
|
<property name="use_markup">True</property>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
@@ -118,16 +118,43 @@
|
|||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkAlignment" id="authentication-aligement">
|
<widget class="GtkAlignment" id="client-aligement">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="left_padding">12</property>
|
<property name="left_padding">12</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkTable" id="authentication-table">
|
<widget class="GtkTable" id="client-table">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="n_rows">2</property>
|
<property name="n_rows">3</property>
|
||||||
<property name="n_columns">2</property>
|
<property name="n_columns">2</property>
|
||||||
<property name="column_spacing">6</property>
|
<property name="column_spacing">6</property>
|
||||||
<property name="row_spacing">6</property>
|
<property name="row_spacing">6</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkFileChooserButton" id="usercert-button">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="tooltip_text">Client certificate to use for client authentication.</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="right_attach">2</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
<property name="bottom_attach">3</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="usercert-label">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="label" translatable="yes">Ce_rtificate:</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="mnemonic_widget">usercert-button</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
<property name="bottom_attach">3</property>
|
||||||
|
<property name="x_options">GTK_FILL</property>
|
||||||
|
<property name="y_options"></property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkEntry" id="user-entry">
|
<widget class="GtkEntry" id="user-entry">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
@@ -138,6 +165,23 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">1</property>
|
<property name="left_attach">1</property>
|
||||||
<property name="right_attach">2</property>
|
<property name="right_attach">2</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="bottom_attach">2</property>
|
||||||
|
<property name="y_options"></property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="user-label">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="label" translatable="yes">_Username:</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="mnemonic_widget">user-entry</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="bottom_attach">2</property>
|
||||||
|
<property name="x_options">GTK_FILL</property>
|
||||||
<property name="y_options"></property>
|
<property name="y_options"></property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
@@ -145,13 +189,11 @@
|
|||||||
<widget class="GtkLabel" id="method-label">
|
<widget class="GtkLabel" id="method-label">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="xalign">0</property>
|
<property name="xalign">0</property>
|
||||||
<property name="label" translatable="yes">_Method:</property>
|
<property name="label" translatable="yes">Au_thentication:</property>
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<property name="mnemonic_widget">method-combo</property>
|
<property name="mnemonic_widget">method-combo</property>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="top_attach">1</property>
|
|
||||||
<property name="bottom_attach">2</property>
|
|
||||||
<property name="x_options">GTK_FILL</property>
|
<property name="x_options">GTK_FILL</property>
|
||||||
<property name="y_options"></property>
|
<property name="y_options"></property>
|
||||||
</packing>
|
</packing>
|
||||||
@@ -166,21 +208,6 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">1</property>
|
<property name="left_attach">1</property>
|
||||||
<property name="right_attach">2</property>
|
<property name="right_attach">2</property>
|
||||||
<property name="top_attach">1</property>
|
|
||||||
<property name="bottom_attach">2</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkLabel" id="user-label">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="xalign">0</property>
|
|
||||||
<property name="label" translatable="yes">_Username:</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="mnemonic_widget">user-entry</property>
|
|
||||||
</widget>
|
|
||||||
<packing>
|
|
||||||
<property name="x_options">GTK_FILL</property>
|
|
||||||
<property name="y_options"></property>
|
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
|
|||||||
@@ -119,26 +119,38 @@ check_validity (StrongswanPluginUiWidget *self, GError **error)
|
|||||||
"address");
|
"address");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
widget = glade_xml_get_widget (priv->xml, "user-entry");
|
|
||||||
str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
|
|
||||||
if (!str || !strlen (str)) {
|
|
||||||
g_set_error (error,
|
|
||||||
STRONGSWAN_PLUGIN_UI_ERROR,
|
|
||||||
STRONGSWAN_PLUGIN_UI_ERROR_INVALID_PROPERTY,
|
|
||||||
"user");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stuff_changed_cb (GtkWidget *widget, gpointer user_data)
|
settings_changed_cb (GtkWidget *widget, gpointer user_data)
|
||||||
{
|
{
|
||||||
g_signal_emit_by_name (STRONGSWAN_PLUGIN_UI_WIDGET (user_data), "changed");
|
g_signal_emit_by_name (STRONGSWAN_PLUGIN_UI_WIDGET (user_data), "changed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
method_changed_cb (GtkWidget *widget, gpointer user_data)
|
||||||
|
{
|
||||||
|
StrongswanPluginUiWidget *self = STRONGSWAN_PLUGIN_UI_WIDGET (user_data);
|
||||||
|
StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
if (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) == 0)
|
||||||
|
{
|
||||||
|
gtk_widget_show (glade_xml_get_widget (priv->xml, "usercert-label"));
|
||||||
|
gtk_widget_show (glade_xml_get_widget (priv->xml, "usercert-button"));
|
||||||
|
gtk_widget_hide (glade_xml_get_widget (priv->xml, "user-label"));
|
||||||
|
gtk_widget_hide (glade_xml_get_widget (priv->xml, "user-entry"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gtk_widget_hide (glade_xml_get_widget (priv->xml, "usercert-label"));
|
||||||
|
gtk_widget_hide (glade_xml_get_widget (priv->xml, "usercert-button"));
|
||||||
|
gtk_widget_show (glade_xml_get_widget (priv->xml, "user-label"));
|
||||||
|
gtk_widget_show (glade_xml_get_widget (priv->xml, "user-entry"));
|
||||||
|
}
|
||||||
|
g_signal_emit_by_name (STRONGSWAN_PLUGIN_UI_WIDGET (user_data), "changed");
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
init_plugin_ui (StrongswanPluginUiWidget *self, NMConnection *connection, GError **error)
|
init_plugin_ui (StrongswanPluginUiWidget *self, NMConnection *connection, GError **error)
|
||||||
{
|
{
|
||||||
@@ -149,83 +161,87 @@ init_plugin_ui (StrongswanPluginUiWidget *self, NMConnection *connection, GError
|
|||||||
gboolean active;
|
gboolean active;
|
||||||
|
|
||||||
settings = NM_SETTING_VPN(nm_connection_get_setting(connection, NM_TYPE_SETTING_VPN));
|
settings = NM_SETTING_VPN(nm_connection_get_setting(connection, NM_TYPE_SETTING_VPN));
|
||||||
if (!settings)
|
|
||||||
return FALSE;
|
|
||||||
widget = glade_xml_get_widget (priv->xml, "address-entry");
|
widget = glade_xml_get_widget (priv->xml, "address-entry");
|
||||||
if (!widget)
|
|
||||||
return FALSE;
|
|
||||||
value = g_hash_table_lookup (settings->data, "address");
|
value = g_hash_table_lookup (settings->data, "address");
|
||||||
if (value)
|
if (value)
|
||||||
gtk_entry_set_text (GTK_ENTRY (widget), value);
|
gtk_entry_set_text (GTK_ENTRY (widget), value);
|
||||||
g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
|
g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (settings_changed_cb), self);
|
||||||
|
|
||||||
widget = glade_xml_get_widget (priv->xml, "certificate-button");
|
widget = glade_xml_get_widget (priv->xml, "certificate-button");
|
||||||
if (!widget)
|
|
||||||
return FALSE;
|
|
||||||
value = g_hash_table_lookup (settings->data, "certificate");
|
value = g_hash_table_lookup (settings->data, "certificate");
|
||||||
if (value)
|
if (value)
|
||||||
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), value);
|
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), value);
|
||||||
g_signal_connect (G_OBJECT (widget), "selection-changed", G_CALLBACK (stuff_changed_cb), self);
|
g_signal_connect (G_OBJECT (widget), "selection-changed", G_CALLBACK (settings_changed_cb), self);
|
||||||
|
|
||||||
|
widget = glade_xml_get_widget (priv->xml, "user-label");
|
||||||
|
gtk_widget_set_no_show_all (widget, TRUE);
|
||||||
widget = glade_xml_get_widget (priv->xml, "user-entry");
|
widget = glade_xml_get_widget (priv->xml, "user-entry");
|
||||||
if (!widget)
|
gtk_widget_set_no_show_all (widget, TRUE);
|
||||||
return FALSE;
|
|
||||||
value = g_hash_table_lookup (settings->data, "user");
|
value = g_hash_table_lookup (settings->data, "user");
|
||||||
if (value)
|
if (value)
|
||||||
gtk_entry_set_text (GTK_ENTRY (widget), value);
|
gtk_entry_set_text (GTK_ENTRY (widget), value);
|
||||||
g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
|
g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (settings_changed_cb), self);
|
||||||
|
|
||||||
widget = glade_xml_get_widget (priv->xml, "method-combo");
|
widget = glade_xml_get_widget (priv->xml, "method-combo");
|
||||||
if (!widget)
|
gtk_combo_box_append_text (GTK_COMBO_BOX (widget), _("Certificate/ssh-agent"));
|
||||||
return FALSE;
|
|
||||||
gtk_combo_box_append_text (GTK_COMBO_BOX (widget), _("EAP"));
|
gtk_combo_box_append_text (GTK_COMBO_BOX (widget), _("EAP"));
|
||||||
/* TODO: PSK is disabled until we have the possibility to enforce strong
|
|
||||||
* secrets.
|
|
||||||
gtk_combo_box_append_text (GTK_COMBO_BOX (widget), _("Preshared Key")); */
|
|
||||||
value = g_hash_table_lookup (settings->data, "method");
|
value = g_hash_table_lookup (settings->data, "method");
|
||||||
if (value) {
|
if (value) {
|
||||||
if (g_strcasecmp (value, "eap") == 0) {
|
if (g_strcasecmp (value, "agent") == 0) {
|
||||||
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
|
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
|
||||||
}
|
}
|
||||||
if (g_strcasecmp (value, "psk") == 0) {
|
if (g_strcasecmp (value, "eap") == 0) {
|
||||||
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1);
|
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
|
g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (method_changed_cb), self);
|
||||||
if (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) == -1)
|
if (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) == -1)
|
||||||
{ /* default to EAP */
|
{
|
||||||
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
|
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
|
||||||
}
|
}
|
||||||
|
if (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) != 0)
|
||||||
|
{
|
||||||
|
gtk_widget_hide (glade_xml_get_widget (priv->xml, "usercert-label"));
|
||||||
|
gtk_widget_hide (glade_xml_get_widget (priv->xml, "usercert-button"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gtk_widget_hide (glade_xml_get_widget (priv->xml, "user-label"));
|
||||||
|
gtk_widget_hide (glade_xml_get_widget (priv->xml, "user-entry"));
|
||||||
|
}
|
||||||
|
|
||||||
|
widget = glade_xml_get_widget (priv->xml, "usercert-label");
|
||||||
|
gtk_widget_set_no_show_all (widget, TRUE);
|
||||||
|
widget = glade_xml_get_widget (priv->xml, "usercert-button");
|
||||||
|
gtk_widget_set_no_show_all (widget, TRUE);
|
||||||
|
value = g_hash_table_lookup (settings->data, "usercert");
|
||||||
|
if (value)
|
||||||
|
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), value);
|
||||||
|
g_signal_connect (G_OBJECT (widget), "selection-changed", G_CALLBACK (settings_changed_cb), self);
|
||||||
|
|
||||||
widget = glade_xml_get_widget (priv->xml, "virtual-check");
|
widget = glade_xml_get_widget (priv->xml, "virtual-check");
|
||||||
if (!widget)
|
|
||||||
return FALSE;
|
|
||||||
value = g_hash_table_lookup (settings->data, "virtual");
|
value = g_hash_table_lookup (settings->data, "virtual");
|
||||||
if (value && strcmp(value, "yes") == 0)
|
if (value && strcmp(value, "yes") == 0)
|
||||||
{
|
{
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
|
||||||
}
|
}
|
||||||
g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (stuff_changed_cb), self);
|
g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (settings_changed_cb), self);
|
||||||
|
|
||||||
widget = glade_xml_get_widget (priv->xml, "encap-check");
|
widget = glade_xml_get_widget (priv->xml, "encap-check");
|
||||||
if (!widget)
|
|
||||||
return FALSE;
|
|
||||||
value = g_hash_table_lookup (settings->data, "encap");
|
value = g_hash_table_lookup (settings->data, "encap");
|
||||||
if (value && strcmp(value, "yes") == 0)
|
if (value && strcmp(value, "yes") == 0)
|
||||||
{
|
{
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
|
||||||
}
|
}
|
||||||
g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (stuff_changed_cb), self);
|
g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (settings_changed_cb), self);
|
||||||
|
|
||||||
widget = glade_xml_get_widget (priv->xml, "ipcomp-check");
|
widget = glade_xml_get_widget (priv->xml, "ipcomp-check");
|
||||||
if (!widget)
|
|
||||||
return FALSE;
|
|
||||||
value = g_hash_table_lookup (settings->data, "ipcomp");
|
value = g_hash_table_lookup (settings->data, "ipcomp");
|
||||||
if (value && strcmp(value, "yes") == 0)
|
if (value && strcmp(value, "yes") == 0)
|
||||||
{
|
{
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
|
||||||
}
|
}
|
||||||
g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (stuff_changed_cb), self);
|
g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (settings_changed_cb), self);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -270,24 +286,26 @@ update_connection (NMVpnPluginUiWidgetInterface *iface,
|
|||||||
if (str) {
|
if (str) {
|
||||||
g_hash_table_insert (settings->data, g_strdup ("certificate"), g_strdup(str));
|
g_hash_table_insert (settings->data, g_strdup ("certificate"), g_strdup(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
widget = glade_xml_get_widget (priv->xml, "user-entry");
|
|
||||||
str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
|
|
||||||
if (str && strlen (str)) {
|
|
||||||
g_hash_table_insert (settings->data, g_strdup ("user"), g_strdup(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
widget = glade_xml_get_widget (priv->xml, "method-combo");
|
widget = glade_xml_get_widget (priv->xml, "method-combo");
|
||||||
switch (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)))
|
switch (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)))
|
||||||
{
|
{
|
||||||
|
case 0:
|
||||||
default:
|
default:
|
||||||
str = "eap";
|
widget = glade_xml_get_widget (priv->xml, "usercert-button");
|
||||||
|
str = (char *) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
|
||||||
|
if (str) {
|
||||||
|
g_hash_table_insert (settings->data, g_strdup ("usercert"), g_strdup(str));
|
||||||
|
}
|
||||||
|
str = "agent";
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
str = "psk";
|
widget = glade_xml_get_widget (priv->xml, "user-entry");
|
||||||
break;
|
str = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
|
||||||
case 2:
|
if (str && strlen (str)) {
|
||||||
str = "pubkey";
|
g_hash_table_insert (settings->data, g_strdup ("user"), g_strdup(str));
|
||||||
|
}
|
||||||
|
str = "eap";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
g_hash_table_insert (settings->data, g_strdup ("method"), g_strdup(str));
|
g_hash_table_insert (settings->data, g_strdup ("method"), g_strdup(str));
|
||||||
|
|||||||
@@ -49,12 +49,54 @@ struct private_nm_creds_t {
|
|||||||
*/
|
*/
|
||||||
char *pass;
|
char *pass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* users certificate
|
||||||
|
*/
|
||||||
|
certificate_t *usercert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* users private key
|
||||||
|
*/
|
||||||
|
private_key_t *key;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read/write lock
|
* read/write lock
|
||||||
*/
|
*/
|
||||||
pthread_rwlock_t lock;
|
pthread_rwlock_t lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumerator for user certificate
|
||||||
|
*/
|
||||||
|
static enumerator_t *create_usercert_enumerator(private_nm_creds_t *this,
|
||||||
|
certificate_type_t cert, key_type_t key)
|
||||||
|
{
|
||||||
|
public_key_t *public;
|
||||||
|
|
||||||
|
if (cert != CERT_ANY && cert != this->usercert->get_type(this->usercert))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (key != KEY_ANY)
|
||||||
|
{
|
||||||
|
public = this->usercert->get_public_key(this->usercert);
|
||||||
|
if (!public)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (public->get_type(public) != key)
|
||||||
|
{
|
||||||
|
public->destroy(public);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
public->destroy(public);
|
||||||
|
}
|
||||||
|
pthread_rwlock_rdlock(&this->lock);
|
||||||
|
return enumerator_create_cleaner(
|
||||||
|
enumerator_create_single(this->usercert, NULL),
|
||||||
|
(void*)pthread_rwlock_unlock, &this->lock);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements credential_set_t.create_cert_enumerator
|
* Implements credential_set_t.create_cert_enumerator
|
||||||
*/
|
*/
|
||||||
@@ -62,6 +104,12 @@ static enumerator_t* create_cert_enumerator(private_nm_creds_t *this,
|
|||||||
certificate_type_t cert, key_type_t key,
|
certificate_type_t cert, key_type_t key,
|
||||||
identification_t *id, bool trusted)
|
identification_t *id, bool trusted)
|
||||||
{
|
{
|
||||||
|
if (id && this->usercert &&
|
||||||
|
id->equals(id, this->usercert->get_subject(this->usercert)))
|
||||||
|
{
|
||||||
|
return create_usercert_enumerator(this, cert, key);
|
||||||
|
}
|
||||||
|
|
||||||
if (!this->cert)
|
if (!this->cert)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -95,6 +143,35 @@ static enumerator_t* create_cert_enumerator(private_nm_creds_t *this,
|
|||||||
(void*)pthread_rwlock_unlock, &this->lock);
|
(void*)pthread_rwlock_unlock, &this->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements credential_set_t.create_cert_enumerator
|
||||||
|
*/
|
||||||
|
static enumerator_t* create_private_enumerator(private_nm_creds_t *this,
|
||||||
|
key_type_t type, identification_t *id)
|
||||||
|
{
|
||||||
|
if (this->key == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (type != KEY_ANY && type != this->key->get_type(this->key))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (id && id->get_type(id) != ID_ANY)
|
||||||
|
{
|
||||||
|
identification_t *keyid;
|
||||||
|
|
||||||
|
keyid = this->key->get_id(this->key, id->get_type(id));
|
||||||
|
if (!keyid || !keyid->equals(keyid, id))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_rwlock_rdlock(&this->lock);
|
||||||
|
return enumerator_create_cleaner(enumerator_create_single(this->key, NULL),
|
||||||
|
(void*)pthread_rwlock_unlock, &this->lock);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shared key enumerator implementation
|
* shared key enumerator implementation
|
||||||
*/
|
*/
|
||||||
@@ -179,7 +256,7 @@ static void set_certificate(private_nm_creds_t *this, certificate_t *cert)
|
|||||||
/**
|
/**
|
||||||
* Implementation of nm_creds_t.set_password
|
* Implementation of nm_creds_t.set_password
|
||||||
*/
|
*/
|
||||||
static void set_password(private_nm_creds_t *this, identification_t *id,
|
static void set_username_password(private_nm_creds_t *this, identification_t *id,
|
||||||
char *password)
|
char *password)
|
||||||
{
|
{
|
||||||
pthread_rwlock_wrlock(&this->lock);
|
pthread_rwlock_wrlock(&this->lock);
|
||||||
@@ -188,18 +265,47 @@ static void set_password(private_nm_creds_t *this, identification_t *id,
|
|||||||
this->user = identification_create_from_encoding(ID_EAP,
|
this->user = identification_create_from_encoding(ID_EAP,
|
||||||
id->get_encoding(id));
|
id->get_encoding(id));
|
||||||
free(this->pass);
|
free(this->pass);
|
||||||
this->pass = strdup(password);
|
this->pass = password ? strdup(password) : NULL;
|
||||||
pthread_rwlock_unlock(&this->lock);
|
pthread_rwlock_unlock(&this->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of nm_creds_t.set_cert_and_key
|
||||||
|
*/
|
||||||
|
static void set_cert_and_key(private_nm_creds_t *this, certificate_t *cert,
|
||||||
|
private_key_t *key)
|
||||||
|
{
|
||||||
|
pthread_rwlock_wrlock(&this->lock);
|
||||||
|
DESTROY_IF(this->key);
|
||||||
|
DESTROY_IF(this->usercert);
|
||||||
|
this->key = key;
|
||||||
|
this->usercert = cert;
|
||||||
|
pthread_rwlock_unlock(&this->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of nm_creds_t.clear
|
||||||
|
*/
|
||||||
|
static void clear(private_nm_creds_t *this)
|
||||||
|
{
|
||||||
|
DESTROY_IF(this->cert);
|
||||||
|
DESTROY_IF(this->user);
|
||||||
|
free(this->pass);
|
||||||
|
DESTROY_IF(this->usercert);
|
||||||
|
DESTROY_IF(this->key);
|
||||||
|
this->key = NULL;
|
||||||
|
this->usercert = NULL;
|
||||||
|
this->pass = NULL;
|
||||||
|
this->cert = NULL;
|
||||||
|
this->user = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of nm_creds_t.destroy
|
* Implementation of nm_creds_t.destroy
|
||||||
*/
|
*/
|
||||||
static void destroy(private_nm_creds_t *this)
|
static void destroy(private_nm_creds_t *this)
|
||||||
{
|
{
|
||||||
DESTROY_IF(this->cert);
|
clear(this);
|
||||||
DESTROY_IF(this->user);
|
|
||||||
free(this->pass);
|
|
||||||
pthread_rwlock_destroy(&this->lock);
|
pthread_rwlock_destroy(&this->lock);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
@@ -211,13 +317,15 @@ nm_creds_t *nm_creds_create()
|
|||||||
{
|
{
|
||||||
private_nm_creds_t *this = malloc_thing(private_nm_creds_t);
|
private_nm_creds_t *this = malloc_thing(private_nm_creds_t);
|
||||||
|
|
||||||
this->public.set.create_private_enumerator = (void*)return_null;
|
this->public.set.create_private_enumerator = (void*)create_private_enumerator;
|
||||||
this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
|
this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
|
||||||
this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
|
this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
|
||||||
this->public.set.create_cdp_enumerator = (void*)return_null;
|
this->public.set.create_cdp_enumerator = (void*)return_null;
|
||||||
this->public.set.cache_cert = (void*)nop;
|
this->public.set.cache_cert = (void*)nop;
|
||||||
this->public.set_certificate = (void(*)(nm_creds_t*, certificate_t *cert))set_certificate;
|
this->public.set_certificate = (void(*)(nm_creds_t*, certificate_t *cert))set_certificate;
|
||||||
this->public.set_password = (void(*)(nm_creds_t*, identification_t *id, char *password))set_password;
|
this->public.set_username_password = (void(*)(nm_creds_t*, identification_t *id, char *password))set_username_password;
|
||||||
|
this->public.set_cert_and_key = (void(*)(nm_creds_t*, certificate_t *cert, private_key_t *key))set_cert_and_key;
|
||||||
|
this->public.clear = (void(*)(nm_creds_t*))clear;
|
||||||
this->public.destroy = (void(*)(nm_creds_t*))destroy;
|
this->public.destroy = (void(*)(nm_creds_t*))destroy;
|
||||||
|
|
||||||
pthread_rwlock_init(&this->lock, NULL);
|
pthread_rwlock_init(&this->lock, NULL);
|
||||||
@@ -225,6 +333,8 @@ nm_creds_t *nm_creds_create()
|
|||||||
this->cert = NULL;
|
this->cert = NULL;
|
||||||
this->user = NULL;
|
this->user = NULL;
|
||||||
this->pass = NULL;
|
this->pass = NULL;
|
||||||
|
this->usercert = NULL;
|
||||||
|
this->key = NULL;
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,8 +50,21 @@ struct nm_creds_t {
|
|||||||
* @param id ID of the user
|
* @param id ID of the user
|
||||||
* @param password password to use for authentication
|
* @param password password to use for authentication
|
||||||
*/
|
*/
|
||||||
void (*set_password)(nm_creds_t *this, identification_t *id, char *password);
|
void (*set_username_password)(nm_creds_t *this, identification_t *id,
|
||||||
|
char *password);
|
||||||
|
/**
|
||||||
|
* Set the certificate and private key to use for client authentication.
|
||||||
|
*
|
||||||
|
* @param cert client certificate
|
||||||
|
* @param key associated private key
|
||||||
|
*/
|
||||||
|
void (*set_cert_and_key)(nm_creds_t *this, certificate_t *cert,
|
||||||
|
private_key_t *key);
|
||||||
|
/**
|
||||||
|
* Clear the stored credentials.
|
||||||
|
*/
|
||||||
|
void (*clear)(nm_creds_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a nm_creds instance.
|
* Destroy a nm_creds instance.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <processing/jobs/callback_job.h>
|
#include <processing/jobs/callback_job.h>
|
||||||
|
|
||||||
|
#define CAP_DAC_OVERRIDE 1
|
||||||
|
|
||||||
typedef struct private_nm_plugin_t private_nm_plugin_t;
|
typedef struct private_nm_plugin_t private_nm_plugin_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,6 +108,9 @@ plugin_t *plugin_create()
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* bypass file permissions to read from users ssh-agent */
|
||||||
|
charon->keep_cap(charon, CAP_DAC_OVERRIDE);
|
||||||
|
|
||||||
charon->processor->queue_job(charon->processor,
|
charon->processor->queue_job(charon->processor,
|
||||||
(job_t*)callback_job_create((callback_job_cb_t)run, this, NULL, NULL));
|
(job_t*)callback_job_create((callback_job_cb_t)run, this, NULL, NULL));
|
||||||
|
|
||||||
|
|||||||
@@ -183,19 +183,6 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
|||||||
|
|
||||||
DBG1(DBG_CFG, "received NetworkManager connection: %s",
|
DBG1(DBG_CFG, "received NetworkManager connection: %s",
|
||||||
nm_setting_to_string(NM_SETTING(settings)));
|
nm_setting_to_string(NM_SETTING(settings)));
|
||||||
str = g_hash_table_lookup(settings->data, "user");
|
|
||||||
if (!str)
|
|
||||||
{
|
|
||||||
g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
|
|
||||||
"Username missing.");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
user = identification_create_from_string(str);
|
|
||||||
if (!user)
|
|
||||||
{ /* fallback to ID_KEY_ID for non-qualified usernames */
|
|
||||||
user = identification_create_from_encoding(ID_KEY_ID,
|
|
||||||
chunk_create(str, strlen(str)));
|
|
||||||
}
|
|
||||||
address = g_hash_table_lookup(settings->data, "address");
|
address = g_hash_table_lookup(settings->data, "address");
|
||||||
if (!address || !*address)
|
if (!address || !*address)
|
||||||
{
|
{
|
||||||
@@ -216,7 +203,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
|||||||
{
|
{
|
||||||
auth_class = AUTH_CLASS_PSK;
|
auth_class = AUTH_CLASS_PSK;
|
||||||
}
|
}
|
||||||
else if (streq(str, "pubkey"))
|
else if (streq(str, "agent"))
|
||||||
{
|
{
|
||||||
auth_class = AUTH_CLASS_PUBKEY;
|
auth_class = AUTH_CLASS_PUBKEY;
|
||||||
}
|
}
|
||||||
@@ -226,7 +213,9 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
|||||||
* Register credentials
|
* Register credentials
|
||||||
*/
|
*/
|
||||||
creds = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->creds;
|
creds = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->creds;
|
||||||
|
creds->clear(creds);
|
||||||
|
|
||||||
|
/* gateway cert */
|
||||||
str = g_hash_table_lookup(settings->data, "certificate");
|
str = g_hash_table_lookup(settings->data, "certificate");
|
||||||
if (str)
|
if (str)
|
||||||
{
|
{
|
||||||
@@ -237,14 +226,69 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
|||||||
if (!cert)
|
if (!cert)
|
||||||
{
|
{
|
||||||
g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
|
g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
|
||||||
"Loading certificate failed.");
|
"Loading gateway certificate failed.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
gateway = cert->get_subject(cert);
|
gateway = cert->get_subject(cert);
|
||||||
str = g_hash_table_lookup(settings->data, "password");
|
|
||||||
if (str)
|
if (auth_class == AUTH_CLASS_EAP)
|
||||||
{
|
{
|
||||||
creds->set_password(creds, user, str);
|
/* username/password authentication ... */
|
||||||
|
str = g_hash_table_lookup(settings->data, "user");
|
||||||
|
if (str)
|
||||||
|
{
|
||||||
|
user = identification_create_from_string(str);
|
||||||
|
str = g_hash_table_lookup(settings->data, "password");
|
||||||
|
creds->set_username_password(creds, user, str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auth_class == AUTH_CLASS_PUBKEY)
|
||||||
|
{
|
||||||
|
/* ... or certificate/private key authenitcation */
|
||||||
|
str = g_hash_table_lookup(settings->data, "usercert");
|
||||||
|
if (str)
|
||||||
|
{
|
||||||
|
public_key_t *public;
|
||||||
|
private_key_t *private = NULL;
|
||||||
|
|
||||||
|
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||||
|
BUILD_FROM_FILE, str, BUILD_END);
|
||||||
|
str = g_hash_table_lookup(settings->data, "agent");
|
||||||
|
if (str && cert)
|
||||||
|
{
|
||||||
|
public = cert->get_public_key(cert);
|
||||||
|
if (public)
|
||||||
|
{
|
||||||
|
private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
|
||||||
|
public->get_type(public),
|
||||||
|
BUILD_AGENT_SOCKET, str,
|
||||||
|
BUILD_PUBLIC_KEY, public,
|
||||||
|
BUILD_END);
|
||||||
|
public->destroy(public);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (private)
|
||||||
|
{
|
||||||
|
user = cert->get_subject(cert);
|
||||||
|
user = user->clone(user);
|
||||||
|
creds->set_cert_and_key(creds, cert, private);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DESTROY_IF(cert);
|
||||||
|
g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
|
||||||
|
"Loading user certificate/private key failed.");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user)
|
||||||
|
{
|
||||||
|
g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
|
||||||
|
"Configuration parameters missing.");
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -255,7 +299,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
|||||||
peer_cfg = peer_cfg_create(CONFIG_NAME, 2, ike_cfg,
|
peer_cfg = peer_cfg_create(CONFIG_NAME, 2, ike_cfg,
|
||||||
user, gateway->clone(gateway),
|
user, gateway->clone(gateway),
|
||||||
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
|
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
|
||||||
18000, 0, /* rekey 5h, reauth none */
|
36000, 0, /* rekey 10h, reauth none */
|
||||||
600, 600, /* jitter, over 10min */
|
600, 600, /* jitter, over 10min */
|
||||||
TRUE, 0, /* mobike, DPD */
|
TRUE, 0, /* mobike, DPD */
|
||||||
virtual ? host_create_from_string("0.0.0.0", 0) : NULL,
|
virtual ? host_create_from_string("0.0.0.0", 0) : NULL,
|
||||||
@@ -263,10 +307,10 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
|||||||
auth = peer_cfg->get_auth(peer_cfg);
|
auth = peer_cfg->get_auth(peer_cfg);
|
||||||
auth->add_item(auth, AUTHN_AUTH_CLASS, &auth_class);
|
auth->add_item(auth, AUTHN_AUTH_CLASS, &auth_class);
|
||||||
child_cfg = child_cfg_create(CONFIG_NAME,
|
child_cfg = child_cfg_create(CONFIG_NAME,
|
||||||
3600, 3000, /* lifetime 1h, rekey 50min */
|
10800, 10200, /* lifetime 3h, rekey 2h50min */
|
||||||
300, /* jitter 5min */
|
300, /* jitter 5min */
|
||||||
NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */
|
NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */
|
||||||
ACTION_NONE, ACTION_NONE, ipcomp);
|
ACTION_NONE, ACTION_RESTART, ipcomp);
|
||||||
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
|
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
|
||||||
ts = traffic_selector_create_dynamic(0, 0, 65535);
|
ts = traffic_selector_create_dynamic(0, 0, 65535);
|
||||||
child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
|
child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
|
||||||
@@ -315,15 +359,30 @@ static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection,
|
|||||||
char **setting_name, GError **error)
|
char **setting_name, GError **error)
|
||||||
{
|
{
|
||||||
NMSettingVPN *settings;
|
NMSettingVPN *settings;
|
||||||
|
char *method;
|
||||||
|
|
||||||
settings = NM_SETTING_VPN(nm_connection_get_setting(connection,
|
settings = NM_SETTING_VPN(nm_connection_get_setting(connection,
|
||||||
NM_TYPE_SETTING_VPN));
|
NM_TYPE_SETTING_VPN));
|
||||||
if (!g_hash_table_lookup(settings->data, "password"))
|
method = g_hash_table_lookup(settings->data, "method");
|
||||||
|
if (method)
|
||||||
{
|
{
|
||||||
*setting_name = NM_SETTING_VPN_SETTING_NAME;
|
if (streq(method, "eap"))
|
||||||
return TRUE;
|
{
|
||||||
|
if (g_hash_table_lookup(settings->data, "password"))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (streq(method, "agent"))
|
||||||
|
{
|
||||||
|
if (g_hash_table_lookup(settings->data, "agent"))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return FALSE;
|
*setting_name = NM_SETTING_VPN_SETTING_NAME;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user