fi]
)
+AC_ARG_ENABLE(
+ [nm],
+ AS_HELP_STRING([--enable-nm],[enable NetworkManager plugin (default is NO).]),
+ [if test x$enableval = xyes; then
+ nm=true
+ fi]
+)
+
dnl =========================
dnl check required programs
dnl =========================
AC_CHECK_HEADER([uci.h],,[AC_MSG_ERROR([UCI header uci.h not found!])])
fi
+if test x$nm = xtrue; then
+ PKG_CHECK_MODULES(nm, [NetworkManager libnm_glib_vpn gthread-2.0])
+ AC_SUBST(nm_CFLAGS)
+ AC_SUBST(nm_LIBS)
+fi
+
dnl ======================================
dnl collect all plugins for libstrongswan
dnl ======================================
AM_CONDITIONAL(USE_STROKE, test x$stroke = xtrue)
AM_CONDITIONAL(USE_MEDSRV, test x$medsrv = xtrue)
AM_CONDITIONAL(USE_MEDCLI, test x$medcli = xtrue)
+AM_CONDITIONAL(USE_NM, test x$nm = xtrue)
AM_CONDITIONAL(USE_UCI, test x$uci = xtrue)
AM_CONDITIONAL(USE_SMP, test x$smp = xtrue)
AM_CONDITIONAL(USE_SQL, test x$sql = xtrue)
src/charon/plugins/sql/Makefile
src/charon/plugins/medsrv/Makefile
src/charon/plugins/medcli/Makefile
+ src/charon/plugins/nm/Makefile
src/charon/plugins/uci/Makefile
src/charon/plugins/stroke/Makefile
src/charon/plugins/unit_tester/Makefile
PLUGINS += medcli
endif
+if USE_NM
+ SUBDIRS += plugins/nm
+ PLUGINS += nm
+endif
+
if USE_UCI
SUBDIRS += plugins/uci
PLUGINS += uci
+++ /dev/null
-
-INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon ${dbus_CFLAGS}
-
-AM_CFLAGS = -rdynamic
-
-plugin_LTLIBRARIES = libstrongswan-dbus.la
-
-libstrongswan_dbus_la_SOURCES = dbus.h dbus.c
-libstrongswan_dbus_la_LDFLAGS = -module
-libstrongswan_dbus_la_LIBADD = ${dbus_LIBS}
-
+++ /dev/null
-/*
- * Copyright (C) 2007 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.
- *
- * $Id$
- */
-
-#define DBUS_API_SUBJECT_TO_CHANGE
-#include <dbus/dbus.h>
-#include <NetworkManager/NetworkManager.h>
-#include <NetworkManager/NetworkManagerVPN.h>
-#include <stdlib.h>
-
-#include "dbus.h"
-
-#include <library.h>
-#include <daemon.h>
-#include <processing/jobs/callback_job.h>
-
-
-#define NM_DBUS_SERVICE_STRONG "org.freedesktop.NetworkManager.strongswan"
-#define NM_dbus_STRONG "org.freedesktop.NetworkManager.strongswan"
-#define NM_DBUS_PATH_STRONG "/org/freedesktop/NetworkManager/strongswan"
-
-typedef struct private_dbus_t private_dbus_t;
-
-/**
- * Private data of an dbus_t object.
- */
-struct private_dbus_t {
-
- /**
- * Public part of dbus_t object.
- */
- dbus_t public;
-
- /**
- * DBUS connection
- */
- DBusConnection* conn;
-
- /**
- * error value used here and there
- */
- DBusError err;
-
- /**
- * state of the daemon
- */
- NMVPNState state;
-
- /**
- * job accepting stroke messages
- */
- callback_job_t *job;
-
- /**
- * name of the currently active connection
- */
- char *name;
-};
-
-/**
- * set daemon state and send StateChange signal to the bus
- */
-static void set_state(private_dbus_t *this, NMVPNState state)
-{
- DBusMessage* msg;
-
- msg = dbus_message_new_signal(NM_DBUS_PATH_STRONG, NM_dbus_STRONG, NM_DBUS_VPN_SIGNAL_STATE_CHANGE);
-
- if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &this->state,
- DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID) ||
- !dbus_connection_send(this->conn, msg, NULL))
- {
- DBG1(DBG_CFG, "unable to send DBUS StateChange signal");
- }
- dbus_connection_flush(this->conn);
- dbus_message_unref(msg);
- this->state = state;
-}
-
-
-/**
- * get the child_cfg with the same name as the peer cfg
- */
-static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
-{
- child_cfg_t *current, *found = NULL;
- iterator_t *iterator;
-
- iterator = peer_cfg->create_child_cfg_iterator(peer_cfg);
- while (iterator->iterate(iterator, (void**)¤t))
- {
- if (streq(current->get_name(current), name))
- {
- found = current;
- found->get_ref(found);
- break;
- }
- }
- iterator->destroy(iterator);
- return found;
-}
-
-
-/**
- * process NetworkManagers startConnection method call
- */
-static bool start_connection(private_dbus_t *this, DBusMessage* msg)
-{
- DBusMessage *reply, *signal;
- char *name, *user, **data, **passwords, **routes;
- int data_count, passwords_count, routes_count;
- u_int32_t me, other, p2p, netmask, mss;
- char *dev, *domain, *banner;
- const dbus_int32_t array[] = {};
- const dbus_int32_t *varray = array;
- peer_cfg_t *peer_cfg;
- child_cfg_t *child_cfg;
- status_t status = FAILED;
-
- dbus_error_free(&this->err);
-
- if (!dbus_message_get_args(msg, &this->err,
- DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &user,
- DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &passwords, &passwords_count,
- DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &data, &data_count,
- DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &routes, &routes_count,
- DBUS_TYPE_INVALID))
- {
- return FALSE;
- }
- set_state(this, NM_VPN_STATE_STARTING);
-
- peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, name);
- if (peer_cfg)
- {
- free(this->name);
- this->name = strdup(peer_cfg->get_name(peer_cfg));
- child_cfg = get_child_from_peer(peer_cfg, name);
- if (child_cfg)
- {
- status = charon->controller->initiate(charon->controller,
- peer_cfg, child_cfg, controller_cb_empty, NULL);
- }
- else
- {
- peer_cfg->destroy(peer_cfg);
- }
- }
- reply = dbus_message_new_method_return(msg);
- dbus_connection_send(this->conn, reply, NULL);
- dbus_message_unref(reply);
-
- if (status == SUCCESS)
- {
-
- set_state(this, NM_VPN_STATE_STARTED);
- signal = dbus_message_new_signal(NM_DBUS_PATH_STRONG,
- NM_dbus_STRONG,
- NM_DBUS_VPN_SIGNAL_IP4_CONFIG);
- me = other = p2p = mss = netmask = 0;
- dev = domain = banner = "";
- if (dbus_message_append_args(signal,
- DBUS_TYPE_UINT32, &other,
- DBUS_TYPE_STRING, &dev,
- DBUS_TYPE_UINT32, &me,
- DBUS_TYPE_UINT32, &p2p,
- DBUS_TYPE_UINT32, &netmask,
- DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &varray, 0,
- DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &varray, 0,
- DBUS_TYPE_UINT32, &mss,
- DBUS_TYPE_STRING, &domain,
- DBUS_TYPE_STRING, &banner, DBUS_TYPE_INVALID))
- {
- dbus_connection_send(this->conn, signal, NULL);
- }
- dbus_message_unref(signal);
- }
- else
- {
- set_state(this, NM_VPN_STATE_STOPPED);
- }
-
- dbus_connection_flush(this->conn);
- return TRUE;
-}
-
-/**
- * process NetworkManagers stopConnection method call
- */
-static bool stop_connection(private_dbus_t *this, DBusMessage* msg)
-{
- u_int32_t id;
- enumerator_t *enumerator;
- ike_sa_t *ike_sa;
-
- if (this->name == NULL)
- {
- return FALSE;
- }
-
- dbus_error_free(&this->err);
-
- set_state(this, NM_VPN_STATE_STOPPING);
-
- enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
- while (enumerator->enumerate(enumerator, (void**)&ike_sa))
- {
- child_sa_t *child_sa;
- iterator_t *children;
-
- if (this->name && streq(this->name, ike_sa->get_name(ike_sa)))
- {
- id = ike_sa->get_unique_id(ike_sa);
- enumerator->destroy(enumerator);
- charon->controller->terminate_ike(charon->controller, id, NULL, NULL);
- set_state(this, NM_VPN_STATE_STOPPED);
- return TRUE;;
- }
- children = ike_sa->create_child_sa_iterator(ike_sa);
- while (children->iterate(children, (void**)&child_sa))
- {
- if (this->name && streq(this->name, child_sa->get_name(child_sa)))
- {
- id = child_sa->get_reqid(child_sa);
- children->destroy(children);
- enumerator->destroy(enumerator);
- charon->controller->terminate_child(charon->controller, id, NULL, NULL);
- set_state(this, NM_VPN_STATE_STOPPED);
- return TRUE;
- }
- }
- children->destroy(children);
- }
- enumerator->destroy(enumerator);
- set_state(this, NM_VPN_STATE_STOPPED);
- return TRUE;
-}
-
-/**
- * process NetworkManagers getState method call
- */
-static bool get_state(private_dbus_t *this, DBusMessage* msg)
-{
- DBusMessage* reply;
- reply = dbus_message_new_method_return(msg);
- if (!reply || !dbus_message_append_args(reply,
- DBUS_TYPE_UINT32, &this->state,
- DBUS_TYPE_INVALID))
- {
- return FALSE;
- }
- dbus_connection_send(this->conn, reply, NULL);
- return TRUE;
-}
-
-/**
- * Handle incoming messages
- */
-static DBusHandlerResult message_handler(DBusConnection *con, DBusMessage *msg,
- private_dbus_t *this)
-{
- bool handled;
-
- if (dbus_message_is_method_call(msg, NM_dbus_STRONG,
- "startConnection"))
- {
- handled = start_connection(this, msg);
- }
- else if (dbus_message_is_method_call(msg, NM_dbus_STRONG,
- "stopConnection"))
- {
- handled = stop_connection(this, msg);
- }
- else if (dbus_message_is_method_call(msg, NM_dbus_STRONG,
- "getState"))
- {
- handled = get_state(this, msg);
- }
- else
- {
- DBG1(DBG_CFG, "ignoring DBUS message %s.%s",
- dbus_message_get_interface(msg), dbus_message_get_member(msg));
- handled = FALSE;
- }
-
- if (handled)
- {
- return DBUS_HANDLER_RESULT_HANDLED;
- }
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-/**
- * Handle received signals
-
-static DBusHandlerResult signal_handler(DBusConnection *con, DBusMessage *msg,
- private_dbus_t *this)
-{
- bool handled;
-
- if (dbus_message_is_signal(msg, NM_dbus, "VPNConnectionStateChange"))
- {
- NMVPNState state;
- char *name;
-
- if (dbus_message_get_args(msg, &this->err, DBUS_TYPE_STRING, &name,
- DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID))
- {
- DBG1(DBG_CFG, "got state %d for %s", state, name);
- }
- handled = TRUE;
- }
- else
- {
- DBG1(DBG_CFG, "ignoring DBUS signal %s.%s",
- dbus_message_get_interface(msg), dbus_message_get_member(msg));
- handled = FALSE;
- }
- if (handled)
- {
- return DBUS_HANDLER_RESULT_HANDLED;
- }
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-} */
-
-/**
- * dispatcher function processed by a seperate thread
- */
-static job_requeue_t dispatch(private_dbus_t *this)
-{
- if (dbus_connection_read_write_dispatch(this->conn, -1))
- {
- return JOB_REQUEUE_DIRECT;
- }
- return JOB_REQUEUE_NONE;
-}
-
-/**
- * Implementation of interface_t.destroy.
- */
-static void destroy(private_dbus_t *this)
-{
- this->job->cancel(this->job);
- dbus_connection_close(this->conn);
- dbus_error_free(&this->err);
- dbus_shutdown();
- free(this->name);
- free(this);
-}
-
-/*
- * Described in header file
- */
-plugin_t *plugin_create()
-{
- int ret;
- DBusObjectPathVTable v = {NULL, (void*)&message_handler, NULL, NULL, NULL, NULL};
- private_dbus_t *this = malloc_thing(private_dbus_t);
-
- this->public.plugin.destroy = (void (*)(plugin_t*))destroy;
-
- dbus_error_init(&this->err);
- this->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &this->err);
- if (dbus_error_is_set(&this->err))
- {
- DBG1(DBG_CFG, "unable to open DBUS connection: %s", this->err.message);
- charon->kill(charon, "DBUS initialization failed");
- }
- dbus_connection_set_exit_on_disconnect(this->conn, FALSE);
-
- ret = dbus_bus_request_name(this->conn, NM_DBUS_SERVICE_STRONG,
- DBUS_NAME_FLAG_REPLACE_EXISTING , &this->err);
- if (dbus_error_is_set(&this->err))
- {
- DBG1(DBG_CFG, "unable to set DBUS name: %s", this->err.message);
- charon->kill(charon, "unable to set DBUS name");
- }
- if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
- {
- charon->kill(charon, "DBUS name already owned");
- }
- if (!dbus_connection_register_object_path(this->conn, NM_DBUS_PATH_STRONG, &v, this))
- {
- charon->kill(charon, "unable to register DBUS message handler");
- }
- /*
- if (!dbus_connection_add_filter(this->conn, (void*)signal_handler, this, NULL))
- {
- charon->kill(charon, "unable to register DBUS signal handler");
- }
-
- dbus_bus_add_match(this->conn, "type='signal', "
- "interface='" NM_dbus_VPN "',"
- "path='" NM_DBUS_PATH_VPN "'", &this->err);
- if (dbus_error_is_set (&this->err))
- {
- charon->kill(charon, "unable to add DBUS signal match");
- }*/
-
- this->name = NULL;
- this->state = NM_VPN_STATE_INIT;
- set_state(this, NM_VPN_STATE_STOPPED);
-
- this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL);
- charon->processor->queue_job(charon->processor, (job_t*)this->job);
-
- return &this->public.plugin;
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2007-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 dbus dbus
- * @ingroup cplugins
- *
- * @defgroup dbus_i dbus
- * @{ @ingroup dbus
- */
-
-#ifndef DBUS_H_
-#define DBUS_H_
-
-#include <plugins/plugin.h>
-
-typedef struct dbus_t dbus_t;
-
-/**
- * NetworkManager DBUS control plugin.
- *
- * This plugin uses a DBUS connection. It is designed to work in conjuction
- * with NetworkManager to configure and control the daemon.
- */
-struct dbus_t {
-
- /**
- * implements plugin interface
- */
- plugin_t plugin;
-};
-
-/**
- * Create a dbus plugin instance.
- */
-plugin_t *plugin_create();
-
-#endif /* DBUS_H_ @}*/
+++ /dev/null
-<!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 at_console="true">
- <allow send_destination="org.freedesktop.NetworkManager.strongswan"/>
- <allow send_interface="org.freedesktop.NetworkManager.strongswan"/>
- </policy>
- <policy context="default">
- <deny own="org.strongswan.charon"/>
- <deny send_destination="org.freedesktop.NetworkManager.strongswan"/>
- <deny send_interface="org.freedesktop.NetworkManager.strongswan"/>
- </policy>
-</busconfig>
-
+++ /dev/null
-[VPN Connection]
-name=strongSwan
-service=org.freedesktop.NetworkManager.strongswan
-program=/usr/local/libexec/ipsec/charon
-
-[GNOME]
-auth-dialog=/home/martin/strongswan/trunk/src/networkmanager/nm_applet_auth
-properties=/home/martin/strongswan/trunk/src/networkmanager/strongswan.so
+++ /dev/null
-#include <stdio.h>
-
-
-int main()
-{
- char buf[1];
- printf("PASSWORDL\n");
- printf ("\n\n");
- //fread (buf, sizeof (char), sizeof (buf), stdin);
- return 0;
-}
+++ /dev/null
-/*
- * Copyright (C) 2007 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.
- *
- * $Id$
- */
-
-#include <glade/glade.h>
-
-#define NM_VPN_API_SUBJECT_TO_CHANGE
-#include <nm-vpn-ui-interface.h>
-
-
-typedef struct private_nm_applet_gui_t private_nm_applet_gui_t;
-
-/**
- * Private data of an nm_applet_gui_t object.
- */
-struct private_nm_applet_gui_t {
-
- /**
- * Implements NetworkManagerVpnUI interface.
- */
- NetworkManagerVpnUI public;
-
- /**
- * callback registered by NM to update validity
- */
- NetworkManagerVpnUIDialogValidityCallback callback;
-
- /**
- * loaded Glade XML interface description
- */
- GladeXML *xml;
-
- /**
- * root widget to return to druid
- */
- GtkWidget *widget;
-
- /**
- * name of the connection
- */
- GtkEntry *name;
-
- /**
- * gateway address
- */
- GtkEntry *gateway;
-
- /**
- * username
- */
- GtkEntry *user;
-};
-
-static const char *get_display_name(private_nm_applet_gui_t *this)
-{
- return "strongSwan (IPsec/IKEv2)";
-}
-
-static const char *get_service_name(private_nm_applet_gui_t *this)
-{
- return "org.freedesktop.NetworkManager.strongswan";
-}
-
-static GtkWidget *get_widget(private_nm_applet_gui_t *this, GSList *properties,
- GSList *routes, const char *connection_name)
-{
- GSList *i;
-
- gtk_entry_set_text(this->name, "");
- gtk_entry_set_text(this->gateway, "");
- gtk_entry_set_text(this->user, "");
-
- if (connection_name)
- {
- gtk_entry_set_text(this->name, connection_name);
- }
-
- while (properties)
- {
- const char *key;
- const char *value;
-
- key = properties->data;
- properties = g_slist_next(properties);
- if (properties)
- {
- value = properties->data;
- if (strcmp(key, "gateway") == 0)
- {
- gtk_entry_set_text(this->gateway, value);
- }
- if (strcmp(key, "user") == 0)
- {
- gtk_entry_set_text(this->user, value);
- }
- properties = g_slist_next(properties);
- }
- }
- return this->widget;
-}
-
-static GSList *get_properties(private_nm_applet_gui_t *this)
-{
- GSList *props = NULL;
-
- props = g_slist_append(props, g_strdup("gateway"));
- props = g_slist_append(props, g_strdup(gtk_entry_get_text(this->gateway)));
- props = g_slist_append(props, g_strdup("user"));
- props = g_slist_append(props, g_strdup(gtk_entry_get_text(this->user)));
-
- return props;
-}
-
-static GSList *get_routes(private_nm_applet_gui_t *this)
-{
- return NULL;
-}
-
-static char *get_connection_name(private_nm_applet_gui_t *this)
-{
- const char *name;
-
- name = gtk_entry_get_text(this->name);
- if (name != NULL)
- {
- return g_strdup(name);
- }
- return NULL;
-}
-
-static gboolean is_valid(private_nm_applet_gui_t *this)
-{
- return TRUE;
-}
-
-static void set_validity_changed_callback(private_nm_applet_gui_t *this,
- NetworkManagerVpnUIDialogValidityCallback callback,
- gpointer user_data)
-{
- this->callback = callback;
-}
-
-static void get_confirmation_details(private_nm_applet_gui_t *this, gchar **retval)
-{
- *retval = g_strdup_printf("connection %s\n", gtk_entry_get_text(this->name));
-}
-
-static gboolean can_export(private_nm_applet_gui_t *this)
-{
- return FALSE;
-}
-
-static gboolean import_file (private_nm_applet_gui_t *this, const char *path)
-{
- return FALSE;
-}
-
-static gboolean export(private_nm_applet_gui_t *this, GSList *properties,
- GSList *routes, const char *connection_name)
-{
- return FALSE;
-}
-
-NetworkManagerVpnUI* nm_vpn_properties_factory(void)
-{
- private_nm_applet_gui_t *this = g_new0(private_nm_applet_gui_t, 1);
-
- this->public.get_display_name = (const char *(*)(NetworkManagerVpnUI *))get_display_name;
- this->public.get_service_name = (const char *(*) (NetworkManagerVpnUI *))get_service_name;
- this->public.get_widget = (GtkWidget *(*) (NetworkManagerVpnUI *self, GSList *, GSList *, const char *))get_widget;
- this->public.get_connection_name = (char *(*) (NetworkManagerVpnUI *))get_connection_name;
- this->public.get_properties = (GSList *(*) (NetworkManagerVpnUI *))get_properties;
- this->public.get_routes = (GSList *(*) (NetworkManagerVpnUI *))get_routes;
- this->public.set_validity_changed_callback = (void (*) (NetworkManagerVpnUI *, NetworkManagerVpnUIDialogValidityCallback, gpointer))set_validity_changed_callback;
- this->public.is_valid = (gboolean (*) (NetworkManagerVpnUI *))is_valid;
- this->public.get_confirmation_details = (void (*)(NetworkManagerVpnUI *, gchar **))get_confirmation_details;
- this->public.can_export = (gboolean (*) (NetworkManagerVpnUI *))can_export;
- this->public.import_file = (gboolean (*) (NetworkManagerVpnUI *, const char *))import_file;
- this->public.export = (gboolean (*) (NetworkManagerVpnUI *, GSList *, GSList *, const char *))export;
- this->public.data = NULL;
-
- this->callback = NULL;
- this->xml = glade_xml_new("/home/martin/strongswan/trunk/src/charon/plugins/dbus/nm_applet_gui.xml", NULL, NULL);
-
- if (this->xml != NULL)
- {
- this->widget = glade_xml_get_widget(this->xml, "main");
- this->name = GTK_ENTRY(glade_xml_get_widget(this->xml, "name"));
- this->gateway = GTK_ENTRY(glade_xml_get_widget(this->xml, "gateway"));
- this->user = GTK_ENTRY(glade_xml_get_widget(this->xml, "user"));
-
- if (this->widget && this->name && this->gateway && this->user)
- {
- return &this->public;
- }
- }
- g_free(this);
- return NULL;
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--Generated with glade3 3.4.0 on Sat Mar 15 17:12:28 2008 -->
-<glade-interface>
- <widget class="GtkWindow" id="window1">
- <child>
- <widget class="GtkTable" id="main">
- <property name="visible">True</property>
- <property name="n_rows">3</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">5</property>
- <property name="row_spacing">5</property>
- <child>
- <widget class="GtkEntry" id="user">
- <property name="visible">True</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>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label8">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Username</property>
- <property name="use_underline">True</property>
- <property name="justify">GTK_JUSTIFY_CENTER</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">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <widget class="GtkEntry" id="gateway">
- <property name="visible">True</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="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label3">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Gateway</property>
- <property name="use_underline">True</property>
- <property name="justify">GTK_JUSTIFY_RIGHT</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">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <widget class="GtkEntry" id="name">
- <property name="visible">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Connection _name</property>
- <property name="use_underline">True</property>
- <property name="justify">GTK_JUSTIFY_FILL</property>
- </widget>
- <packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
-</glade-interface>
--- /dev/null
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon ${nm_CFLAGS}
+
+AM_CFLAGS = -rdynamic
+
+plugin_LTLIBRARIES = libstrongswan-nm.la
+libstrongswan_nm_la_SOURCES = \
+ nm_plugin.h nm_plugin.c nm_service.h nm_service.c
+libstrongswan_nm_la_LDFLAGS = -module
+libstrongswan_nm_la_LIBADD = ${nm_LIBS}
+
--- /dev/null
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#include "nm_plugin.h"
+#include "nm_service.h"
+
+#include <daemon.h>
+#include <processing/jobs/callback_job.h>
+
+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;
+
+ GMainLoop *loop;
+};
+
+/**
+ * NM plugin processing routine, creates and handles NMVPNPlugin
+ */
+static job_requeue_t run(private_nm_plugin_t *this)
+{
+ NMStrongswanPlugin *plugin;
+ GMainLoop *loop;
+
+ plugin = nm_strongswan_plugin_new();
+
+ this->loop = loop = g_main_loop_new(NULL, FALSE);
+ g_main_loop_run(loop);
+
+ g_main_loop_unref(loop);
+ g_object_unref(plugin);
+
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_nm_plugin_t *this)
+{
+ if (this->loop)
+ {
+ g_main_loop_quit(this->loop);
+ }
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *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);
+ }
+
+ charon->processor->queue_job(charon->processor,
+ (job_t*)callback_job_create((callback_job_cb_t)run, this, NULL, NULL));
+
+ return &this->public.plugin;
+}
+
--- /dev/null
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+/**
+ * @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;
+};
+
+/**
+ * Create a nm_plugin instance.
+ */
+plugin_t *plugin_create();
+
+#endif /* NM_PLUGIN_H_ @}*/
--- /dev/null
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#include <nm-setting-vpn.h>
+#include <nm-setting-vpn-properties.h>
+#include "nm_service.h"
+
+#include <daemon.h>
+#include <utils/host.h>
+#include <utils/identification.h>
+#include <config/peer_cfg.h>
+
+#include <stdio.h>
+
+#define CONFIG_NAME "NetworkManager"
+
+G_DEFINE_TYPE(NMStrongswanPlugin, nm_strongswan_plugin, NM_TYPE_VPN_PLUGIN)
+
+/**
+ * Private data of NMStrongswanPlugin
+ */
+typedef struct {
+ bus_listener_t listener;
+ ike_sa_t *ike_sa;
+ NMVPNPlugin *plugin;
+} NMStrongswanPluginPrivate;
+
+#define NM_STRONGSWAN_PLUGIN_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+ NM_TYPE_STRONGSWAN_PLUGIN, NMStrongswanPluginPrivate))
+
+/**
+ * convert a traffic selector address range to subnet and its mask.
+ */
+static u_int ts2subnet(traffic_selector_t* ts, u_int8_t *mask)
+{
+ /* there is no way to do this cleanly, as the address range may
+ * be anything else but a subnet. We use from_addr as subnet
+ * and try to calculate a usable subnet mask.
+ */
+ int byte, bit, net;
+ bool found = FALSE;
+ chunk_t from, to;
+ size_t size = (ts->get_type(ts) == TS_IPV4_ADDR_RANGE) ? 4 : 16;
+
+ from = ts->get_from_address(ts);
+ to = ts->get_to_address(ts);
+
+ *mask = (size * 8);
+ /* go trough all bits of the addresses, beginning in the front.
+ * as long as they are equal, the subnet gets larger
+ */
+ for (byte = 0; byte < size; byte++)
+ {
+ for (bit = 7; bit >= 0; bit--)
+ {
+ if ((1<<bit & from.ptr[byte]) != (1<<bit & to.ptr[byte]))
+ {
+ *mask = ((7 - bit) + (byte * 8));
+ found = TRUE;
+ break;
+ }
+ }
+ if (found)
+ {
+ break;
+ }
+ }
+ net = *(u_int32_t*)from.ptr;
+ chunk_free(&from);
+ chunk_free(&to);
+ return net;
+}
+
+/**
+ * signal IPv4 config to NM, set connection as established
+ */
+static void signal_ipv4_config(NMVPNPlugin *plugin, child_sa_t *child_sa)
+{
+ linked_list_t *list;
+ traffic_selector_t *ts = NULL;
+ enumerator_t *enumerator;
+
+ list = child_sa->get_traffic_selectors(child_sa, FALSE);
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &ts))
+ {
+ GValue *val;
+ GHashTable *config;
+ u_int8_t mask;
+
+ config = g_hash_table_new(g_str_hash, g_str_equal);
+
+ val = g_slice_new0(GValue);
+ g_value_init(val, G_TYPE_UINT);
+ g_value_set_uint(val, ts2subnet(ts, &mask));
+ 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, mask);
+ g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val);
+
+ nm_vpn_plugin_set_ip4_config(plugin, config);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Bus listen function to wait for SA establishing
+ */
+bool listen_bus(bus_listener_t *listener, signal_t signal, level_t level,
+ int thread, ike_sa_t *ike_sa, void *data,
+ char* format, va_list args)
+{
+ NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
+
+ if (private->ike_sa == ike_sa)
+ {
+ switch (signal)
+ {
+ case CHD_UP_SUCCESS:
+ if (data)
+ {
+ signal_ipv4_config(private->plugin, (child_sa_t*)data);
+ return FALSE;
+ }
+ /* FALL */
+ case IKE_UP_FAILED:
+ case CHD_UP_FAILED:
+ nm_vpn_plugin_failure(private->plugin,
+ NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
+ /* TODO: NM does not react on this failure!? So additionaly
+ * reset state */
+ nm_vpn_plugin_set_state(private->plugin,
+ NM_VPN_SERVICE_STATE_STOPPED);
+ return FALSE;
+ default:
+ break;
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Read a string from a hash table using a given key
+ */
+static char* get_str(GHashTable *hash, char *key)
+{
+ GValue *value;
+
+ value = g_hash_table_lookup(hash, key);
+ if (G_VALUE_TYPE (value) == G_TYPE_STRING)
+ {
+ return (char*)g_value_get_string(value);
+ }
+ return NULL;
+}
+
+/**
+ * Connect function called from NM via DBUS
+ */
+static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
+ GError **err)
+{
+ NMSettingVPNProperties *properties;
+ identification_t *user = NULL;
+ char *address, *str;
+ ike_cfg_t *ike_cfg;
+ peer_cfg_t *peer_cfg;
+ child_cfg_t *child_cfg;
+ traffic_selector_t *ts;
+ ike_sa_t *ike_sa;
+
+ /**
+ * Read parameters
+ */
+ properties = NM_SETTING_VPN_PROPERTIES(
+ nm_connection_get_setting(connection, NM_TYPE_SETTING_VPN_PROPERTIES));
+
+ if (!properties)
+ {
+ g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+ "%s", "Invalid arguments.");
+ return FALSE;
+ }
+
+ DBG2(DBG_CFG, "received NetworkManager connection: %s",
+ nm_setting_to_string(NM_SETTING(properties)));
+
+ str = get_str(properties->data, "user");
+ if (str)
+ {
+ user = identification_create_from_string(str);
+ }
+ if (!user)
+ {
+ g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+ "Username '%s' invalid.", str);
+ return FALSE;
+ }
+ address = get_str(properties->data, "address");
+ if (!address || !*address)
+ {
+ g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+ "Gateway address missing.");
+ return FALSE;
+ }
+
+ /**
+ * Set up configurations
+ */
+ ike_cfg = ike_cfg_create(TRUE, TRUE, "0.0.0.0", address);
+ ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+ peer_cfg = peer_cfg_create(CONFIG_NAME, 2, ike_cfg, user,
+ identification_create_from_encoding(ID_ANY, chunk_empty),
+ CERT_SEND_IF_ASKED, UNIQUE_REPLACE, CONF_AUTH_PUBKEY,
+ 0, 0, 1, /* EAP method, vendor, keyingtries */
+ 18000, 0, /* rekey 5h, reauth none */
+ 600, 600, /* jitter, over 10min */
+ TRUE, 0, /* mobike, DPD */
+ host_create_from_string("0.0.0.0", 0), /* virtual ip */
+ NULL, FALSE, NULL, NULL); /* pool, mediation */
+ child_cfg = child_cfg_create(CONFIG_NAME,
+ 3600, 3000, /* lifetime 1h, rekey 50min */
+ 300, /* jitter 5min */
+ NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */
+ ACTION_NONE, ACTION_NONE, FALSE); /* ipcomp */
+ 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);
+
+ /**
+ * Start to initiate
+ */
+ 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);
+ }
+ else
+ {
+ peer_cfg->destroy(peer_cfg);
+ }
+ if (ike_sa->initiate(ike_sa, child_cfg) != SUCCESS)
+ {
+ 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;
+ }
+
+ /**
+ * Register listener
+ */
+ NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->ike_sa = ike_sa;
+ charon->bus->add_listener(charon->bus,
+ &NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->listener);
+ 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)
+{
+ return FALSE;
+}
+
+/**
+ * Disconnect called from NM via DBUS
+ */
+static gboolean disconnect(NMVPNPlugin *plugin, GError **err)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ u_int id;
+
+ enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ if (streq(CONFIG_NAME, ike_sa->get_name(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);
+ return FALSE;
+}
+
+/**
+ * Initializer
+ */
+static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
+{
+ NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->plugin = NM_VPN_PLUGIN(plugin);
+ NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->listener.signal = listen_bus;
+}
+
+/**
+ * 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(void)
+{
+ return (NMStrongswanPlugin *)g_object_new (
+ NM_TYPE_STRONGSWAN_PLUGIN, NM_VPN_PLUGIN_DBUS_SERVICE_NAME,
+ NM_DBUS_SERVICE_STRONGSWAN, NULL);
+}
+
--- /dev/null
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+/**
+ * @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>
+#undef TRUE
+#undef FALSE
+
+#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(void);
+
+#endif /* NM_SERVICE_H_ */