Integrate nm plugin directly in charon-nm.
authorTobias Brunner <tobias@strongswan.org>
Thu, 19 Apr 2012 14:40:21 +0000 (16:40 +0200)
committerTobias Brunner <tobias@strongswan.org>
Thu, 3 May 2012 11:57:03 +0000 (13:57 +0200)
21 files changed:
configure.in
src/charon-nm/Makefile.am
src/charon-nm/charon-nm.c
src/charon-nm/nm/nm_backend.c [new file with mode: 0644]
src/charon-nm/nm/nm_backend.h [new file with mode: 0644]
src/charon-nm/nm/nm_creds.c [new file with mode: 0644]
src/charon-nm/nm/nm_creds.h [new file with mode: 0644]
src/charon-nm/nm/nm_handler.c [new file with mode: 0644]
src/charon-nm/nm/nm_handler.h [new file with mode: 0644]
src/charon-nm/nm/nm_service.c [new file with mode: 0644]
src/charon-nm/nm/nm_service.h [new file with mode: 0644]
src/libcharon/Makefile.am
src/libcharon/plugins/nm/Makefile.am [deleted file]
src/libcharon/plugins/nm/nm_creds.c [deleted file]
src/libcharon/plugins/nm/nm_creds.h [deleted file]
src/libcharon/plugins/nm/nm_handler.c [deleted file]
src/libcharon/plugins/nm/nm_handler.h [deleted file]
src/libcharon/plugins/nm/nm_plugin.c [deleted file]
src/libcharon/plugins/nm/nm_plugin.h [deleted file]
src/libcharon/plugins/nm/nm_service.c [deleted file]
src/libcharon/plugins/nm/nm_service.h [deleted file]

index 786d47c..43f6640 100755 (executable)
@@ -37,7 +37,7 @@ ARG_WITH_SUBST([ipsecdir],           [${libexecdir%/}/ipsec], [set installation
 ARG_WITH_SUBST([ipseclibdir],        [${libdir%/}/ipsec], [set installation path for ipsec libraries])
 ARG_WITH_SUBST([plugindir],          [${ipseclibdir%/}/plugins], [set the installation path of plugins])
 ARG_WITH_SUBST([imcvdir],            [${ipseclibdir%/}/imcvs], [set the installation path of IMC and IMV dynamic librariers])
-ARG_WITH_SUBST([nm-ca-dir],          [/usr/share/ca-certificates], [directory the NM plugin uses to look up trusted root certificates])
+ARG_WITH_SUBST([nm-ca-dir],          [/usr/share/ca-certificates], [directory the NM backend uses to look up trusted root certificates])
 ARG_WITH_SUBST([linux-headers],      [\${top_srcdir}/src/include], [set directory of linux header files to use])
 ARG_WITH_SUBST([routing-table],      [220], [set routing table to use for IPsec routes])
 ARG_WITH_SUBST([routing-table-prio], [220], [set priority for IPsec routing table])
@@ -890,7 +890,6 @@ ADD_PLUGIN([tnccs-11],             [c charon])
 ADD_PLUGIN([tnccs-dynamic],        [c charon])
 ADD_PLUGIN([medsrv],               [c charon])
 ADD_PLUGIN([medcli],               [c charon])
-ADD_PLUGIN([nm],                   [c charon])
 ADD_PLUGIN([dhcp],                 [c charon])
 ADD_PLUGIN([android],              [c charon])
 ADD_PLUGIN([ha],                   [c charon])
@@ -972,7 +971,6 @@ 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_ANDROID, test x$android = xtrue)
 AM_CONDITIONAL(USE_MAEMO, test x$maemo = xtrue)
@@ -1215,7 +1213,6 @@ AC_OUTPUT(
        src/libcharon/plugins/sql/Makefile
        src/libcharon/plugins/medsrv/Makefile
        src/libcharon/plugins/medcli/Makefile
-       src/libcharon/plugins/nm/Makefile
        src/libcharon/plugins/addrblock/Makefile
        src/libcharon/plugins/uci/Makefile
        src/libcharon/plugins/ha/Makefile
index 41c94b7..80fc13b 100644 (file)
@@ -1,20 +1,26 @@
 ipsec_PROGRAMS = charon-nm
 
 charon_nm_SOURCES = \
-charon-nm.c
+charon-nm.c \
+nm/nm_backend.c nm/nm_backend.h \
+nm/nm_creds.c nm/nm_creds.h \
+nm/nm_handler.c nm/nm_handler.h \
+nm/nm_service.c nm/nm_service.h
 
 INCLUDES = \
        -I$(top_srcdir)/src/libstrongswan \
        -I$(top_srcdir)/src/libhydra \
-       -I$(top_srcdir)/src/libcharon
+       -I$(top_srcdir)/src/libcharon \
+       ${nm_CFLAGS}
 
 AM_CFLAGS = \
        -DIPSEC_DIR=\"${ipsecdir}\" \
        -DIPSEC_PIDDIR=\"${piddir}\" \
+       -DNM_CA_DIR=\"${nm_ca_dir}\" \
        -DPLUGINS=\""${nm_plugins}\""
 
 charon_nm_LDADD = \
        $(top_builddir)/src/libstrongswan/libstrongswan.la \
        $(top_builddir)/src/libhydra/libhydra.la \
        $(top_builddir)/src/libcharon/libcharon.la \
-       -lm $(PTHREADLIB) $(DLLIB)
+       -lm $(PTHREADLIB) $(DLLIB) ${nm_LIBS}
index 8b73f6a..16b0ed8 100644 (file)
@@ -31,6 +31,8 @@
 #include <utils/backtrace.h>
 #include <threading/thread.h>
 
+#include <nm/nm_backend.h>
+
 /**
  * Hook in library for debugging messages
  */
@@ -270,10 +272,17 @@ int main(int argc, char *argv[])
                goto deinit;
        }
 
+       /* load NM backend */
+       if (!nm_backend_init())
+       {
+               DBG1(DBG_DMN, "failed to initialize NetworkManager backend - aborting charon-nm");
+               goto deinit_nm;
+       }
+
        if (!drop_capabilities())
        {
                DBG1(DBG_DMN, "capability dropping failed - aborting charon-nm");
-               goto deinit;
+               goto deinit_nm;
        }
 
        /* add handler for SEGV and ILL,
@@ -299,6 +308,8 @@ int main(int argc, char *argv[])
 
        status = 0;
 
+deinit_nm:
+       nm_backend_deinit();
 deinit:
        libcharon_deinit();
        libhydra_deinit();
diff --git a/src/charon-nm/nm/nm_backend.c b/src/charon-nm/nm/nm_backend.c
new file mode 100644 (file)
index 0000000..19382a0
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * 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_service.h"
+#include "nm_creds.h"
+#include "nm_handler.h"
+
+#include <hydra.h>
+#include <daemon.h>
+#include <processing/jobs/callback_job.h>
+
+#define CAP_DAC_OVERRIDE 1
+
+typedef struct nm_backend_t nm_backend_t;
+
+/**
+ * Data for the NetworkManager backend.
+ */
+struct nm_backend_t {
+
+       /**
+        * 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;
+};
+
+/**
+ * Global (but private) instance of the NM backend.
+ */
+static nm_backend_t *nm_backend = NULL;
+
+/**
+ * NM plugin processing routine, creates and handles NMVPNPlugin
+ */
+static job_requeue_t run(nm_backend_t *this)
+{
+       this->loop = g_main_loop_new(NULL, FALSE);
+       g_main_loop_run(this->loop);
+       return JOB_REQUEUE_NONE;
+}
+
+/*
+ * see header file
+ */
+void nm_backend_deinit()
+{
+       nm_backend_t *this = nm_backend;
+
+       if (!this)
+       {
+               return;
+       }
+       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);
+       }
+       lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
+       hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
+       this->creds->destroy(this->creds);
+       this->handler->destroy(this->handler);
+       free(this);
+
+       nm_backend = NULL;
+}
+
+/*
+ * see header file
+ */
+bool nm_backend_init()
+{
+       nm_backend_t *this;
+
+       g_type_init ();
+       if (!g_thread_supported())
+       {
+               g_thread_init(NULL);
+       }
+
+       INIT(this,
+               .creds = nm_creds_create(),
+               .handler = nm_handler_create(),
+       );
+       this->plugin = nm_strongswan_plugin_new(this->creds, this->handler);
+       nm_backend = this;
+
+       hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
+       lib->credmgr->add_set(lib->credmgr, &this->creds->set);
+       if (!this->plugin)
+       {
+               DBG1(DBG_CFG, "DBUS binding failed");
+               nm_backend_deinit();
+               return FALSE;
+       }
+
+       /* bypass file permissions to read from users ssh-agent */
+       charon->keep_cap(charon, CAP_DAC_OVERRIDE);
+
+       lib->processor->queue_job(lib->processor,
+                               (job_t*)callback_job_create_with_prio((callback_job_cb_t)run,
+                                                                               this, NULL, NULL, JOB_PRIO_CRITICAL));
+       return TRUE;
+}
+
diff --git a/src/charon-nm/nm/nm_backend.h b/src/charon-nm/nm/nm_backend.h
new file mode 100644 (file)
index 0000000..bff9d4d
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * 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 charon-nm charon-nm
+ *
+ * @defgroup nm nm
+ * @ingroup charon-nm
+ *
+ * @defgroup nm_backend nm_backend
+ * @{ @ingroup nm
+ */
+
+#ifndef NM_BACKEND_H_
+#define NM_BACKEND_H_
+
+/**
+ * Initialize the NetworkManager backend.
+ *
+ * @return             TRUE, if initialization was successful
+ */
+bool nm_backend_init();
+
+/**
+ * Deinitialize the NetworkManager backend.
+ */
+void nm_backend_deinit();
+
+#endif /** NM_BACKEND_H_ @}*/
diff --git a/src/charon-nm/nm/nm_creds.c b/src/charon-nm/nm/nm_creds.c
new file mode 100644 (file)
index 0000000..f8fae95
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ * 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;
+
+       /**
+        * Private key decryption password / smartcard pin
+        */
+       char *keypass;
+
+       /**
+        * private key ID of smartcard key
+        */
+       chunk_t keyid;
+
+       /**
+        * 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;
+
+       INIT(data,
+               .this = this,
+               .id = id,
+               .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);
+}
+
+METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
+       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;
+}
+
+METHOD(credential_set_t, create_private_enumerator, enumerator_t*,
+       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;
+
+METHOD(enumerator_t, shared_enumerate, bool,
+       shared_enumerator_t *this, shared_key_t **key, id_match_t *me,
+       id_match_t *other)
+{
+       if (this->done)
+       {
+               return FALSE;
+       }
+       *key = this->key;
+       if (me)
+       {
+               *me = ID_MATCH_PERFECT;
+       }
+       if (other)
+       {
+               *other = ID_MATCH_ANY;
+       }
+       this->done = TRUE;
+       return TRUE;
+}
+
+METHOD(enumerator_t, shared_destroy, void,
+       shared_enumerator_t *this)
+{
+       this->key->destroy(this->key);
+       this->this->lock->unlock(this->this->lock);
+       free(this);
+}
+
+METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
+       private_nm_creds_t *this, shared_key_type_t type, identification_t *me,
+       identification_t *other)
+{
+       shared_enumerator_t *enumerator;
+       chunk_t key;
+
+       this->lock->read_lock(this->lock);
+
+       switch (type)
+       {
+               case SHARED_EAP:
+               case SHARED_IKE:
+                       if (!this->pass || !this->user)
+                       {
+                               goto no_secret;
+                       }
+                       if (me && !me->equals(me, this->user))
+                       {
+                               goto no_secret;
+                       }
+                       key = chunk_create(this->pass, strlen(this->pass));
+                       break;
+               case SHARED_PRIVATE_KEY_PASS:
+                       if (!this->keypass)
+                       {
+                               goto no_secret;
+                       }
+                       key = chunk_create(this->keypass, strlen(this->keypass));
+                       break;
+               case SHARED_PIN:
+                       if (!this->keypass || !me ||
+                               !chunk_equals(me->get_encoding(me), this->keyid))
+                       {
+                               goto no_secret;
+                       }
+                       key = chunk_create(this->keypass, strlen(this->keypass));
+                       break;
+               default:
+                       goto no_secret;
+       }
+
+       INIT(enumerator,
+               .public = {
+                       .enumerate = (void*)_shared_enumerate,
+                       .destroy = _shared_destroy,
+               },
+               .this = this,
+       );
+       enumerator->key = shared_key_create(type, chunk_clone(key));
+       return &enumerator->public;
+
+no_secret:
+       this->lock->unlock(this->lock);
+       return NULL;
+}
+
+METHOD(nm_creds_t, add_certificate, void,
+       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);
+       }
+}
+
+METHOD(nm_creds_t, load_ca_dir, void,
+       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);
+       }
+}
+
+METHOD(nm_creds_t, set_username_password, void,
+       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 = strdupnull(password);
+       this->lock->unlock(this->lock);
+}
+
+METHOD(nm_creds_t, set_key_password, void,
+       private_nm_creds_t *this, char *password)
+{
+       this->lock->write_lock(this->lock);
+       free(this->keypass);
+       this->keypass = strdupnull(password);
+       this->lock->unlock(this->lock);
+}
+
+METHOD(nm_creds_t, set_pin, void,
+       private_nm_creds_t *this, chunk_t keyid, char *pin)
+{
+       this->lock->write_lock(this->lock);
+       free(this->keypass);
+       free(this->keyid.ptr);
+       this->keypass = strdupnull(pin);
+       this->keyid = chunk_clone(keyid);
+       this->lock->unlock(this->lock);
+}
+
+METHOD(nm_creds_t, set_cert_and_key, void,
+       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);
+}
+
+METHOD(nm_creds_t, clear, void,
+       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);
+       free(this->keypass);
+       free(this->keyid.ptr);
+       DESTROY_IF(this->usercert);
+       DESTROY_IF(this->key);
+       this->key = NULL;
+       this->usercert = NULL;
+       this->pass = NULL;
+       this->user = NULL;
+       this->keypass = NULL;
+       this->keyid = chunk_empty;
+}
+
+METHOD(nm_creds_t, destroy, void,
+       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;
+
+       INIT(this,
+               .public = {
+                       .set = {
+                               .create_private_enumerator = _create_private_enumerator,
+                               .create_cert_enumerator = _create_cert_enumerator,
+                               .create_shared_enumerator = _create_shared_enumerator,
+                               .create_cdp_enumerator = (void*)return_null,
+                               .cache_cert = (void*)nop,
+                       },
+                       .add_certificate = _add_certificate,
+                       .load_ca_dir = _load_ca_dir,
+                       .set_username_password = _set_username_password,
+                       .set_key_password = _set_key_password,
+                       .set_pin = _set_pin,
+                       .set_cert_and_key = _set_cert_and_key,
+                       .clear = _clear,
+                       .destroy = _destroy,
+               },
+               .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+               .certs = linked_list_create(),
+       );
+       return &this->public;
+}
+
diff --git a/src/charon-nm/nm/nm_creds.h b/src/charon-nm/nm/nm_creds.h
new file mode 100644 (file)
index 0000000..91f645c
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 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 passphrase to use for private key decryption.
+        *
+        * @param password      password to use
+        */
+       void (*set_key_password)(nm_creds_t *this, char *password);
+
+       /**
+        * Set the PIN to unlock a smartcard.
+        *
+        * @param keyid         keyid of the smartcard key
+        * @param pin           PIN
+        */
+       void (*set_pin)(nm_creds_t *this, chunk_t keyid, char *pin);
+
+       /**
+        * Set the certificate and private key to use for client authentication.
+        *
+        * @param cert          client certificate
+        * @param key           associated private key
+        */
+       void (*set_cert_and_key)(nm_creds_t *this, certificate_t *cert,
+                                                        private_key_t *key);
+
+       /**
+        * Clear the stored credentials.
+        */
+       void (*clear)(nm_creds_t *this);
+
+       /**
+        * Destroy a nm_creds instance.
+        */
+       void (*destroy)(nm_creds_t *this);
+};
+
+/**
+ * Create a nm_creds instance.
+ */
+nm_creds_t *nm_creds_create();
+
+#endif /** NM_CREDS_H_ @}*/
diff --git a/src/charon-nm/nm/nm_handler.c b/src/charon-nm/nm/nm_handler.c
new file mode 100644 (file)
index 0000000..408129e
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * 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;
+};
+
+METHOD(attribute_handler_t, handle, bool,
+       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;
+}
+
+METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
+       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;
+}
+
+METHOD(nm_handler_t, create_enumerator, enumerator_t*,
+       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);
+}
+
+METHOD(nm_handler_t, reset, void,
+       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);
+       }
+}
+
+METHOD(nm_handler_t, destroy, void,
+       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;
+
+       INIT(this,
+               .public = {
+                       .handler = {
+                               .handle = _handle,
+                               .release = nop,
+                               .create_attribute_enumerator = _create_attribute_enumerator,
+                       },
+                       .create_enumerator = _create_enumerator,
+                       .reset = _reset,
+                       .destroy = _destroy,
+               },
+               .dns = linked_list_create(),
+               .nbns = linked_list_create(),
+       );
+
+       return &this->public;
+}
+
diff --git a/src/charon-nm/nm/nm_handler.h b/src/charon-nm/nm/nm_handler.h
new file mode 100644 (file)
index 0000000..bb35ce7
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup nm_handler nm_handler
+ * @{ @ingroup nm
+ */
+
+#ifndef NM_HANDLER_H_
+#define NM_HANDLER_H_
+
+#include <attributes/attribute_handler.h>
+
+typedef struct nm_handler_t nm_handler_t;
+
+/**
+ * Handles DNS/NBNS attributes to pass to NM.
+ */
+struct nm_handler_t {
+
+       /**
+        * Implements attribute handler interface
+        */
+       attribute_handler_t handler;
+
+       /**
+        * Create an enumerator over received attributes of a given kind.
+        *
+        * @param type          type of attributes to enumerate
+        * @return                      enumerator over attribute data (chunk_t)
+        */
+       enumerator_t* (*create_enumerator)(nm_handler_t *this,
+                                                                          configuration_attribute_type_t type);
+       /**
+        * Reset state, flush all received attributes.
+        */
+       void (*reset)(nm_handler_t *this);
+
+       /**
+        * Destroy a nm_handler_t.
+        */
+       void (*destroy)(nm_handler_t *this);
+};
+
+/**
+ * Create a nm_handler instance.
+ */
+nm_handler_t *nm_handler_create();
+
+#endif /** NM_HANDLER_H_ @}*/
diff --git a/src/charon-nm/nm/nm_service.c b/src/charon-nm/nm/nm_service.c
new file mode 100644 (file)
index 0000000..64da53f
--- /dev/null
@@ -0,0 +1,712 @@
+/*
+ * 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;
+       nm_handler_t *handler;
+
+       config = g_hash_table_new(g_str_hash, g_str_equal);
+       me = ike_sa->get_my_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;
+}
+
+/**
+ * Find a certificate for which we have a private key on a smartcard
+ */
+static identification_t *find_smartcard_key(NMStrongswanPluginPrivate *priv,
+                                                                                       char *pin)
+{
+       enumerator_t *enumerator, *sans;
+       identification_t *id = NULL;
+       certificate_t *cert;
+       x509_t *x509;
+       private_key_t *key;
+       chunk_t keyid;
+
+       enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
+                                                                                       CERT_X509, KEY_ANY, NULL, FALSE);
+       while (enumerator->enumerate(enumerator, &cert))
+       {
+               x509 = (x509_t*)cert;
+
+               /* there might be a lot of certificates, filter them by usage */
+               if ((x509->get_flags(x509) & X509_CLIENT_AUTH) &&
+                       !(x509->get_flags(x509) & X509_CA))
+               {
+                       keyid = x509->get_subjectKeyIdentifier(x509);
+                       if (keyid.ptr)
+                       {
+                               /* try to find a private key by the certificate keyid */
+                               priv->creds->set_pin(priv->creds, keyid, pin);
+                               key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
+                                                               KEY_ANY, BUILD_PKCS11_KEYID, keyid, BUILD_END);
+                               if (key)
+                               {
+                                       /* prefer a more convenient subjectAltName */
+                                       sans = x509->create_subjectAltName_enumerator(x509);
+                                       if (!sans->enumerate(sans, &id))
+                                       {
+                                               id = cert->get_subject(cert);
+                                       }
+                                       id = id->clone(id);
+                                       sans->destroy(sans);
+
+                                       DBG1(DBG_CFG, "using smartcard certificate '%Y'", id);
+                                       priv->creds->set_cert_and_key(priv->creds,
+                                                                                                 cert->get_ref(cert), key);
+                                       break;
+                               }
+                       }
+               }
+       }
+       enumerator->destroy(enumerator);
+       return id;
+}
+
+/**
+ * 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, smartcard = 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;
+               }
+               else if (streq(str, "smartcard"))
+               {
+                       auth_class = AUTH_CLASS_PUBKEY;
+                       smartcard = TRUE;
+               }
+       }
+
+       /**
+        * 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)
+       {
+               if (smartcard)
+               {
+                       char *pin;
+
+                       pin = (char*)nm_setting_vpn_get_secret(vpn, "password");
+                       if (pin)
+                       {
+                               user = find_smartcard_key(priv, pin);
+                       }
+                       if (!user)
+                       {
+                               g_set_error(err, NM_VPN_PLUGIN_ERROR,
+                                                       NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+                                                       "no usable smartcard certificate found.");
+                               gateway->destroy(gateway);
+                               return FALSE;
+                       }
+               }
+               /* ... or certificate/private key authenitcation */
+               else if ((str = nm_setting_vpn_get_data_item(vpn, "usercert")))
+               {
+                       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)
+                       {
+                               char *secret;
+
+                               secret = (char*)nm_setting_vpn_get_secret(vpn, "password");
+                               if (secret)
+                               {
+                                       priv->creds->set_key_password(priv->creds, secret);
+                               }
+                               private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
+                                                               KEY_RSA, BUILD_FROM_FILE, str, 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, IKEV2, ike_cfg,
+                                       CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
+                                       36000, 0, /* rekey 10h, reauth none */
+                                       600, 600, /* jitter, over 10min */
+                                       TRUE, FALSE, 0, /* mobike, aggressive, 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, ACTION_NONE, ipcomp,
+                                                                0, 0, NULL, NULL, 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)
+       {
+               peer_cfg->destroy(peer_cfg);
+               g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
+                                       "IKE version not supported.");
+               return FALSE;
+       }
+       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
+        */
+       child_cfg->get_ref(child_cfg);
+       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;
+
+                               /* try to load/decrypt the private key */
+                               key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
+                                                               KEY_RSA, BUILD_FROM_FILE, path, BUILD_END);
+                               if (key)
+                               {
+                                       key->destroy(key);
+                                       return FALSE;
+                               }
+                       }
+               }
+               else if streq(method, "smartcard")
+               {
+                       if (nm_setting_vpn_get_secret(settings, "password"))
+                       {
+                               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, TRUE);
+       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, 0);
+                       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, 0, sizeof(listener_t));
+       priv->listener.child_updown = child_updown;
+       priv->listener.ike_rekey = ike_rekey;
+}
+
+/**
+ * Class constructor
+ */
+static void nm_strongswan_plugin_class_init(
+                                                                       NMStrongswanPluginClass *strongswan_class)
+{
+       NMVPNPluginClass *parent_class = NM_VPN_PLUGIN_CLASS(strongswan_class);
+
+       g_type_class_add_private(G_OBJECT_CLASS(strongswan_class),
+                                                        sizeof(NMStrongswanPluginPrivate));
+       parent_class->connect = connect_;
+       parent_class->need_secrets = need_secrets;
+       parent_class->disconnect = disconnect;
+}
+
+/**
+ * Object constructor
+ */
+NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds,
+                                                                                        nm_handler_t *handler)
+{
+       NMStrongswanPlugin *plugin = (NMStrongswanPlugin *)g_object_new (
+                                       NM_TYPE_STRONGSWAN_PLUGIN,
+                                       NM_VPN_PLUGIN_DBUS_SERVICE_NAME, NM_DBUS_SERVICE_STRONGSWAN,
+                                       NULL);
+       if (plugin)
+       {
+               NMStrongswanPluginPrivate *priv;
+
+               priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
+               priv->creds = creds;
+               priv->handler = handler;
+               priv->name = NULL;
+       }
+       return plugin;
+}
+
diff --git a/src/charon-nm/nm/nm_service.h b/src/charon-nm/nm/nm_service.h
new file mode 100644 (file)
index 0000000..828d1a4
--- /dev/null
@@ -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.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_ @}*/
index 8b16de1..e31d532 100755 (executable)
@@ -444,13 +444,6 @@ if MONOLITHIC
 endif
 endif
 
-if USE_NM
-  SUBDIRS += plugins/nm
-if MONOLITHIC
-  libcharon_la_LIBADD += plugins/nm/libstrongswan-nm.la
-endif
-endif
-
 if USE_DHCP
   SUBDIRS += plugins/dhcp
 if MONOLITHIC
diff --git a/src/libcharon/plugins/nm/Makefile.am b/src/libcharon/plugins/nm/Makefile.am
deleted file mode 100644 (file)
index 8e12a72..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-
-INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
-       -I$(top_srcdir)/src/libcharon ${nm_CFLAGS}
-
-AM_CFLAGS = -rdynamic \
-  -DNM_CA_DIR=\"${nm_ca_dir}\"
-
-if MONOLITHIC
-noinst_LTLIBRARIES = libstrongswan-nm.la
-else
-plugin_LTLIBRARIES = libstrongswan-nm.la
-endif
-
-libstrongswan_nm_la_SOURCES = \
-       nm_plugin.h nm_plugin.c \
-       nm_service.h nm_service.c \
-       nm_creds.h nm_creds.c \
-       nm_handler.h nm_handler.c
-
-libstrongswan_nm_la_LDFLAGS = -module -avoid-version
-libstrongswan_nm_la_LIBADD  = ${nm_LIBS}
diff --git a/src/libcharon/plugins/nm/nm_creds.c b/src/libcharon/plugins/nm/nm_creds.c
deleted file mode 100644 (file)
index f8fae95..0000000
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * 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;
-
-       /**
-        * Private key decryption password / smartcard pin
-        */
-       char *keypass;
-
-       /**
-        * private key ID of smartcard key
-        */
-       chunk_t keyid;
-
-       /**
-        * 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;
-
-       INIT(data,
-               .this = this,
-               .id = id,
-               .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);
-}
-
-METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
-       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;
-}
-
-METHOD(credential_set_t, create_private_enumerator, enumerator_t*,
-       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;
-
-METHOD(enumerator_t, shared_enumerate, bool,
-       shared_enumerator_t *this, shared_key_t **key, id_match_t *me,
-       id_match_t *other)
-{
-       if (this->done)
-       {
-               return FALSE;
-       }
-       *key = this->key;
-       if (me)
-       {
-               *me = ID_MATCH_PERFECT;
-       }
-       if (other)
-       {
-               *other = ID_MATCH_ANY;
-       }
-       this->done = TRUE;
-       return TRUE;
-}
-
-METHOD(enumerator_t, shared_destroy, void,
-       shared_enumerator_t *this)
-{
-       this->key->destroy(this->key);
-       this->this->lock->unlock(this->this->lock);
-       free(this);
-}
-
-METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
-       private_nm_creds_t *this, shared_key_type_t type, identification_t *me,
-       identification_t *other)
-{
-       shared_enumerator_t *enumerator;
-       chunk_t key;
-
-       this->lock->read_lock(this->lock);
-
-       switch (type)
-       {
-               case SHARED_EAP:
-               case SHARED_IKE:
-                       if (!this->pass || !this->user)
-                       {
-                               goto no_secret;
-                       }
-                       if (me && !me->equals(me, this->user))
-                       {
-                               goto no_secret;
-                       }
-                       key = chunk_create(this->pass, strlen(this->pass));
-                       break;
-               case SHARED_PRIVATE_KEY_PASS:
-                       if (!this->keypass)
-                       {
-                               goto no_secret;
-                       }
-                       key = chunk_create(this->keypass, strlen(this->keypass));
-                       break;
-               case SHARED_PIN:
-                       if (!this->keypass || !me ||
-                               !chunk_equals(me->get_encoding(me), this->keyid))
-                       {
-                               goto no_secret;
-                       }
-                       key = chunk_create(this->keypass, strlen(this->keypass));
-                       break;
-               default:
-                       goto no_secret;
-       }
-
-       INIT(enumerator,
-               .public = {
-                       .enumerate = (void*)_shared_enumerate,
-                       .destroy = _shared_destroy,
-               },
-               .this = this,
-       );
-       enumerator->key = shared_key_create(type, chunk_clone(key));
-       return &enumerator->public;
-
-no_secret:
-       this->lock->unlock(this->lock);
-       return NULL;
-}
-
-METHOD(nm_creds_t, add_certificate, void,
-       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);
-       }
-}
-
-METHOD(nm_creds_t, load_ca_dir, void,
-       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);
-       }
-}
-
-METHOD(nm_creds_t, set_username_password, void,
-       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 = strdupnull(password);
-       this->lock->unlock(this->lock);
-}
-
-METHOD(nm_creds_t, set_key_password, void,
-       private_nm_creds_t *this, char *password)
-{
-       this->lock->write_lock(this->lock);
-       free(this->keypass);
-       this->keypass = strdupnull(password);
-       this->lock->unlock(this->lock);
-}
-
-METHOD(nm_creds_t, set_pin, void,
-       private_nm_creds_t *this, chunk_t keyid, char *pin)
-{
-       this->lock->write_lock(this->lock);
-       free(this->keypass);
-       free(this->keyid.ptr);
-       this->keypass = strdupnull(pin);
-       this->keyid = chunk_clone(keyid);
-       this->lock->unlock(this->lock);
-}
-
-METHOD(nm_creds_t, set_cert_and_key, void,
-       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);
-}
-
-METHOD(nm_creds_t, clear, void,
-       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);
-       free(this->keypass);
-       free(this->keyid.ptr);
-       DESTROY_IF(this->usercert);
-       DESTROY_IF(this->key);
-       this->key = NULL;
-       this->usercert = NULL;
-       this->pass = NULL;
-       this->user = NULL;
-       this->keypass = NULL;
-       this->keyid = chunk_empty;
-}
-
-METHOD(nm_creds_t, destroy, void,
-       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;
-
-       INIT(this,
-               .public = {
-                       .set = {
-                               .create_private_enumerator = _create_private_enumerator,
-                               .create_cert_enumerator = _create_cert_enumerator,
-                               .create_shared_enumerator = _create_shared_enumerator,
-                               .create_cdp_enumerator = (void*)return_null,
-                               .cache_cert = (void*)nop,
-                       },
-                       .add_certificate = _add_certificate,
-                       .load_ca_dir = _load_ca_dir,
-                       .set_username_password = _set_username_password,
-                       .set_key_password = _set_key_password,
-                       .set_pin = _set_pin,
-                       .set_cert_and_key = _set_cert_and_key,
-                       .clear = _clear,
-                       .destroy = _destroy,
-               },
-               .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
-               .certs = linked_list_create(),
-       );
-       return &this->public;
-}
-
diff --git a/src/libcharon/plugins/nm/nm_creds.h b/src/libcharon/plugins/nm/nm_creds.h
deleted file mode 100644 (file)
index 91f645c..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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 passphrase to use for private key decryption.
-        *
-        * @param password      password to use
-        */
-       void (*set_key_password)(nm_creds_t *this, char *password);
-
-       /**
-        * Set the PIN to unlock a smartcard.
-        *
-        * @param keyid         keyid of the smartcard key
-        * @param pin           PIN
-        */
-       void (*set_pin)(nm_creds_t *this, chunk_t keyid, char *pin);
-
-       /**
-        * Set the certificate and private key to use for client authentication.
-        *
-        * @param cert          client certificate
-        * @param key           associated private key
-        */
-       void (*set_cert_and_key)(nm_creds_t *this, certificate_t *cert,
-                                                        private_key_t *key);
-
-       /**
-        * Clear the stored credentials.
-        */
-       void (*clear)(nm_creds_t *this);
-
-       /**
-        * Destroy a nm_creds instance.
-        */
-       void (*destroy)(nm_creds_t *this);
-};
-
-/**
- * Create a nm_creds instance.
- */
-nm_creds_t *nm_creds_create();
-
-#endif /** NM_CREDS_H_ @}*/
diff --git a/src/libcharon/plugins/nm/nm_handler.c b/src/libcharon/plugins/nm/nm_handler.c
deleted file mode 100644 (file)
index 408129e..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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;
-};
-
-METHOD(attribute_handler_t, handle, bool,
-       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;
-}
-
-METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
-       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;
-}
-
-METHOD(nm_handler_t, create_enumerator, enumerator_t*,
-       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);
-}
-
-METHOD(nm_handler_t, reset, void,
-       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);
-       }
-}
-
-METHOD(nm_handler_t, destroy, void,
-       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;
-
-       INIT(this,
-               .public = {
-                       .handler = {
-                               .handle = _handle,
-                               .release = nop,
-                               .create_attribute_enumerator = _create_attribute_enumerator,
-                       },
-                       .create_enumerator = _create_enumerator,
-                       .reset = _reset,
-                       .destroy = _destroy,
-               },
-               .dns = linked_list_create(),
-               .nbns = linked_list_create(),
-       );
-
-       return &this->public;
-}
-
diff --git a/src/libcharon/plugins/nm/nm_handler.h b/src/libcharon/plugins/nm/nm_handler.h
deleted file mode 100644 (file)
index bb35ce7..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup nm_handler nm_handler
- * @{ @ingroup nm
- */
-
-#ifndef NM_HANDLER_H_
-#define NM_HANDLER_H_
-
-#include <attributes/attribute_handler.h>
-
-typedef struct nm_handler_t nm_handler_t;
-
-/**
- * Handles DNS/NBNS attributes to pass to NM.
- */
-struct nm_handler_t {
-
-       /**
-        * Implements attribute handler interface
-        */
-       attribute_handler_t handler;
-
-       /**
-        * Create an enumerator over received attributes of a given kind.
-        *
-        * @param type          type of attributes to enumerate
-        * @return                      enumerator over attribute data (chunk_t)
-        */
-       enumerator_t* (*create_enumerator)(nm_handler_t *this,
-                                                                          configuration_attribute_type_t type);
-       /**
-        * Reset state, flush all received attributes.
-        */
-       void (*reset)(nm_handler_t *this);
-
-       /**
-        * Destroy a nm_handler_t.
-        */
-       void (*destroy)(nm_handler_t *this);
-};
-
-/**
- * Create a nm_handler instance.
- */
-nm_handler_t *nm_handler_create();
-
-#endif /** NM_HANDLER_H_ @}*/
diff --git a/src/libcharon/plugins/nm/nm_plugin.c b/src/libcharon/plugins/nm/nm_plugin.c
deleted file mode 100644 (file)
index 84b7c81..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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 <hydra.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;
-}
-
-METHOD(plugin_t, get_name, char*,
-       private_nm_plugin_t *this)
-{
-       return "nm";
-}
-
-METHOD(plugin_t, destroy, void,
-       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);
-       }
-       lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
-       hydra->attributes->remove_handler(hydra->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;
-
-       g_type_init ();
-       if (!g_thread_supported())
-       {
-               g_thread_init(NULL);
-       }
-
-       INIT(this,
-               .public = {
-                       .plugin = {
-                               .get_name = _get_name,
-                               .reload = (void*)return_false,
-                               .destroy = _destroy,
-                       },
-               },
-               .creds = nm_creds_create(),
-               .handler = nm_handler_create(),
-       );
-       this->plugin = nm_strongswan_plugin_new(this->creds, this->handler);
-
-       hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
-       lib->credmgr->add_set(lib->credmgr, &this->creds->set);
-       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);
-
-       lib->processor->queue_job(lib->processor,
-                               (job_t*)callback_job_create_with_prio((callback_job_cb_t)run,
-                                                                               this, NULL, NULL, JOB_PRIO_CRITICAL));
-
-       return &this->public.plugin;
-}
-
diff --git a/src/libcharon/plugins/nm/nm_plugin.h b/src/libcharon/plugins/nm/nm_plugin.h
deleted file mode 100644 (file)
index b64b3ed..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup nm nm
- * @ingroup cplugins
- *
- * @defgroup nm_plugin nm_plugin
- * @{ @ingroup nm
- */
-
-#ifndef NM_PLUGIN_H_
-#define NM_PLUGIN_H_
-
-#include <plugins/plugin.h>
-
-typedef struct nm_plugin_t nm_plugin_t;
-
-/**
- * NetworkManager integration plugin.
- */
-struct nm_plugin_t {
-
-       /**
-        * implements plugin interface
-        */
-       plugin_t plugin;
-};
-
-#endif /** NM_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c
deleted file mode 100644 (file)
index d51b699..0000000
+++ /dev/null
@@ -1,712 +0,0 @@
-/*
- * 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;
-       nm_handler_t *handler;
-
-       config = g_hash_table_new(g_str_hash, g_str_equal);
-       me = ike_sa->get_my_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;
-}
-
-/**
- * Find a certificate for which we have a private key on a smartcard
- */
-static identification_t *find_smartcard_key(NMStrongswanPluginPrivate *priv,
-                                                                                       char *pin)
-{
-       enumerator_t *enumerator, *sans;
-       identification_t *id = NULL;
-       certificate_t *cert;
-       x509_t *x509;
-       private_key_t *key;
-       chunk_t keyid;
-
-       enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
-                                                                                       CERT_X509, KEY_ANY, NULL, FALSE);
-       while (enumerator->enumerate(enumerator, &cert))
-       {
-               x509 = (x509_t*)cert;
-
-               /* there might be a lot of certificates, filter them by usage */
-               if ((x509->get_flags(x509) & X509_CLIENT_AUTH) &&
-                       !(x509->get_flags(x509) & X509_CA))
-               {
-                       keyid = x509->get_subjectKeyIdentifier(x509);
-                       if (keyid.ptr)
-                       {
-                               /* try to find a private key by the certificate keyid */
-                               priv->creds->set_pin(priv->creds, keyid, pin);
-                               key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
-                                                               KEY_ANY, BUILD_PKCS11_KEYID, keyid, BUILD_END);
-                               if (key)
-                               {
-                                       /* prefer a more convenient subjectAltName */
-                                       sans = x509->create_subjectAltName_enumerator(x509);
-                                       if (!sans->enumerate(sans, &id))
-                                       {
-                                               id = cert->get_subject(cert);
-                                       }
-                                       id = id->clone(id);
-                                       sans->destroy(sans);
-
-                                       DBG1(DBG_CFG, "using smartcard certificate '%Y'", id);
-                                       priv->creds->set_cert_and_key(priv->creds,
-                                                                                                 cert->get_ref(cert), key);
-                                       break;
-                               }
-                       }
-               }
-       }
-       enumerator->destroy(enumerator);
-       return id;
-}
-
-/**
- * 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, smartcard = 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;
-               }
-               else if (streq(str, "smartcard"))
-               {
-                       auth_class = AUTH_CLASS_PUBKEY;
-                       smartcard = TRUE;
-               }
-       }
-
-       /**
-        * 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)
-       {
-               if (smartcard)
-               {
-                       char *pin;
-
-                       pin = (char*)nm_setting_vpn_get_secret(vpn, "password");
-                       if (pin)
-                       {
-                               user = find_smartcard_key(priv, pin);
-                       }
-                       if (!user)
-                       {
-                               g_set_error(err, NM_VPN_PLUGIN_ERROR,
-                                                       NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
-                                                       "no usable smartcard certificate found.");
-                               gateway->destroy(gateway);
-                               return FALSE;
-                       }
-               }
-               /* ... or certificate/private key authenitcation */
-               else if ((str = nm_setting_vpn_get_data_item(vpn, "usercert")))
-               {
-                       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)
-                       {
-                               char *secret;
-
-                               secret = (char*)nm_setting_vpn_get_secret(vpn, "password");
-                               if (secret)
-                               {
-                                       priv->creds->set_key_password(priv->creds, secret);
-                               }
-                               private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
-                                                               KEY_RSA, BUILD_FROM_FILE, str, 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, IKEV2, ike_cfg,
-                                       CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
-                                       36000, 0, /* rekey 10h, reauth none */
-                                       600, 600, /* jitter, over 10min */
-                                       TRUE, FALSE, 0, /* mobike, aggressive, 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, ACTION_NONE, ipcomp,
-                                                                0, 0, NULL, NULL, 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)
-       {
-               peer_cfg->destroy(peer_cfg);
-               g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
-                                       "IKE version not supported.");
-               return FALSE;
-       }
-       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
-        */
-       child_cfg->get_ref(child_cfg);
-       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;
-
-                               /* try to load/decrypt the private key */
-                               key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
-                                                               KEY_RSA, BUILD_FROM_FILE, path, BUILD_END);
-                               if (key)
-                               {
-                                       key->destroy(key);
-                                       return FALSE;
-                               }
-                       }
-               }
-               else if streq(method, "smartcard")
-               {
-                       if (nm_setting_vpn_get_secret(settings, "password"))
-                       {
-                               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, TRUE);
-       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, 0);
-                       return TRUE;
-               }
-       }
-       enumerator->destroy(enumerator);
-
-       g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_GENERAL,
-                               "Connection not found.");
-       return FALSE;
-}
-
-/**
- * Initializer
- */
-static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
-{
-       NMStrongswanPluginPrivate *priv;
-
-       priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
-       priv->plugin = NM_VPN_PLUGIN(plugin);
-       memset(&priv->listener.log, 0, sizeof(listener_t));
-       priv->listener.child_updown = child_updown;
-       priv->listener.ike_rekey = ike_rekey;
-}
-
-/**
- * Class constructor
- */
-static void nm_strongswan_plugin_class_init(
-                                                                       NMStrongswanPluginClass *strongswan_class)
-{
-       NMVPNPluginClass *parent_class = NM_VPN_PLUGIN_CLASS(strongswan_class);
-
-       g_type_class_add_private(G_OBJECT_CLASS(strongswan_class),
-                                                        sizeof(NMStrongswanPluginPrivate));
-       parent_class->connect = connect_;
-       parent_class->need_secrets = need_secrets;
-       parent_class->disconnect = disconnect;
-}
-
-/**
- * Object constructor
- */
-NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds,
-                                                                                        nm_handler_t *handler)
-{
-       NMStrongswanPlugin *plugin = (NMStrongswanPlugin *)g_object_new (
-                                       NM_TYPE_STRONGSWAN_PLUGIN,
-                                       NM_VPN_PLUGIN_DBUS_SERVICE_NAME, NM_DBUS_SERVICE_STRONGSWAN,
-                                       NULL);
-       if (plugin)
-       {
-               NMStrongswanPluginPrivate *priv;
-
-               priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
-               priv->creds = creds;
-               priv->handler = handler;
-               priv->name = NULL;
-       }
-       return plugin;
-}
-
diff --git a/src/libcharon/plugins/nm/nm_service.h b/src/libcharon/plugins/nm/nm_service.h
deleted file mode 100644 (file)
index 828d1a4..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.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_ @}*/