diff options
Diffstat (limited to 'src/libcharon/plugins/nm')
39 files changed, 3440 insertions, 0 deletions
diff --git a/src/libcharon/plugins/nm/.gitignore b/src/libcharon/plugins/nm/.gitignore new file mode 100644 index 000000000..517d94ca2 --- /dev/null +++ b/src/libcharon/plugins/nm/.gitignore @@ -0,0 +1 @@ +network-manager-strongswan_* diff --git a/src/libcharon/plugins/nm/Makefile.am b/src/libcharon/plugins/nm/Makefile.am new file mode 100644 index 000000000..a6d29dea6 --- /dev/null +++ b/src/libcharon/plugins/nm/Makefile.am @@ -0,0 +1,20 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon ${nm_CFLAGS} + +AM_CFLAGS = -rdynamic \ + -DNM_CA_DIR=\"${nm_ca_dir}\" + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-nm.la +else +plugin_LTLIBRARIES = libstrongswan-nm.la +endif + +libstrongswan_nm_la_SOURCES = \ + nm_plugin.h nm_plugin.c \ + nm_service.h nm_service.c \ + nm_creds.h nm_creds.c \ + nm_handler.h nm_handler.c + +libstrongswan_nm_la_LDFLAGS = -module -avoid-version +libstrongswan_nm_la_LIBADD = ${nm_LIBS} diff --git a/src/libcharon/plugins/nm/gnome/.gitignore b/src/libcharon/plugins/nm/gnome/.gitignore new file mode 100644 index 000000000..64bb14511 --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/.gitignore @@ -0,0 +1,11 @@ +compile +config.h +config.h.in +intltool-extract.in +intltool-merge.in +intltool-update.in +mkinstalldirs +nm-strongswan-service.name +stamp-h1 +config.guess.cdbs-orig +config.sub.cdbs-orig diff --git a/src/libcharon/plugins/nm/gnome/Makefile.am b/src/libcharon/plugins/nm/gnome/Makefile.am new file mode 100644 index 000000000..fb29085a6 --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/Makefile.am @@ -0,0 +1,26 @@ +AUTOMAKE_OPTIONS = foreign + +SUBDIRS = properties auth-dialog po + +dbusservicedir = $(sysconfdir)/dbus-1/system.d +dbusservice_DATA = nm-strongswan-service.conf + +nmvpnservicedir = $(sysconfdir)/NetworkManager/VPN +nmvpnservice_DATA = nm-strongswan-service.name + +@INTLTOOL_DESKTOP_RULE@ + +nm-strongswan-service.name: $(srcdir)/nm-strongswan-service.name.in + sed -e 's|[@]LIBEXECDIR[@]|$(libexecdir)|' \ + -e 's|[@]CHARON[@]|$(charon)|' $< >$@ + +EXTRA_DIST = nm-strongswan-service.name.in \ + $(dbusservice_DATA) \ + intltool-extract.in \ + intltool-merge.in \ + intltool-update.in + +CLEANFILES = $(nmvpnservice_DATA) *~ +DISTCLEANFILES = intltool-extract intltool-merge intltool-update + +ACLOCAL_AMFLAGS = -I m4 diff --git a/src/libcharon/plugins/nm/gnome/NEWS b/src/libcharon/plugins/nm/gnome/NEWS new file mode 100644 index 000000000..762e2f512 --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/NEWS @@ -0,0 +1,24 @@ +NetworkManager-strongswan-1.1.2 +------------------------------- + +- Additionally look for libnm-glib[-vpn] pkgconfig packages during configure +- Tooltips are translatable +- Update german translations + +NetworkManager-strongswan-1.1.1 +------------------------------- + +- Implemented save_secrets(), fixes crash when saving connections + +NetworkManager-strongswan-1.1.0 +------------------------------- + +- updated to NetworkManager 7.1 API + +- requires >= strongswan-4.1.13 + + +NetworkManager-strongswan-1.0.0 +------------------------------- + +- First release diff --git a/src/libcharon/plugins/nm/gnome/auth-dialog/.gitignore b/src/libcharon/plugins/nm/gnome/auth-dialog/.gitignore new file mode 100644 index 000000000..bceb305e1 --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/auth-dialog/.gitignore @@ -0,0 +1 @@ +nm-strongswan-auth-dialog diff --git a/src/libcharon/plugins/nm/gnome/auth-dialog/Makefile.am b/src/libcharon/plugins/nm/gnome/auth-dialog/Makefile.am new file mode 100644 index 000000000..672287123 --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/auth-dialog/Makefile.am @@ -0,0 +1,26 @@ +libexec_PROGRAMS = nm-strongswan-auth-dialog + +nm_strongswan_auth_dialog_CPPFLAGS = \ + $(GTHREAD_CFLAGS) \ + $(GTK_CFLAGS) \ + $(LIBGNOMEUI_CFLAGS) \ + $(GNOMEKEYRING_CFLAGS) \ + $(NETWORK_MANAGER_CFLAGS) \ + $(NM_UTILS_CFLAGS) \ + -DICONDIR=\""$(datadir)/pixmaps"\" \ + -DGLADEDIR=\""$(gladedir)"\" \ + -DBINDIR=\""$(bindir)"\" \ + -DG_DISABLE_DEPRECATED \ + -DGDK_DISABLE_DEPRECATED \ + -DGNOME_DISABLE_DEPRECATED \ + -DGNOMELOCALEDIR=\"$(datadir)/locale\" \ + -DVERSION=\"$(VERSION)\" + +nm_strongswan_auth_dialog_SOURCES = \ + main.c + +nm_strongswan_auth_dialog_LDADD = \ + $(GTK_LIBS) \ + $(LIBGNOMEUI_LIBS) \ + $(GNOMEKEYRING_LIBS) + diff --git a/src/libcharon/plugins/nm/gnome/auth-dialog/main.c b/src/libcharon/plugins/nm/gnome/auth-dialog/main.c new file mode 100644 index 000000000..f2716f2d0 --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/auth-dialog/main.c @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * Copyright (C) 2004 Dan Williams + * Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <glib/gi18n.h> +#include <gtk/gtk.h> +#include <gnome-keyring.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" + +/** + * lookup a password in the keyring + */ +static char *lookup_password(char *name, char *service) +{ + GList *list; + GList *iter; + char *pass = NULL; + + if (gnome_keyring_find_network_password_sync(g_get_user_name(), NULL, name, + NULL, service, NULL, 0, &list) != GNOME_KEYRING_RESULT_OK) + { + return NULL; + } + + for (iter = list; iter; iter = iter->next) + { + GnomeKeyringNetworkPasswordData *data = iter->data; + + if (strcmp(data->object, "password") == 0 && data->password) + { + pass = g_strdup(data->password); + break; + } + } + gnome_keyring_network_password_list_free(list); + return pass; +} + +/** + * get the connection type + */ +static char* get_connection_type(char *uuid) +{ + GConfClient *client = NULL; + GSList *list; + GSList *iter; + char *key, *str, *path, *found = NULL, *method = NULL; + + client = gconf_client_get_default(); + + list = gconf_client_all_dirs(client, "/system/networking/connections", NULL); + g_return_val_if_fail(list, NULL); + + for (iter = list; iter; iter = iter->next) + { + path = (char *) iter->data; + + key = g_strdup_printf("%s/%s/%s", path, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_UUID); + str = gconf_client_get_string(client, key, NULL); + g_free (key); + + if (str && !strcmp(str, uuid)) + { + found = g_strdup(path); + } + g_free (str); + if (found) + { + break; + } + } + g_slist_foreach(list, (GFunc)g_free, NULL); + g_slist_free(list); + + if (found) + { + key = g_strdup_printf ("%s/%s/%s", found, + NM_SETTING_VPN_SETTING_NAME, "method"); + method = gconf_client_get_string(client, key, NULL); + g_free(found); + g_free(key); + } + g_object_unref(client); + return method; +} + +int main (int argc, char *argv[]) +{ + gboolean retry = FALSE; + gchar *name = NULL, *uuid = NULL, *service = NULL, *keyring = NULL, *pass; + GOptionContext *context; + GnomeProgram *program = NULL; + char buf, *agent, *type; + guint32 itemid; + GtkWidget *dialog; + GOptionEntry entries[] = { + { "reprompt", 'r', 0, G_OPTION_ARG_NONE, &retry, "Reprompt for passwords", NULL}, + { "uuid", 'u', 0, G_OPTION_ARG_STRING, &uuid, "UUID of VPN connection", NULL}, + { "name", 'n', 0, G_OPTION_ARG_STRING, &name, "Name of VPN connection", NULL}, + { "service", 's', 0, G_OPTION_ARG_STRING, &service, "VPN service type", NULL}, + { NULL } + }; + + bindtextdomain(GETTEXT_PACKAGE, NULL); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + textdomain(GETTEXT_PACKAGE); + + context = g_option_context_new ("- strongswan auth dialog"); + g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); + + program = gnome_program_init ("nm-strongswan-auth-dialog", VERSION, + LIBGNOMEUI_MODULE, + argc, argv, + GNOME_PARAM_GOPTION_CONTEXT, context, + GNOME_PARAM_NONE); + + if (uuid == NULL || name == NULL || service == NULL) + { + fprintf (stderr, "Have to supply UUID, name, and service\n"); + g_object_unref (program); + return 1; + } + + if (strcmp(service, NM_DBUS_SERVICE_STRONGSWAN) != 0) + { + fprintf(stderr, "This dialog only works with the '%s' service\n", + NM_DBUS_SERVICE_STRONGSWAN); + g_object_unref (program); + return 1; + } + + type = get_connection_type(uuid); + if (!type) + { + fprintf(stderr, "Connection lookup failed\n"); + g_object_unref (program); + return 1; + } + if (!strcmp(type, "eap") || !strcmp(type, "key")) + { + pass = lookup_password(name, service); + if (!pass || retry) + { + if (!strcmp(type, "eap")) + { + dialog = gnome_password_dialog_new(_("VPN password required"), + _("EAP password required to establish VPN connection:"), + NULL, NULL, TRUE); + } + else + { + dialog = gnome_password_dialog_new(_("VPN password required"), + _("Private key decryption 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; + } + } + printf("password\n%s\n", pass); + } + else + { + agent = getenv("SSH_AUTH_SOCK"); + if (agent) + { + printf("agent\n%s\n", agent); + } + else + { + 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; + } + } + printf("\n\n"); + /* flush output, wait for input */ + fflush(stdout); + if (fread(&buf, 1, sizeof(buf), stdin)); + g_object_unref(program); + return 0; +} + diff --git a/src/libcharon/plugins/nm/gnome/autogen.sh b/src/libcharon/plugins/nm/gnome/autogen.sh new file mode 100755 index 000000000..25847e7c3 --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/autogen.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. +REQUIRED_AUTOMAKE_VERSION=1.7 +PKG_NAME=NetworkManager-strongswan + +which gnome-autogen.sh || { + echo "You need to install gnome-common from the GNOME CVS" + exit 1 +} +USE_GNOME2_MACROS=1 . gnome-autogen.sh + + diff --git a/src/libcharon/plugins/nm/gnome/configure.ac b/src/libcharon/plugins/nm/gnome/configure.ac new file mode 100644 index 000000000..b15e6e6cf --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/configure.ac @@ -0,0 +1,101 @@ +AC_PREREQ(2.52) + +AC_INIT(NetworkManager-strongswan, 1.1.2, martin@strongswan.org, NetworkManager-strongswan) +AM_INIT_AUTOMAKE([subdir-objects]) +AM_MAINTAINER_MODE + +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_HEADERS([config.h]) + +dnl +dnl Require programs +dnl +AC_PROG_CC +AM_PROG_CC_C_O +AC_PROG_INSTALL +AC_PROG_LIBTOOL + +dnl +dnl Required headers +dnl +AC_HEADER_STDC +AC_CHECK_HEADERS(fcntl.h paths.h sys/ioctl.h sys/time.h syslog.h unistd.h) + +dnl +dnl Checks for typedefs, structures, and compiler characteristics. +dnl +AC_TYPE_MODE_T +AC_TYPE_PID_T +AC_HEADER_TIME + +dnl +dnl Checks for library functions. +dnl +AC_PROG_GCC_TRADITIONAL +AC_FUNC_MEMCMP +AC_CHECK_FUNCS(select socket uname) + +GETTEXT_PACKAGE=NetworkManager-strongswan +AC_SUBST(GETTEXT_PACKAGE) +AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Gettext package]) + +IT_PROG_INTLTOOL([0.35]) +AM_GLIB_GNU_GETTEXT + +PKG_CHECK_MODULES(GTHREAD, gthread-2.0) +AC_SUBST(GTHREAD_CFLAGS) +AC_SUBST(GTHREAD_LIBS) + +PKG_CHECK_MODULES(DBUS, dbus-glib-1 >= 0.30) +AC_SUBST(DBUS_CFLAGS) +AC_SUBST(DBUS_LIBS) + +if test x"$with_gnome" != xno; then + PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.6) + AC_SUBST(GTK_CFLAGS) + AC_SUBST(GTK_LIBS) + + PKG_CHECK_MODULES(GDK_PIXBUF, gdk-pixbuf-2.0) + AC_SUBST(GDK_PIXBUF_CFLAGS) + AC_SUBST(GDK_PIXBUF_LIBS) + + PKG_CHECK_MODULES(GLADE, libglade-2.0) + AC_SUBST(GLADE_CFLAGS) + AC_SUBST(GLADE_LIBS) + + PKG_CHECK_MODULES(LIBGNOMEUI, libgnomeui-2.0) + AC_SUBST(LIBGNOMEUI_CFLAGS) + AC_SUBST(LIBGNOMEUI_LIBS) + + PKG_CHECK_MODULES(GCONF, gconf-2.0) + AC_SUBST(GCONF_CFLAGS) + AC_SUBST(GCONF_LIBS) + + PKG_CHECK_MODULES(GNOMEKEYRING, gnome-keyring-1) + AC_SUBST(GNOMEKEYRING_CFLAGS) + AC_SUBST(GNOMEKEYRING_LIBS) +fi + +PKG_CHECK_EXISTS([libnm-glib], + [PKG_CHECK_MODULES(NM_UTILS, NetworkManager >= 0.7.0 libnm-util libnm-glib libnm-glib-vpn)], + [PKG_CHECK_MODULES(NM_UTILS, NetworkManager >= 0.7.0 libnm-util libnm_glib libnm_glib_vpn)] +) +AC_SUBST(NM_UTILS_CFLAGS) +AC_SUBST(NM_UTILS_LIBS) + +AC_ARG_WITH( + [charon], + AS_HELP_STRING([--with-charon=file],[path to the strongSwan IKEv2 daemon charon"]), + [AC_SUBST(charon, "$withval")], + [AC_SUBST(charon, "${libexecdir}/ipsec/charon")] +) + +NM_COMPILER_WARNINGS + +AC_CONFIG_FILES([ +Makefile +properties/Makefile +auth-dialog/Makefile +po/Makefile.in +]) +AC_OUTPUT diff --git a/src/libcharon/plugins/nm/gnome/debian/.gitignore b/src/libcharon/plugins/nm/gnome/debian/.gitignore new file mode 100644 index 000000000..69c984b17 --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/debian/.gitignore @@ -0,0 +1,6 @@ +files +network-manager-strongswan.debhelper.log +network-manager-strongswan.substvars +network-manager-strongswan/ +stamp-autotools-files +stamp-makefile-build diff --git a/src/libcharon/plugins/nm/gnome/debian/changelog b/src/libcharon/plugins/nm/gnome/debian/changelog new file mode 100644 index 000000000..27add5160 --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/debian/changelog @@ -0,0 +1,33 @@ +network-manager-strongswan (1.1.2-1) unstable; urgency=low + + * New upstream release, fixes pkgconfig for new libnm-glib packages + (Closes: #569302) + + -- Martin Willi <martin@strongswan.org> Thu, 18 Feb 2010 09:41:39 +0100 + +network-manager-strongswan (1.1.1-2) unstable; urgency=low + + * Added ${shlibs:Depends} dependency + * Reload network-manager after installation, reloading dbus is insufficient. + * Fixed debhelper-but-no-misc-depends, out-of-date-standards-version and + copyright-without-copyright-notice lintian warnings + + -- Martin Willi <martin@strongswan.org> Mon, 12 Oct 2009 10:19:40 +0200 + +network-manager-strongswan (1.1.1-1) unstable; urgency=low + + * New upstream release fixing a crasher when saving connections + * Fix "Wrong path to network-manager initscript in postinst" + Reload dbus instead of network-manager, as other VPN plugins do. + (Closes: #529189) + * Fix "FTBFS: No package 'libnm-util' found" + added dependencies to libnm-util-dev and libnm-glib-vpn-dev + (Closes: #528977) + + -- Martin Willi <martin@strongswan.org> Tue, 19 May 2009 13:16:51 +0200 + +network-manager-strongswan (1.1.0-1) unstable; urgency=low + + * Initial Debian packaging of NetworkManager plugin for strongSwan + + -- Martin Willi <martin@strongswan.org> Wed, 25 Mar 2009 09:07:05 +0100 diff --git a/src/libcharon/plugins/nm/gnome/debian/compat b/src/libcharon/plugins/nm/gnome/debian/compat new file mode 100644 index 000000000..7f8f011eb --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/debian/compat @@ -0,0 +1 @@ +7 diff --git a/src/libcharon/plugins/nm/gnome/debian/control b/src/libcharon/plugins/nm/gnome/debian/control new file mode 100644 index 000000000..71d8bc922 --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/debian/control @@ -0,0 +1,29 @@ +Source: network-manager-strongswan +Section: net +Priority: extra +Maintainer: Martin Willi <martin@strongswan.org> +Build-Depends: cdbs, + debhelper (>= 7), + network-manager-dev (>= 0.7), + libnm-util-dev (>= 0.7), + libnm-glib-dev (>= 0.7), + libnm-glib-vpn-dev (>= 0.7), + libdbus-glib-1-dev, + libglade2-dev, + libgnomeui-dev, + automake1.9, + gnome-common, +Standards-Version: 3.8.3 + +Package: network-manager-strongswan +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, strongswan-nm, network-manager +Description: network management framework (strongSwan plugin) + NetworkManager attempts to keep an active network connection available at + all times. It is intended primarily for laptops where it allows easy + switching between local wireless networks, it's also useful on desktops + with a selection of different interfaces to use. It is not intended for + usage on servers. + . + This package provides a VPN plugin for strongSwan, providing easy access to + IKEv2 IPSec VPN's. diff --git a/src/libcharon/plugins/nm/gnome/debian/copyright b/src/libcharon/plugins/nm/gnome/debian/copyright new file mode 100644 index 000000000..8542aeaae --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/debian/copyright @@ -0,0 +1,10 @@ +Format-Specification: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?op=file&rev=59 +Name: NetworkManager-strongswan +Source: http://download.strongswan.org/NetworkManager + +Copyright: 2008-2009, Martin Willi <martin@strongswan.org> + 2005-2008, Dan Williams + 2005, David Zeuthen +License: GPL-2 + On Debian systems the full text of the GNU General Public License can be found + in the `/usr/share/common-licenses/GPL-2' file. diff --git a/src/libcharon/plugins/nm/gnome/debian/docs b/src/libcharon/plugins/nm/gnome/debian/docs new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/debian/docs diff --git a/src/libcharon/plugins/nm/gnome/debian/network-manager-strongswan.postinst b/src/libcharon/plugins/nm/gnome/debian/network-manager-strongswan.postinst new file mode 100644 index 000000000..f855e713c --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/debian/network-manager-strongswan.postinst @@ -0,0 +1,19 @@ +#!/bin/sh + +set -e + +case "$1" in + configure) + if [ -x "/etc/init.d/network-manager" ]; then + if [ -x /usr/sbin/invoke-rc.d ]; then + invoke-rc.d network-manager force-reload || true + else + /etc/init.d/network-manager force-reload || true + fi + fi + ;; +esac + +#DEBHELPER# + +exit 0 diff --git a/src/libcharon/plugins/nm/gnome/debian/rules b/src/libcharon/plugins/nm/gnome/debian/rules new file mode 100755 index 000000000..0f723246e --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/debian/rules @@ -0,0 +1,15 @@ +#!/usr/bin/make -f + +include /usr/share/cdbs/1/rules/debhelper.mk +include /usr/share/cdbs/1/class/autotools.mk + +DEB_CONFIGURE_EXTRA_FLAGS := --with-charon=/usr/lib/ipsec/charon + +DEB_CONFIGURE_LIBEXECDIR := "\$$(prefix)/lib/NetworkManager" + +DEB_DH_MAKESHLIBS_ARGS_ALL := -X/usr/lib/NetworkManager/ + +DEB_DH_INSTALL_SOURCEDIR := debian/tmp + + + diff --git a/src/libcharon/plugins/nm/gnome/m4/.gitignore b/src/libcharon/plugins/nm/gnome/m4/.gitignore new file mode 100644 index 000000000..3d067d03a --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/m4/.gitignore @@ -0,0 +1,7 @@ +intltool.m4 +libtool.m4 +ltoptions.m4 +ltsugar.m4 +ltversion.m4 +lt~obsolete.m4 + diff --git a/src/libcharon/plugins/nm/gnome/m4/compiler_warnings.m4 b/src/libcharon/plugins/nm/gnome/m4/compiler_warnings.m4 new file mode 100644 index 000000000..6cea2f74e --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/m4/compiler_warnings.m4 @@ -0,0 +1,31 @@ +AC_DEFUN([NM_COMPILER_WARNINGS], +[AC_ARG_ENABLE(more-warnings, + AS_HELP_STRING([--enable-more-warnings], [Maximum compiler warnings]), + set_more_warnings="$enableval",set_more_warnings=yes) +AC_MSG_CHECKING(for more warnings, including -Werror) +if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then + AC_MSG_RESULT(yes) + CFLAGS="-Wall -Werror -std=gnu89 $CFLAGS" + + for option in -Wshadow -Wmissing-declarations -Wmissing-prototypes \ + -Wdeclaration-after-statement -Wstrict-prototypes \ + -Wfloat-equal -Wno-unused-parameter -Wno-sign-compare \ + -fno-strict-aliasing; do + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $option" + AC_MSG_CHECKING([whether gcc understands $option]) + AC_TRY_COMPILE([], [], + has_option=yes, + has_option=no,) + if test $has_option = no; then + CFLAGS="$SAVE_CFLAGS" + fi + AC_MSG_RESULT($has_option) + unset has_option + unset SAVE_CFLAGS + done + unset option +else + AC_MSG_RESULT(no) +fi +]) diff --git a/src/libcharon/plugins/nm/gnome/nm-strongswan-service.conf b/src/libcharon/plugins/nm/gnome/nm-strongswan-service.conf new file mode 100644 index 000000000..dccc19af9 --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/nm-strongswan-service.conf @@ -0,0 +1,16 @@ +<!DOCTYPE busconfig PUBLIC + "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> +<busconfig> + <policy user="root"> + <allow own="org.freedesktop.NetworkManager.strongswan"/> + <allow send_destination="org.freedesktop.NetworkManager.strongswan"/> + <allow send_interface="org.freedesktop.NetworkManager.strongswan"/> + </policy> + <policy context="default"> + <deny own="org.freedesktop.NetworkManager.strongswan"/> + <deny send_destination="org.freedesktop.NetworkManager.strongswan"/> + <deny send_interface="org.freedesktop.NetworkManager.strongswan"/> + </policy> +</busconfig> + diff --git a/src/libcharon/plugins/nm/gnome/nm-strongswan-service.name.in b/src/libcharon/plugins/nm/gnome/nm-strongswan-service.name.in new file mode 100644 index 000000000..4120e55ae --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/nm-strongswan-service.name.in @@ -0,0 +1,8 @@ +[VPN Connection] +name=strongswan +service=org.freedesktop.NetworkManager.strongswan +program=@CHARON@ + +[GNOME] +auth-dialog=@LIBEXECDIR@/nm-strongswan-auth-dialog +properties=libnm-strongswan-properties diff --git a/src/libcharon/plugins/nm/gnome/po/.gitignore b/src/libcharon/plugins/nm/gnome/po/.gitignore new file mode 100644 index 000000000..b02b6e4ac --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/po/.gitignore @@ -0,0 +1,4 @@ +Makefile.in.in +POTFILES +de.gmo +stamp-it diff --git a/src/libcharon/plugins/nm/gnome/po/ChangeLog b/src/libcharon/plugins/nm/gnome/po/ChangeLog new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/po/ChangeLog diff --git a/src/libcharon/plugins/nm/gnome/po/LINGUAS b/src/libcharon/plugins/nm/gnome/po/LINGUAS new file mode 100644 index 000000000..adc376a70 --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/po/LINGUAS @@ -0,0 +1,2 @@ +# please keep this list sorted alphabetically +de diff --git a/src/libcharon/plugins/nm/gnome/po/POTFILES.in b/src/libcharon/plugins/nm/gnome/po/POTFILES.in new file mode 100644 index 000000000..3732874e9 --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/po/POTFILES.in @@ -0,0 +1,5 @@ +# List of source files containing translatable strings. +# Please keep this file sorted alphabetically. +properties/nm-strongswan.c +properties/nm-strongswan-dialog.glade +auth-dialog/main.c diff --git a/src/libcharon/plugins/nm/gnome/po/de.po b/src/libcharon/plugins/nm/gnome/po/de.po new file mode 100644 index 000000000..52fb7ff5e --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/po/de.po @@ -0,0 +1,163 @@ +# Translations for NetworkManager-strongswan. +# Copyright (C) 2010 Martin Willi <martin@strongswan.org> +# This file is distributed under the same license as the +# NetworkManager-strongswan package. +msgid "" +msgstr "" +"Project-Id-Version: NetworkManager-strongswan\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-02-18 09:20+0100\n" +"PO-Revision-Date: 2010-02-18 09:20+0100\n" +"Last-Translator: Martin Willi <martin@strongswan.org>\n" +"Language-Team: de <martin@strongswan.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../properties/nm-strongswan.c:38 +msgid "IPsec/IKEv2 (strongswan)" +msgstr "IPsec/IKEv2 (strongswan)" + +#: ../properties/nm-strongswan.c:39 +msgid "IPsec with the IKEv2 key exchange protocol." +msgstr "IPsec mit dem IKEv2 Protokoll." + +#: ../properties/nm-strongswan.c:200 +msgid "Certificate/private key" +msgstr "Zertifikat/Privater Schlüssel" + +#: ../properties/nm-strongswan.c:201 +msgid "Certificate/ssh-agent" +msgstr "Zertifikat/ssh-agent" + +#: ../properties/nm-strongswan.c:202 +msgid "EAP" +msgstr "EAP" + +#: ../properties/nm-strongswan-dialog.glade.h:1 +msgid "<b>Client</b>" +msgstr "<b>Client</b>" + +#: ../properties/nm-strongswan-dialog.glade.h:2 +msgid "<b>Gateway</b>" +msgstr "<b>Gateway</b>" + +#: ../properties/nm-strongswan-dialog.glade.h:3 +msgid "<b>Options</b>" +msgstr "<b>Optionen</b>" + +#: ../properties/nm-strongswan-dialog.glade.h:4 +msgid "An IP address or hostname the Gateway can be contacted." +msgstr "Ein IP-Adresse oder einen Rechnernamen des Gateways." + +#: ../properties/nm-strongswan-dialog.glade.h:5 +msgid "Au_thentication:" +msgstr "Au_thentisierung:" + +#: ../properties/nm-strongswan-dialog.glade.h:6 +msgid "Authentication Method to use for authentication against the Gateway. " +msgstr "Methode zur Authentisierung gegenüber dem Gateway." + +#: ../properties/nm-strongswan-dialog.glade.h:7 +msgid "C_ertificate:" +msgstr "Z_ertifikat:" + +#: ../properties/nm-strongswan-dialog.glade.h:8 +msgid "Ce_rtificate:" +msgstr "Ze_rtifikat:" + +#: ../properties/nm-strongswan-dialog.glade.h:9 +msgid "Client certificate to use for client authentication." +msgstr "Zertifikat des Clients für dessen Authentisierung." + +#: ../properties/nm-strongswan-dialog.glade.h:10 +msgid "En_force UDP encapsulation" +msgstr "Erzwingen einer zusätzlichen Einbettung der Datenpakete in _UDP" + +#: ../properties/nm-strongswan-dialog.glade.h:11 +msgid "" +"Gateway or CA certificate to use for gateway authentication. If none is " +"specified, pre-installed CA certificates are used." +msgstr "" +"Gateway- oder CA-Zertifikat für die Authentisierung des Gateways. Ohne " +"Angabe eines Zertifikates werden die CA-Zertifikate des Systems verwendet." + +#: ../properties/nm-strongswan-dialog.glade.h:12 +msgid "" +"IPComp compresses raw IP packets before they get encrypted. This saves some " +"bandwith, but uses more processing power." +msgstr "" +"IPComp komprimiert IP-Pakete, bevor sie verschlsselt werden. Diese Option " +"kann Bandbreite sparen, bentigt jedoch zustzliche Rechenleistung." + +#: ../properties/nm-strongswan-dialog.glade.h:13 +msgid "Private _key:" +msgstr "Privater _Schlüssel:" + +#: ../properties/nm-strongswan-dialog.glade.h:14 +msgid "" +"Private key to use for client authentication. This key has to match the " +"certificates public key and may be encrypted." +msgstr "" +"Privater Schlüssel für die Authentisierung des Clients. Dieser Schlüssel " +"muss zum konfigurierten Zertifikat passen und kann verschlüsselt sein." + +#: ../properties/nm-strongswan-dialog.glade.h:15 +msgid "Request an _inner IP address" +msgstr "_Innere IP-Adresse beziehen" + +#: ../properties/nm-strongswan-dialog.glade.h:16 +msgid "" +"Some firewalls block ESP traffic. Enforcing UDP capsulation even if no NAT " +"situation is detected might help in such cases." +msgstr "" +"Manche Firewalls blockieren Datenverkehr mit dem ESP-Protokoll. Das " +"erzwingen einer zustzlichen Einbettung in UDP, auch wenn kein NAT-Router " +"detektiert wurde, kann in solchen Situationen hilfreich sein." + +#: ../properties/nm-strongswan-dialog.glade.h:17 +msgid "" +"The Gateway may provide addresses from a pool to use for communication in " +"the Gateways network. Check to request such an address." +msgstr "" +"Der Gateway kann IP-Adressen bereitstellen, welche der Client für die " +"Kommunikation im dahinterliegenden Netz verwenden kann. Aktivieren, um eine " +"solche Adresse zu beziehen." + +#: ../properties/nm-strongswan-dialog.glade.h:18 +msgid "The username (identity) to use for authentication against the gateway." +msgstr "Benutzername/Identitt für die Authentisierung gegenüber dem Gateway." + +#: ../properties/nm-strongswan-dialog.glade.h:19 +msgid "Use IP c_ompression" +msgstr "IP-Pakete k_omprimieren" + +#: ../properties/nm-strongswan-dialog.glade.h:20 +msgid "_Address:" +msgstr "_Adresse:" + +#: ../properties/nm-strongswan-dialog.glade.h:21 +msgid "_Username:" +msgstr "_Benutzername:" + +#: ../auth-dialog/main.c:172 ../auth-dialog/main.c:178 +msgid "VPN password required" +msgstr "VPN Passwort notwendig" + +#: ../auth-dialog/main.c:173 +msgid "EAP password required to establish VPN connection:" +msgstr "Für die Erstellung des VPN-Tunnels ist ein EAP-Passwort erforderlich:" + +#: ../auth-dialog/main.c:179 +msgid "Private key decryption password required to establish VPN connection:" +msgstr "" +"Der Private Schlüssel für die Erstellung des VPN-Tunnels ist durch ein " +"Passwort geschützt:" + +#: ../auth-dialog/main.c:225 +msgid "" +"Configuration uses ssh-agent for authentication, but ssh-agent is not " +"running!" +msgstr "" +"Die Konfiguration verwendet ssh-agent fr die Authentisierung, aber ssh-agent " +"ist nicht gestartet!" diff --git a/src/libcharon/plugins/nm/gnome/properties/Makefile.am b/src/libcharon/plugins/nm/gnome/properties/Makefile.am new file mode 100644 index 000000000..3db7c226e --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/properties/Makefile.am @@ -0,0 +1,37 @@ +plugindir = $(libdir)/NetworkManager +plugin_LTLIBRARIES = libnm-strongswan-properties.la + +libnm_strongswan_properties_la_SOURCES = \ + nm-strongswan.c \ + nm-strongswan.h + +gladedir = $(datadir)/gnome-vpn-properties/strongswan +glade_DATA = nm-strongswan-dialog.glade + +libnm_strongswan_properties_la_CFLAGS = \ + $(GLADE_CFLAGS) \ + $(GTK_CFLAGS) \ + $(GCONF_CFLAGS) \ + $(LIBGNOMEUI_CFLAGS) \ + $(NM_UTILS_CFLAGS) \ + -DICONDIR=\""$(datadir)/pixmaps"\" \ + -DGLADEDIR=\""$(gladedir)"\" \ + -DG_DISABLE_DEPRECATED \ + -DGDK_DISABLE_DEPRECATED \ + -DGNOME_DISABLE_DEPRECATED \ + -DGNOMELOCALEDIR=\"$(datadir)/locale\" \ + -DVERSION=\"$(VERSION)\" + +libnm_strongswan_properties_la_LIBADD = \ + $(GLADE_LIBS) \ + $(GTK_LIBS) \ + $(GCONF_LIBS) \ + $(LIBGNOMEUI_LIBS) \ + $(NM_UTILS_LIBS) + +libnm_strongswan_properties_la_LDFLAGS = \ + -avoid-version + +CLEANFILES = *.bak *.gladep *~ + +EXTRA_DIST = $(glade_DATA) diff --git a/src/libcharon/plugins/nm/gnome/properties/nm-strongswan-dialog.glade b/src/libcharon/plugins/nm/gnome/properties/nm-strongswan-dialog.glade new file mode 100644 index 000000000..02c68888d --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/properties/nm-strongswan-dialog.glade @@ -0,0 +1,346 @@ +<?xml version="1.0"?> +<glade-interface> + <!-- interface-requires gtk+ 2.12 --> + <!-- interface-naming-policy project-wide --> + <widget class="GtkWindow" id="strongswan-widget"> + <property name="title" translatable="yes">window1</property> + <child> + <widget class="GtkVBox" id="strongswan-vbox"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="orientation">vertical</property> + <property name="spacing">16</property> + <child> + <widget class="GtkVBox" id="gateway-vbox"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="gateway-label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>Gateway</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkAlignment" id="gateway-alignement"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <widget class="GtkTable" id="gateway-table"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="column_spacing">6</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkLabel" id="address-label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">_Address:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">address-entry</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="address-entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="has_tooltip">True</property> + <property name="tooltip" translatable="yes">An IP address or hostname the Gateway can be contacted.</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="y_options"></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="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkFileChooserButton" id="certificate-button"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Gateway or CA certificate to use for gateway authentication. If none is specified, pre-installed CA certificates are used.</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> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="client-vbox"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="client-label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>Client</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkAlignment" id="client-aligement"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <widget class="GtkTable" id="client-table"> + <property name="visible">True</property> + <property name="n_rows">4</property> + <property name="n_columns">2</property> + <property name="column_spacing">6</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkFileChooserButton" id="userkey-button"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Private key to use for client authentication. This key has to match the certificates public key and may be encrypted.</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="userkey-label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Private _key:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">userkey-button</property> + </widget> + <packing> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkComboBox" id="method-combo"> + <property name="visible">True</property> + <property name="has_tooltip">True</property> + <property name="tooltip" translatable="yes">Authentication Method to use for authentication against the Gateway. </property> + <property name="items"></property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="method-label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Au_thentication:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">method-combo</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</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> + </packing> + </child> + <child> + <widget class="GtkEntry" id="user-entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="has_tooltip">True</property> + <property name="tooltip" translatable="yes">The username (identity) to use for authentication against the gateway.</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> + <property name="y_options"></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> + <widget class="GtkFileChooserButton" id="usercert-button"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">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> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="options-vbox"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="options-label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>Options</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkAlignment" id="options-alignement"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <widget class="GtkVBox" id="options-inner-vbox"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <child> + <widget class="GtkCheckButton" id="virtual-check"> + <property name="label" translatable="yes">Request an _inner IP address</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="has_tooltip">True</property> + <property name="tooltip" translatable="yes">The Gateway may provide addresses from a pool to use for communication in the Gateways network. Check to request such an address.</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="encap-check"> + <property name="label" translatable="yes">En_force UDP encapsulation</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="has_tooltip">True</property> + <property name="tooltip" translatable="yes">Some firewalls block ESP traffic. Enforcing UDP capsulation even if no NAT situation is detected might help in such cases.</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="ipcomp-check"> + <property name="label" translatable="yes">Use IP c_ompression</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="has_tooltip">True</property> + <property name="tooltip" translatable="yes">IPComp compresses raw IP packets before they get encrypted. This saves some bandwith, but uses more processing power.</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + </child> + </widget> +</glade-interface> diff --git a/src/libcharon/plugins/nm/gnome/properties/nm-strongswan.c b/src/libcharon/plugins/nm/gnome/properties/nm-strongswan.c new file mode 100644 index 000000000..4b69296b4 --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/properties/nm-strongswan.c @@ -0,0 +1,526 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * Copyright (C) 2005 David Zeuthen + * Copyright (C) 2005-2008 Dan Williams + * + * Based on NetworkManager's vpnc plugin + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <glib.h> +#include <glib/gi18n-lib.h> +#include <gtk/gtk.h> +#include <glade/glade.h> + +#define NM_VPN_API_SUBJECT_TO_CHANGE + +#include <nm-vpn-plugin-ui-interface.h> +#include <nm-setting-vpn.h> +#include <nm-setting-connection.h> +#include <nm-setting-ip4-config.h> + +#include "nm-strongswan.h" + +#define STRONGSWAN_PLUGIN_NAME _("IPsec/IKEv2 (strongswan)") +#define STRONGSWAN_PLUGIN_DESC _("IPsec with the IKEv2 key exchange protocol.") +#define STRONGSWAN_PLUGIN_SERVICE "org.freedesktop.NetworkManager.strongswan" +#define NM_DBUS_SERVICE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan" + +/************** plugin class **************/ + +static void strongswan_plugin_ui_interface_init (NMVpnPluginUiInterface *iface_class); + +G_DEFINE_TYPE_EXTENDED (StrongswanPluginUi, strongswan_plugin_ui, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_VPN_PLUGIN_UI_INTERFACE, + strongswan_plugin_ui_interface_init)) + +/************** UI widget class **************/ + +static void strongswan_plugin_ui_widget_interface_init (NMVpnPluginUiWidgetInterface *iface_class); + +G_DEFINE_TYPE_EXTENDED (StrongswanPluginUiWidget, strongswan_plugin_ui_widget, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_VPN_PLUGIN_UI_WIDGET_INTERFACE, + strongswan_plugin_ui_widget_interface_init)) + +#define STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), STRONGSWAN_TYPE_PLUGIN_UI_WIDGET, StrongswanPluginUiWidgetPrivate)) + +typedef struct { + GladeXML *xml; + GtkWidget *widget; +} StrongswanPluginUiWidgetPrivate; + + +#define STRONGSWAN_PLUGIN_UI_ERROR strongswan_plugin_ui_error_quark () + +static GQuark +strongswan_plugin_ui_error_quark (void) +{ + static GQuark error_quark = 0; + + if (G_UNLIKELY (error_quark == 0)) + error_quark = g_quark_from_static_string ("strongswan-plugin-ui-error-quark"); + + return error_quark; +} + +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +strongswan_plugin_ui_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (STRONGSWAN_PLUGIN_UI_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (STRONGSWAN_PLUGIN_UI_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (STRONGSWAN_PLUGIN_UI_ERROR_MISSING_PROPERTY, "MissingProperty"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("StrongswanPluginUiError", values); + } + return etype; +} + +static gboolean +check_validity (StrongswanPluginUiWidget *self, GError **error) +{ + StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self); + GtkWidget *widget; + char *str; + + widget = glade_xml_get_widget (priv->xml, "address-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, + "address"); + return FALSE; + } + return TRUE; +} + +static void update_layout (GtkWidget *widget, StrongswanPluginUiWidgetPrivate *priv) +{ + switch (gtk_combo_box_get_active (GTK_COMBO_BOX (widget))) + { + default: + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0); + /* FALL */ + case 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_show (glade_xml_get_widget (priv->xml, "userkey-label")); + gtk_widget_show (glade_xml_get_widget (priv->xml, "userkey-button")); + gtk_widget_hide (glade_xml_get_widget (priv->xml, "user-label")); + gtk_widget_hide (glade_xml_get_widget (priv->xml, "user-entry")); + break; + case 1: + 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")); + gtk_widget_hide (glade_xml_get_widget (priv->xml, "userkey-label")); + gtk_widget_hide (glade_xml_get_widget (priv->xml, "userkey-button")); + break; + case 2: + gtk_widget_show (glade_xml_get_widget (priv->xml, "user-label")); + gtk_widget_show (glade_xml_get_widget (priv->xml, "user-entry")); + gtk_widget_hide (glade_xml_get_widget (priv->xml, "usercert-label")); + gtk_widget_hide (glade_xml_get_widget (priv->xml, "usercert-button")); + gtk_widget_hide (glade_xml_get_widget (priv->xml, "userkey-label")); + gtk_widget_hide (glade_xml_get_widget (priv->xml, "userkey-button")); + break; + } + +} + +static void +settings_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 (widget == glade_xml_get_widget (priv->xml, "method-combo")) + { + update_layout(glade_xml_get_widget (priv->xml, "method-combo"), priv); + } + g_signal_emit_by_name (STRONGSWAN_PLUGIN_UI_WIDGET (user_data), "changed"); +} + +static gboolean +init_plugin_ui (StrongswanPluginUiWidget *self, NMConnection *connection, GError **error) +{ + StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self); + NMSettingVPN *settings; + GtkWidget *widget; + const char *value; + + settings = NM_SETTING_VPN(nm_connection_get_setting(connection, NM_TYPE_SETTING_VPN)); + widget = glade_xml_get_widget (priv->xml, "address-entry"); + value = nm_setting_vpn_get_data_item (settings, "address"); + if (value) + gtk_entry_set_text (GTK_ENTRY (widget), value); + g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (settings_changed_cb), self); + + widget = glade_xml_get_widget (priv->xml, "certificate-button"); + value = nm_setting_vpn_get_data_item (settings, "certificate"); + 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, "user-label"); + gtk_widget_set_no_show_all (widget, TRUE); + widget = glade_xml_get_widget (priv->xml, "user-entry"); + gtk_widget_set_no_show_all (widget, TRUE); + value = nm_setting_vpn_get_data_item (settings, "user"); + if (value) + gtk_entry_set_text (GTK_ENTRY (widget), value); + g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (settings_changed_cb), self); + + widget = glade_xml_get_widget (priv->xml, "method-combo"); + gtk_combo_box_append_text (GTK_COMBO_BOX (widget), _("Certificate/private key")); + gtk_combo_box_append_text (GTK_COMBO_BOX (widget), _("Certificate/ssh-agent")); + gtk_combo_box_append_text (GTK_COMBO_BOX (widget), _("EAP")); + value = nm_setting_vpn_get_data_item (settings, "method"); + if (value) { + if (g_strcmp0 (value, "key") == 0) { + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0); + } + if (g_strcmp0 (value, "agent") == 0) { + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1); + } + if (g_strcmp0 (value, "eap") == 0) { + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 2); + } + } + if (gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) == -1) + { + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0); + } + update_layout (widget, priv); + g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (settings_changed_cb), self); + + 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 = nm_setting_vpn_get_data_item (settings, "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, "userkey-label"); + gtk_widget_set_no_show_all (widget, TRUE); + widget = glade_xml_get_widget (priv->xml, "userkey-button"); + gtk_widget_set_no_show_all (widget, TRUE); + value = nm_setting_vpn_get_data_item (settings, "userkey"); + 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"); + value = nm_setting_vpn_get_data_item (settings, "virtual"); + if (value && strcmp(value, "yes") == 0) + { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE); + } + g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (settings_changed_cb), self); + + widget = glade_xml_get_widget (priv->xml, "encap-check"); + value = nm_setting_vpn_get_data_item (settings, "encap"); + if (value && strcmp(value, "yes") == 0) + { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE); + } + g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (settings_changed_cb), self); + + widget = glade_xml_get_widget (priv->xml, "ipcomp-check"); + value = nm_setting_vpn_get_data_item (settings, "ipcomp"); + if (value && strcmp(value, "yes") == 0) + { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE); + } + g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (settings_changed_cb), self); + + return TRUE; +} + +static GObject * +get_widget (NMVpnPluginUiWidgetInterface *iface) +{ + StrongswanPluginUiWidget *self = STRONGSWAN_PLUGIN_UI_WIDGET (iface); + StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self); + + return G_OBJECT (priv->widget); +} + +static gboolean +update_connection (NMVpnPluginUiWidgetInterface *iface, + NMConnection *connection, + GError **error) +{ + StrongswanPluginUiWidget *self = STRONGSWAN_PLUGIN_UI_WIDGET (iface); + StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (self); + NMSettingVPN *settings; + GtkWidget *widget; + gboolean active; + char *str; + + if (!check_validity (self, error)) + return FALSE; + settings = NM_SETTING_VPN (nm_setting_vpn_new ()); + + g_object_set (settings, NM_SETTING_VPN_SERVICE_TYPE, + NM_DBUS_SERVICE_STRONGSWAN, NULL); + + widget = glade_xml_get_widget (priv->xml, "address-entry"); + str = (char *) gtk_entry_get_text (GTK_ENTRY (widget)); + if (str && strlen (str)) { + nm_setting_vpn_add_data_item (settings, "address", str); + } + + widget = glade_xml_get_widget (priv->xml, "certificate-button"); + str = (char *) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget)); + if (str) { + nm_setting_vpn_add_data_item (settings, "certificate", str); + } + + widget = glade_xml_get_widget (priv->xml, "method-combo"); + switch (gtk_combo_box_get_active (GTK_COMBO_BOX (widget))) + { + default: + case 0: + widget = glade_xml_get_widget (priv->xml, "userkey-button"); + str = (char *) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget)); + if (str) { + nm_setting_vpn_add_data_item (settings, "userkey", str); + } + widget = glade_xml_get_widget (priv->xml, "usercert-button"); + str = (char *) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget)); + if (str) { + nm_setting_vpn_add_data_item (settings, "usercert", str); + } + str = "key"; + break; + case 1: + widget = glade_xml_get_widget (priv->xml, "usercert-button"); + str = (char *) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget)); + if (str) { + nm_setting_vpn_add_data_item (settings, "usercert", str); + } + str = "agent"; + break; + case 2: + widget = glade_xml_get_widget (priv->xml, "user-entry"); + str = (char *) gtk_entry_get_text (GTK_ENTRY (widget)); + if (str && strlen (str)) { + nm_setting_vpn_add_data_item (settings, "user", str); + } + str = "eap"; + break; + } + nm_setting_vpn_add_data_item (settings, "method", str); + + widget = glade_xml_get_widget (priv->xml, "virtual-check"); + active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + nm_setting_vpn_add_data_item (settings, "virtual", active ? "yes" : "no"); + + widget = glade_xml_get_widget (priv->xml, "encap-check"); + active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + nm_setting_vpn_add_data_item (settings, "encap", active ? "yes" : "no"); + + widget = glade_xml_get_widget (priv->xml, "ipcomp-check"); + active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + nm_setting_vpn_add_data_item (settings, "ipcomp", active ? "yes" : "no"); + + nm_connection_add_setting (connection, NM_SETTING (settings)); + return TRUE; +} + +static gboolean +save_secrets (NMVpnPluginUiWidgetInterface *iface, + NMConnection *connection, GError **error) +{ + /* no secrets to save */ + return TRUE; +} + +static NMVpnPluginUiWidgetInterface * +nm_vpn_plugin_ui_widget_interface_new (NMConnection *connection, GError **error) +{ + NMVpnPluginUiWidgetInterface *object; + StrongswanPluginUiWidgetPrivate *priv; + char *glade_file; + + if (error) + g_return_val_if_fail (*error == NULL, NULL); + + object = NM_VPN_PLUGIN_UI_WIDGET_INTERFACE (g_object_new (STRONGSWAN_TYPE_PLUGIN_UI_WIDGET, NULL)); + if (!object) { + g_set_error (error, STRONGSWAN_PLUGIN_UI_ERROR, 0, "could not create strongswan object"); + return NULL; + } + + priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (object); + + glade_file = g_strdup_printf ("%s/%s", GLADEDIR, "nm-strongswan-dialog.glade"); + priv->xml = glade_xml_new (glade_file, "strongswan-vbox", GETTEXT_PACKAGE); + if (priv->xml == NULL) { + g_set_error (error, STRONGSWAN_PLUGIN_UI_ERROR, 0, + "could not load required resources at %s", glade_file); + g_free (glade_file); + g_object_unref (object); + return NULL; + } + g_free (glade_file); + + priv->widget = glade_xml_get_widget (priv->xml, "strongswan-vbox"); + if (!priv->widget) { + g_set_error (error, STRONGSWAN_PLUGIN_UI_ERROR, 0, "could not load UI widget"); + g_object_unref (object); + return NULL; + } + g_object_ref_sink (priv->widget); + + if (!init_plugin_ui (STRONGSWAN_PLUGIN_UI_WIDGET (object), connection, error)) { + g_object_unref (object); + return NULL; + } + + return object; +} + +static void +dispose (GObject *object) +{ + StrongswanPluginUiWidget *plugin = STRONGSWAN_PLUGIN_UI_WIDGET (object); + StrongswanPluginUiWidgetPrivate *priv = STRONGSWAN_PLUGIN_UI_WIDGET_GET_PRIVATE (plugin); + + if (priv->widget) + g_object_unref (priv->widget); + + if (priv->xml) + g_object_unref (priv->xml); + + G_OBJECT_CLASS (strongswan_plugin_ui_widget_parent_class)->dispose (object); +} + +static void +strongswan_plugin_ui_widget_class_init (StrongswanPluginUiWidgetClass *req_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (req_class); + + g_type_class_add_private (req_class, sizeof (StrongswanPluginUiWidgetPrivate)); + + object_class->dispose = dispose; +} + +static void +strongswan_plugin_ui_widget_init (StrongswanPluginUiWidget *plugin) +{ +} + +static void +strongswan_plugin_ui_widget_interface_init (NMVpnPluginUiWidgetInterface *iface_class) +{ + /* interface implementation */ + iface_class->get_widget = get_widget; + iface_class->update_connection = update_connection; + iface_class->save_secrets = save_secrets; +} + +static guint32 +get_capabilities (NMVpnPluginUiInterface *iface) +{ + return 0; +} + +static NMVpnPluginUiWidgetInterface * +ui_factory (NMVpnPluginUiInterface *iface, NMConnection *connection, GError **error) +{ + return nm_vpn_plugin_ui_widget_interface_new (connection, error); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + case NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME: + g_value_set_string (value, STRONGSWAN_PLUGIN_NAME); + break; + case NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC: + g_value_set_string (value, STRONGSWAN_PLUGIN_DESC); + break; + case NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE: + g_value_set_string (value, STRONGSWAN_PLUGIN_SERVICE); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +strongswan_plugin_ui_class_init (StrongswanPluginUiClass *req_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (req_class); + + object_class->get_property = get_property; + + g_object_class_override_property (object_class, + NM_VPN_PLUGIN_UI_INTERFACE_PROP_NAME, + NM_VPN_PLUGIN_UI_INTERFACE_NAME); + + g_object_class_override_property (object_class, + NM_VPN_PLUGIN_UI_INTERFACE_PROP_DESC, + NM_VPN_PLUGIN_UI_INTERFACE_DESC); + + g_object_class_override_property (object_class, + NM_VPN_PLUGIN_UI_INTERFACE_PROP_SERVICE, + NM_VPN_PLUGIN_UI_INTERFACE_SERVICE); +} + +static void +strongswan_plugin_ui_init (StrongswanPluginUi *plugin) +{ +} + +static void +strongswan_plugin_ui_interface_init (NMVpnPluginUiInterface *iface_class) +{ + /* interface implementation */ + iface_class->ui_factory = ui_factory; + iface_class->get_capabilities = get_capabilities; + /* TODO: implement delete_connection to purge associated secrets */ +} + + +G_MODULE_EXPORT NMVpnPluginUiInterface * +nm_vpn_plugin_ui_factory (GError **error) +{ + if (error) + g_return_val_if_fail (*error == NULL, NULL); + + return NM_VPN_PLUGIN_UI_INTERFACE (g_object_new (STRONGSWAN_TYPE_PLUGIN_UI, NULL)); +} + diff --git a/src/libcharon/plugins/nm/gnome/properties/nm-strongswan.h b/src/libcharon/plugins/nm/gnome/properties/nm-strongswan.h new file mode 100644 index 000000000..e2b66bb15 --- /dev/null +++ b/src/libcharon/plugins/nm/gnome/properties/nm-strongswan.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * Copyright (C) 2008 Dan Williams + * + * Based on NetworkManager's vpnc plugin + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef _NM_STRONGSWAN_H_ +#define _NM_STRONGSWAN_H_ + +#include <glib-object.h> + +typedef enum +{ + STRONGSWAN_PLUGIN_UI_ERROR_UNKNOWN = 0, + STRONGSWAN_PLUGIN_UI_ERROR_INVALID_PROPERTY, + STRONGSWAN_PLUGIN_UI_ERROR_MISSING_PROPERTY +} StrongswanPluginUiError; + +#define STRONGSWAN_TYPE_PLUGIN_UI_ERROR (strongswan_plugin_ui_error_get_type ()) +GType strongswan_plugin_ui_error_get_type (void); + +#define STRONGSWAN_TYPE_PLUGIN_UI (strongswan_plugin_ui_get_type ()) +#define STRONGSWAN_PLUGIN_UI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), STRONGSWAN_TYPE_PLUGIN_UI, StrongswanPluginUi)) +#define STRONGSWAN_PLUGIN_UI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), STRONGSWAN_TYPE_PLUGIN_UI, StrongswanPluginUiClass)) +#define STRONGSWAN_IS_PLUGIN_UI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STRONGSWAN_TYPE_PLUGIN_UI)) +#define STRONGSWAN_IS_PLUGIN_UI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), STRONGSWAN_TYPE_PLUGIN_UI)) +#define STRONGSWAN_PLUGIN_UI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), STRONGSWAN_TYPE_PLUGIN_UI, StrongswanPluginUiClass)) + +typedef struct _StrongswanPluginUi StrongswanPluginUi; +typedef struct _StrongswanPluginUiClass StrongswanPluginUiClass; + +struct _StrongswanPluginUi { + GObject parent; +}; + +struct _StrongswanPluginUiClass { + GObjectClass parent; +}; + +GType strongswan_plugin_ui_get_type (void); + + +#define STRONGSWAN_TYPE_PLUGIN_UI_WIDGET (strongswan_plugin_ui_widget_get_type ()) +#define STRONGSWAN_PLUGIN_UI_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), STRONGSWAN_TYPE_PLUGIN_UI_WIDGET, StrongswanPluginUiWidget)) +#define STRONGSWAN_PLUGIN_UI_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), STRONGSWAN_TYPE_PLUGIN_UI_WIDGET, StrongswanPluginUiWidgetClass)) +#define STRONGSWAN_IS_PLUGIN_UI_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STRONGSWAN_TYPE_PLUGIN_UI_WIDGET)) +#define STRONGSWAN_IS_PLUGIN_UI_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), STRONGSWAN_TYPE_PLUGIN_UI_WIDGET)) +#define STRONGSWAN_PLUGIN_UI_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), STRONGSWAN_TYPE_PLUGIN_UI_WIDGET, StrongswanPluginUiWidgetClass)) + +typedef struct _StrongswanPluginUiWidget StrongswanPluginUiWidget; +typedef struct _StrongswanPluginUiWidgetClass StrongswanPluginUiWidgetClass; + +struct _StrongswanPluginUiWidget { + GObject parent; +}; + +struct _StrongswanPluginUiWidgetClass { + GObjectClass parent; +}; + +GType strongswan_plugin_ui_widget_get_type (void); + +#endif /* _NM_STRONGSWAN_H_ */ + diff --git a/src/libcharon/plugins/nm/nm_creds.c b/src/libcharon/plugins/nm/nm_creds.c new file mode 100644 index 000000000..193838e6b --- /dev/null +++ b/src/libcharon/plugins/nm/nm_creds.c @@ -0,0 +1,447 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "nm_creds.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <daemon.h> +#include <threading/rwlock.h> +#include <credentials/certificates/x509.h> + +typedef struct private_nm_creds_t private_nm_creds_t; + +/** + * private data of nm_creds + */ +struct private_nm_creds_t { + + /** + * public functions + */ + nm_creds_t public; + + /** + * List of trusted certificates, certificate_t* + */ + linked_list_t *certs; + + /** + * User name + */ + identification_t *user; + + /** + * User password + */ + char *pass; + + /** + * users certificate + */ + certificate_t *usercert; + + /** + * users private key + */ + private_key_t *key; + + /** + * read/write lock + */ + 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); + } + this->lock->read_lock(this->lock); + return enumerator_create_cleaner( + enumerator_create_single(this->usercert, NULL), + (void*)this->lock->unlock, this->lock); +} + +/** + * CA certificate enumerator data + */ +typedef struct { + /** ref to credential credential store */ + private_nm_creds_t *this; + /** type of key we are looking for */ + key_type_t key; + /** CA certificate ID */ + identification_t *id; +} cert_data_t; + +/** + * Destroy CA certificate enumerator data + */ +static void cert_data_destroy(cert_data_t *data) +{ + data->this->lock->unlock(data->this->lock); + free(data); +} + +/** + * Filter function for certificates enumerator + */ +static bool cert_filter(cert_data_t *data, certificate_t **in, + certificate_t **out) +{ + certificate_t *cert = *in; + public_key_t *public; + + public = cert->get_public_key(cert); + if (!public) + { + return FALSE; + } + if (data->key != KEY_ANY && public->get_type(public) != data->key) + { + public->destroy(public); + return FALSE; + } + if (data->id && data->id->get_type(data->id) == ID_KEY_ID && + public->has_fingerprint(public, data->id->get_encoding(data->id))) + { + public->destroy(public); + *out = cert; + return TRUE; + } + public->destroy(public); + if (data->id && !cert->has_subject(cert, data->id)) + { + return FALSE; + } + *out = cert; + return TRUE; +} + +/** + * Create enumerator for trusted certificates + */ +static enumerator_t *create_trusted_cert_enumerator(private_nm_creds_t *this, + key_type_t key, identification_t *id) +{ + cert_data_t *data = malloc_thing(cert_data_t); + + data->this = this; + data->id = id; + data->key = key; + + this->lock->read_lock(this->lock); + return enumerator_create_filter( + this->certs->create_enumerator(this->certs), + (void*)cert_filter, data, (void*)cert_data_destroy); +} + +/** + * Implements credential_set_t.create_cert_enumerator + */ +static enumerator_t* create_cert_enumerator(private_nm_creds_t *this, + certificate_type_t cert, key_type_t key, + 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 (cert == CERT_X509 || cert == CERT_ANY) + { + return create_trusted_cert_enumerator(this, key, id); + } + return NULL; +} + +/** + * 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) + { + if (id->get_type(id) != ID_KEY_ID || + !this->key->has_fingerprint(this->key, id->get_encoding(id))) + { + return NULL; + } + } + this->lock->read_lock(this->lock); + return enumerator_create_cleaner(enumerator_create_single(this->key, NULL), + (void*)this->lock->unlock, this->lock); +} + +/** + * shared key enumerator implementation + */ +typedef struct { + enumerator_t public; + private_nm_creds_t *this; + shared_key_t *key; + bool done; +} shared_enumerator_t; + +/** + * enumerate function for shared enumerator + */ +static bool shared_enumerate(shared_enumerator_t *this, shared_key_t **key, + id_match_t *me, id_match_t *other) +{ + if (this->done) + { + return FALSE; + } + *key = this->key; + *me = ID_MATCH_PERFECT; + *other = ID_MATCH_ANY; + this->done = TRUE; + return TRUE; +} + +/** + * Destroy function for shared enumerator + */ +static void shared_destroy(shared_enumerator_t *this) +{ + this->key->destroy(this->key); + this->this->lock->unlock(this->this->lock); + free(this); +} +/** + * Implements credential_set_t.create_cert_enumerator + */ +static enumerator_t* create_shared_enumerator(private_nm_creds_t *this, + shared_key_type_t type, identification_t *me, + identification_t *other) +{ + shared_enumerator_t *enumerator; + + if (!this->pass || !this->user) + { + return NULL; + } + if (type != SHARED_EAP && type != SHARED_IKE) + { + return NULL; + } + if (me && !me->equals(me, this->user)) + { + return NULL; + } + + enumerator = malloc_thing(shared_enumerator_t); + enumerator->public.enumerate = (void*)shared_enumerate; + enumerator->public.destroy = (void*)shared_destroy; + enumerator->this = this; + enumerator->done = FALSE; + this->lock->read_lock(this->lock); + enumerator->key = shared_key_create(type, + chunk_clone(chunk_create(this->pass, + strlen(this->pass)))); + return &enumerator->public; +} + +/** + * Implementation of nm_creds_t.add_certificate + */ +static void add_certificate(private_nm_creds_t *this, certificate_t *cert) +{ + this->lock->write_lock(this->lock); + this->certs->insert_last(this->certs, cert); + this->lock->unlock(this->lock); +} + +/** + * Load a certificate file + */ +static void load_ca_file(private_nm_creds_t *this, char *file) +{ + certificate_t *cert; + + /* We add the CA constraint, as many CAs miss it */ + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, file, BUILD_END); + if (!cert) + { + DBG1(DBG_CFG, "loading CA certificate '%s' failed", file); + } + else + { + DBG2(DBG_CFG, "loaded CA certificate '%Y'", cert->get_subject(cert)); + x509_t *x509 = (x509_t*)cert; + if (!(x509->get_flags(x509) & X509_SELF_SIGNED)) + { + DBG1(DBG_CFG, "%Y is not self signed", cert->get_subject(cert)); + } + this->certs->insert_last(this->certs, cert); + } +} + +/** + * Implementation of nm_creds_t.load_ca_dir + */ +static void load_ca_dir(private_nm_creds_t *this, char *dir) +{ + enumerator_t *enumerator; + char *rel, *abs; + struct stat st; + + enumerator = enumerator_create_directory(dir); + if (enumerator) + { + while (enumerator->enumerate(enumerator, &rel, &abs, &st)) + { + /* skip '.', '..' and hidden files */ + if (rel[0] != '.') + { + if (S_ISDIR(st.st_mode)) + { + load_ca_dir(this, abs); + } + else if (S_ISREG(st.st_mode)) + { + load_ca_file(this, abs); + } + } + } + enumerator->destroy(enumerator); + } +} + +/** + * Implementation of nm_creds_t.set_password + */ +static void set_username_password(private_nm_creds_t *this, identification_t *id, + char *password) +{ + this->lock->write_lock(this->lock); + DESTROY_IF(this->user); + this->user = id->clone(id); + free(this->pass); + this->pass = password ? strdup(password) : NULL; + this->lock->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) +{ + this->lock->write_lock(this->lock); + DESTROY_IF(this->key); + DESTROY_IF(this->usercert); + this->key = key; + this->usercert = cert; + this->lock->unlock(this->lock); +} + +/** + * Implementation of nm_creds_t.clear + */ +static void clear(private_nm_creds_t *this) +{ + certificate_t *cert; + + while (this->certs->remove_last(this->certs, (void**)&cert) == SUCCESS) + { + cert->destroy(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->user = NULL; +} + +/** + * Implementation of nm_creds_t.destroy + */ +static void destroy(private_nm_creds_t *this) +{ + clear(this); + this->certs->destroy(this->certs); + this->lock->destroy(this->lock); + free(this); +} + +/* + * see header file + */ +nm_creds_t *nm_creds_create() +{ + private_nm_creds_t *this = malloc_thing(private_nm_creds_t); + + this->public.set.create_private_enumerator = (void*)create_private_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_cdp_enumerator = (void*)return_null; + this->public.set.cache_cert = (void*)nop; + this->public.add_certificate = (void(*)(nm_creds_t*, certificate_t *cert))add_certificate; + this->public.load_ca_dir = (void(*)(nm_creds_t*, char *dir))load_ca_dir; + 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->lock = rwlock_create(RWLOCK_TYPE_DEFAULT); + + this->certs = linked_list_create(); + this->user = NULL; + this->pass = NULL; + this->usercert = NULL; + this->key = NULL; + + return &this->public; +} + diff --git a/src/libcharon/plugins/nm/nm_creds.h b/src/libcharon/plugins/nm/nm_creds.h new file mode 100644 index 000000000..b55cff31e --- /dev/null +++ b/src/libcharon/plugins/nm/nm_creds.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup nm_creds nm_creds + * @{ @ingroup nm + */ + +#ifndef NM_CREDS_H_ +#define NM_CREDS_H_ + +#include <credentials/keys/private_key.h> +#include <credentials/credential_set.h> + +typedef struct nm_creds_t nm_creds_t; + +/** + * NetworkManager credentials helper. + */ +struct nm_creds_t { + + /** + * Implements credential_set_t + */ + credential_set_t set; + + /** + * Add a trusted gateway certificate to serve by this set. + * + * @param cert certificate to serve + */ + void (*add_certificate)(nm_creds_t *this, certificate_t *cert); + + /** + * Load CA certificates recursively from a directory. + * + * @param dir directory to PEM encoded CA certificates + */ + void (*load_ca_dir)(nm_creds_t *this, char *dir); + + /** + * Set the username/password for authentication. + * + * @param id ID of the user + * @param password password to use for authentication + */ + 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. + */ + void (*destroy)(nm_creds_t *this); +}; + +/** + * Create a nm_creds instance. + */ +nm_creds_t *nm_creds_create(); + +#endif /** NM_CREDS_H_ @}*/ diff --git a/src/libcharon/plugins/nm/nm_handler.c b/src/libcharon/plugins/nm/nm_handler.c new file mode 100644 index 000000000..eacb54dda --- /dev/null +++ b/src/libcharon/plugins/nm/nm_handler.c @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "nm_handler.h" + +#include <daemon.h> + +typedef struct private_nm_handler_t private_nm_handler_t; + +/** + * Private data of an nm_handler_t object. + */ +struct private_nm_handler_t { + + /** + * Public nm_handler_t interface. + */ + nm_handler_t public; + + /** + * list of received DNS server attributes, pointer to 4 byte data + */ + linked_list_t *dns; + + /** + * list of received NBNS server attributes, pointer to 4 byte data + */ + linked_list_t *nbns; +}; + +/** + * Implementation of attribute_handler_t.handle + */ +static bool handle(private_nm_handler_t *this, identification_t *server, + configuration_attribute_type_t type, chunk_t data) +{ + linked_list_t *list; + + switch (type) + { + case INTERNAL_IP4_DNS: + list = this->dns; + break; + case INTERNAL_IP4_NBNS: + list = this->nbns; + break; + default: + return FALSE; + } + if (data.len != 4) + { + return FALSE; + } + list->insert_last(list, chunk_clone(data).ptr); + return TRUE; +} + +/** + * Implementation of create_attribute_enumerator().enumerate() for WINS + */ +static bool enumerate_nbns(enumerator_t *this, + configuration_attribute_type_t *type, chunk_t *data) +{ + *type = INTERNAL_IP4_NBNS; + *data = chunk_empty; + /* done */ + this->enumerate = (void*)return_false; + return TRUE; +} + +/** + * Implementation of create_attribute_enumerator().enumerate() for DNS + */ +static bool enumerate_dns(enumerator_t *this, + configuration_attribute_type_t *type, chunk_t *data) +{ + *type = INTERNAL_IP4_DNS; + *data = chunk_empty; + /* enumerate WINS server as next attribute ... */ + this->enumerate = (void*)enumerate_nbns; + return TRUE; +} + +/** + * Implementation of attribute_handler_t.create_attribute_enumerator + */ +static enumerator_t* create_attribute_enumerator(private_nm_handler_t *this, + identification_t *server, host_t *vip) +{ + if (vip && vip->get_family(vip) == AF_INET) + { /* no IPv6 attributes yet */ + enumerator_t *enumerator = malloc_thing(enumerator_t); + /* enumerate DNS attribute first ... */ + enumerator->enumerate = (void*)enumerate_dns; + enumerator->destroy = (void*)free; + + return enumerator; + } + return enumerator_create_empty(); +} + +/** + * convert plain byte ptrs to handy chunk during enumeration + */ +static bool filter_chunks(void* null, char **in, chunk_t *out) +{ + *out = chunk_create(*in, 4); + return TRUE; +} + +/** + * Implementation of nm_handler_t.create_enumerator + */ +static enumerator_t* create_enumerator(private_nm_handler_t *this, + configuration_attribute_type_t type) +{ + linked_list_t *list; + + switch (type) + { + case INTERNAL_IP4_DNS: + list = this->dns; + break; + case INTERNAL_IP4_NBNS: + list = this->nbns; + break; + default: + return enumerator_create_empty(); + } + return enumerator_create_filter(list->create_enumerator(list), + (void*)filter_chunks, NULL, NULL); +} + +/** + * Implementation of nm_handler_t.reset + */ +static void reset(private_nm_handler_t *this) +{ + void *data; + + while (this->dns->remove_last(this->dns, (void**)&data) == SUCCESS) + { + free(data); + } + while (this->nbns->remove_last(this->nbns, (void**)&data) == SUCCESS) + { + free(data); + } +} + +/** + * Implementation of nm_handler_t.destroy. + */ +static void destroy(private_nm_handler_t *this) +{ + reset(this); + this->dns->destroy(this->dns); + this->nbns->destroy(this->nbns); + free(this); +} + +/** + * See header + */ +nm_handler_t *nm_handler_create() +{ + private_nm_handler_t *this = malloc_thing(private_nm_handler_t); + + this->public.handler.handle = (bool(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))handle; + this->public.handler.release = (void(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))nop; + this->public.handler.create_attribute_enumerator = (enumerator_t*(*)(attribute_handler_t*, identification_t *server, host_t *vip))create_attribute_enumerator; + this->public.create_enumerator = (enumerator_t*(*)(nm_handler_t*, configuration_attribute_type_t type))create_enumerator; + this->public.reset = (void(*)(nm_handler_t*))reset; + this->public.destroy = (void(*)(nm_handler_t*))destroy; + + this->dns = linked_list_create(); + this->nbns = linked_list_create(); + + return &this->public; +} + diff --git a/src/libcharon/plugins/nm/nm_handler.h b/src/libcharon/plugins/nm/nm_handler.h new file mode 100644 index 000000000..bb35ce767 --- /dev/null +++ b/src/libcharon/plugins/nm/nm_handler.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup nm_handler nm_handler + * @{ @ingroup nm + */ + +#ifndef NM_HANDLER_H_ +#define NM_HANDLER_H_ + +#include <attributes/attribute_handler.h> + +typedef struct nm_handler_t nm_handler_t; + +/** + * Handles DNS/NBNS attributes to pass to NM. + */ +struct nm_handler_t { + + /** + * Implements attribute handler interface + */ + attribute_handler_t handler; + + /** + * Create an enumerator over received attributes of a given kind. + * + * @param type type of attributes to enumerate + * @return enumerator over attribute data (chunk_t) + */ + enumerator_t* (*create_enumerator)(nm_handler_t *this, + configuration_attribute_type_t type); + /** + * Reset state, flush all received attributes. + */ + void (*reset)(nm_handler_t *this); + + /** + * Destroy a nm_handler_t. + */ + void (*destroy)(nm_handler_t *this); +}; + +/** + * Create a nm_handler instance. + */ +nm_handler_t *nm_handler_create(); + +#endif /** NM_HANDLER_H_ @}*/ diff --git a/src/libcharon/plugins/nm/nm_plugin.c b/src/libcharon/plugins/nm/nm_plugin.c new file mode 100644 index 000000000..f2abcaf49 --- /dev/null +++ b/src/libcharon/plugins/nm/nm_plugin.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2008-2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "nm_plugin.h" +#include "nm_service.h" +#include "nm_creds.h" +#include "nm_handler.h" + +#include <daemon.h> +#include <processing/jobs/callback_job.h> + +#define CAP_DAC_OVERRIDE 1 + +typedef struct private_nm_plugin_t private_nm_plugin_t; + +/** + * private data of nm plugin + */ +struct private_nm_plugin_t { + + /** + * implements plugin interface + */ + nm_plugin_t public; + + /** + * NetworkManager service (VPNPlugin) + */ + NMStrongswanPlugin *plugin; + + /** + * Glib main loop for a thread, handles DBUS calls + */ + GMainLoop *loop; + + /** + * credential set registered at the daemon + */ + nm_creds_t *creds; + + /** + * attribute handler regeisterd at the daemon + */ + nm_handler_t *handler; +}; + +/** + * NM plugin processing routine, creates and handles NMVPNPlugin + */ +static job_requeue_t run(private_nm_plugin_t *this) +{ + this->loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(this->loop); + return JOB_REQUEUE_NONE; +} + +/** + * Implementation of plugin_t.destroy + */ +static void destroy(private_nm_plugin_t *this) +{ + if (this->loop) + { + if (g_main_loop_is_running(this->loop)) + { + g_main_loop_quit(this->loop); + } + g_main_loop_unref(this->loop); + } + if (this->plugin) + { + g_object_unref(this->plugin); + } + charon->credentials->remove_set(charon->credentials, &this->creds->set); + lib->attributes->remove_handler(lib->attributes, &this->handler->handler); + this->creds->destroy(this->creds); + this->handler->destroy(this->handler); + free(this); +} + +/* + * see header file + */ +plugin_t *nm_plugin_create() +{ + private_nm_plugin_t *this = malloc_thing(private_nm_plugin_t); + + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + + this->loop = NULL; + g_type_init (); + if (!g_thread_supported()) + { + g_thread_init(NULL); + } + + this->creds = nm_creds_create(); + this->handler = nm_handler_create(); + lib->attributes->add_handler(lib->attributes, &this->handler->handler); + charon->credentials->add_set(charon->credentials, &this->creds->set); + this->plugin = nm_strongswan_plugin_new(this->creds, this->handler); + if (!this->plugin) + { + DBG1(DBG_CFG, "DBUS binding failed"); + destroy(this); + return NULL; + } + + /* bypass file permissions to read from users ssh-agent */ + charon->keep_cap(charon, CAP_DAC_OVERRIDE); + + charon->processor->queue_job(charon->processor, + (job_t*)callback_job_create((callback_job_cb_t)run, this, NULL, NULL)); + + return &this->public.plugin; +} + diff --git a/src/libcharon/plugins/nm/nm_plugin.h b/src/libcharon/plugins/nm/nm_plugin.h new file mode 100644 index 000000000..b64b3edf6 --- /dev/null +++ b/src/libcharon/plugins/nm/nm_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup nm nm + * @ingroup cplugins + * + * @defgroup nm_plugin nm_plugin + * @{ @ingroup nm + */ + +#ifndef NM_PLUGIN_H_ +#define NM_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct nm_plugin_t nm_plugin_t; + +/** + * NetworkManager integration plugin. + */ +struct nm_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** NM_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c new file mode 100644 index 000000000..cdf7dc962 --- /dev/null +++ b/src/libcharon/plugins/nm/nm_service.c @@ -0,0 +1,629 @@ +/* + * Copyright (C) 2008-2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <nm-setting-vpn.h> +#include <nm-setting-connection.h> +#include "nm_service.h" + +#include <daemon.h> +#include <utils/host.h> +#include <utils/identification.h> +#include <config/peer_cfg.h> +#include <credentials/certificates/x509.h> + +#include <stdio.h> + +G_DEFINE_TYPE(NMStrongswanPlugin, nm_strongswan_plugin, NM_TYPE_VPN_PLUGIN) + +/** + * Private data of NMStrongswanPlugin + */ +typedef struct { + /* implements bus listener interface */ + listener_t listener; + /* IKE_SA we are listening on */ + ike_sa_t *ike_sa; + /* backref to public plugin */ + NMVPNPlugin *plugin; + /* credentials to use for authentication */ + nm_creds_t *creds; + /* attribute handler for DNS/NBNS server information */ + nm_handler_t *handler; + /* name of the connection */ + char *name; +} NMStrongswanPluginPrivate; + +#define NM_STRONGSWAN_PLUGIN_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + NM_TYPE_STRONGSWAN_PLUGIN, NMStrongswanPluginPrivate)) + +/** + * convert enumerated handler chunks to a UINT_ARRAY GValue + */ +static GValue* handler_to_val(nm_handler_t *handler, + configuration_attribute_type_t type) +{ + GValue *val; + GArray *array; + enumerator_t *enumerator; + chunk_t chunk; + + enumerator = handler->create_enumerator(handler, type); + array = g_array_new (FALSE, TRUE, sizeof (guint32)); + while (enumerator->enumerate(enumerator, &chunk)) + { + g_array_append_val (array, *(u_int32_t*)chunk.ptr); + } + enumerator->destroy(enumerator); + val = g_slice_new0 (GValue); + g_value_init (val, DBUS_TYPE_G_UINT_ARRAY); + g_value_set_boxed (val, array); + + return val; +} + +/** + * signal IPv4 config to NM, set connection as established + */ +static void signal_ipv4_config(NMVPNPlugin *plugin, + ike_sa_t *ike_sa, child_sa_t *child_sa) +{ + GValue *val; + GHashTable *config; + host_t *me, *other; + nm_handler_t *handler; + + config = g_hash_table_new(g_str_hash, g_str_equal); + me = ike_sa->get_my_host(ike_sa); + other = ike_sa->get_other_host(ike_sa); + handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler; + + /* NM requires a tundev, but netkey does not use one. Passing an invalid + * iface makes NM complain, but it accepts it without fiddling on eth0. */ + val = g_slice_new0 (GValue); + g_value_init (val, G_TYPE_STRING); + g_value_set_string (val, "none"); + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, val); + + val = g_slice_new0(GValue); + g_value_init(val, G_TYPE_UINT); + g_value_set_uint(val, *(u_int32_t*)me->get_address(me).ptr); + g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val); + + val = g_slice_new0(GValue); + g_value_init(val, G_TYPE_UINT); + g_value_set_uint(val, me->get_address(me).len * 8); + g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val); + + val = handler_to_val(handler, INTERNAL_IP4_DNS); + g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_DNS, val); + + val = handler_to_val(handler, INTERNAL_IP4_NBNS); + g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_NBNS, val); + + handler->reset(handler); + + nm_vpn_plugin_set_ip4_config(plugin, config); +} + +/** + * signal failure to NM, connecting failed + */ +static void signal_failure(NMVPNPlugin *plugin, NMVPNPluginFailure failure) +{ + nm_handler_t *handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler; + + handler->reset(handler); + + /* TODO: NM does not handle this failure!? */ + nm_vpn_plugin_failure(plugin, failure); + nm_vpn_plugin_set_state(plugin, NM_VPN_SERVICE_STATE_STOPPED); +} + +/** + * Implementation of listener_t.ike_state_change + */ +static bool ike_state_change(listener_t *listener, ike_sa_t *ike_sa, + ike_sa_state_t state) +{ + NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener; + + if (private->ike_sa == ike_sa && state == IKE_DESTROYING) + { + signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED); + return FALSE; + } + return TRUE; +} + +/** + * Implementation of listener_t.child_state_change + */ +static bool child_state_change(listener_t *listener, ike_sa_t *ike_sa, + child_sa_t *child_sa, child_sa_state_t state) +{ + NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener; + + if (private->ike_sa == ike_sa && state == CHILD_DESTROYING) + { + signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); + return FALSE; + } + return TRUE; +} + +/** + * Implementation of listener_t.child_updown + */ +static bool child_updown(listener_t *listener, ike_sa_t *ike_sa, + child_sa_t *child_sa, bool up) +{ + NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener; + + if (private->ike_sa == ike_sa) + { + if (up) + { /* disable initiate-failure-detection hooks */ + private->listener.ike_state_change = NULL; + private->listener.child_state_change = NULL; + signal_ipv4_config(private->plugin, ike_sa, child_sa); + } + else + { + signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); + return FALSE; + } + } + return TRUE; +} + +/** + * Implementation of listener_t.ike_rekey + */ +static bool ike_rekey(listener_t *listener, ike_sa_t *old, ike_sa_t *new) +{ + NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener; + + if (private->ike_sa == old) + { /* follow a rekeyed IKE_SA */ + private->ike_sa = new; + } + return TRUE; +} + +/** + * Connect function called from NM via DBUS + */ +static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, + GError **err) +{ + NMStrongswanPluginPrivate *priv; + NMSettingConnection *conn; + NMSettingVPN *vpn; + identification_t *user = NULL, *gateway = NULL; + const char *address, *str; + bool virtual, encap, ipcomp; + ike_cfg_t *ike_cfg; + peer_cfg_t *peer_cfg; + child_cfg_t *child_cfg; + traffic_selector_t *ts; + ike_sa_t *ike_sa; + auth_cfg_t *auth; + auth_class_t auth_class = AUTH_CLASS_EAP; + certificate_t *cert = NULL; + x509_t *x509; + bool agent = FALSE; + lifetime_cfg_t lifetime = { + .time = { + .life = 10800 /* 3h */, + .rekey = 10200 /* 2h50min */, + .jitter = 300 /* 5min */ + } + }; + + /** + * Read parameters + */ + priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin); + conn = NM_SETTING_CONNECTION(nm_connection_get_setting(connection, + NM_TYPE_SETTING_CONNECTION)); + vpn = NM_SETTING_VPN(nm_connection_get_setting(connection, + NM_TYPE_SETTING_VPN)); + if (priv->name) + { + free(priv->name); + } + priv->name = strdup(nm_setting_connection_get_id(conn)); + DBG1(DBG_CFG, "received initiate for NetworkManager connection %s", + priv->name); + DBG4(DBG_CFG, "%s", + nm_setting_to_string(NM_SETTING(vpn))); + address = nm_setting_vpn_get_data_item(vpn, "address"); + if (!address || !*address) + { + g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Gateway address missing."); + return FALSE; + } + str = nm_setting_vpn_get_data_item(vpn, "virtual"); + virtual = str && streq(str, "yes"); + str = nm_setting_vpn_get_data_item(vpn, "encap"); + encap = str && streq(str, "yes"); + str = nm_setting_vpn_get_data_item(vpn, "ipcomp"); + ipcomp = str && streq(str, "yes"); + str = nm_setting_vpn_get_data_item(vpn, "method"); + if (str) + { + if (streq(str, "psk")) + { + auth_class = AUTH_CLASS_PSK; + } + else if (streq(str, "agent")) + { + auth_class = AUTH_CLASS_PUBKEY; + agent = TRUE; + } + else if (streq(str, "key")) + { + auth_class = AUTH_CLASS_PUBKEY; + } + } + + /** + * Register credentials + */ + priv->creds->clear(priv->creds); + + /* gateway/CA cert */ + str = nm_setting_vpn_get_data_item(vpn, "certificate"); + if (str) + { + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, str, BUILD_END); + if (!cert) + { + g_set_error(err, NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Loading gateway certificate failed."); + return FALSE; + } + priv->creds->add_certificate(priv->creds, cert); + + x509 = (x509_t*)cert; + if (!(x509->get_flags(x509) & X509_CA)) + { /* For a gateway certificate, we use the cert subject as identity. */ + gateway = cert->get_subject(cert); + gateway = gateway->clone(gateway); + DBG1(DBG_CFG, "using gateway certificate, identity '%Y'", gateway); + } + } + else + { + /* no certificate defined, fall back to system-wide CA certificates */ + priv->creds->load_ca_dir(priv->creds, NM_CA_DIR); + } + if (!gateway) + { + /* If the user configured a CA certificate, we use the IP/DNS + * of the gateway as its identity. This identity will be used for + * certificate lookup and requires the configured IP/DNS to be + * included in the gateway certificate. */ + gateway = identification_create_from_string((char*)address); + DBG1(DBG_CFG, "using CA certificate, gateway identity '%Y'", gateway); + } + + if (auth_class == AUTH_CLASS_EAP) + { + /* username/password authentication ... */ + str = nm_setting_vpn_get_data_item(vpn, "user"); + if (str) + { + user = identification_create_from_string((char*)str); + str = nm_setting_vpn_get_secret(vpn, "password"); + priv->creds->set_username_password(priv->creds, user, (char*)str); + } + } + + if (auth_class == AUTH_CLASS_PUBKEY) + { + /* ... or certificate/private key authenitcation */ + str = nm_setting_vpn_get_data_item(vpn, "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); + if (!cert) + { + g_set_error(err, NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Loading peer certificate failed."); + gateway->destroy(gateway); + return FALSE; + } + /* try agent */ + str = nm_setting_vpn_get_secret(vpn, "agent"); + if (agent && str) + { + 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) + { + g_set_error(err, NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Connecting to SSH agent failed."); + } + } + /* ... or key file */ + str = nm_setting_vpn_get_data_item(vpn, "userkey"); + if (!agent && str) + { + chunk_t secret; + + secret.ptr = (char*)nm_setting_vpn_get_secret(vpn, "password"); + if (secret.ptr) + { + secret.len = strlen(secret.ptr); + } + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, + KEY_RSA, BUILD_FROM_FILE, str, + BUILD_PASSPHRASE, secret, BUILD_END); + if (!private) + { + g_set_error(err, NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Loading private key failed."); + } + } + if (private) + { + user = cert->get_subject(cert); + user = user->clone(user); + priv->creds->set_cert_and_key(priv->creds, cert, private); + } + else + { + DESTROY_IF(cert); + gateway->destroy(gateway); + return FALSE; + } + } + } + + if (!user) + { + g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Configuration parameters missing."); + gateway->destroy(gateway); + return FALSE; + } + + /** + * Set up configurations + */ + ike_cfg = ike_cfg_create(TRUE, encap, + "0.0.0.0", IKEV2_UDP_PORT, (char*)address, IKEV2_UDP_PORT); + ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); + peer_cfg = peer_cfg_create(priv->name, 2, ike_cfg, + CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */ + 36000, 0, /* rekey 10h, reauth none */ + 600, 600, /* jitter, over 10min */ + TRUE, 0, /* mobike, DPD */ + virtual ? host_create_from_string("0.0.0.0", 0) : NULL, + NULL, FALSE, NULL, NULL); /* pool, mediation */ + auth = auth_cfg_create(); + auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_class); + auth->add(auth, AUTH_RULE_IDENTITY, user); + peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE); + auth = auth_cfg_create(); + auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); + auth->add(auth, AUTH_RULE_IDENTITY, gateway); + peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE); + + child_cfg = child_cfg_create(priv->name, &lifetime, + NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */ + ACTION_NONE, ACTION_NONE, ipcomp, 0); + child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); + ts = traffic_selector_create_dynamic(0, 0, 65535); + child_cfg->add_traffic_selector(child_cfg, TRUE, ts); + ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, + "0.0.0.0", 0, + "255.255.255.255", 65535); + child_cfg->add_traffic_selector(child_cfg, FALSE, ts); + peer_cfg->add_child_cfg(peer_cfg, child_cfg); + + /** + * Prepare IKE_SA + */ + ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager, + peer_cfg); + if (!ike_sa->get_peer_cfg(ike_sa)) + { + ike_sa->set_peer_cfg(ike_sa, peer_cfg); + } + peer_cfg->destroy(peer_cfg); + + /** + * Register listener, enable initiate-failure-detection hooks + */ + priv->ike_sa = ike_sa; + priv->listener.ike_state_change = ike_state_change; + priv->listener.child_state_change = child_state_change; + charon->bus->add_listener(charon->bus, &priv->listener); + + /** + * Initiate + */ + if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS) + { + charon->bus->remove_listener(charon->bus, &priv->listener); + charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa); + + g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, + "Initiating failed."); + return FALSE; + } + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + return TRUE; +} + +/** + * NeedSecrets called from NM via DBUS + */ +static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection, + char **setting_name, GError **error) +{ + NMSettingVPN *settings; + const char *method, *path; + + settings = NM_SETTING_VPN(nm_connection_get_setting(connection, + NM_TYPE_SETTING_VPN)); + method = nm_setting_vpn_get_data_item(settings, "method"); + if (method) + { + if (streq(method, "eap")) + { + if (nm_setting_vpn_get_secret(settings, "password")) + { + return FALSE; + } + } + else if (streq(method, "agent")) + { + if (nm_setting_vpn_get_secret(settings, "agent")) + { + return FALSE; + } + } + else if (streq(method, "key")) + { + path = nm_setting_vpn_get_data_item(settings, "userkey"); + if (path) + { + private_key_t *key; + chunk_t secret; + + secret.ptr = (char*)nm_setting_vpn_get_secret(settings, "password"); + if (secret.ptr) + { + secret.len = strlen(secret.ptr); + } + /* try to load/decrypt the private key */ + key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, + KEY_RSA, BUILD_FROM_FILE, path, + BUILD_PASSPHRASE, secret, BUILD_END); + if (key) + { + key->destroy(key); + return FALSE; + } + } + } + } + *setting_name = NM_SETTING_VPN_SETTING_NAME; + return TRUE; +} + +/** + * Disconnect called from NM via DBUS + */ +static gboolean disconnect(NMVPNPlugin *plugin, GError **err) +{ + NMStrongswanPluginPrivate *priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin); + enumerator_t *enumerator; + ike_sa_t *ike_sa; + u_int id; + + /* our ike_sa pointer might be invalid, lookup sa */ + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (priv->ike_sa == ike_sa) + { + id = ike_sa->get_unique_id(ike_sa); + enumerator->destroy(enumerator); + charon->controller->terminate_ike(charon->controller, id, + controller_cb_empty, NULL); + return TRUE; + } + } + enumerator->destroy(enumerator); + + g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_GENERAL, + "Connection not found."); + return FALSE; +} + +/** + * Initializer + */ +static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin) +{ + NMStrongswanPluginPrivate *priv; + + priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin); + priv->plugin = NM_VPN_PLUGIN(plugin); + memset(&priv->listener.log, 0, sizeof(listener_t)); + priv->listener.child_updown = child_updown; + priv->listener.ike_rekey = ike_rekey; +} + +/** + * Class constructor + */ +static void nm_strongswan_plugin_class_init( + NMStrongswanPluginClass *strongswan_class) +{ + NMVPNPluginClass *parent_class = NM_VPN_PLUGIN_CLASS(strongswan_class); + + g_type_class_add_private(G_OBJECT_CLASS(strongswan_class), + sizeof(NMStrongswanPluginPrivate)); + parent_class->connect = connect_; + parent_class->need_secrets = need_secrets; + parent_class->disconnect = disconnect; +} + +/** + * Object constructor + */ +NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds, + nm_handler_t *handler) +{ + NMStrongswanPlugin *plugin = (NMStrongswanPlugin *)g_object_new ( + NM_TYPE_STRONGSWAN_PLUGIN, + NM_VPN_PLUGIN_DBUS_SERVICE_NAME, NM_DBUS_SERVICE_STRONGSWAN, + NULL); + if (plugin) + { + NMStrongswanPluginPrivate *priv; + + priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin); + priv->creds = creds; + priv->handler = handler; + priv->name = NULL; + } + return plugin; +} + diff --git a/src/libcharon/plugins/nm/nm_service.h b/src/libcharon/plugins/nm/nm_service.h new file mode 100644 index 000000000..b00000b6f --- /dev/null +++ b/src/libcharon/plugins/nm/nm_service.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008-2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup nm_service nm_service + * @{ @ingroup nm + */ + +#ifndef NM_SERVICE_H_ +#define NM_SERVICE_H_ + +#include <glib/gtypes.h> +#include <glib-object.h> +#include <nm-vpn-plugin.h> + +#include "nm_creds.h" +#include "nm_handler.h" + +#define NM_TYPE_STRONGSWAN_PLUGIN (nm_strongswan_plugin_get_type ()) +#define NM_STRONGSWAN_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_STRONGSWAN_PLUGIN, NMSTRONGSWANPlugin)) +#define NM_STRONGSWAN_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_STRONGSWAN_PLUGIN, NMSTRONGSWANPluginClass)) +#define NM_IS_STRONGSWAN_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_STRONGSWAN_PLUGIN)) +#define NM_IS_STRONGSWAN_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_STRONGSWAN_PLUGIN)) +#define NM_STRONGSWAN_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_STRONGSWAN_PLUGIN, NMSTRONGSWANPluginClass)) + +#define NM_DBUS_SERVICE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan" +#define NM_DBUS_INTERFACE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan" +#define NM_DBUS_PATH_STRONGSWAN "/org/freedesktop/NetworkManager/strongswan" + +typedef struct { + NMVPNPlugin parent; +} NMStrongswanPlugin; + +typedef struct { + NMVPNPluginClass parent; +} NMStrongswanPluginClass; + +GType nm_strongswan_plugin_get_type(void); + +NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds, + nm_handler_t *handler); + +#endif /** NM_SERVICE_H_ @}*/ |