merged the modularization branch (credentials) back to trunk
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -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**)¤t))
|
||||
{
|
||||
if (streq(current->get_name(current), name))
|
||||
{
|
||||
found = current;
|
||||
found->get_ref(found);
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* process NetworkManagers startConnection method call
|
||||
*/
|
||||
static bool start_connection(private_dbus_t *this, DBusMessage* msg)
|
||||
{
|
||||
DBusMessage *reply, *signal;
|
||||
char *name, *user, **data, **passwords, **routes;
|
||||
int data_count, passwords_count, routes_count;
|
||||
u_int32_t me, other, p2p, netmask, mss;
|
||||
char *dev, *domain, *banner;
|
||||
const dbus_int32_t array[] = {};
|
||||
const dbus_int32_t *varray = array;
|
||||
peer_cfg_t *peer_cfg;
|
||||
child_cfg_t *child_cfg;
|
||||
status_t status = FAILED;
|
||||
|
||||
dbus_error_free(&this->err);
|
||||
|
||||
if (!dbus_message_get_args(msg, &this->err,
|
||||
DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &user,
|
||||
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &passwords, &passwords_count,
|
||||
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &data, &data_count,
|
||||
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &routes, &routes_count,
|
||||
DBUS_TYPE_INVALID))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
set_state(this, NM_VPN_STATE_STARTING);
|
||||
|
||||
peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, name);
|
||||
if (peer_cfg)
|
||||
{
|
||||
free(this->name);
|
||||
this->name = strdup(peer_cfg->get_name(peer_cfg));
|
||||
child_cfg = get_child_from_peer(peer_cfg, name);
|
||||
if (child_cfg)
|
||||
{
|
||||
status = charon->controller->initiate(charon->controller,
|
||||
peer_cfg, child_cfg, controller_cb_empty, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
peer_cfg->destroy(peer_cfg);
|
||||
}
|
||||
}
|
||||
reply = dbus_message_new_method_return(msg);
|
||||
dbus_connection_send(this->conn, reply, NULL);
|
||||
dbus_message_unref(reply);
|
||||
|
||||
if (status == SUCCESS)
|
||||
{
|
||||
|
||||
set_state(this, NM_VPN_STATE_STARTED);
|
||||
signal = dbus_message_new_signal(NM_DBUS_PATH_STRONG,
|
||||
NM_dbus_STRONG,
|
||||
NM_DBUS_VPN_SIGNAL_IP4_CONFIG);
|
||||
me = other = p2p = mss = netmask = 0;
|
||||
dev = domain = banner = "";
|
||||
if (dbus_message_append_args(signal,
|
||||
DBUS_TYPE_UINT32, &other,
|
||||
DBUS_TYPE_STRING, &dev,
|
||||
DBUS_TYPE_UINT32, &me,
|
||||
DBUS_TYPE_UINT32, &p2p,
|
||||
DBUS_TYPE_UINT32, &netmask,
|
||||
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &varray, 0,
|
||||
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &varray, 0,
|
||||
DBUS_TYPE_UINT32, &mss,
|
||||
DBUS_TYPE_STRING, &domain,
|
||||
DBUS_TYPE_STRING, &banner, DBUS_TYPE_INVALID))
|
||||
{
|
||||
dbus_connection_send(this->conn, signal, NULL);
|
||||
}
|
||||
dbus_message_unref(signal);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_state(this, NM_VPN_STATE_STOPPED);
|
||||
}
|
||||
|
||||
dbus_connection_flush(this->conn);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* process NetworkManagers stopConnection method call
|
||||
*/
|
||||
static bool stop_connection(private_dbus_t *this, DBusMessage* msg)
|
||||
{
|
||||
u_int32_t id;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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
@@ -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_ @}*/
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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
@@ -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_ @}*/
|
||||
@@ -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_ @}*/
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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
|
||||
);
|
||||
@@ -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
|
||||
|
||||
Executable
+3335
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ @}*/
|
||||
Reference in New Issue
Block a user