Moving charon to libcharon.

This commit is contained in:
Tobias Brunner
2010-03-19 13:34:52 +01:00
parent 7c11d10eb8
commit 08c5572602
480 changed files with 0 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
network-manager-strongswan_*
+20
View File
@@ -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}
+11
View File
@@ -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
@@ -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
+24
View File
@@ -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
@@ -0,0 +1 @@
nm-strongswan-auth-dialog
@@ -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)
@@ -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;
}
+15
View File
@@ -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
+101
View File
@@ -0,0 +1,101 @@
AC_PREREQ(2.52)
AC_INIT(NetworkManager-strongswan, 1.1.2, [email protected], 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
@@ -0,0 +1,6 @@
files
network-manager-strongswan.debhelper.log
network-manager-strongswan.substvars
network-manager-strongswan/
stamp-autotools-files
stamp-makefile-build
@@ -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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> Wed, 25 Mar 2009 09:07:05 +0100
@@ -0,0 +1 @@
7
@@ -0,0 +1,29 @@
Source: network-manager-strongswan
Section: net
Priority: extra
Maintainer: Martin Willi <[email protected]>
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.
@@ -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 <[email protected]>
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.
@@ -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
+15
View File
@@ -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
@@ -0,0 +1,7 @@
intltool.m4
libtool.m4
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.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
])
@@ -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>
@@ -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
@@ -0,0 +1,4 @@
Makefile.in.in
POTFILES
de.gmo
stamp-it
@@ -0,0 +1,2 @@
# please keep this list sorted alphabetically
de
@@ -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
+163
View File
@@ -0,0 +1,163 @@
# Translations for NetworkManager-strongswan.
# Copyright (C) 2010 Martin Willi <[email protected]>
# 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 <[email protected]>\n"
"Language-Team: de <[email protected]>\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!"
@@ -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)
@@ -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">&lt;b&gt;Gateway&lt;/b&gt;</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">&lt;b&gt;Client&lt;/b&gt;</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">&lt;b&gt;Options&lt;/b&gt;</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>
@@ -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));
}
@@ -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_ */
+447
View File
@@ -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;
}
+85
View File
@@ -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_ @}*/
+193
View File
@@ -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;
}
+62
View File
@@ -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_ @}*/
+129
View File
@@ -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;
}
+42
View File
@@ -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_ @}*/
+629
View File
@@ -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;
}
+55
View File
@@ -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_ @}*/