merged the modularization branch (credentials) back to trunk

This commit is contained in:
Martin Willi
2008-03-13 14:14:44 +00:00
parent 2df655134c
commit 552cc11b1f
495 changed files with 30378 additions and 23843 deletions
+11
View File
@@ -0,0 +1,11 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon ${dbus_CFLAGS}
AM_CFLAGS = -rdynamic
plugin_LTLIBRARIES = libcharon-dbus.la
libcharon_dbus_la_SOURCES = dbus.h dbus.c
libcharon_dbus_la_LDFLAGS = -module
libcharon_dbus_la_LIBADD = ${dbus_LIBS}
+422
View File
@@ -0,0 +1,422 @@
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>
#include <NetworkManager/NetworkManager.h>
#include <NetworkManager/NetworkManagerVPN.h>
#include <stdlib.h>
#include "dbus.h"
#include <library.h>
#include <daemon.h>
#include <processing/jobs/callback_job.h>
#define NM_DBUS_SERVICE_STRONG "org.freedesktop.NetworkManager.strongswan"
#define NM_dbus_STRONG "org.freedesktop.NetworkManager.strongswan"
#define NM_DBUS_PATH_STRONG "/org/freedesktop/NetworkManager/strongswan"
typedef struct private_dbus_t private_dbus_t;
/**
* Private data of an dbus_t object.
*/
struct private_dbus_t {
/**
* Public part of dbus_t object.
*/
dbus_t public;
/**
* DBUS connection
*/
DBusConnection* conn;
/**
* error value used here and there
*/
DBusError err;
/**
* state of the daemon
*/
NMVPNState state;
/**
* job accepting stroke messages
*/
callback_job_t *job;
/**
* name of the currently active connection
*/
char *name;
};
/**
* set daemon state and send StateChange signal to the bus
*/
static void set_state(private_dbus_t *this, NMVPNState state)
{
DBusMessage* msg;
msg = dbus_message_new_signal(NM_DBUS_PATH_STRONG, NM_dbus_STRONG, NM_DBUS_VPN_SIGNAL_STATE_CHANGE);
if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &this->state,
DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID) ||
!dbus_connection_send(this->conn, msg, NULL))
{
DBG1(DBG_CFG, "unable to send DBUS StateChange signal");
}
dbus_connection_flush(this->conn);
dbus_message_unref(msg);
this->state = state;
}
/**
* get the child_cfg with the same name as the peer cfg
*/
static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
{
child_cfg_t *current, *found = NULL;
iterator_t *iterator;
iterator = peer_cfg->create_child_cfg_iterator(peer_cfg);
while (iterator->iterate(iterator, (void**)&current))
{
if (streq(current->get_name(current), name))
{
found = current;
found->get_ref(found);
break;
}
}
iterator->destroy(iterator);
return found;
}
/**
* process NetworkManagers startConnection method call
*/
static bool start_connection(private_dbus_t *this, DBusMessage* msg)
{
DBusMessage *reply, *signal;
char *name, *user, **data, **passwords, **routes;
int data_count, passwords_count, routes_count;
u_int32_t me, other, p2p, netmask, mss;
char *dev, *domain, *banner;
const dbus_int32_t array[] = {};
const dbus_int32_t *varray = array;
peer_cfg_t *peer_cfg;
child_cfg_t *child_cfg;
status_t status = FAILED;
dbus_error_free(&this->err);
if (!dbus_message_get_args(msg, &this->err,
DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &user,
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &passwords, &passwords_count,
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &data, &data_count,
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &routes, &routes_count,
DBUS_TYPE_INVALID))
{
return FALSE;
}
set_state(this, NM_VPN_STATE_STARTING);
peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, name);
if (peer_cfg)
{
free(this->name);
this->name = strdup(peer_cfg->get_name(peer_cfg));
child_cfg = get_child_from_peer(peer_cfg, name);
if (child_cfg)
{
status = charon->controller->initiate(charon->controller,
peer_cfg, child_cfg, controller_cb_empty, NULL);
}
else
{
peer_cfg->destroy(peer_cfg);
}
}
reply = dbus_message_new_method_return(msg);
dbus_connection_send(this->conn, reply, NULL);
dbus_message_unref(reply);
if (status == SUCCESS)
{
set_state(this, NM_VPN_STATE_STARTED);
signal = dbus_message_new_signal(NM_DBUS_PATH_STRONG,
NM_dbus_STRONG,
NM_DBUS_VPN_SIGNAL_IP4_CONFIG);
me = other = p2p = mss = netmask = 0;
dev = domain = banner = "";
if (dbus_message_append_args(signal,
DBUS_TYPE_UINT32, &other,
DBUS_TYPE_STRING, &dev,
DBUS_TYPE_UINT32, &me,
DBUS_TYPE_UINT32, &p2p,
DBUS_TYPE_UINT32, &netmask,
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &varray, 0,
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &varray, 0,
DBUS_TYPE_UINT32, &mss,
DBUS_TYPE_STRING, &domain,
DBUS_TYPE_STRING, &banner, DBUS_TYPE_INVALID))
{
dbus_connection_send(this->conn, signal, NULL);
}
dbus_message_unref(signal);
}
else
{
set_state(this, NM_VPN_STATE_STOPPED);
}
dbus_connection_flush(this->conn);
return TRUE;
}
/**
* process NetworkManagers stopConnection method call
*/
static bool stop_connection(private_dbus_t *this, DBusMessage* msg)
{
u_int32_t id;
iterator_t *iterator;
ike_sa_t *ike_sa;
if (this->name == NULL)
{
return FALSE;
}
dbus_error_free(&this->err);
set_state(this, NM_VPN_STATE_STOPPING);
iterator = charon->controller->create_ike_sa_iterator(charon->controller);
while (iterator->iterate(iterator, (void**)&ike_sa))
{
child_sa_t *child_sa;
iterator_t *children;
if (this->name && streq(this->name, ike_sa->get_name(ike_sa)))
{
id = ike_sa->get_unique_id(ike_sa);
iterator->destroy(iterator);
charon->controller->terminate_ike(charon->controller, id, NULL, NULL);
set_state(this, NM_VPN_STATE_STOPPED);
return TRUE;;
}
children = ike_sa->create_child_sa_iterator(ike_sa);
while (children->iterate(children, (void**)&child_sa))
{
if (this->name && streq(this->name, child_sa->get_name(child_sa)))
{
id = child_sa->get_reqid(child_sa);
children->destroy(children);
iterator->destroy(iterator);
charon->controller->terminate_child(charon->controller, id, NULL, NULL);
set_state(this, NM_VPN_STATE_STOPPED);
return TRUE;
}
}
children->destroy(children);
}
iterator->destroy(iterator);
set_state(this, NM_VPN_STATE_STOPPED);
return TRUE;
}
/**
* process NetworkManagers getState method call
*/
static bool get_state(private_dbus_t *this, DBusMessage* msg)
{
DBusMessage* reply;
reply = dbus_message_new_method_return(msg);
if (!reply || !dbus_message_append_args(reply,
DBUS_TYPE_UINT32, &this->state,
DBUS_TYPE_INVALID))
{
return FALSE;
}
dbus_connection_send(this->conn, reply, NULL);
return TRUE;
}
/**
* Handle incoming messages
*/
static DBusHandlerResult message_handler(DBusConnection *con, DBusMessage *msg,
private_dbus_t *this)
{
bool handled;
if (dbus_message_is_method_call(msg, NM_dbus_STRONG,
"startConnection"))
{
handled = start_connection(this, msg);
}
else if (dbus_message_is_method_call(msg, NM_dbus_STRONG,
"stopConnection"))
{
handled = stop_connection(this, msg);
}
else if (dbus_message_is_method_call(msg, NM_dbus_STRONG,
"getState"))
{
handled = get_state(this, msg);
}
else
{
DBG1(DBG_CFG, "ignoring DBUS message %s.%s",
dbus_message_get_interface(msg), dbus_message_get_member(msg));
handled = FALSE;
}
if (handled)
{
return DBUS_HANDLER_RESULT_HANDLED;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
/**
* Handle received signals
static DBusHandlerResult signal_handler(DBusConnection *con, DBusMessage *msg,
private_dbus_t *this)
{
bool handled;
if (dbus_message_is_signal(msg, NM_dbus, "VPNConnectionStateChange"))
{
NMVPNState state;
char *name;
if (dbus_message_get_args(msg, &this->err, DBUS_TYPE_STRING, &name,
DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID))
{
DBG1(DBG_CFG, "got state %d for %s", state, name);
}
handled = TRUE;
}
else
{
DBG1(DBG_CFG, "ignoring DBUS signal %s.%s",
dbus_message_get_interface(msg), dbus_message_get_member(msg));
handled = FALSE;
}
if (handled)
{
return DBUS_HANDLER_RESULT_HANDLED;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
} */
/**
* dispatcher function processed by a seperate thread
*/
static job_requeue_t dispatch(private_dbus_t *this)
{
if (dbus_connection_read_write_dispatch(this->conn, -1))
{
return JOB_REQUEUE_DIRECT;
}
return JOB_REQUEUE_NONE;
}
/**
* Implementation of interface_t.destroy.
*/
static void destroy(private_dbus_t *this)
{
this->job->cancel(this->job);
dbus_connection_close(this->conn);
dbus_error_free(&this->err);
dbus_shutdown();
free(this->name);
free(this);
}
/*
* Described in header file
*/
plugin_t *plugin_create()
{
int ret;
DBusObjectPathVTable v = {NULL, (void*)&message_handler, NULL, NULL, NULL, NULL};
private_dbus_t *this = malloc_thing(private_dbus_t);
this->public.plugin.destroy = (void (*)(plugin_t*))destroy;
dbus_error_init(&this->err);
this->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &this->err);
if (dbus_error_is_set(&this->err))
{
DBG1(DBG_CFG, "unable to open DBUS connection: %s", this->err.message);
charon->kill(charon, "DBUS initialization failed");
}
dbus_connection_set_exit_on_disconnect(this->conn, FALSE);
ret = dbus_bus_request_name(this->conn, NM_DBUS_SERVICE_STRONG,
DBUS_NAME_FLAG_REPLACE_EXISTING , &this->err);
if (dbus_error_is_set(&this->err))
{
DBG1(DBG_CFG, "unable to set DBUS name: %s", this->err.message);
charon->kill(charon, "unable to set DBUS name");
}
if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
{
charon->kill(charon, "DBUS name already owned");
}
if (!dbus_connection_register_object_path(this->conn, NM_DBUS_PATH_STRONG, &v, this))
{
charon->kill(charon, "unable to register DBUS message handler");
}
/*
if (!dbus_connection_add_filter(this->conn, (void*)signal_handler, this, NULL))
{
charon->kill(charon, "unable to register DBUS signal handler");
}
dbus_bus_add_match(this->conn, "type='signal', "
"interface='" NM_dbus_VPN "',"
"path='" NM_DBUS_PATH_VPN "'", &this->err);
if (dbus_error_is_set (&this->err))
{
charon->kill(charon, "unable to add DBUS signal match");
}*/
this->name = NULL;
this->state = NM_VPN_STATE_INIT;
set_state(this, NM_VPN_STATE_STOPPED);
this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL);
charon->processor->queue_job(charon->processor, (job_t*)this->job);
return &this->public.plugin;
}
+50
View File
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2007-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup dbus dbus
* @ingroup cplugins
*
* @defgroup dbus_i dbus
* @{ @ingroup dbus
*/
#ifndef DBUS_H_
#define DBUS_H_
#include <plugins/plugin.h>
typedef struct dbus_t dbus_t;
/**
* NetworkManager DBUS control plugin.
*
* This plugin uses a DBUS connection. It is designed to work in conjuction
* with NetworkManager to configure and control the daemon.
*/
struct dbus_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
/**
* Create a dbus plugin instance.
*/
plugin_t *plugin_create();
#endif /* DBUS_H_ @}*/
+11
View File
@@ -0,0 +1,11 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
AM_CFLAGS = -rdynamic
plugin_LTLIBRARIES = libcharon-eapaka.la
libcharon_eapaka_la_SOURCES = eap_aka_plugin.h eap_aka_plugin.c eap_aka.h eap_aka.c
libcharon_eapaka_la_LDFLAGS = -module
libcharon_eapaka_la_LIBADD = -lgmp
File diff suppressed because it is too large Load Diff
+83
View File
@@ -0,0 +1,83 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
/**
* @defgroup eap_aka_i eap_aka
* @{ @ingroup eap_aka
*/
#ifndef EAP_AKA_H_
#define EAP_AKA_H_
typedef struct eap_aka_t eap_aka_t;
#include <sa/authenticators/eap/eap_method.h>
/** check SEQ values as client for validity, disabled by default */
#ifndef SEQ_CHECK
# define SEQ_CHECK 0
#endif
/**
* Implementation of the eap_method_t interface using EAP-AKA.
*
* EAP-AKA uses 3rd generation mobile phone standard authentication
* mechanism for authentication. It is a mutual authentication
* mechanism which establishs a shared key and therefore supports EAP_ONLY
* authentication. This implementation follows the standard of the
* 3GPP2 (S.S0055) and not the one of 3GGP.
* The shared key used for authentication is from ipsec.secrets. The
* peers ID is used to query it.
* The AKA mechanism uses sequence numbers to detect replay attacks. The
* peer stores the sequence number normally in a USIM and accepts
* incremental sequence numbers (incremental for lifetime of the USIM). To
* prevent a complex sequence number management, this implementation uses
* a sequence number derived from time. It is initialized to the startup
* time of the daemon. As long as the (UTC) time of the system is not
* turned back while the daemon is not running, this method is secure.
* To enable time based SEQs, #define SEQ_CHECK as 1. Default is to accept
* any SEQ numbers. This allows an attacker to do replay attacks. But since
* the server has proven his identity via IKE, such an attack is only
* possible between server and AAA (if any).
*/
struct eap_aka_t {
/**
* Implemented eap_method_t interface.
*/
eap_method_t eap_method_interface;
};
/**
* Creates the server implementation of the EAP method EAP-AKA.
*
* @param server ID of the EAP server
* @param peer ID of the EAP client
* @return eap_aka_t object
*/
eap_aka_t *eap_aka_create_server(identification_t *server, identification_t *peer);
/**
* Creates the peer implementation of the EAP method EAP-AKA.
*
* @param server ID of the EAP server
* @param peer ID of the EAP client
* @return eap_aka_t object
*/
eap_aka_t *eap_aka_create_peer(identification_t *server, identification_t *peer);
#endif /* EAP_AKA_H_ @}*/
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include "eap_aka_plugin.h"
#include "eap_aka.h"
#include <daemon.h>
/**
* Implementation of plugin_t.destroy
*/
static void destroy(eap_aka_plugin_t *this)
{
charon->eap->remove_method(charon->eap,
(eap_constructor_t)eap_aka_create_server);
charon->eap->remove_method(charon->eap,
(eap_constructor_t)eap_aka_create_peer);
free(this);
}
/*
* see header file
*/
plugin_t *plugin_create()
{
eap_aka_plugin_t *this = malloc_thing(eap_aka_plugin_t);
this->plugin.destroy = (void(*)(plugin_t*))destroy;
charon->eap->add_method(charon->eap, EAP_AKA, 0, EAP_SERVER,
(eap_constructor_t)eap_aka_create_server);
charon->eap->add_method(charon->eap, EAP_AKA, 0, EAP_PEER,
(eap_constructor_t)eap_aka_create_peer);
return &this->plugin;
}
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
/**
* @defgroup eap_aka eap_aka
* @ingroup cplugins
*
* @defgroup eap_aka_plugin eap_aka_plugin
* @{ @ingroup eap_aka
*/
#ifndef EAP_AKA_PLUGIN_H_
#define EAP_AKA_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct eap_aka_plugin_t eap_aka_plugin_t;
/**
* EAP-AKA plugin
*/
struct eap_aka_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
/**
* Create a eap_aka_plugin instance.
*/
plugin_t *plugin_create();
#endif /* EAP_AKA_PLUGIN_H_ @}*/
@@ -0,0 +1,10 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
AM_CFLAGS = -rdynamic
plugin_LTLIBRARIES = libcharon-eapidentity.la
libcharon_eapidentity_la_SOURCES = \
eap_identity_plugin.h eap_identity_plugin.c eap_identity.h eap_identity.c
libcharon_eapidentity_la_LDFLAGS = -module
@@ -0,0 +1,125 @@
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include "eap_identity.h"
#include <daemon.h>
#include <library.h>
typedef struct private_eap_identity_t private_eap_identity_t;
/**
* Private data of an eap_identity_t object.
*/
struct private_eap_identity_t {
/**
* Public authenticator_t interface.
*/
eap_identity_t public;
/**
* ID of the peer
*/
identification_t *peer;
};
/**
* Implementation of eap_method_t.process for the peer
*/
static status_t process(private_eap_identity_t *this,
eap_payload_t *in, eap_payload_t **out)
{
chunk_t id, hdr;
hdr = chunk_alloca(5);
id = this->peer->get_encoding(this->peer);
*(hdr.ptr + 0) = EAP_RESPONSE;
*(hdr.ptr + 1) = in->get_identifier(in);
*(u_int16_t*)(hdr.ptr + 2) = htons(hdr.len + id.len);
*(hdr.ptr + 4) = EAP_IDENTITY;
*out = eap_payload_create_data(chunk_cata("cc", hdr, id));
return SUCCESS;
}
/**
* Implementation of eap_method_t.initiate for the peer
*/
static status_t initiate(private_eap_identity_t *this, eap_payload_t **out)
{
/* peer never initiates */
return FAILED;
}
/**
* Implementation of eap_method_t.get_type.
*/
static eap_type_t get_type(private_eap_identity_t *this, u_int32_t *vendor)
{
*vendor = 0;
return EAP_IDENTITY;
}
/**
* Implementation of eap_method_t.get_msk.
*/
static status_t get_msk(private_eap_identity_t *this, chunk_t *msk)
{
return FAILED;
}
/**
* Implementation of eap_method_t.is_mutual.
*/
static bool is_mutual(private_eap_identity_t *this)
{
return FALSE;
}
/**
* Implementation of eap_method_t.destroy.
*/
static void destroy(private_eap_identity_t *this)
{
free(this);
}
/*
* Described in header.
*/
eap_identity_t *eap_identity_create_peer(identification_t *server,
identification_t *peer)
{
private_eap_identity_t *this = malloc_thing(private_eap_identity_t);
/* public functions */
this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate;
this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process;
this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
/* private data */
this->peer = peer;
return &this->public;
}
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
/**
* @defgroup eap_identity_i eap_identity
* @{ @ingroup eap_identity
*/
#ifndef EAP_IDENTITY_H_
#define EAP_IDENTITY_H_
typedef struct eap_identity_t eap_identity_t;
#include <sa/authenticators/eap/eap_method.h>
/**
* Implementation of the eap_method_t interface using EAP Identity.
*/
struct eap_identity_t {
/**
* Implemented eap_method_t interface.
*/
eap_method_t eap_method_interface;
};
/**
* Creates the EAP method EAP Identity, acting as peer.
*
* @param server ID of the EAP server
* @param peer ID of the EAP client
* @return eap_identity_t object
*/
eap_identity_t *eap_identity_create_peer(identification_t *server,
identification_t *peer);
#endif /* EAP_IDENTITY_H_ @}*/
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include "eap_identity_plugin.h"
#include "eap_identity.h"
#include <daemon.h>
/**
* Implementation of plugin_t.destroy
*/
static void destroy(eap_identity_plugin_t *this)
{
charon->eap->remove_method(charon->eap,
(eap_constructor_t)eap_identity_create_peer);
free(this);
}
/*
* see header file
*/
plugin_t *plugin_create()
{
eap_identity_plugin_t *this = malloc_thing(eap_identity_plugin_t);
this->plugin.destroy = (void(*)(plugin_t*))destroy;
charon->eap->add_method(charon->eap, EAP_IDENTITY, 0, EAP_PEER,
(eap_constructor_t)eap_identity_create_peer);
return &this->plugin;
}
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
/**
* @defgroup eap_identity eap_identity
* @ingroup cplugins
*
* @defgroup eap_identity_plugin eap_identity_plugin
* @{ @ingroup eap_identity
*/
#ifndef EAP_IDENTITY_PLUGIN_H_
#define EAP_IDENTITY_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct eap_identity_plugin_t eap_identity_plugin_t;
/**
* EAP-IDENTITY plugin.
*/
struct eap_identity_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
/**
* Create a eap_identity_plugin instance.
*/
plugin_t *plugin_create();
#endif /* EAP_IDENTITY_PLUGIN_H_ @}*/
+10
View File
@@ -0,0 +1,10 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
AM_CFLAGS = -rdynamic
plugin_LTLIBRARIES = libcharon-eapmd5.la
libcharon_eapmd5_la_SOURCES = eap_md5_plugin.h eap_md5_plugin.c eap_md5.h eap_md5.c
libcharon_eapmd5_la_LDFLAGS = -module
+300
View File
@@ -0,0 +1,300 @@
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include "eap_md5.h"
#include <daemon.h>
#include <library.h>
#include <crypto/hashers/hasher.h>
typedef struct private_eap_md5_t private_eap_md5_t;
/**
* Private data of an eap_md5_t object.
*/
struct private_eap_md5_t {
/**
* Public authenticator_t interface.
*/
eap_md5_t public;
/**
* ID of the server
*/
identification_t *server;
/**
* ID of the peer
*/
identification_t *peer;
/**
* challenge sent by the server
*/
chunk_t challenge;
/**
* EAP message identififier
*/
u_int8_t identifier;
};
typedef struct eap_md5_header_t eap_md5_header_t;
/**
* packed eap MD5 header struct
*/
struct eap_md5_header_t {
/** EAP code (REQUEST/RESPONSE) */
u_int8_t code;
/** unique message identifier */
u_int8_t identifier;
/** length of whole message */
u_int16_t length;
/** EAP type */
u_int8_t type;
/** length of value (challenge) */
u_int8_t value_size;
/** actual value */
u_int8_t value[];
} __attribute__((__packed__));
#define CHALLENGE_LEN 16
#define PAYLOAD_LEN (CHALLENGE_LEN + sizeof(eap_md5_header_t))
/**
* Hash the challenge string, create response
*/
static status_t hash_challenge(private_eap_md5_t *this, chunk_t *response)
{
shared_key_t *shared;
chunk_t concat;
hasher_t *hasher;
shared = charon->credentials->get_shared(charon->credentials, SHARED_EAP,
this->server, this->peer);
if (shared == NULL)
{
DBG1(DBG_IKE, "no EAP key found for hosts '%D' - '%D'",
this->server, this->peer);
return NOT_FOUND;
}
concat = chunk_cata("ccc", chunk_from_thing(this->identifier),
shared->get_key(shared), this->challenge);
shared->destroy(shared);
hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
if (hasher == NULL)
{
DBG1(DBG_IKE, "EAP-MD5 failed, MD5 not supported");
return FAILED;
}
hasher->allocate_hash(hasher, concat, response);
hasher->destroy(hasher);
return SUCCESS;
}
/**
* Implementation of eap_method_t.initiate for the peer
*/
static status_t initiate_peer(private_eap_md5_t *this, eap_payload_t **out)
{
/* peer never initiates */
return FAILED;
}
/**
* Implementation of eap_method_t.initiate for the server
*/
static status_t initiate_server(private_eap_md5_t *this, eap_payload_t **out)
{
randomizer_t *randomizer;
status_t status;
eap_md5_header_t *req;
randomizer = randomizer_create();
status = randomizer->allocate_pseudo_random_bytes(randomizer, CHALLENGE_LEN,
&this->challenge);
randomizer->destroy(randomizer);
if (status != SUCCESS)
{
return FAILED;
}
req = alloca(PAYLOAD_LEN);
req->length = htons(PAYLOAD_LEN);
req->code = EAP_REQUEST;
req->identifier = this->identifier;
req->type = EAP_MD5;
req->value_size = this->challenge.len;
memcpy(req->value, this->challenge.ptr, this->challenge.len);
*out = eap_payload_create_data(chunk_create((void*)req, PAYLOAD_LEN));
return NEED_MORE;
}
/**
* Implementation of eap_method_t.process for the peer
*/
static status_t process_peer(private_eap_md5_t *this,
eap_payload_t *in, eap_payload_t **out)
{
chunk_t response;
chunk_t data;
eap_md5_header_t *req;
this->identifier = in->get_identifier(in);
data = in->get_data(in);
this->challenge = chunk_clone(chunk_skip(data, 6));
if (data.len < 6 || this->challenge.len < *(data.ptr + 5))
{
DBG1(DBG_IKE, "received invalid EAP-MD5 message");
return FAILED;
}
if (hash_challenge(this, &response) != SUCCESS)
{
return FAILED;
}
req = alloca(PAYLOAD_LEN);
req->length = htons(PAYLOAD_LEN);
req->code = EAP_RESPONSE;
req->identifier = this->identifier;
req->type = EAP_MD5;
req->value_size = response.len;
memcpy(req->value, response.ptr, response.len);
chunk_free(&response);
*out = eap_payload_create_data(chunk_create((void*)req, PAYLOAD_LEN));
return NEED_MORE;
}
/**
* Implementation of eap_method_t.process for the server
*/
static status_t process_server(private_eap_md5_t *this,
eap_payload_t *in, eap_payload_t **out)
{
chunk_t response, expected;
chunk_t data;
if (this->identifier != in->get_identifier(in))
{
DBG1(DBG_IKE, "received invalid EAP-MD5 message");
return FAILED;
}
if (hash_challenge(this, &expected) != SUCCESS)
{
return FAILED;
}
data = in->get_data(in);
response = chunk_skip(data, 6);
if (response.len < expected.len ||
!memeq(response.ptr, expected.ptr, expected.len))
{
chunk_free(&expected);
DBG1(DBG_IKE, "EAP-MD5 verification failed");
return FAILED;
}
chunk_free(&expected);
return SUCCESS;
}
/**
* Implementation of eap_method_t.get_type.
*/
static eap_type_t get_type(private_eap_md5_t *this, u_int32_t *vendor)
{
*vendor = 0;
return EAP_MD5;
}
/**
* Implementation of eap_method_t.get_msk.
*/
static status_t get_msk(private_eap_md5_t *this, chunk_t *msk)
{
return FAILED;
}
/**
* Implementation of eap_method_t.is_mutual.
*/
static bool is_mutual(private_eap_md5_t *this)
{
return FALSE;
}
/**
* Implementation of eap_method_t.destroy.
*/
static void destroy(private_eap_md5_t *this)
{
chunk_free(&this->challenge);
free(this);
}
/**
* Generic constructor
*/
static private_eap_md5_t *eap_md5_create_generic(identification_t *server,
identification_t *peer)
{
private_eap_md5_t *this = malloc_thing(private_eap_md5_t);
this->public.eap_method_interface.initiate = NULL;
this->public.eap_method_interface.process = NULL;
this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
/* private data */
this->peer = peer;
this->server = server;
this->challenge = chunk_empty;
this->identifier = random();
return this;
}
/*
* see header
*/
eap_md5_t *eap_md5_create_server(identification_t *server, identification_t *peer)
{
private_eap_md5_t *this = eap_md5_create_generic(server, peer);
this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_server;
this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_server;
return &this->public;
}
/*
* see header
*/
eap_md5_t *eap_md5_create_peer(identification_t *server, identification_t *peer)
{
private_eap_md5_t *this = eap_md5_create_generic(server, peer);
this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_peer;
this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_peer;
return &this->public;
}
+59
View File
@@ -0,0 +1,59 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
/**
* @defgroup eap_md5_i eap_md5
* @{ @ingroup eap_md5
*/
#ifndef EAP_MD5_H_
#define EAP_MD5_H_
typedef struct eap_md5_t eap_md5_t;
#include <sa/authenticators/eap/eap_method.h>
/**
* Implementation of the eap_method_t interface using EAP-MD5 (CHAP).
*/
struct eap_md5_t {
/**
* Implemented eap_method_t interface.
*/
eap_method_t eap_method_interface;
};
/**
* Creates the EAP method EAP-MD5 acting as server.
*
* @param server ID of the EAP server
* @param peer ID of the EAP client
* @return eap_md5_t object
*/
eap_md5_t *eap_md5_create_server(identification_t *server, identification_t *peer);
/**
* Creates the EAP method EAP-MD5 acting as peer.
*
* @param server ID of the EAP server
* @param peer ID of the EAP client
* @return eap_md5_t object
*/
eap_md5_t *eap_md5_create_peer(identification_t *server, identification_t *peer);
#endif /* EAP_MD5_H_ @}*/
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include "eap_md5_plugin.h"
#include "eap_md5.h"
#include <daemon.h>
/**
* Implementation of plugin_t.destroy
*/
static void destroy(eap_md5_plugin_t *this)
{
charon->eap->remove_method(charon->eap,
(eap_constructor_t)eap_md5_create_server);
charon->eap->remove_method(charon->eap,
(eap_constructor_t)eap_md5_create_peer);
free(this);
}
/*
* see header file
*/
plugin_t *plugin_create()
{
eap_md5_plugin_t *this = malloc_thing(eap_md5_plugin_t);
this->plugin.destroy = (void(*)(plugin_t*))destroy;
charon->eap->add_method(charon->eap, EAP_MD5, 0, EAP_SERVER,
(eap_constructor_t)eap_md5_create_server);
charon->eap->add_method(charon->eap, EAP_MD5, 0, EAP_PEER,
(eap_constructor_t)eap_md5_create_peer);
return &this->plugin;
}
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
/**
* @defgroup eap_md5 eap_md5
* @ingroup cplugins
*
* @defgroup eap_md5_plugin eap_md5_plugin
* @{ @ingroup eap_md5
*/
#ifndef EAP_MD5_PLUGIN_H_
#define EAP_MD5_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct eap_md5_plugin_t eap_md5_plugin_t;
/**
* EAP-MD5 plugin
*/
struct eap_md5_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
/**
* Create a eap_md5_plugin instance.
*/
plugin_t *plugin_create();
#endif /* EAP_MD5_PLUGIN_H_ @}*/
+13
View File
@@ -0,0 +1,13 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DSIM_READER_LIB=\"${simreader}\"
plugin_LTLIBRARIES = libcharon-eapsim.la libeapsim-file.la
libcharon_eapsim_la_SOURCES = eap_sim_plugin.h eap_sim_plugin.c eap_sim.h eap_sim.c
libcharon_eapsim_la_LDFLAGS = -module
libeapsim_file_la_SOURCES = eap_sim_file.c
libeapsim_file_la_LDFLAGS = -module
File diff suppressed because it is too large Load Diff
+111
View File
@@ -0,0 +1,111 @@
/*
* Copyright (C) 2007-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup eap_sim_i eap_sim
* @{ @ingroup eap_sim
*/
#ifndef EAP_SIM_H_
#define EAP_SIM_H_
typedef struct eap_sim_t eap_sim_t;
#include <sa/authenticators/eap/eap_method.h>
/** the library containing with the triplet functions */
#ifndef SIM_READER_LIB
#error SIM_READER_LIB not specified, use --with-sim-reader option
#endif /* SIM_READER_LIB */
/**
* Cardreaders SIM function.
*
* @param rand RAND to run algo with
* @param rand_length length of value in rand
* @param sres buffer to get SRES
* @param sres_length size of buffer in sres, returns bytes written to SRES
* @param kc buffer to get Kc
* @param kc_length size of buffer in Kc, returns bytes written to Kc
* @return zero on success
*/
typedef int (*sim_algo_t)(const unsigned char *rand, int rand_length,
unsigned char *sres, int *sres_length,
unsigned char *kc, int *kc_length);
#ifndef SIM_READER_ALG
/** the SIM_READER_LIB's algorithm, uses sim_algo_t signature */
#define SIM_READER_ALG "sim_run_alg"
#endif /* SIM_READER_ALG */
/**
* Function to get a SIM triplet.
*
* @param identity identity (imsi) to get a triplet for
* @param rand buffer to get RAND
* @param rand_length size of buffer in rand, returns bytes written to RAND
* @param sres buffer to get SRES
* @param sres_length size of buffer in sres, returns bytes written to SRES
* @param kc buffer to get Kc
* @param kc_length size of buffer in Kc, returns bytes written to Kc
* @return zero on success
*/
typedef int (*sim_get_triplet_t)(char *identity,
unsigned char *rand, int *rand_length,
unsigned char *sres, int *sres_length,
unsigned char *kc, int *kc_length);
#ifndef SIM_READER_GET_TRIPLET
/** the SIM_READER_LIB's get-triplet function, uses sim_get_triplet_t signature */
#define SIM_READER_GET_TRIPLET "sim_get_triplet"
#endif /* SIM_READER_GET_TRIPLET */
/**
* Implementation of the eap_method_t interface using EAP-SIM.
*
* This EAP-SIM client implementation uses another pluggable library to
* access the SIM card/triplet provider. This module is specified using the
* SIM_READER_LIB definition. It has to privde a sim_run_alg() function to
* calculate a triplet (client), and/or a sim_get_triplet() function to get
* a triplet (server). These functions are named to the SIM_READER_ALG and
* the SIM_READER_GET_TRIPLET definitions.
*/
struct eap_sim_t {
/**
* Implemented eap_method_t interface.
*/
eap_method_t eap_method_interface;
};
/**
* Creates the EAP method EAP-SIM acting as server.
*
* @param server ID of the EAP server
* @param peer ID of the EAP client
* @return eap_sim_t object
*/
eap_sim_t *eap_sim_create_server(identification_t *server, identification_t *peer);
/**
* Creates the EAP method EAP-SIM acting as peer.
*
* @param server ID of the EAP server
* @param peer ID of the EAP client
* @return eap_sim_t object
*/
eap_sim_t *eap_sim_create_peer(identification_t *server, identification_t *peer);
#endif /* EAP_SIM_H_ @}*/
+283
View File
@@ -0,0 +1,283 @@
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <daemon.h>
#define IMSI_LEN 64
#define RAND_LEN 16
#define SRES_LEN 4
#define KC_LEN 8
typedef struct triplet_t triplet_t;
struct triplet_t {
unsigned char imsi[IMSI_LEN];
unsigned char rand[RAND_LEN];
unsigned char sres[SRES_LEN];
unsigned char kc[KC_LEN];
};
static triplet_t *triplets = NULL;
static int triplet_count = 0;
#define TRIPLET_FILE IPSEC_CONFDIR "/ipsec.d/triplets.dat"
/**
* convert a single HEX char to its integer value
*/
static int hexchr(char chr)
{
switch (chr)
{
case '0'...'9':
return chr - '0';
case 'A'...'F':
return 10 + chr - 'A';
case 'a'...'f':
return 10 + chr - 'a';
}
return 0;
}
/**
* convert a HEX string into a char array bin, limited by array length len
*/
static void hex2bin(char *hex, unsigned char *bin, size_t len)
{
char *pos;
int i, even = 1;
pos = hex - 1;
/* find the end, as we convert bottom up */
while (TRUE)
{
switch (*(pos+1))
{
case '0'...'9':
case 'A'...'F':
case 'a'...'f':
pos++;
continue;
}
break;
}
/* convert two hex chars into a single bin byte */
for (i = 0; pos >= hex && i < len; pos--)
{
if (even)
{
bin[len - 1 - i] = hexchr(*pos);
}
else
{
bin[len - 1 - i] |= 16 * hexchr(*pos);
i++;
}
even = !even;
}
}
/**
* free up allocated triplets
*/
static void __attribute__ ((destructor)) free_triplets()
{
free(triplets);
}
/**
* read the triplets from the file, using freeradius triplet file syntax:
* http://www.freeradius.org/radiusd/doc/rlm_sim_triplets
*/
static void __attribute__ ((constructor)) read_triplets()
{
char line[512], *data[4], *pos;
FILE *file;
int i, nr = 0;
triplet_t *triplet;
file = fopen(TRIPLET_FILE, "r");
if (file == NULL)
{
DBG1(DBG_CFG, "opening triplet file %s failed: %s",
TRIPLET_FILE, strerror(errno));
return;
}
if (triplets)
{
free(triplets);
triplets = NULL;
triplet_count = 0;
}
/* read line by line */
while (fgets(line, sizeof(line), file))
{
nr++;
/* skip comments, empty lines */
switch (line[0])
{
case '\n':
case '\r':
case '#':
case '\0':
continue;
default:
break;
}
/* read comma separated values */
pos = line;
for (i = 0; i < 4; i++)
{
data[i] = pos;
pos = strchr(pos, ',');
if (pos)
{
*pos = '\0';
pos++;
}
else if (i != 3)
{
DBG1(DBG_CFG, "error in triplet file, line %d", nr);
fclose(file);
return;
}
}
/* allocate new triplet */
triplet_count++;
triplets = realloc(triplets, triplet_count * sizeof(triplet_t));
triplet = &triplets[triplet_count - 1];
memset(triplet, 0, sizeof(triplet_t));
/* convert/copy triplet data */
for (i = 0; i < IMSI_LEN - 1; i++)
{
switch (data[0][i])
{
case '\n':
case '\r':
case '\0':
break;
default:
triplet->imsi[i] = data[0][i];
continue;
}
break;
}
hex2bin(data[1], triplet->rand, RAND_LEN);
hex2bin(data[2], triplet->sres, SRES_LEN);
hex2bin(data[3], triplet->kc, KC_LEN);
DBG4(DBG_CFG, "triplet: imsi %b\nrand %b\nsres %b\nkc %b",
triplet->imsi, IMSI_LEN, triplet->rand, RAND_LEN,
triplet->sres, SRES_LEN, triplet->kc, KC_LEN);
}
fclose(file);
DBG2(DBG_CFG, "read %d triplets from %s", triplet_count, TRIPLET_FILE);
}
/**
* Run the sim algorithm, see eap_sim.h
*/
int sim_run_alg(const unsigned char *rand, int rand_length,
unsigned char *sres, int *sres_length,
unsigned char *kc, int *kc_length)
{
int current;
if (rand_length != RAND_LEN ||
*sres_length < SRES_LEN ||
*kc_length < KC_LEN)
{
return 1;
}
for (current = 0; current < triplet_count; current++)
{
if (memcmp(triplets[current].rand, rand, RAND_LEN) == 0)
{
memcpy(sres, triplets[current].sres, SRES_LEN);
memcpy(kc, triplets[current].kc, KC_LEN);
*sres_length = SRES_LEN;
*kc_length = KC_LEN;
return 0;
}
}
return 2;
}
/**
* Get a single triplet, see_eap_sim.h
*/
int sim_get_triplet(char *imsi,
unsigned char *rand, int *rand_length,
unsigned char *sres, int *sres_length,
unsigned char *kc, int *kc_length)
{
int current;
triplet_t *triplet;
static int skip = -1;
DBG2(DBG_CFG, "getting triplet for %s", imsi);
if (*rand_length < RAND_LEN ||
*sres_length < SRES_LEN ||
*kc_length < KC_LEN)
{
return 1;
}
if (triplet_count == 0)
{
return 2;
}
for (current = 0; current < triplet_count; current++)
{
triplet = &triplets[current];
if (streq(imsi, triplet->imsi))
{
/* skip triplet if already used */
if (skip >= current)
{
continue;
}
*rand_length = RAND_LEN;
*sres_length = SRES_LEN;
*kc_length = KC_LEN;
memcpy(rand, triplet->rand, RAND_LEN);
memcpy(sres, triplet->sres, SRES_LEN);
memcpy(kc, triplet->kc, KC_LEN);
/* remember used triplet */
skip = current;
return 0;
}
}
if (skip > -1)
{
/* no triplet left, reuse triplets */
skip = -1;
return sim_get_triplet(imsi, rand, rand_length,
sres, sres_length, kc, kc_length);
}
return 2;
}
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include "eap_sim_plugin.h"
#include "eap_sim.h"
#include <daemon.h>
/**
* Implementation of plugin_t.destroy
*/
static void destroy(eap_sim_plugin_t *this)
{
charon->eap->remove_method(charon->eap,
(eap_constructor_t)eap_sim_create_server);
charon->eap->remove_method(charon->eap,
(eap_constructor_t)eap_sim_create_peer);
free(this);
}
/*
* see header file
*/
plugin_t *plugin_create()
{
eap_sim_plugin_t *this = malloc_thing(eap_sim_plugin_t);
this->plugin.destroy = (void(*)(plugin_t*))destroy;
charon->eap->add_method(charon->eap, EAP_SIM, 0, EAP_SERVER,
(eap_constructor_t)eap_sim_create_server);
charon->eap->add_method(charon->eap, EAP_SIM, 0, EAP_PEER,
(eap_constructor_t)eap_sim_create_peer);
return &this->plugin;
}
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
/**
* @defgroup eap_sim eap_sim
* @ingroup cplugins
*
* @defgroup eap_sim_plugin eap_sim_plugin
* @{ @ingroup eap_sim
*/
#ifndef EAP_SIM_PLUGIN_H_
#define EAP_SIM_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct eap_sim_plugin_t eap_sim_plugin_t;
/**
* EAP-sim plugin
*/
struct eap_sim_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
/**
* Create a eap_sim_plugin instance.
*/
plugin_t *plugin_create();
#endif /* EAP_SIM_PLUGIN_H_ @}*/
+10
View File
@@ -0,0 +1,10 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
AM_CFLAGS = -rdynamic
plugin_LTLIBRARIES = libcharon-med-db.la
libcharon_med_db_la_SOURCES = med_db_plugin.h med_db_plugin.c \
med_db_creds.h med_db_creds.c
libcharon_med_db_la_LDFLAGS = -module
+211
View File
@@ -0,0 +1,211 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include "med_db_creds.h"
#include <daemon.h>
#include <library.h>
#include <utils/enumerator.h>
typedef struct private_med_db_creds_t private_med_db_creds_t;
/**
* Private data of an med_db_creds_t object
*/
struct private_med_db_creds_t {
/**
* Public part
*/
med_db_creds_t public;
/**
* underlying database handle
*/
database_t *db;
};
/**
* data passed between enumerate calls
*/
typedef struct {
/** current shared key */
shared_key_t *current;
} data_t;
typedef struct private_shared_key_t private_shared_key_t;
/**
* shared key implementation
*/
struct private_shared_key_t {
/** implements shared_key_t*/
shared_key_t public;
/** data of the key */
chunk_t key;
/** reference counter */
refcount_t ref;
};
/**
* Destroy allocated data_t struct
*/
static void data_destroy(data_t *this)
{
DESTROY_IF(this->current);
free(this);
}
/**
* Implementation of shared_key_t.get_type.
*/
static shared_key_type_t get_type(private_shared_key_t *this)
{
return SHARED_IKE;
}
/**
* Implementation of shared_key_t.get_ref.
*/
static private_shared_key_t* get_ref(private_shared_key_t *this)
{
ref_get(&this->ref);
return this;
}
/**
* Implementation of shared_key_t.destroy
*/
static void shared_key_destroy(private_shared_key_t *this)
{
if (ref_put(&this->ref))
{
chunk_free(&this->key);
free(this);
}
}
/**
* Implementation of shared_key_t.get_key.
*/
static chunk_t get_key(private_shared_key_t *this)
{
return this->key;
}
/**
* create a shared key
*/
static shared_key_t *shared_key_create(chunk_t key)
{
private_shared_key_t *this = malloc_thing(private_shared_key_t);
this->public.get_type = (shared_key_type_t(*)(shared_key_t*))get_type;
this->public.get_key = (chunk_t(*)(shared_key_t*))get_key;
this->public.get_ref = (shared_key_t*(*)(shared_key_t*))get_ref;
this->public.destroy = (void(*)(shared_key_t*))shared_key_destroy;
this->key = chunk_clone(key);
this->ref = 1;
return &this->public;
}
/**
* filter for enumerator, returns for each SQL result a shared key and match
*/
static bool filter(data_t *this, chunk_t *chunk, shared_key_t **out,
void **unused1, id_match_t *match_me,
void **unused2, id_match_t *match_other)
{
DESTROY_IF(this->current);
this->current = shared_key_create(*chunk);
*out = this->current;
/* we have unique matches only, but do not compare own ID */
if (match_me)
{
*match_me = ID_MATCH_ANY;
}
if (match_other)
{
*match_other = ID_MATCH_PERFECT;
}
return TRUE;
}
/**
* Implements credential_set_t.create_shared_enumerator
*/
static enumerator_t* create_shared_enumerator(private_med_db_creds_t *this,
shared_key_type_t type, identification_t *me,
identification_t *other)
{
enumerator_t *enumerator;
data_t *data;
if (type != SHARED_IKE)
{
return NULL;
}
enumerator = this->db->query(this->db,
"SELECT Psk FROM Peer WHERE PeerId = ?",
DB_BLOB, other->get_encoding(other),
DB_BLOB);
if (enumerator)
{
data = malloc_thing(data_t);
data->current = NULL;
return enumerator_create_filter(enumerator, (void*)filter,
data, (void*)data_destroy);
}
return NULL;
}
/**
* returns null
*/
static void *return_null()
{
return NULL;
}
/**
* Implementation of backend_t.destroy.
*/
static void destroy(private_med_db_creds_t *this)
{
free(this);
}
/**
* Described in header.
*/
med_db_creds_t *med_db_creds_create(database_t *db)
{
private_med_db_creds_t *this = malloc_thing(private_med_db_creds_t);
this->public.set.create_private_enumerator = (void*)return_null;
this->public.set.create_cert_enumerator = (void*)return_null;
this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
this->public.set.create_cdp_enumerator = (void*)return_null;
this->public.destroy = (void (*)(med_db_creds_t*))destroy;
this->db = db;
return &this->public;
}
+55
View File
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2007-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
/**
* @defgroup med_db_creds_i med_db_creds
* @{ @ingroup med_db_creds
*/
#ifndef MED_DB_CREDS_H_
#define MED_DB_CREDS_H_
#include <credentials/credential_set.h>
#include <database/database.h>
typedef struct med_db_creds_t med_db_creds_t;
/**
* Mediation credentials database.
*/
struct med_db_creds_t {
/**
* Implements credential_set_t interface
*/
credential_set_t set;
/**
* Destroy the credentials databse.
*/
void (*destroy)(med_db_creds_t *this);
};
/**
* Create the med_db credentials db.
*
* @param database underlying database
* @return credential set implementation on that database
*/
med_db_creds_t *med_db_creds_create(database_t *database);
#endif /* MED_DB_CREDS_H_ @}*/
+88
View File
@@ -0,0 +1,88 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include "med_db_plugin.h"
#include "med_db_creds.h"
#include <daemon.h>
typedef struct private_med_db_plugin_t private_med_db_plugin_t;
/**
* private data of med_db plugin
*/
struct private_med_db_plugin_t {
/**
* implements plugin interface
*/
med_db_plugin_t public;
/**
* database connection instance
*/
database_t *db;
/**
* med_db credential set instance
*/
med_db_creds_t *creds;
};
/**
* Implementation of plugin_t.destroy
*/
static void destroy(private_med_db_plugin_t *this)
{
charon->credentials->remove_set(charon->credentials, &this->creds->set);
this->creds->destroy(this->creds);
free(this);
}
/*
* see header file
*/
plugin_t *plugin_create()
{
char *uri;
private_med_db_plugin_t *this = malloc_thing(private_med_db_plugin_t);
this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
uri = lib->settings->get_str(lib->settings, "plugins.med_db.database", NULL);
if (!uri)
{
DBG1(DBG_CFG, "mediation database URI not defined, skipped");
free(this);
return NULL;
}
if (this->db == NULL)
{
DBG1(DBG_CFG, "opening mediation server database failed");
free(this);
return NULL;
}
this->creds = med_db_creds_create(this->db);
charon->credentials->add_set(charon->credentials, &this->creds->set);
return &this->public.plugin;
}
+49
View File
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
/**
* @defgroup med_db med_db
* @ingroup cplugins
*
* @defgroup med_db_plugin med_db_plugin
* @{ @ingroup med_db
*/
#ifndef MED_DB_PLUGIN_H_
#define MED_DB_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct med_db_plugin_t med_db_plugin_t;
/**
* Mediation server database plugin.
*/
struct med_db_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
/**
* Create a med_db_plugin instance.
*/
plugin_t *plugin_create();
#endif /* MED_DB_PLUGIN_H_ @}*/
+10
View File
@@ -0,0 +1,10 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
AM_CFLAGS = -rdynamic
plugin_LTLIBRARIES = libcharon-sql.la
libcharon_sql_la_SOURCES = sql_plugin.h sql_plugin.c \
sql_config.h sql_config.c
libcharon_sql_la_LDFLAGS = -module
+73
View File
@@ -0,0 +1,73 @@
DROP TABLE IF EXISTS ike_configs;
CREATE TABLE ike_configs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
certreq INTEGER,
force_encap INTEGER,
local TEXT,
remote TEXT
);
DROP TABLE IF EXISTS child_configs;
CREATE TABLE child_configs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
lifetime INTEGER,
rekeytime INTEGER,
jitter INTEGER,
updown TEXT,
hostaccess INTEGER,
mode INTEGER
);
DROP TABLE IF EXISTS peer_config_child_config;
CREATE TABLE peer_config_child_config (
peer_cfg INTEGER,
child_cfg INTEGER
);
DROP TABLE IF EXISTS traffic_selectors;
CREATE TABLE traffic_selectors (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type INTEGER,
protocol INTEGER,
start_addr TEXT,
end_addr TEXT,
start_port INTEGER,
end_port INTEGER
);
DROP TABLE IF EXISTS child_config_traffic_selector;
CREATE TABLE child_config_traffic_selector (
child_cfg INTEGER,
traffic_selector INTEGER,
kind INTEGER
);
DROP TABLE IF EXISTS peer_configs;
CREATE TABLE peer_configs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
ike_version INTEGER,
ike_cfg INTEGER,
local_id TEXT,
remote_id TEXT,
cert_policy INTEGER,
auth_method INTEGER,
eap_type INTEGER,
eap_vendor INTEGER,
keyingtries INTEGER,
rekeytime INTEGER,
reauthtime INTEGER,
jitter INTEGER,
overtime INTEGER,
mobike INTEGER,
dpd_delay INTEGER,
dpd_action INTEGER,
local_vip TEXT,
remote_vip TEXT,
mediation INTEGER,
mediated_by INTEGER,
peer_id TEXT
);
+24
View File
@@ -0,0 +1,24 @@
DROP TABLE IF EXISTS shared_secrets;
CREATE TABLE shared_secrets (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type INTEGER,
local TEXT,
remote TEXT
);
DROP TABLE IF EXISTS certificates;
CREATE TABLE certificates (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type INTEGER,
subject TEXT,
data BLOB,
);
DROP TABLE IF EXISTS private_keys;
CREATE TABLE private_keys (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type INTEGER,
keyid BLOB,
data BLOB,
);
+538
View File
@@ -0,0 +1,538 @@
/*
* Copyright (C) 2006-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include <string.h>
#include "sql_config.h"
#include <daemon.h>
typedef struct private_sql_config_t private_sql_config_t;
/**
* Private data of an sql_config_t object
*/
struct private_sql_config_t {
/**
* Public part
*/
sql_config_t public;
/**
* database connection
*/
database_t *db;
};
/**
* forward declaration
*/
static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
identification_t *me, identification_t *other);
/**
* build a traffic selector from a SQL query
*/
static traffic_selector_t *build_traffic_selector(private_sql_config_t *this,
enumerator_t *e, bool *local)
{
int type, protocol, start_port, end_port;
char *start_addr, *end_addr;
traffic_selector_t *ts;
enum {
TS_LOCAL = 0,
TS_REMOTE = 1,
TS_LOCAL_DYNAMIC = 2,
TS_REMOTE_DYNAMIC = 3,
} kind;
while (e->enumerate(e, &kind, &type, &protocol,
&start_addr, &end_addr, &start_port, &end_port))
{
*local = FALSE;
switch (kind)
{
case TS_LOCAL:
*local = TRUE;
/* FALL */
case TS_REMOTE:
ts = traffic_selector_create_from_string(protocol, type,
start_addr, start_port, end_addr, end_port);
break;
case TS_LOCAL_DYNAMIC:
*local = TRUE;
/* FALL */
case TS_REMOTE_DYNAMIC:
ts = traffic_selector_create_dynamic(protocol, type,
start_port, end_port);
break;
default:
continue;
}
if (ts)
{
return ts;
}
}
return NULL;
}
/**
* Add traffic selectors to a child config
*/
static void add_traffic_selectors(private_sql_config_t *this,
child_cfg_t *child, int id)
{
enumerator_t *e;
traffic_selector_t *ts;
bool local;
e = this->db->query(this->db,
"SELECT kind, type, protocol, "
"start_addr, end_addr, start_port, end_port "
"FROM traffic_selectors JOIN child_config_traffic_selector "
"ON id = traffic_selector WHERE child_cfg = ?",
DB_INT, id,
DB_INT, DB_INT, DB_INT,
DB_TEXT, DB_TEXT, DB_INT, DB_INT);
if (e)
{
while ((ts = build_traffic_selector(this, e, &local)))
{
child->add_traffic_selector(child, local, ts);
}
e->destroy(e);
}
}
/**
* build a Child configuration from a SQL query
*/
static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
{
int id, lifetime, rekeytime, jitter, hostaccess, mode;
char *name, *updown;
child_cfg_t *child_cfg;
if (e->enumerate(e, &id, &name, &lifetime, &rekeytime, &jitter,
&updown, &hostaccess, &mode))
{
child_cfg = child_cfg_create(name, lifetime, rekeytime, jitter,
updown, hostaccess, mode);
/* TODO: read proposal from db */
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
add_traffic_selectors(this, child_cfg, id);
return child_cfg;
}
return NULL;
}
/**
* Add child configs to peer config
*/
static void add_child_cfgs(private_sql_config_t *this, peer_cfg_t *peer, int id)
{
enumerator_t *e;
child_cfg_t *child_cfg;
e = this->db->query(this->db,
"SELECT id, name, lifetime, rekeytime, jitter, "
"updown, hostaccess, mode "
"FROM child_configs JOIN peer_config_child_config ON id = child_cfg "
"WHERE peer_cfg = ?",
DB_INT, id,
DB_INT, DB_TEXT, DB_INT, DB_INT, DB_INT,
DB_TEXT, DB_INT, DB_INT);
if (e)
{
while ((child_cfg = build_child_cfg(this, e)))
{
peer->add_child_cfg(peer, child_cfg);
}
e->destroy(e);
}
}
/**
* build a ike configuration from a SQL query
*/
static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e,
host_t *my_host, host_t *other_host)
{
int certreq, force_encap;
char *local, *remote;
while (e->enumerate(e, &certreq, &force_encap, &local, &remote))
{
host_t *me, *other;
ike_cfg_t *ike_cfg;
me = host_create_from_string(local, 500);
if (!me)
{
continue;
}
if (my_host && !me->is_anyaddr(me) &&
!me->ip_equals(me, my_host))
{
me->destroy(me);
continue;
}
other = host_create_from_string(remote, 500);
if (!other)
{
me->destroy(me);
continue;
}
if (other_host && !other->is_anyaddr(other) &&
!other->ip_equals(other, other_host))
{
me->destroy(me);
other->destroy(other);
continue;
}
ike_cfg = ike_cfg_create(certreq, force_encap, me, other);
/* TODO: read proposal from db */
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
return ike_cfg;
}
return NULL;
}
/**
* Query a IKE config by its id
*/
static ike_cfg_t* get_ike_cfg_by_id(private_sql_config_t *this, int id)
{
enumerator_t *e;
ike_cfg_t *ike_cfg = NULL;
e = this->db->query(this->db,
"SELECT certreq, force_encap, local, remote "
"FROM ike_configs WHERE id = ?",
DB_INT, id,
DB_INT, DB_INT, DB_TEXT, DB_TEXT);
if (e)
{
ike_cfg = build_ike_cfg(this, e, NULL, NULL);
e->destroy(e);
}
return ike_cfg;
}
/**
* Query a peer config by its id
*/
static peer_cfg_t *get_peer_cfg_by_id(private_sql_config_t *this, int id)
{
enumerator_t *e;
peer_cfg_t *peer_cfg = NULL;
e = this->db->query(this->db,
"SELECT id, name, ike_cfg, local_id, remote_id, cert_policy, "
"auth_method, eap_type, eap_vendor, keyingtries, "
"rekeytime, reauthtime, jitter, overtime, mobike, "
"dpd_delay, dpd_action, local_vip, remote_vip, "
"mediation, mediated_by, peer_id "
"FROM peer_configs WHERE id = ?",
DB_INT, id,
DB_INT, DB_INT, DB_TEXT, DB_TEXT, DB_INT,
DB_INT, DB_INT, DB_INT, DB_INT,
DB_INT, DB_INT, DB_INT, DB_INT, DB_INT,
DB_INT, DB_INT, DB_TEXT, DB_TEXT,
DB_INT, DB_INT, DB_TEXT);
if (e)
{
peer_cfg = build_peer_cfg(this, e, NULL, NULL);
e->destroy(e);
}
return peer_cfg;
}
/**
* build a peer configuration from a SQL query
*/
static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
identification_t *me, identification_t *other)
{
int id, ike_cfg, cert_policy, auth_method, eap_type, eap_vendor,
keyingtries, rekeytime, reauthtime, jitter, overtime, mobike,
dpd_delay, dpd_action, mediation, mediated_by;
char *local_id, *remote_id, *local_vip, *remote_vip, *peer_id, *name;
while (e->enumerate(e, &id, &name, &ike_cfg, &local_id, &remote_id, &cert_policy,
&auth_method, &eap_type, &eap_vendor, &keyingtries,
&rekeytime, &reauthtime, &jitter, &overtime, &mobike,
&dpd_delay, &dpd_action, &local_vip, &remote_vip,
&mediation, &mediated_by, &peer_id))
{
ike_cfg_t *ike;
peer_cfg_t *peer_cfg, *mediated_cfg;
identification_t *my_id, *other_id, *peer;
host_t *my_vip, *other_vip;
my_id = identification_create_from_string(local_id);
if (!my_id)
{
continue;
}
if (me && !me->matches(me, my_id))
{
my_id->destroy(my_id);
continue;
}
other_id = identification_create_from_string(remote_id);
if (!other_id)
{
my_id->destroy(my_id);
continue;
}
if (other && !other->matches(other, other_id))
{
other_id->destroy(other_id);
my_id->destroy(my_id);
continue;
}
ike = get_ike_cfg_by_id(this, ike_cfg);
mediated_cfg = mediated_by ? get_peer_cfg_by_id(this, mediated_by) : NULL;
peer = peer_id ? identification_create_from_string(peer_id) : NULL;
my_vip = local_vip ? host_create_from_string(local_vip, 0) : NULL;
other_vip = remote_vip ? host_create_from_string(remote_vip, 0) : NULL;
if (ike)
{
peer_cfg = peer_cfg_create(
name, 2, ike, my_id, other_id, cert_policy,
auth_method, eap_type, eap_vendor, keyingtries,
rekeytime, reauthtime, jitter, overtime, mobike,
dpd_delay, dpd_action, my_vip, other_vip,
mediation, mediated_cfg, peer);
add_child_cfgs(this, peer_cfg, id);
return peer_cfg;
}
DESTROY_IF(ike);
DESTROY_IF(mediated_cfg);
DESTROY_IF(peer);
DESTROY_IF(my_vip);
DESTROY_IF(other_vip);
DESTROY_IF(my_id);
DESTROY_IF(other_id);
}
return NULL;
}
/**
* implements backend_t.get_peer_cfg_by_name.
*/
static peer_cfg_t *get_peer_cfg_by_name(private_sql_config_t *this, char *name)
{
enumerator_t *e;
peer_cfg_t *peer_cfg = NULL;
e = this->db->query(this->db,
"SELECT id, name, ike_cfg, local_id, remote_id, cert_policy, "
"auth_method, eap_type, eap_vendor, keyingtries, "
"rekeytime, reauthtime, jitter, overtime, mobike, "
"dpd_delay, dpd_action, local_vip, remote_vip, "
"mediation, mediated_by, peer_id "
"FROM peer_configs WHERE ike_version = ? AND name = ?",
DB_INT, 2, DB_TEXT, name,
DB_INT, DB_TEXT, DB_INT, DB_TEXT, DB_TEXT, DB_INT,
DB_INT, DB_INT, DB_INT, DB_INT,
DB_INT, DB_INT, DB_INT, DB_INT, DB_INT,
DB_INT, DB_INT, DB_TEXT, DB_TEXT,
DB_INT, DB_INT, DB_TEXT);
if (e)
{
peer_cfg = build_peer_cfg(this, e, NULL, NULL);
e->destroy(e);
}
return peer_cfg;
}
typedef struct {
/** implements enumerator */
enumerator_t public;
/** reference to context */
private_sql_config_t *this;
/** filtering own host */
host_t *me;
/** filtering remote host */
host_t *other;
/** inner SQL enumerator */
enumerator_t *inner;
/** currently enumerated peer config */
ike_cfg_t *current;
} ike_enumerator_t;
/**
* Implementation of ike_enumerator_t.public.enumerate
*/
static bool ike_enumerator_enumerate(ike_enumerator_t *this, ike_cfg_t **cfg)
{
DESTROY_IF(this->current);
this->current = build_ike_cfg(this->this, this->inner, this->me, this->other);
if (this->current)
{
*cfg = this->current;
return TRUE;
}
return FALSE;
}
/**
* Implementation of ike_enumerator_t.public.destroy
*/
static void ike_enumerator_destroy(ike_enumerator_t *this)
{
DESTROY_IF(this->current);
this->inner->destroy(this->inner);
free(this);
}
/**
* Implementation of backend_t.create_ike_cfg_enumerator.
*/
static enumerator_t* create_ike_cfg_enumerator(private_sql_config_t *this,
host_t *me, host_t *other)
{
ike_enumerator_t *e = malloc_thing(ike_enumerator_t);
e->this = this;
e->me = me;
e->other = other;
e->current = NULL;
e->public.enumerate = (void*)ike_enumerator_enumerate;
e->public.destroy = (void*)ike_enumerator_destroy;
e->inner = this->db->query(this->db,
"SELECT certreq, force_encap, local, remote "
"FROM ike_configs",
DB_INT, DB_INT, DB_TEXT, DB_TEXT);
if (!e->inner)
{
free(e);
return NULL;
}
return &e->public;
}
typedef struct {
/** implements enumerator */
enumerator_t public;
/** reference to context */
private_sql_config_t *this;
/** filtering own identity */
identification_t *me;
/** filtering remote identity */
identification_t *other;
/** inner SQL enumerator */
enumerator_t *inner;
/** currently enumerated peer config */
peer_cfg_t *current;
} peer_enumerator_t;
/**
* Implementation of peer_enumerator_t.public.enumerate
*/
static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
{
DESTROY_IF(this->current);
this->current = build_peer_cfg(this->this, this->inner, this->me, this->other);
if (this->current)
{
*cfg = this->current;
return TRUE;
}
return FALSE;
}
/**
* Implementation of peer_enumerator_t.public.destroy
*/
static void peer_enumerator_destroy(peer_enumerator_t *this)
{
DESTROY_IF(this->current);
this->inner->destroy(this->inner);
free(this);
}
/**
* Implementation of backend_t.create_peer_cfg_enumerator.
*/
static enumerator_t* create_peer_cfg_enumerator(private_sql_config_t *this,
identification_t *me,
identification_t *other)
{
peer_enumerator_t *e = malloc_thing(peer_enumerator_t);
e->this = this;
e->me = me;
e->other = other;
e->current = NULL;
e->public.enumerate = (void*)peer_enumerator_enumerate;
e->public.destroy = (void*)peer_enumerator_destroy;
/* TODO: only get configs whose IDs match exactly or contain wildcards */
e->inner = this->db->query(this->db,
"SELECT id, name, ike_cfg, local_id, remote_id, cert_policy, "
"auth_method, eap_type, eap_vendor, keyingtries, "
"rekeytime, reauthtime, jitter, overtime, mobike, "
"dpd_delay, dpd_action, local_vip, remote_vip, "
"mediation, mediated_by, peer_id "
"FROM peer_configs WHERE ike_version = ? ",
DB_INT, 2,
DB_INT, DB_TEXT, DB_INT, DB_TEXT, DB_TEXT, DB_INT,
DB_INT, DB_INT, DB_INT, DB_INT,
DB_INT, DB_INT, DB_INT, DB_INT, DB_INT,
DB_INT, DB_INT, DB_TEXT, DB_TEXT,
DB_INT, DB_INT, DB_TEXT);
if (!e->inner)
{
free(e);
return NULL;
}
return &e->public;
}
/**
* Implementation of sql_config_t.destroy.
*/
static void destroy(private_sql_config_t *this)
{
free(this);
}
/**
* Described in header.
*/
sql_config_t *sql_config_create(database_t *db)
{
private_sql_config_t *this = malloc_thing(private_sql_config_t);
this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator;
this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name;
this->public.destroy = (void(*)(sql_config_t*))destroy;
this->db = db;
return &this->public;
}
+55
View File
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
/**
* @defgroup sql_config_i sql_config
* @{ @ingroup sql_config
*/
#ifndef SQL_CONFIG_H_
#define SQL_CONFIG_H_
#include <config/backend.h>
#include <database/database.h>
typedef struct sql_config_t sql_config_t;
/**
* SQL database configuration backend.
*/
struct sql_config_t {
/**
* Implements backend_t interface
*/
backend_t backend;
/**
* Destry the backend.
*/
void (*destroy)(sql_config_t *this);
};
/**
* Create a sql_config backend instance.
*
* @param db underlying database
* @return backend instance
*/
sql_config_t *sql_config_create(database_t *db);
#endif /* SQL_CONFIG_H_ @}*/
+89
View File
@@ -0,0 +1,89 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include "sql_plugin.h"
#include <daemon.h>
#include "sql_config.h"
typedef struct private_sql_plugin_t private_sql_plugin_t;
/**
* private data of sql plugin
*/
struct private_sql_plugin_t {
/**
* implements plugin interface
*/
sql_plugin_t public;
/**
* database connection instance
*/
database_t *db;
/**
* configuration backend
*/
sql_config_t *config;
};
/**
* Implementation of plugin_t.destroy
*/
static void destroy(private_sql_plugin_t *this)
{
charon->backends->remove_backend(charon->backends, &this->config->backend);
this->config->destroy(this->config);
this->db->destroy(this->db);
free(this);
}
/*
* see header file
*/
plugin_t *plugin_create()
{
char *uri;
private_sql_plugin_t *this;
uri = lib->settings->get_str(lib->settings, "charon.plugins.sql.database", NULL);
if (!uri)
{
DBG1(DBG_CFG, "SQL plugin database URI not set");
return NULL;
}
this = malloc_thing(private_sql_plugin_t);
this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
this->db = lib->db->create(lib->db, uri);
if (!this->db)
{
DBG1(DBG_CFG, "SQL plugin failed to connect to database");
free(this);
return NULL;
}
this->config = sql_config_create(this->db);
charon->backends->add_backend(charon->backends, &this->config->backend);
return &this->public.plugin;
}
+49
View File
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
/**
* @defgroup sql sql
* @ingroup cplugins
*
* @defgroup sql_plugin sql_plugin
* @{ @ingroup sql
*/
#ifndef SQL_PLUGIN_H_
#define SQL_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct sql_plugin_t sql_plugin_t;
/**
* SQL database configuration plugin
*/
struct sql_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
/**
* Create a sql_plugin instance.
*/
plugin_t *plugin_create();
#endif /* SQL_PLUGIN_H_ @}*/
+47
View File
@@ -0,0 +1,47 @@
INSERT INTO ike_configs (
certreq, force_encap, local, remote
) VALUES (
0, 0, '0.0.0.0', '152.96.52.150'
);
INSERT INTO child_configs (
name, lifetime, rekeytime, jitter, updown, hostaccess, mode
) VALUES (
'sqltest', 500, 400, 50, NULL, 1, 1
);
INSERT INTO peer_config_child_config (
peer_cfg, child_cfg
) VALUES (
1, 1
);
INSERT INTO traffic_selectors (
type, protocol
) values (
7, 0
);
INSERT INTO child_config_traffic_selector (
child_cfg, traffic_selector, kind
) VALUES (
1, 1, 2
);
INSERT INTO child_config_traffic_selector (
child_cfg, traffic_selector, kind
) VALUES (
1, 1, 3
);
INSERT INTO peer_configs (
name, ike_version, ike_cfg, local_id, remote_id, cert_policy, auth_method,
eap_type, eap_vendor, keyingtries, rekeytime, reauthtime, jitter, overtime,
mobike, dpd_delay, dpd_action, local_vip, remote_vip,
mediation, mediated_by, peer_id
) VALUES (
'sqltest', 2, 1, 'C=CH, O=Linux strongSwan, CN=martin', 'sidv0150.hsr.ch', 0, 0,
0, 0, 0, 500, 2000, 20, 20,
1, 120, 0, NULL, NULL, 0, 0, NULL
);
+10
View File
@@ -0,0 +1,10 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon -I$(top_srcdir)/src/stroke
AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DIPSEC_PIDDIR=\"${piddir}\"
plugin_LTLIBRARIES = libcharon-stroke.la
libcharon_stroke_la_SOURCES = stroke.h stroke.c
libcharon_stroke_la_LDFLAGS = -module
+3335
View File
File diff suppressed because it is too large Load Diff
+52
View File
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2006-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
/**
* @defgroup stroke stroke
* @ingroup cplugins
*
* @defgroup stroke_i stroke
* @{ @ingroup stroke
*/
#ifndef STROKE_H_
#define STROKE_H_
#include <plugins/plugin.h>
typedef struct stroke_t stroke_t;
/**
* strongSwan 2.x style configuration and control interface.
*
* Stroke is a home-brewed communication interface inspired by whack. It
* uses a unix socket (/var/run/charon.ctl).
*/
struct stroke_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
/**
* Instanciate stroke plugin.
*/
plugin_t *plugin_create();
#endif /* STROKE_H_ @}*/
@@ -0,0 +1,17 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
AM_CFLAGS = -rdynamic
plugin_LTLIBRARIES = libcharon-unit-tester.la
libcharon_unit_tester_la_SOURCES = unit_tester.c unit_tester.h \
tests/test_enumerator.c \
tests/test_auth_info.c \
tests/test_fips_prf.c \
tests/test_curl.c \
tests/test_mysql.c \
tests/test_sqlite.c \
tests/test_mutex.c
libcharon_unit_tester_la_LDFLAGS = -module
+33
View File
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
/**
* @defgroup tests tests
* @{ @ingroup unit_tester
*/
DEFINE_TEST("linked_list_t->remove()", test_list_remove, FALSE)
DEFINE_TEST("simple enumerator", test_enumerate, FALSE)
DEFINE_TEST("nested enumerator", test_enumerate_nested, FALSE)
DEFINE_TEST("filtered enumerator", test_enumerate_filtered, FALSE)
DEFINE_TEST("auth info", test_auth_info, FALSE)
DEFINE_TEST("FIPS PRF", fips_prf_test, FALSE)
DEFINE_TEST("CURL get", test_curl_get, FALSE)
DEFINE_TEST("MySQL operations", test_mysql, FALSE)
DEFINE_TEST("SQLite operations", test_sqlite, FALSE)
DEFINE_TEST("mutex primitive", test_mutex, TRUE)
@@ -0,0 +1,142 @@
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <daemon.h>
#include <library.h>
#include <credentials/auth_info.h>
char buf[] = {0x01,0x02,0x03,0x04};
chunk_t chunk = chunk_from_buf(buf);
char certbuf[] = {
0x30,0x82,0x02,0xfa,0x30,0x82,0x01,0xe2,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x5a,
0xf2,0x65,0xae,0x78,0xff,0x23,0xde,0xf7,0xa6,0xa3,0x94,0x8c,0x3f,0xa0,0xc1,0x30,
0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x39,
0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x19,0x30,
0x17,0x06,0x03,0x55,0x04,0x0a,0x13,0x10,0x4c,0x69,0x6e,0x75,0x78,0x20,0x73,0x74,
0x72,0x6f,0x6e,0x67,0x53,0x77,0x61,0x6e,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04,
0x03,0x13,0x06,0x6d,0x61,0x72,0x74,0x69,0x6e,0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,
0x34,0x32,0x37,0x30,0x37,0x31,0x34,0x32,0x36,0x5a,0x17,0x0d,0x31,0x32,0x30,0x34,
0x32,0x35,0x30,0x37,0x31,0x34,0x32,0x36,0x5a,0x30,0x39,0x31,0x0b,0x30,0x09,0x06,
0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,
0x0a,0x13,0x10,0x4c,0x69,0x6e,0x75,0x78,0x20,0x73,0x74,0x72,0x6f,0x6e,0x67,0x53,
0x77,0x61,0x6e,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04,0x03,0x13,0x06,0x6d,0x61,
0x72,0x74,0x69,0x6e,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,
0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,
0x02,0x82,0x01,0x01,0x00,0xd7,0xb9,0xba,0x4d,0xe2,0x3b,0x3d,0x35,0x7a,0x3f,0x88,
0x67,0x95,0xe7,0xfd,0x9f,0xe9,0x0a,0x0d,0x79,0x3a,0x9e,0x21,0x8f,0xcb,0xe4,0x67,
0x24,0xae,0x0c,0xda,0xb3,0xcc,0xec,0x36,0xb4,0xa8,0x4d,0xf1,0x3d,0xad,0xe4,0x8c,
0x63,0x92,0x54,0xb7,0xb2,0x02,0xa2,0x00,0x62,0x8b,0x04,0xac,0xa0,0x17,0xad,0x17,
0x9a,0x05,0x0d,0xd7,0xb3,0x08,0x02,0xc5,0x26,0xcf,0xdd,0x05,0x42,0xfc,0x13,0x6d,
0x9f,0xb1,0xf3,0x4f,0x82,0x1d,0xef,0x01,0xc9,0x91,0xea,0x37,0x1b,0x79,0x28,0xfa,
0xbf,0x9f,0xb3,0xeb,0x82,0x4f,0x10,0xc6,0x4b,0xa4,0x08,0xf7,0x8e,0xf2,0x00,0xea,
0x04,0x97,0x80,0x9f,0x65,0x86,0xde,0x6b,0xc7,0xda,0x83,0xfc,0xad,0x4a,0xaf,0x52,
0x8b,0x4d,0x33,0xee,0x49,0x87,0x2f,0x3b,0x60,0x45,0x66,0x8f,0xe6,0x89,0xcc,0xb1,
0x92,0x02,0x17,0x2b,0x7b,0x8e,0x90,0x47,0x84,0x84,0x59,0x95,0x81,0xd8,0xe0,0xf3,
0x87,0xe0,0x04,0x09,0xfd,0xcc,0x3a,0x21,0x34,0xfa,0xec,0xbe,0xf5,0x9c,0xcf,0x55,
0x80,0x7b,0xe3,0x75,0x9d,0x36,0x68,0xab,0x83,0xe3,0xad,0x01,0x53,0x0d,0x8a,0x9a,
0xa6,0xb0,0x15,0xc9,0xc5,0xf8,0x9b,0x51,0x32,0xcf,0x97,0x6c,0xfe,0x4a,0x56,0x3c,
0xc8,0x8f,0x4a,0x70,0x23,0x4f,0xf6,0xf7,0xe6,0x9f,0x09,0xcd,0x8f,0xea,0x20,0x7d,
0x34,0xc0,0xc5,0xc0,0x34,0x06,0x6f,0x8b,0xeb,0x04,0x54,0x3f,0x0e,0xcd,0xe2,0x85,
0xab,0x94,0x3e,0x91,0x6c,0x18,0x6f,0x96,0x5d,0xf2,0x8b,0x10,0xe9,0x90,0x43,0xb0,
0x61,0x52,0xac,0xcf,0x75,0x02,0x03,0x01,0x00,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,
0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x09,0x63,
0x42,0xad,0xe5,0xa3,0xf6,0xc9,0x5d,0x08,0xf2,0x78,0x7b,0xeb,0x8a,0xef,0x50,0x00,
0xc8,0xeb,0xe9,0x26,0x94,0xcb,0x84,0x10,0x7e,0x42,0x6b,0x86,0x38,0x57,0xa6,0x02,
0x98,0x5a,0x2c,0x8f,0x44,0x32,0x1b,0x97,0x8c,0x7e,0x4b,0xd8,0xe8,0xe8,0x0f,0x4a,
0xb9,0x31,0x9f,0xf6,0x9f,0x0e,0x67,0x26,0x05,0x2a,0x99,0x14,0x35,0x41,0x47,0x9a,
0xfa,0x12,0x94,0x0b,0xe9,0x27,0x7c,0x71,0x20,0xd7,0x8d,0x3b,0x97,0x19,0x2d,0x15,
0xff,0xa4,0xf3,0x89,0x8d,0x29,0x5f,0xf6,0x3f,0x93,0xaf,0x78,0x61,0xe4,0xe1,0x2e,
0x75,0xc1,0x2c,0xc4,0x76,0x95,0x19,0xf8,0x37,0xdc,0xd8,0x00,0x7a,0x3c,0x0f,0x49,
0x2e,0x88,0x09,0x16,0xb3,0x92,0x33,0xdf,0x77,0x83,0x4f,0xb5,0x9e,0x30,0x8c,0x48,
0x1d,0xd8,0x84,0xfb,0xf1,0xb9,0xa0,0xbe,0x25,0xff,0x4c,0xeb,0xef,0x2b,0xcd,0xfa,
0x0b,0x94,0x66,0x3b,0x28,0x08,0x3f,0x3a,0xda,0x41,0xd0,0x6b,0xab,0x5e,0xbb,0x8a,
0x9f,0xdc,0x98,0x3e,0x59,0x37,0x48,0xbe,0x69,0xde,0x85,0x82,0xf2,0x53,0x8b,0xe4,
0x44,0xe4,0x71,0x91,0x14,0x85,0x0e,0x1e,0x79,0xdd,0x62,0xf5,0xdc,0x25,0x89,0xab,
0x50,0x5b,0xaa,0xae,0xe3,0x64,0x6a,0x23,0x34,0xd7,0x30,0xe2,0x2a,0xc8,0x81,0x0c,
0xec,0xd2,0x31,0xc6,0x1e,0xb6,0xc0,0x57,0xd9,0xe1,0x14,0x06,0x9b,0xf8,0x51,0x69,
0x47,0xf0,0x9c,0xcd,0x69,0xef,0x8e,0x5f,0x62,0xda,0x10,0xf7,0x3c,0x6d,0x0f,0x33,
0xec,0x6f,0xfd,0x94,0x07,0x16,0x41,0x32,0x06,0xa4,0xe1,0x08,0x31,0x87,
};
chunk_t certchunk = chunk_from_buf(certbuf);
/*******************************************************************************
* auth info test
******************************************************************************/
bool test_auth_info()
{
auth_info_t *auth = auth_info_create(), *auth2;
certificate_t *c1, *c2;
enumerator_t *enumerator;
int round = 0;
void *value;
auth_item_t type;
c1 = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, chunk_clone(certchunk),
BUILD_END);
if (!c1)
{
return FALSE;
}
auth->add_item(auth, AUTHN_SUBJECT_CERT, c1);
if (!auth->get_item(auth, AUTHN_SUBJECT_CERT, (void**)&c2))
{
return FALSE;
}
if (!c1->equals(c1, c2))
{
return FALSE;
}
enumerator = auth->create_item_enumerator(auth);
while (enumerator->enumerate(enumerator, &type, &value))
{
round++;
if (round == 1 && type == AUTHN_SUBJECT_CERT && value == c1)
{
continue;
}
return FALSE;
}
enumerator->destroy(enumerator);
auth2 = auth_info_create();
auth2->add_item(auth2, AUTHN_CA_CERT, c1);
auth2->merge(auth2, auth);
round = 0;
enumerator = auth2->create_item_enumerator(auth2);
while (enumerator->enumerate(enumerator, &type, &value))
{
round++;
if (round == 1 && type == AUTHN_CA_CERT && value == c1)
{
continue;
}
if (round == 2 && type == AUTHN_SUBJECT_CERT && value == c1)
{
continue;
}
return FALSE;
}
enumerator->destroy(enumerator);
auth->destroy(auth);
auth2->destroy(auth2);
c1->destroy(c1);
return TRUE;
}
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <daemon.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
/*******************************************************************************
* curl get test
******************************************************************************/
bool test_curl_get()
{
chunk_t chunk;
if (lib->fetcher->fetch(lib->fetcher, "http://www.strongswan.org",
&chunk, FETCH_END) != SUCCESS)
{
return FALSE;
}
free(chunk.ptr);
if (lib->fetcher->fetch(lib->fetcher, "http://www.google.com",
&chunk, FETCH_END) != SUCCESS)
{
return FALSE;
}
free(chunk.ptr);
return TRUE;
}
@@ -0,0 +1,214 @@
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <utils/linked_list.h>
/*******************************************************************************
* linked list remove test
******************************************************************************/
bool test_list_remove()
{
void *a = (void*)1, *b = (void*)2;
linked_list_t *list;
list = linked_list_create();
list->insert_last(list, a);
if (list->remove(list, a, NULL) != 1)
{
return FALSE;
}
list->insert_last(list, a);
list->insert_first(list, a);
list->insert_last(list, a);
list->insert_last(list, b);
if (list->remove(list, a, NULL) != 3)
{
return FALSE;
}
if (list->remove(list, a, NULL) != 0)
{
return FALSE;
}
if (list->get_count(list) != 1)
{
return FALSE;
}
if (list->remove(list, b, NULL) != 1)
{
return FALSE;
}
if (list->remove(list, b, NULL) != 0)
{
return FALSE;
}
list->destroy(list);
return TRUE;
}
/*******************************************************************************
* Simple insert first/last and enumerate test
******************************************************************************/
bool test_enumerate()
{
int round, x;
void *a = (void*)4, *b = (void*)3, *c = (void*)2, *d = (void*)5, *e = (void*)1;
linked_list_t *list;
enumerator_t *enumerator;
list = linked_list_create();
list->insert_last(list, a);
list->insert_first(list, b);
list->insert_first(list, c);
list->insert_last(list, d);
list->insert_first(list, e);
round = 1;
enumerator = list->create_enumerator(list);
while (enumerator->enumerate(enumerator, &x))
{
if (round != x)
{
return FALSE;
}
round++;
}
enumerator->destroy(enumerator);
list->destroy(list);
return TRUE;
}
/*******************************************************************************
* nested enumerator test
******************************************************************************/
static bool bad_data;
static enumerator_t* create_inner(linked_list_t *outer, void *data)
{
if (data != (void*)101)
{
bad_data = TRUE;
}
return outer->create_enumerator(outer);
}
static void destroy_data(void *data)
{
if (data != (void*)101)
{
bad_data = TRUE;
}
}
bool test_enumerate_nested()
{
int round, x;
void *a = (void*)1, *b = (void*)2, *c = (void*)3, *d = (void*)4, *e = (void*)5;
linked_list_t *list, *l1, *l2, *l3;
enumerator_t *enumerator;
bad_data = FALSE;
list = linked_list_create();
l1 = linked_list_create();
l2 = linked_list_create();
l3 = linked_list_create();
list->insert_last(list, l1);
list->insert_last(list, l2);
list->insert_last(list, l3);
l1->insert_last(l1, a);
l1->insert_last(l1, b);
l3->insert_last(l3, c);
l3->insert_last(l3, d);
l3->insert_last(l3, e);
round = 1;
enumerator = enumerator_create_nested(list->create_enumerator(list),
(void*)create_inner, (void*)101, destroy_data);
while (enumerator->enumerate(enumerator, &x))
{
if (round != x)
{
return FALSE;
}
round++;
}
enumerator->destroy(enumerator);
list->destroy(list);
l1->destroy(l1);
l2->destroy(l2);
l3->destroy(l3);
return !bad_data;
}
/*******************************************************************************
* filtered enumerator test
******************************************************************************/
static bool filter(void *data, int *v, int *vo, int *w, int *wo,
int *x, int *xo, int *y, int *yo, int *z, int *zo)
{
int val = *v;
*vo = val++;
*wo = val++;
*xo = val++;
*yo = val++;
*zo = val++;
if (data != (void*)101)
{
return FALSE;
}
return TRUE;
}
bool test_enumerate_filtered()
{
int round, v, w, x, y, z;
void *a = (void*)1, *b = (void*)2, *c = (void*)3, *d = (void*)4, *e = (void*)5;
linked_list_t *list;
enumerator_t *enumerator;
bad_data = FALSE;
list = linked_list_create();
list->insert_last(list, a);
list->insert_last(list, b);
list->insert_last(list, c);
list->insert_last(list, d);
list->insert_last(list, e);
round = 1;
enumerator = enumerator_create_filter(list->create_enumerator(list),
(void*)filter, (void*)101, destroy_data);
while (enumerator->enumerate(enumerator, &v, &w, &x, &y, &z))
{
if (v != round || w != round + 1 || x != round + 2 ||
y != round + 3 || z != round + 4)
{
return FALSE;
}
round++;
}
enumerator->destroy(enumerator);
list->destroy(list);
return !bad_data;
}
@@ -0,0 +1,61 @@
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <utils/linked_list.h>
#include <daemon.h>
/*******************************************************************************
* fips prf known value test
******************************************************************************/
bool fips_prf_test()
{
prf_t *prf;
u_int8_t key_buf[] = {
0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b,
0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f,
0xeb, 0x5a, 0x38, 0xb6
};
u_int8_t seed_buf[] = {
0x00
};
u_int8_t result_buf[] = {
0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f,
0xde, 0x1c, 0x0f, 0xfc, 0x7b, 0x2e, 0x3b, 0x49,
0x8b, 0x26, 0x06, 0x14, 0x3c, 0x6c, 0x18, 0xba,
0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78,
0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16
};
chunk_t key = chunk_from_buf(key_buf);
chunk_t seed = chunk_from_buf(seed_buf);
chunk_t expected = chunk_from_buf(result_buf);
chunk_t result;
prf = lib->crypto->create_prf(lib->crypto, PRF_FIPS_SHA1_160);
if (prf == NULL)
{
return FALSE;
}
prf->set_key(prf, key);
prf->allocate_bytes(prf, seed, &result);
prf->destroy(prf);
if (!chunk_equals(result, expected))
{
chunk_free(&result);
return FALSE;
}
chunk_free(&result);
return TRUE;
}
@@ -0,0 +1,100 @@
/*
* 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 <library.h>
#include <utils/mutex.h>
#include <unistd.h>
#include <sched.h>
#include <pthread.h>
static mutex_t *mutex;
static int locked = 0;
static bool failed = FALSE;
static pthread_barrier_t barrier;
static void* run(void* null)
{
int i;
/* wait for all threads before getting in action */
pthread_barrier_wait(&barrier);
for (i = 0; i < 100; i++)
{
mutex->lock(mutex);
mutex->lock(mutex);
mutex->lock(mutex);
locked++;
sched_yield();
if (locked > 1)
{
failed = TRUE;
}
locked--;
mutex->unlock(mutex);
mutex->unlock(mutex);
mutex->unlock(mutex);
}
return NULL;
}
#define THREADS 20
/*******************************************************************************
* mutex test
******************************************************************************/
bool test_mutex()
{
int i;
pthread_t threads[THREADS];
mutex = mutex_create(MUTEX_RECURSIVE);
for (i = 0; i < 10; i++)
{
mutex->lock(mutex);
mutex->unlock(mutex);
}
for (i = 0; i < 10; i++)
{
mutex->lock(mutex);
}
for (i = 0; i < 10; i++)
{
mutex->unlock(mutex);
}
pthread_barrier_init(&barrier, NULL, THREADS);
for (i = 0; i < THREADS; i++)
{
pthread_create(&threads[i], NULL, run, NULL);
}
for (i = 0; i < THREADS; i++)
{
pthread_join(threads[i], NULL);
}
pthread_barrier_destroy(&barrier);
mutex->destroy(mutex);
return !failed;
}
@@ -0,0 +1,90 @@
/*
* 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 <library.h>
#include <daemon.h>
#include <utils/enumerator.h>
/*******************************************************************************
* mysql simple test
******************************************************************************/
bool test_mysql()
{
database_t *db;
char *txt = "I'm a superduper test";
char buf[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
chunk_t data = chunk_from_buf(buf);
int row;
chunk_t qdata;
char *qtxt;
bool good = FALSE;
enumerator_t *enumerator;
db = lib->db->create(lib->db, "mysql://testuser:testpass@localhost/test");
if (!db)
{
return FALSE;
}
if (db->execute(db, NULL, "CREATE TABLE test ("
"id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, "
"txt TEXT, data BLOB)") < 0)
{
return FALSE;
}
if (db->execute(db, &row, "INSERT INTO test (txt, data) VALUES (?,?)",
DB_TEXT, txt, DB_BLOB, data) < 0)
{
return FALSE;
}
if (row != 1)
{
return FALSE;
}
enumerator = db->query(db, "SELECT txt, data FROM test WHERE id = ?",
DB_INT, row,
DB_TEXT, DB_BLOB);
if (!enumerator)
{
return FALSE;
}
while (enumerator->enumerate(enumerator, &qtxt, &qdata))
{
if (good)
{ /* only one row */
good = FALSE;
break;
}
if (streq(qtxt, txt) && chunk_equals(data, qdata))
{
good = TRUE;
}
}
enumerator->destroy(enumerator);
if (!good)
{
return FALSE;
}
if (db->execute(db, NULL, "DELETE FROM test WHERE id = ?", DB_INT, row) != 1)
{
return FALSE;
}
if (db->execute(db, NULL, "DROP TABLE test") < 0)
{
return FALSE;
}
db->destroy(db);
return TRUE;
}
@@ -0,0 +1,94 @@
/*
* 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 <library.h>
#include <daemon.h>
#include <utils/enumerator.h>
#include <unistd.h>
#define DBFILE "/tmp/strongswan-test.db"
/*******************************************************************************
* sqlite simple test
******************************************************************************/
bool test_sqlite()
{
database_t *db;
char *txt = "I'm a superduper test";
char buf[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
chunk_t data = chunk_from_buf(buf);
int row;
chunk_t qdata;
char *qtxt;
bool good = FALSE;
enumerator_t *enumerator;
db = lib->db->create(lib->db, "sqlite://" DBFILE);
if (!db)
{
return FALSE;
}
if (db->execute(db, NULL, "CREATE TABLE test (txt TEXT, data BLOB)") < 0)
{
return FALSE;
}
if (db->execute(db, &row, "INSERT INTO test (txt, data) VALUES (?,?)",
DB_TEXT, txt, DB_BLOB, data) < 0)
{
return FALSE;
}
if (row != 1)
{
return FALSE;
}
enumerator = db->query(db, "SELECT txt, data FROM test WHERE oid = ?",
DB_INT, row,
DB_TEXT, DB_BLOB);
if (!enumerator)
{
return FALSE;
}
while (enumerator->enumerate(enumerator, &qtxt, &qdata))
{
if (good)
{ /* only one row */
good = FALSE;
break;
}
if (streq(qtxt, txt) && chunk_equals(data, qdata))
{
good = TRUE;
}
}
enumerator->destroy(enumerator);
if (!good)
{
return FALSE;
}
if (db->execute(db, NULL, "DELETE FROM test WHERE oid = ?", DB_INT, row) != 1)
{
return FALSE;
}
if (db->execute(db, NULL, "DROP TABLE test") < 0)
{
return FALSE;
}
db->destroy(db);
unlink(DBFILE);
return TRUE;
}
@@ -0,0 +1,118 @@
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include "unit_tester.h"
#include <daemon.h>
typedef struct private_unit_tester_t private_unit_tester_t;
typedef struct unit_test_t unit_test_t;
typedef enum test_status_t test_status_t;
/**
* private data of unit_tester
*/
struct private_unit_tester_t {
/**
* public functions
*/
unit_tester_t public;
};
struct unit_test_t {
/**
* name of the test
*/
char *name;
/**
* test function
*/
bool (*test)(void);
/**
* run the test?
*/
bool enabled;
};
#undef DEFINE_TEST
#define DEFINE_TEST(name, function, enabled) bool function();
#include <plugins/unit_tester/tests.h>
#undef DEFINE_TEST
#define DEFINE_TEST(name, function, enabled) {name, function, enabled},
static unit_test_t tests[] = {
#include <plugins/unit_tester/tests.h>
};
static void run_tests(private_unit_tester_t *this)
{
int i, run = 0, failed = 0, success = 0, skipped = 0;
DBG1(DBG_CFG, "running unit tests, %d tests registered",
sizeof(tests)/sizeof(unit_test_t));
for (i = 0; i < sizeof(tests)/sizeof(unit_test_t); i++)
{
if (tests[i].enabled)
{
run++;
if (tests[i].test())
{
DBG1(DBG_CFG, "test '%s' successful", tests[i].name);
success++;
}
else
{
DBG1(DBG_CFG, "test '%s' failed", tests[i].name);
failed++;
}
}
else
{
DBG1(DBG_CFG, "test '%s' disabled", tests[i].name);
skipped++;
}
}
DBG1(DBG_CFG, "%d/%d tests successful (%d failed, %d disabled)",
success, run, failed, skipped);
}
/**
* Implementation of 2007_t.destroy
*/
static void destroy(private_unit_tester_t *this)
{
free(this);
}
/*
* see header file
*/
plugin_t *plugin_create()
{
private_unit_tester_t *this = malloc_thing(private_unit_tester_t);
this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
run_tests(this);
return &this->public.plugin;
}
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
/**
* @defgroup unit_tester unit_tester
* @{ @ingroup cplugins
*/
#ifndef UNIT_TESTER_H_
#define UNIT_TESTER_H_
#include <plugins/plugin.h>
typedef struct unit_tester_t unit_tester_t;
/**
* Unit testing plugin.
*
* The unit testing plugin runs tests on plugin initialization. Tests are
* defined in tests.h using the DEFINE_TEST macro. Implementation of the
* tests is done in the tests folder. Each test has uses a function which
* returns TRUE for success or FALSE for failure.
*/
struct unit_tester_t {
/**
* Implements the plugin interface.
*/
plugin_t plugin;
};
/**
* Create a unit_tester plugin.
*/
plugin_t *plugin_create();
#endif /* UNIT_TESTER_H_ @}*/
+10
View File
@@ -0,0 +1,10 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon ${xml_CFLAGS}
AM_CFLAGS = -rdynamic -DIPSEC_PIDDIR=\"${piddir}\"
plugin_LTLIBRARIES = libcharon-xml.la
libcharon_xml_la_SOURCES = xml.h xml.c
libcharon_xml_la_LDFLAGS = -module
libcharon_xml_la_LIBADD = ${xml_LIBS}
+400
View File
@@ -0,0 +1,400 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- strongSwan Managment Protocol (SMP) V1.0 -->
<!--
Copyright (C) 2007 Martin Willi
Copyright (C) 2006 Andreas Eigenmann, Joël Stillhart
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.
-->
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
ns="http://www.strongswan.org/smp/1.0">
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- Message -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<start>
<element name="message">
<choice>
<group>
<attribute name="type">
<value>request</value>
</attribute>
<optional>
<element name="query">
<optional>
<ref name="QueryRequestIkesa"/>
</optional>
<optional>
<ref name="QueryRequestConfig"/>
</optional>
<!-- others -->
</element>
</optional>
<optional>
<element name="control">
<optional>
<ref name="ControlRequestIkeTerminate"/>
</optional>
<optional>
<ref name="ControlRequestChildTerminate"/>
</optional>
<optional>
<ref name="ControlRequestIkeInitiate"/>
</optional>
<optional>
<ref name="ControlRequestChildInitiate"/>
</optional>
<!-- others -->
</element>
</optional>
<!-- others -->
</group>
<group>
<attribute name="type">
<value>response</value>
</attribute>
<choice>
<element name="error">
<attribute name="code">
<data type="nonNegativeInteger"/>
</attribute>
<data type="string"/>
</element>
<group>
<optional>
<element name="query">
<optional>
<ref name="QueryResponseIkesa"/>
</optional>
<optional>
<ref name="QueryResponseConfig"/>
</optional>
<!-- others -->
</element>
</optional>
<optional>
<element name="control">
<optional>
<ref name="ControlResponse"/>
</optional>
<!-- others -->
</element>
</optional>
<!-- others -->
</group>
</choice>
</group>
</choice>
</element>
</start>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- Query -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<define name="QueryRequestIkesa">
<element name="ikesalist">
<empty/>
</element>
</define>
<define name="QueryResponseIkesa">
<element name="ikesalist">
<zeroOrMore>
<element name="ikesa">
<element name="id">
<data type="positiveInteger"/>
</element>
<element name="status">
<choice>
<value type="string">created</value>
<value type="string">connecting</value>
<value type="string">established</value>
<value type="string">rekeying</value>
<value type="string">deleting</value>
</choice>
</element>
<element name="role">
<choice>
<value type="string">initiator</value>
<value type="string">responder</value>
</choice>
</element>
<element name="peerconfig">
<data type="string"/>
</element>
<element name="lifetime">
<data type="integer"/>
</element>
<element name="rekeytime">
<data type="integer"/>
</element>
<element name="local">
<ref name="ikeEnd"/>
</element>
<element name="remote">
<ref name="ikeEnd"/>
</element>
<element name="childsalist">
<zeroOrMore>
<element name="childsa">
<ref name="childsa"/>
</element>
</zeroOrMore>
</element>
</element>
</zeroOrMore>
</element>
</define>
<define name="ikeEnd">
<element name="spi">
<data type="hexBinary" />
</element>
<element name="identification">
<ref name="identification"/>
</element>
<element name="address">
<ref name="address"/>
</element>
<element name="port">
<data type="nonNegativeInteger">
<param name="maxInclusive">65535</param>
</data>
</element>
<optional>
<element name="nat">
<data type="boolean"/>
</element>
</optional>
</define>
<define name="childsa">
<element name="reqid">
<data type="nonNegativeInteger"/>
</element>
<element name="lifetime">
<data type="integer"/>
</element>
<element name="rekeytime">
<data type="integer"/>
</element>
<element name="local">
<ref name="childEnd"/>
</element>
<element name="remote">
<ref name="childEnd"/>
</element>
</define>
<define name="childEnd">
<element name="spi">
<element name="networks">
<ref name="networks">
</element>
</define>
<define name="QueryRequestConfig">
<element name="configlist">
<empty/>
</element>
</define>
<define name="QueryResponseConfig">
<element name="configlist">
<zeroOrMore>
<element name="peerconfig">
<element name="name">
<data type="string"/>
</element>
<element name="local">
<ref name="identification"/>
</element>
<element name="remote">
<ref name="identification"/>
</element>
<element name="ikeconfig">
<ref name="ikeconfig"/>
</element>
<element name="childconfiglist">
<zeroOrMore>
<element name="childconfig">
<ref name="childconfig"/>
</element>
</zeroOrMore>
</element>
</element>
</zeroOrMore>
</element>
</define>
<define name="ikeconfig">
<element name="local">
<ref name="address"/>
</element>
<element name="remote">
<ref name="address"/>
</element>
</define>
<define name="childconfig">
<element name="name">
<data type="string"/>
</element>
<element name="local">
<ref name="networks">
</element>
<element name="remote">
<ref name="networks">
</element>
</define>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- Control -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<define name="ControlRequestIkeTerminate">
<element name="ikesaterminate">
<data type="positiveInteger"/>
</element>
</define>
<define name="ControlRequestChildTerminate">
<element name="childsaterminate">
<data type="positiveInteger"/>
</element>
</define>
<define name="ControlRequestIkeInitiate">
<element name="ikesainitiate">
<data type="string"/>
</element>
</define>
<define name="ControlRequestChildInitiate">
<element name="childsainitiate">
<data type="string"/>
</element>
</define>
<define name="QueryResponse">
<element name="status">
<data type="nonNegativeInteger"/>
</element>
<element name="log">
<zeroOrMore>
<element name="item">
<attribute name="level">
<data type="nonNegativeInteger">
</attribute>
<attribute name="thread">
<data type="nonNegativeInteger">
</attribute>
<attribute name="source">
<data type="string">
</attribute>
<data type="string"/>
<element>
</zeroOrMore>
</element>
</define>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- identification and address -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<define name="identification">
<choice>
<group>
<attribute name="type">
<value>any</value>
</attribute>
<empty/>
</group>
<group>
<attribute name="type">
<value>ipv4</value>
</attribute>
<ref name="ipv4"/>
</group>
<group>
<attribute name="type">
<value>ipv6</value>
</attribute>
<ref name="ipv6"/>
</group>
<group>
<attribute name="type">
<value>fqdn</value>
</attribute>
<ref name="fqdn"/>
</group>
<group>
<attribute name="type">
<value>email</value>
</attribute>
<ref name="email"/>
</group>
<group>
<attribute name="type">
<value>asn1gn</value>
</attribute>
<data type="string"/>
</group>
<group>
<attribute name="type">
<value>asn1dn</value>
</attribute>
<data type="string"/>
</group>
<group>
<attribute name="type">
<value>keyid</value>
</attribute>
<data type="base64Binary"/>
</group>
</choice>
</define>
<define name="address">
<choice>
<group>
<attribute name="type">
<value>ipv4</value>
</attribute>
<ref name="ipv4"/>
</group>
<group>
<attribute name="type">
<value>ipv6</value>
</attribute>
<ref name="ipv6"/>
</group>
</choice>
</define>
<define name="ipv4">
<data type="string">
<param name="pattern">(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(/([0-9]|[1-2][0-9]|3[0-2]))?</param>
</data>
</define>
<define name="ipv6">
<data type="string">
<param name="pattern">([0-9a-fA-F]{1,4}:|:){1,7}([0-9a-fA-F]{1,4}|:)(/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?</param>
</data>
</define>
<define name="fqdn">
<data type="string">
<param name="pattern">[a-z0-9\-](\.[a-z0-9\-]+)*</param>
</data>
</define>
<define name="email">
<data type="string">
<param name="pattern">[a-zA-Z0-9_\-\.]+@(([a-z0-9\-](\.[a-z0-9\-]+)*)|(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]))</param>
</data>
</define>
<define name="networks">
<zeroOrMore>
<element name="network">
<optional>
<attribute name="protocol"/>
</optional>
<optional>
<attribute name="port"/>
</optional>
</element>
</zeroOrMore>
</define>
</grammar>
+749
View File
@@ -0,0 +1,749 @@
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include <stdlib.h>
#include "xml.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <libxml/xmlreader.h>
#include <libxml/xmlwriter.h>
#include <library.h>
#include <daemon.h>
#include <processing/jobs/callback_job.h>
typedef struct private_xml_t private_xml_t;
/**
* Private data of an xml_t object.
*/
struct private_xml_t {
/**
* Public part of xml_t object.
*/
xml_t public;
/**
* XML unix socket fd
*/
int socket;
/**
* job accepting stroke messages
*/
callback_job_t *job;
};
ENUM(ike_sa_state_lower_names, IKE_CREATED, IKE_DELETING,
"created",
"connecting",
"established",
"rekeying",
"deleting",
);
/**
* write a bool into element
*/
static void write_bool(xmlTextWriterPtr writer, char *element, bool val)
{
xmlTextWriterWriteElement(writer, element, val ? "true" : "false");
}
/**
* write a identification_t into element
*/
static void write_id(xmlTextWriterPtr writer, char *element, identification_t *id)
{
xmlTextWriterStartElement(writer, element);
switch (id->get_type(id))
{
{
char *type = "";
while (TRUE)
{
case ID_ANY:
type = "any";
break;
case ID_IPV4_ADDR:
type = "ipv4";
break;
case ID_IPV6_ADDR:
type = "ipv6";
break;
case ID_FQDN:
type = "fqdn";
break;
case ID_RFC822_ADDR:
type = "email";
break;
case ID_DER_ASN1_DN:
type = "asn1dn";
break;
case ID_DER_ASN1_GN:
type = "asn1gn";
break;
}
xmlTextWriterWriteAttribute(writer, "type", type);
xmlTextWriterWriteFormatString(writer, "%D", id);
break;
}
default:
/* TODO: base64 keyid */
xmlTextWriterWriteAttribute(writer, "type", "keyid");
break;
}
xmlTextWriterEndElement(writer);
}
/**
* write a host_t address into an element
*/
static void write_address(xmlTextWriterPtr writer, char *element, host_t *host)
{
xmlTextWriterStartElement(writer, element);
xmlTextWriterWriteAttribute(writer, "type",
host->get_family(host) == AF_INET ? "ipv4" : "ipv6");
if (host->is_anyaddr(host))
{ /* do not use %any for XML */
xmlTextWriterWriteFormatString(writer, "%s",
host->get_family(host) == AF_INET ? "0.0.0.0" : "::");
}
else
{
xmlTextWriterWriteFormatString(writer, "%H", host);
}
xmlTextWriterEndElement(writer);
}
/**
* write networks element
*/
static void write_networks(xmlTextWriterPtr writer, char *element,
linked_list_t *list)
{
iterator_t *iterator;
traffic_selector_t *ts;
xmlTextWriterStartElement(writer, element);
iterator = list->create_iterator(list, TRUE);
while (iterator->iterate(iterator, (void**)&ts))
{
xmlTextWriterStartElement(writer, "network");
xmlTextWriterWriteAttribute(writer, "type",
ts->get_type(ts) == TS_IPV4_ADDR_RANGE ? "ipv4" : "ipv6");
xmlTextWriterWriteFormatString(writer, "%R", ts);
xmlTextWriterEndElement(writer);
}
iterator->destroy(iterator);
xmlTextWriterEndElement(writer);
}
/**
* write a childEnd
*/
static void write_childend(xmlTextWriterPtr writer, child_sa_t *child, bool local)
{
linked_list_t *list;
xmlTextWriterWriteFormatElement(writer, "spi", "%lx",
htonl(child->get_spi(child, local)));
list = child->get_traffic_selectors(child, local);
write_networks(writer, "networks", list);
}
/**
* write a child_sa_t
*/
static void write_child(xmlTextWriterPtr writer, child_sa_t *child)
{
mode_t mode;
encryption_algorithm_t encr;
integrity_algorithm_t int_algo;
size_t encr_len, int_len;
u_int32_t rekey, use_in, use_out, use_fwd;
child_cfg_t *config;
config = child->get_config(child);
child->get_stats(child, &mode, &encr, &encr_len, &int_algo, &int_len,
&rekey, &use_in, &use_out, &use_fwd);
xmlTextWriterStartElement(writer, "childsa");
xmlTextWriterWriteFormatElement(writer, "reqid", "%d", child->get_reqid(child));
xmlTextWriterWriteFormatElement(writer, "childconfig", "%s",
config->get_name(config));
xmlTextWriterStartElement(writer, "local");
write_childend(writer, child, TRUE);
xmlTextWriterEndElement(writer);
xmlTextWriterStartElement(writer, "remote");
write_childend(writer, child, FALSE);
xmlTextWriterEndElement(writer);
xmlTextWriterEndElement(writer);
}
/**
* process a ikesalist query request message
*/
static void request_query_ikesa(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
{
iterator_t *iterator;
ike_sa_t *ike_sa;
/* <ikesalist> */
xmlTextWriterStartElement(writer, "ikesalist");
iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
while (iterator->iterate(iterator, (void**)&ike_sa))
{
ike_sa_id_t *id;
host_t *local, *remote;
iterator_t *children;
child_sa_t *child_sa;
id = ike_sa->get_id(ike_sa);
xmlTextWriterStartElement(writer, "ikesa");
xmlTextWriterWriteFormatElement(writer, "id", "%d",
ike_sa->get_unique_id(ike_sa));
xmlTextWriterWriteFormatElement(writer, "status", "%N",
ike_sa_state_lower_names, ike_sa->get_state(ike_sa));
xmlTextWriterWriteElement(writer, "role",
id->is_initiator(id) ? "initiator" : "responder");
xmlTextWriterWriteElement(writer, "peerconfig", ike_sa->get_name(ike_sa));
/* <local> */
local = ike_sa->get_my_host(ike_sa);
xmlTextWriterStartElement(writer, "local");
xmlTextWriterWriteFormatElement(writer, "spi", "%.16llx",
id->is_initiator(id) ? id->get_initiator_spi(id)
: id->get_responder_spi(id));
write_id(writer, "identification", ike_sa->get_my_id(ike_sa));
write_address(writer, "address", local);
xmlTextWriterWriteFormatElement(writer, "port", "%d",
local->get_port(local));
if (ike_sa->supports_extension(ike_sa, EXT_NATT))
{
write_bool(writer, "nat", ike_sa->has_condition(ike_sa, COND_NAT_HERE));
}
xmlTextWriterEndElement(writer);
/* </local> */
/* <remote> */
remote = ike_sa->get_other_host(ike_sa);
xmlTextWriterStartElement(writer, "remote");
xmlTextWriterWriteFormatElement(writer, "spi", "%.16llx",
id->is_initiator(id) ? id->get_responder_spi(id)
: id->get_initiator_spi(id));
write_id(writer, "identification", ike_sa->get_other_id(ike_sa));
write_address(writer, "address", remote);
xmlTextWriterWriteFormatElement(writer, "port", "%d",
remote->get_port(remote));
if (ike_sa->supports_extension(ike_sa, EXT_NATT))
{
write_bool(writer, "nat", ike_sa->has_condition(ike_sa, COND_NAT_THERE));
}
xmlTextWriterEndElement(writer);
/* </remote> */
/* <childsalist> */
xmlTextWriterStartElement(writer, "childsalist");
children = ike_sa->create_child_sa_iterator(ike_sa);
while (children->iterate(children, (void**)&child_sa))
{
write_child(writer, child_sa);
}
children->destroy(children);
/* </childsalist> */
xmlTextWriterEndElement(writer);
/* </ikesa> */
xmlTextWriterEndElement(writer);
}
iterator->destroy(iterator);
/* </ikesalist> */
xmlTextWriterEndElement(writer);
}
/**
* process a configlist query request message
*/
static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
{
enumerator_t *enumerator;
peer_cfg_t *peer_cfg;
/* <configlist> */
xmlTextWriterStartElement(writer, "configlist");
enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends);
while (enumerator->enumerate(enumerator, (void**)&peer_cfg))
{
enumerator_t *children;
child_cfg_t *child_cfg;
ike_cfg_t *ike_cfg;
linked_list_t *list;
if (peer_cfg->get_ike_version(peer_cfg) != 2)
{ /* only IKEv2 connections yet */
continue;
}
/* <peerconfig> */
xmlTextWriterStartElement(writer, "peerconfig");
xmlTextWriterWriteElement(writer, "name", peer_cfg->get_name(peer_cfg));
write_id(writer, "local", peer_cfg->get_my_id(peer_cfg));
write_id(writer, "remote", peer_cfg->get_other_id(peer_cfg));
/* <ikeconfig> */
ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
xmlTextWriterStartElement(writer, "ikeconfig");
write_address(writer, "local", ike_cfg->get_my_host(ike_cfg));
write_address(writer, "remote", ike_cfg->get_other_host(ike_cfg));
xmlTextWriterEndElement(writer);
/* </ikeconfig> */
/* <childconfiglist> */
xmlTextWriterStartElement(writer, "childconfiglist");
children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
while (children->enumerate(children, &child_cfg))
{
/* <childconfig> */
xmlTextWriterStartElement(writer, "childconfig");
xmlTextWriterWriteElement(writer, "name",
child_cfg->get_name(child_cfg));
list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
write_networks(writer, "local", list);
list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
write_networks(writer, "remote", list);
list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
xmlTextWriterEndElement(writer);
/* </childconfig> */
}
children->destroy(children);
/* </childconfiglist> */
xmlTextWriterEndElement(writer);
/* </peerconfig> */
xmlTextWriterEndElement(writer);
}
enumerator->destroy(enumerator);
/* </configlist> */
xmlTextWriterEndElement(writer);
}
/**
* callback which logs to a XML writer
*/
static bool xml_callback(xmlTextWriterPtr writer, signal_t signal, level_t level,
ike_sa_t* ike_sa, char* format, va_list args)
{
if (level <= 1)
{
/* <item> */
xmlTextWriterStartElement(writer, "item");
xmlTextWriterWriteFormatAttribute(writer, "level", "%d", level);
xmlTextWriterWriteFormatAttribute(writer, "source", "%N", signal_names, signal);
xmlTextWriterWriteFormatAttribute(writer, "thread", "%u", pthread_self());
xmlTextWriterWriteVFormatString(writer, format, args);
xmlTextWriterEndElement(writer);
/* </item> */
}
return TRUE;
}
/**
* process a *terminate control request message
*/
static void request_control_terminate(xmlTextReaderPtr reader,
xmlTextWriterPtr writer, bool ike)
{
if (xmlTextReaderRead(reader) &&
xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT)
{
const char *str;
u_int32_t id;
status_t status;
str = xmlTextReaderConstValue(reader);
if (str == NULL || !(id = atoi(str)))
{
DBG1(DBG_CFG, "error parsing XML id string");
return;
}
DBG1(DBG_CFG, "terminating %s_SA %d", ike ? "IKE" : "CHILD", id);
/* <log> */
xmlTextWriterStartElement(writer, "log");
if (ike)
{
status = charon->controller->terminate_ike(
charon->controller, id,
(controller_cb_t)xml_callback, writer);
}
else
{
status = charon->controller->terminate_child(
charon->controller, id,
(controller_cb_t)xml_callback, writer);
}
/* </log> */
xmlTextWriterEndElement(writer);
xmlTextWriterWriteFormatElement(writer, "status", "%d", status);
}
}
/**
* process a *initiate control request message
*/
static void request_control_initiate(xmlTextReaderPtr reader,
xmlTextWriterPtr writer, bool ike)
{
if (xmlTextReaderRead(reader) &&
xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT)
{
const char *str;
status_t status = FAILED;
peer_cfg_t *peer;
child_cfg_t *child = NULL;
enumerator_t *enumerator;
str = xmlTextReaderConstValue(reader);
if (str == NULL)
{
DBG1(DBG_CFG, "error parsing XML config name string");
return;
}
DBG1(DBG_CFG, "initiating %s_SA %s", ike ? "IKE" : "CHILD", str);
/* <log> */
xmlTextWriterStartElement(writer, "log");
peer = charon->backends->get_peer_cfg_by_name(charon->backends, (char*)str);
if (peer)
{
enumerator = peer->create_child_cfg_enumerator(peer);
if (ike)
{
if (!enumerator->enumerate(enumerator, &child))
{
child = NULL;
}
child->get_ref(child);
}
else
{
while (enumerator->enumerate(enumerator, &child))
{
if (streq(child->get_name(child), str))
{
child->get_ref(child);
break;
}
child = NULL;
}
}
enumerator->destroy(enumerator);
if (child)
{
status = charon->controller->initiate(charon->controller,
peer, child, (controller_cb_t)xml_callback,
writer);
}
else
{
peer->destroy(peer);
}
}
/* </log> */
xmlTextWriterEndElement(writer);
xmlTextWriterWriteFormatElement(writer, "status", "%d", status);
}
}
/**
* process a query request
*/
static void request_query(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
{
/* <query> */
xmlTextWriterStartElement(writer, "query");
while (xmlTextReaderRead(reader))
{
if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT)
{
if (streq(xmlTextReaderConstName(reader), "ikesalist"))
{
request_query_ikesa(reader, writer);
break;
}
if (streq(xmlTextReaderConstName(reader), "configlist"))
{
request_query_config(reader, writer);
break;
}
}
}
/* </query> */
xmlTextWriterEndElement(writer);
}
/**
* process a control request
*/
static void request_control(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
{
/* <control> */
xmlTextWriterStartElement(writer, "control");
while (xmlTextReaderRead(reader))
{
if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT)
{
if (streq(xmlTextReaderConstName(reader), "ikesaterminate"))
{
request_control_terminate(reader, writer, TRUE);
break;
}
if (streq(xmlTextReaderConstName(reader), "childsaterminate"))
{
request_control_terminate(reader, writer, FALSE);
break;
}
if (streq(xmlTextReaderConstName(reader), "ikesainitiate"))
{
request_control_initiate(reader, writer, TRUE);
break;
}
if (streq(xmlTextReaderConstName(reader), "childsainitiate"))
{
request_control_initiate(reader, writer, FALSE);
break;
}
}
}
/* </control> */
xmlTextWriterEndElement(writer);
}
/**
* process a request message
*/
static void request(xmlTextReaderPtr reader, char *id, int fd)
{
xmlTextWriterPtr writer;
writer = xmlNewTextWriter(xmlOutputBufferCreateFd(fd, NULL));
if (writer == NULL)
{
DBG1(DBG_CFG, "opening SMP XML writer failed");
return;
}
xmlTextWriterStartDocument(writer, NULL, NULL, NULL);
/* <message xmlns="http://www.strongswan.org/smp/1.0"
id="id" type="response"> */
xmlTextWriterStartElement(writer, "message");
xmlTextWriterWriteAttribute(writer, "xmlns",
"http://www.strongswan.org/smp/1.0");
xmlTextWriterWriteAttribute(writer, "id", id);
xmlTextWriterWriteAttribute(writer, "type", "response");
while (xmlTextReaderRead(reader))
{
if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT)
{
if (streq(xmlTextReaderConstName(reader), "query"))
{
request_query(reader, writer);
break;
}
if (streq(xmlTextReaderConstName(reader), "control"))
{
request_control(reader, writer);
break;
}
}
}
/* </message> and close document */
xmlTextWriterEndDocument(writer);
xmlFreeTextWriter(writer);
}
/**
* cleanup helper function for open file descriptors
*/
static void closefdp(int *fd)
{
close(*fd);
}
/**
* read from a opened connection and process it
*/
static job_requeue_t process(int *fdp)
{
int oldstate, fd = *fdp;
char buffer[4096];
size_t len;
xmlTextReaderPtr reader;
char *id = NULL, *type = NULL;
pthread_cleanup_push((void*)closefdp, (void*)&fd);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
len = read(fd, buffer, sizeof(buffer));
pthread_setcancelstate(oldstate, NULL);
pthread_cleanup_pop(0);
if (len <= 0)
{
close(fd);
DBG2(DBG_CFG, "SMP XML connection closed");
return JOB_REQUEUE_NONE;
}
DBG3(DBG_CFG, "got XML request: %b", buffer, len);
reader = xmlReaderForMemory(buffer, len, NULL, NULL, 0);
if (reader == NULL)
{
DBG1(DBG_CFG, "opening SMP XML reader failed");
return JOB_REQUEUE_FAIR;;
}
/* read message type and id */
while (xmlTextReaderRead(reader))
{
if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT &&
streq(xmlTextReaderConstName(reader), "message"))
{
id = xmlTextReaderGetAttribute(reader, "id");
type = xmlTextReaderGetAttribute(reader, "type");
break;
}
}
/* process message */
if (id && type)
{
if (streq(type, "request"))
{
request(reader, id, fd);
}
else
{
/* response(reader, id) */
}
}
xmlFreeTextReader(reader);
return JOB_REQUEUE_FAIR;;
}
/**
* accept from XML socket and create jobs to process connections
*/
static job_requeue_t dispatch(private_xml_t *this)
{
struct sockaddr_un strokeaddr;
int oldstate, fd, *fdp, strokeaddrlen = sizeof(strokeaddr);
callback_job_t *job;
/* wait for connections, but allow thread to terminate */
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
fd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
pthread_setcancelstate(oldstate, NULL);
if (fd < 0)
{
DBG1(DBG_CFG, "accepting SMP XML socket failed: %s", strerror(errno));
sleep(1);
return JOB_REQUEUE_FAIR;;
}
fdp = malloc_thing(int);
*fdp = fd;
job = callback_job_create((callback_job_cb_t)process, fdp, free, this->job);
charon->processor->queue_job(charon->processor, (job_t*)job);
return JOB_REQUEUE_DIRECT;
}
/**
* Implementation of itnerface_t.destroy.
*/
static void destroy(private_xml_t *this)
{
this->job->cancel(this->job);
close(this->socket);
free(this);
}
/*
* Described in header file
*/
plugin_t *plugin_create()
{
struct sockaddr_un unix_addr = { AF_UNIX, IPSEC_PIDDIR "/charon.xml"};
private_xml_t *this = malloc_thing(private_xml_t);
mode_t old;
this->public.plugin.destroy = (void (*)(plugin_t*))destroy;
/* set up unix socket */
this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (this->socket == -1)
{
DBG1(DBG_CFG, "could not create XML socket");
free(this);
return NULL;
}
unlink(unix_addr.sun_path);
old = umask(~(S_IRWXU | S_IRWXG));
if (bind(this->socket, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) < 0)
{
DBG1(DBG_CFG, "could not bind XML socket: %s", strerror(errno));
close(this->socket);
free(this);
return NULL;
}
umask(old);
if (chown(unix_addr.sun_path, IPSEC_UID, IPSEC_GID) != 0)
{
DBG1(DBG_CFG, "changing XML socket permissions failed: %s", strerror(errno));
}
if (listen(this->socket, 5) < 0)
{
DBG1(DBG_CFG, "could not listen on XML socket: %s", strerror(errno));
close(this->socket);
free(this);
return NULL;
}
this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL);
charon->processor->queue_job(charon->processor, (job_t*)this->job);
return &this->public.plugin;
}
+52
View File
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2007-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
/**
* @defgroup xml xml
* @ingroup cplugins
*
* @defgroup xml_i xml
* @{ @ingroup xml
*/
#ifndef XML_H_
#define XML_H_
#include <plugins/plugin.h>
typedef struct xml_t xml_t;
/**
* XML configuration and control interface.
*
* The XML interface uses a socket and a to communicate. The syntax is strict
* XML, defined in the schema.xml specification.
*/
struct xml_t {
/**
* implements the plugin interface.
*/
plugin_t plugin;
};
/**
* Create a xml plugin instance.
*/
plugin_t *plugin_create();
#endif /* XML_H_ @}*/