restructured file layout
new configuration structure: peer_cfg: configuration related to a peer (authenitcation, ...= ike_cfg: config to use for IKE setup (proposals) child_Cfg: config for CHILD_SA (proposals, traffic selectors) a peer_cfg has one ike_cfg and multiple child_cfg's stroke now uses fixed count of threads
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @file backend.h
|
||||
*
|
||||
* @brief Interface backend_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
#ifndef BACKEND_H_
|
||||
#define BACKEND_H_
|
||||
|
||||
typedef struct backend_t backend_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <config/ike_cfg.h>
|
||||
#include <config/peer_cfg.h>
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief The interface for a configuration backend.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - implementations constructor, such as local_backend_create()
|
||||
*
|
||||
* @ingroup backends
|
||||
*/
|
||||
struct backend_t {
|
||||
|
||||
/**
|
||||
* @brief Get an ike_cfg identified by two hosts.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param my_host address of own host
|
||||
* @param other_host address of remote host
|
||||
* @return matching ike_config, or NULL if none found
|
||||
*/
|
||||
ike_cfg_t *(*get_ike_cfg)(backend_t *this,
|
||||
host_t *my_host, host_t *other_host);
|
||||
|
||||
/**
|
||||
* @brief Get a peer_cfg identified by two IDs.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param my_id own ID
|
||||
* @param other_id peers ID
|
||||
* @return matching peer_config, or NULL if none found
|
||||
*/
|
||||
peer_cfg_t *(*get_peer_cfg)(backend_t *this,
|
||||
identification_t *my_id,
|
||||
identification_t *other_id);
|
||||
|
||||
/**
|
||||
* @brief Get a peer_cfg identified by its name.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param name configs name
|
||||
* @return matching peer_config, or NULL if none found
|
||||
*/
|
||||
peer_cfg_t *(*get_peer_cfg_by_name)(backend_t *this, char *name);
|
||||
};
|
||||
|
||||
#endif /* BACKEND_H_ */
|
||||
@@ -0,0 +1,231 @@
|
||||
/**
|
||||
* @file local_backend.c
|
||||
*
|
||||
* @brief Implementation of local_backend_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006 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 <string.h>
|
||||
|
||||
#include "local_backend.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
|
||||
typedef struct private_local_backend_t private_local_backend_t;
|
||||
|
||||
/**
|
||||
* Private data of an local_backend_t object
|
||||
*/
|
||||
struct private_local_backend_t {
|
||||
|
||||
/**
|
||||
* Public part
|
||||
*/
|
||||
local_backend_t public;
|
||||
|
||||
/**
|
||||
* list of configs
|
||||
*/
|
||||
linked_list_t *cfgs;
|
||||
|
||||
/**
|
||||
* Mutex to exclusivly access list
|
||||
*/
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
/**
|
||||
* implements cfg_store_t.get_ike_cfg.
|
||||
*/
|
||||
static ike_cfg_t *get_ike_cfg(private_local_backend_t *this,
|
||||
host_t *my_host, host_t *other_host)
|
||||
{
|
||||
peer_cfg_t *peer;
|
||||
ike_cfg_t *current, *found = NULL;
|
||||
iterator_t *iterator;
|
||||
host_t *my_candidate, *other_candidate;
|
||||
enum {
|
||||
MATCH_NONE = 0x00,
|
||||
MATCH_ANY = 0x01,
|
||||
MATCH_ME = 0x04,
|
||||
MATCH_OTHER = 0x08,
|
||||
} prio, best = MATCH_ANY;
|
||||
|
||||
DBG2(DBG_CFG, "looking for a config for %H...%H",
|
||||
my_host, other_host);
|
||||
|
||||
iterator = this->cfgs->create_iterator_locked(this->cfgs, &this->mutex);
|
||||
while (iterator->iterate(iterator, (void**)&peer))
|
||||
{
|
||||
prio = MATCH_NONE;
|
||||
current = peer->get_ike_cfg(peer);
|
||||
my_candidate = current->get_my_host(current);
|
||||
other_candidate = current->get_other_host(current);
|
||||
|
||||
if (my_candidate->ip_equals(my_candidate, my_host))
|
||||
{
|
||||
prio += MATCH_ME;
|
||||
}
|
||||
else if (my_candidate->is_anyaddr(my_candidate))
|
||||
{
|
||||
prio += MATCH_ANY;
|
||||
}
|
||||
|
||||
if (other_candidate->ip_equals(other_candidate, other_host))
|
||||
{
|
||||
prio += MATCH_OTHER;
|
||||
}
|
||||
else if (other_candidate->is_anyaddr(other_candidate))
|
||||
{
|
||||
prio += MATCH_ANY;
|
||||
}
|
||||
|
||||
DBG2(DBG_CFG, " candidate '%s': %H...%H, prio %d",
|
||||
peer->get_name(peer), my_candidate, other_candidate, prio);
|
||||
|
||||
/* we require at least two MATCH_ANY */
|
||||
if (prio > best)
|
||||
{
|
||||
best = prio;
|
||||
found = current;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
found->get_ref(found);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* implements cfg_store_t.get_peer.
|
||||
*/
|
||||
static peer_cfg_t *get_peer_cfg(private_local_backend_t *this,
|
||||
identification_t *my_id,
|
||||
identification_t *other_id)
|
||||
{
|
||||
peer_cfg_t *current, *found = NULL;
|
||||
iterator_t *iterator;
|
||||
identification_t *my_candidate, *other_candidate;
|
||||
int wc1, wc2, total, best = MAX_WILDCARDS;
|
||||
|
||||
DBG2(DBG_CFG, "looking for a config for %D...%D", my_id, other_id);
|
||||
|
||||
iterator = this->cfgs->create_iterator_locked(this->cfgs, &this->mutex);
|
||||
while (iterator->iterate(iterator, (void**)¤t))
|
||||
{
|
||||
my_candidate = current->get_my_id(current);
|
||||
other_candidate = current->get_other_id(current);
|
||||
|
||||
if (my_candidate->matches(my_candidate, my_id, &wc1) &&
|
||||
other_id->matches(other_id, other_candidate, &wc2))
|
||||
{
|
||||
total = wc1 + wc2;
|
||||
|
||||
DBG2(DBG_CFG, " candidate '%s': %D...%D, wildcards %d",
|
||||
current->get_name(current), my_candidate, other_candidate,
|
||||
total);
|
||||
|
||||
if (total < best)
|
||||
{
|
||||
found = current;
|
||||
best = total;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
found->get_ref(found);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* implements cfg_store_t.get_peer_by_name.
|
||||
*/
|
||||
static peer_cfg_t *get_peer_cfg_by_name(private_local_backend_t *this,
|
||||
char *name)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
peer_cfg_t *current, *found = NULL;
|
||||
|
||||
iterator = this->cfgs->create_iterator(this->cfgs, TRUE);
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of local_backend_t.create_peer_cfg_iterator.
|
||||
*/
|
||||
static iterator_t* create_peer_cfg_iterator(private_local_backend_t *this)
|
||||
{
|
||||
return this->cfgs->create_iterator_locked(this->cfgs, &this->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of local_backend_t.add_peer_cfg.
|
||||
*/
|
||||
static void add_peer_cfg(private_local_backend_t *this, peer_cfg_t *config)
|
||||
{
|
||||
pthread_mutex_lock(&this->mutex);
|
||||
this->cfgs->insert_last(this->cfgs, config);
|
||||
pthread_mutex_unlock(&this->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of local_backend_t.destroy.
|
||||
*/
|
||||
static void destroy(private_local_backend_t *this)
|
||||
{
|
||||
this->cfgs->destroy_offset(this->cfgs, offsetof(peer_cfg_t, destroy));
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
local_backend_t *local_backend_create(void)
|
||||
{
|
||||
private_local_backend_t *this = malloc_thing(private_local_backend_t);
|
||||
|
||||
this->public.backend.get_ike_cfg = (ike_cfg_t*(*)(backend_t*, host_t *, host_t *))get_ike_cfg;
|
||||
this->public.backend.get_peer_cfg = (peer_cfg_t*(*)(backend_t*, identification_t *, identification_t *))get_peer_cfg;
|
||||
this->public.backend.get_peer_cfg_by_name = (peer_cfg_t*(*)(backend_t*, char *))get_peer_cfg_by_name;
|
||||
this->public.create_peer_cfg_iterator = (iterator_t*(*)(local_backend_t*))create_peer_cfg_iterator;
|
||||
this->public.add_peer_cfg = (void(*)(local_backend_t*, peer_cfg_t *))add_peer_cfg;
|
||||
this->public.destroy = (void(*)(local_backend_t*))destroy;
|
||||
|
||||
/* private variables */
|
||||
this->cfgs = linked_list_create();
|
||||
pthread_mutex_init(&this->mutex, NULL);
|
||||
|
||||
return (&this->public);
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* @file local_backend.h
|
||||
*
|
||||
* @brief Interface of local_backend_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef LOCAL_BACKEND_H_
|
||||
#define LOCAL_BACKEND_H_
|
||||
|
||||
typedef struct local_backend_t local_backend_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <config/backends/backend.h>
|
||||
|
||||
/**
|
||||
* @brief An in-memory backend to store configuration information.
|
||||
*
|
||||
* The local_backend_t stores the configuration in a simple list. Additional
|
||||
* to the backend_t functionality, it adds the modification (add/remove).
|
||||
*
|
||||
* @b Constructors:
|
||||
* - local_backend_create()
|
||||
*
|
||||
* @ingroup backends
|
||||
*/
|
||||
struct local_backend_t {
|
||||
|
||||
/**
|
||||
* Implements backend_t interface
|
||||
*/
|
||||
backend_t backend;
|
||||
|
||||
/**
|
||||
* @brief Add a peer_config to the backend.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param config peer_config to add to the backend
|
||||
*/
|
||||
void (*add_peer_cfg)(local_backend_t *this, peer_cfg_t *config);
|
||||
|
||||
/**
|
||||
* @brief Create an iterator over all peer configs.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return iterator over peer configs
|
||||
*/
|
||||
iterator_t* (*create_peer_cfg_iterator)(local_backend_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroy a local backend.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*destroy)(local_backend_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a local_backend_t instance.
|
||||
*
|
||||
* @return local_backend instance.
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
local_backend_t *local_backend_create(void);
|
||||
|
||||
#endif /* LOCAL_BACKEND_H_ */
|
||||
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* @file cfg_store.c
|
||||
*
|
||||
* @brief Implementation of cfg_store_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <pthread.h>
|
||||
|
||||
#include "cfg_store.h"
|
||||
|
||||
#include <library.h>
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
|
||||
typedef struct private_cfg_store_t private_cfg_store_t;
|
||||
|
||||
/**
|
||||
* Private data of an cfg_store_t object.
|
||||
*/
|
||||
struct private_cfg_store_t {
|
||||
|
||||
/**
|
||||
* Public part of cfg_store_t object.
|
||||
*/
|
||||
cfg_store_t public;
|
||||
|
||||
/**
|
||||
* list of registered backends
|
||||
*/
|
||||
linked_list_t *backends;
|
||||
|
||||
/**
|
||||
* mutex to lock backend list
|
||||
*/
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
/**
|
||||
* implements cfg_store_t.get_ike.
|
||||
*/
|
||||
static ike_cfg_t *get_ike_cfg(private_cfg_store_t *this,
|
||||
host_t *my_host, host_t *other_host)
|
||||
{
|
||||
backend_t *backend;
|
||||
ike_cfg_t *config = NULL;
|
||||
iterator_t *iterator = this->backends->create_iterator_locked(
|
||||
this->backends, &this->mutex);
|
||||
while (config == NULL && iterator->iterate(iterator, (void**)&backend))
|
||||
{
|
||||
config = backend->get_ike_cfg(backend, my_host, other_host);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* implements cfg_store_t.get_peer.
|
||||
*/
|
||||
static peer_cfg_t *get_peer_cfg(private_cfg_store_t *this,
|
||||
identification_t *my_id,
|
||||
identification_t *other_id)
|
||||
{
|
||||
backend_t *backend;
|
||||
peer_cfg_t *config = NULL;
|
||||
iterator_t *iterator = this->backends->create_iterator_locked(
|
||||
this->backends, &this->mutex);
|
||||
while (config == NULL && iterator->iterate(iterator, (void**)&backend))
|
||||
{
|
||||
config = backend->get_peer_cfg(backend, my_id, other_id);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* implements cfg_store_t.get_peer_by_name.
|
||||
*/
|
||||
static peer_cfg_t *get_peer_cfg_by_name(private_cfg_store_t *this, char *name)
|
||||
{
|
||||
backend_t *backend;
|
||||
peer_cfg_t *config = NULL;
|
||||
iterator_t *iterator = this->backends->create_iterator_locked(
|
||||
this->backends, &this->mutex);
|
||||
while (config == NULL && iterator->iterate(iterator, (void**)&backend))
|
||||
{
|
||||
config = backend->get_peer_cfg_by_name(backend, name);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* implements cfg_store_t.register_backend.
|
||||
*/
|
||||
static void register_backend(private_cfg_store_t *this, backend_t *backend)
|
||||
{
|
||||
pthread_mutex_lock(&this->mutex);
|
||||
this->backends->insert_last(this->backends, backend);
|
||||
pthread_mutex_unlock(&this->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* implements cfg_store_t.unregister_backend.
|
||||
*/
|
||||
static void unregister_backend(private_cfg_store_t *this, backend_t *backend)
|
||||
{
|
||||
backend_t *current;
|
||||
iterator_t *iterator = this->backends->create_iterator_locked(
|
||||
this->backends, &this->mutex);
|
||||
while (iterator->iterate(iterator, (void**)¤t))
|
||||
{
|
||||
if (backend == current)
|
||||
{
|
||||
iterator->remove(iterator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of cfg_store_t.destroy.
|
||||
*/
|
||||
static void destroy(private_cfg_store_t *this)
|
||||
{
|
||||
this->backends->destroy(this->backends);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header-file
|
||||
*/
|
||||
cfg_store_t *cfg_store_create()
|
||||
{
|
||||
private_cfg_store_t *this = malloc_thing(private_cfg_store_t);
|
||||
|
||||
this->public.get_ike_cfg = (ike_cfg_t*(*)(cfg_store_t*, host_t *, host_t *))get_ike_cfg;
|
||||
this->public.get_peer_cfg = (peer_cfg_t*(*)(cfg_store_t*, identification_t *, identification_t *))get_peer_cfg;
|
||||
this->public.get_peer_cfg_by_name = (peer_cfg_t*(*)(cfg_store_t*, char *name))get_peer_cfg_by_name;
|
||||
this->public.register_backend = (void(*)(cfg_store_t*, backend_t *))register_backend;
|
||||
this->public.unregister_backend = (void(*)(cfg_store_t*, backend_t *))unregister_backend;
|
||||
this->public.destroy = (void(*)(cfg_store_t*))destroy;
|
||||
|
||||
this->backends = linked_list_create();
|
||||
pthread_mutex_init(&this->mutex, NULL);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* @file cfg_store.h
|
||||
*
|
||||
* @brief Interface cfg_store_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CFG_STORE_H_
|
||||
#define CFG_STORE_H_
|
||||
|
||||
typedef struct cfg_store_t cfg_store_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <utils/host.h>
|
||||
#include <utils/identification.h>
|
||||
#include <config/ike_cfg.h>
|
||||
#include <config/peer_cfg.h>
|
||||
#include <config/backends/backend.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief A multiplexer to use multiple cfg_store backends.
|
||||
*
|
||||
* Charon allows the use of multiple cfg_store backends simultaneously. To
|
||||
* access all this backends by a single call, this class wraps multiple
|
||||
* backends behind a single object.
|
||||
* Backends may be registered and unregister at runtime dynamically.
|
||||
*
|
||||
* +---------+ +---------+ +--------------+ |
|
||||
* | | | | +--------------+ | |
|
||||
* | |----->| config | +--------------+ |-+ <==|==> IPC
|
||||
* | | | |------>| backends |-+ |
|
||||
* | daemon |----->| | +--------------+ |
|
||||
* | core | +---------+ |
|
||||
* | | |
|
||||
* | | +---------+ +--------------+ |
|
||||
* | |<-----| | +--------------+ | |
|
||||
* | | | control-| +--------------+ |-+ <==|==> IPC
|
||||
* | |<-----| ler |------>| controllers |-+ |
|
||||
* | | | | +--------------+ |
|
||||
* +---------+ +---------+ |
|
||||
*
|
||||
* The daemon core only knows the simple and single cfg_store interface.
|
||||
* The cfg_store wraps two kind of objects, backends and trustchains.
|
||||
* If the daemon needs something, it asks the cfg_store. cfg_store
|
||||
* asks all of its backends if they can fullfil the request.
|
||||
*
|
||||
*
|
||||
* @b Constructors:
|
||||
* - stroke_create()
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
struct cfg_store_t {
|
||||
|
||||
/**
|
||||
* @brief Get an ike_config identified by two hosts.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param my_host address of own host
|
||||
* @param other_host address of remote host
|
||||
* @return matching ike_config, or NULL if none found
|
||||
*/
|
||||
ike_cfg_t *(*get_ike_cfg)(cfg_store_t *this,
|
||||
host_t *my_host, host_t *other_host);
|
||||
|
||||
/**
|
||||
* @brief Get a peer_config identified by two IDs.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param my_id own ID
|
||||
* @param other_id peers ID
|
||||
* @return matching peer_config, or NULL if none found
|
||||
*/
|
||||
peer_cfg_t *(*get_peer_cfg)(cfg_store_t *this, identification_t *my_id,
|
||||
identification_t *other_id);
|
||||
|
||||
/**
|
||||
* @brief Get a peer_config identified by its name.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param name name of the peer config
|
||||
* @return matching peer_config, or NULL if none found
|
||||
*/
|
||||
peer_cfg_t *(*get_peer_cfg_by_name)(cfg_store_t *this, char *name);
|
||||
|
||||
/**
|
||||
* @brief Register a backend to be queried by the calls above.
|
||||
*
|
||||
* The backend first added is the most preferred.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*register_backend) (cfg_store_t *this, backend_t *backend);
|
||||
|
||||
/**
|
||||
* @brief Unregister a backend.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*unregister_backend) (cfg_store_t *this, backend_t *backend);
|
||||
|
||||
/**
|
||||
* @brief Destroys a cfg_store_t object.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*destroy) (cfg_store_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create a new instance of the store.
|
||||
*
|
||||
* @return cfg_store instance
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
cfg_store_t *cfg_store_create(void);
|
||||
|
||||
#endif /*CFG_STORE_H_*/
|
||||
@@ -0,0 +1,397 @@
|
||||
/**
|
||||
* @file child_cfg.c
|
||||
*
|
||||
* @brief Implementation of child_cfg_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* 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 "child_cfg.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
ENUM(mode_names, MODE_TRANSPORT, MODE_BEET,
|
||||
"TRANSPORT",
|
||||
"TUNNEL",
|
||||
"2",
|
||||
"3",
|
||||
"BEET",
|
||||
);
|
||||
|
||||
typedef struct private_child_cfg_t private_child_cfg_t;
|
||||
|
||||
/**
|
||||
* Private data of an child_cfg_t object
|
||||
*/
|
||||
struct private_child_cfg_t {
|
||||
|
||||
/**
|
||||
* Public part
|
||||
*/
|
||||
child_cfg_t public;
|
||||
|
||||
/**
|
||||
* Number of references hold by others to this child_cfg
|
||||
*/
|
||||
refcount_t refcount;
|
||||
|
||||
/**
|
||||
* Name of the child_cfg, used to query it
|
||||
*/
|
||||
char *name;
|
||||
|
||||
/**
|
||||
* list for all proposals
|
||||
*/
|
||||
linked_list_t *proposals;
|
||||
|
||||
/**
|
||||
* list for traffic selectors for my site
|
||||
*/
|
||||
linked_list_t *my_ts;
|
||||
|
||||
/**
|
||||
* list for traffic selectors for others site
|
||||
*/
|
||||
linked_list_t *other_ts;
|
||||
|
||||
/**
|
||||
* updown script
|
||||
*/
|
||||
char *updown;
|
||||
|
||||
/**
|
||||
* allow host access
|
||||
*/
|
||||
bool hostaccess;
|
||||
|
||||
/**
|
||||
* Mode to propose for a initiated CHILD: tunnel/transport
|
||||
*/
|
||||
mode_t mode;
|
||||
|
||||
/**
|
||||
* Time before an SA gets invalid
|
||||
*/
|
||||
u_int32_t lifetime;
|
||||
|
||||
/**
|
||||
* Time before an SA gets rekeyed
|
||||
*/
|
||||
u_int32_t rekeytime;
|
||||
|
||||
/**
|
||||
* Time, which specifies the range of a random value
|
||||
* substracted from rekeytime.
|
||||
*/
|
||||
u_int32_t jitter;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of child_cfg_t.get_name
|
||||
*/
|
||||
static char *get_name(private_child_cfg_t *this)
|
||||
{
|
||||
return this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of child_cfg_t.add_proposal
|
||||
*/
|
||||
static void add_proposal(private_child_cfg_t *this, proposal_t *proposal)
|
||||
{
|
||||
this->proposals->insert_last(this->proposals, proposal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of child_cfg_t.get_proposals
|
||||
*/
|
||||
static linked_list_t* get_proposals(private_child_cfg_t *this)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
proposal_t *current;
|
||||
linked_list_t *proposals = linked_list_create();
|
||||
|
||||
iterator = this->proposals->create_iterator(this->proposals, TRUE);
|
||||
while (iterator->iterate(iterator, (void**)¤t))
|
||||
{
|
||||
current = current->clone(current);
|
||||
proposals->insert_last(proposals, current);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
|
||||
return proposals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of child_cfg_t.get_name
|
||||
*/
|
||||
static proposal_t* select_proposal(private_child_cfg_t*this, linked_list_t *proposals)
|
||||
{
|
||||
iterator_t *stored_iter, *supplied_iter;
|
||||
proposal_t *stored, *supplied, *selected = NULL;
|
||||
|
||||
stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
|
||||
supplied_iter = proposals->create_iterator(proposals, TRUE);
|
||||
|
||||
/* compare all stored proposals with all supplied. Stored ones are preferred. */
|
||||
while (stored_iter->iterate(stored_iter, (void**)&stored))
|
||||
{
|
||||
supplied_iter->reset(supplied_iter);
|
||||
while (supplied_iter->iterate(supplied_iter, (void**)&supplied))
|
||||
{
|
||||
selected = stored->select(stored, supplied);
|
||||
if (selected)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (selected)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
stored_iter->destroy(stored_iter);
|
||||
supplied_iter->destroy(supplied_iter);
|
||||
return selected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of child_cfg_t.get_name
|
||||
*/
|
||||
static void add_traffic_selector(private_child_cfg_t *this, bool local,
|
||||
traffic_selector_t *ts)
|
||||
{
|
||||
if (local)
|
||||
{
|
||||
this->my_ts->insert_last(this->my_ts, ts);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->other_ts->insert_last(this->other_ts, ts);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of child_cfg_t.get_name
|
||||
*/
|
||||
static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool local,
|
||||
linked_list_t *supplied,
|
||||
host_t *host)
|
||||
{
|
||||
iterator_t *i1, *i2;
|
||||
traffic_selector_t *ts1, *ts2, *selected;
|
||||
linked_list_t *result = linked_list_create();
|
||||
|
||||
if (local)
|
||||
{
|
||||
i1 = this->my_ts->create_iterator(this->my_ts, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
i1 = this->other_ts->create_iterator(this->other_ts, FALSE);
|
||||
}
|
||||
|
||||
/* no list supplied, just fetch the stored traffic selectors */
|
||||
if (supplied == NULL)
|
||||
{
|
||||
while (i1->iterate(i1, (void**)&ts1))
|
||||
{
|
||||
/* we make a copy of the TS, this allows us to update dynamic TS' */
|
||||
ts1 = ts1->clone(ts1);
|
||||
if (host)
|
||||
{
|
||||
ts1->set_address(ts1, host);
|
||||
}
|
||||
result->insert_last(result, ts1);
|
||||
}
|
||||
i1->destroy(i1);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG2(DBG_CFG, "selecting traffic selectors");
|
||||
i2 = supplied->create_iterator(supplied, TRUE);
|
||||
/* iterate over all stored selectors */
|
||||
while (i1->iterate(i1, (void**)&ts1))
|
||||
{
|
||||
/* we make a copy of the TS, as we have to update dynamic TS' */
|
||||
ts1 = ts1->clone(ts1);
|
||||
if (host)
|
||||
{
|
||||
ts1->set_address(ts1, host);
|
||||
}
|
||||
|
||||
i2->reset(i2);
|
||||
/* iterate over all supplied traffic selectors */
|
||||
while (i2->iterate(i2, (void**)&ts2))
|
||||
{
|
||||
DBG2(DBG_CFG, "stored %R <=> %R received", ts1, ts2);
|
||||
selected = ts1->get_subset(ts1, ts2);
|
||||
if (selected)
|
||||
{
|
||||
result->insert_last(result, selected);
|
||||
DBG2(DBG_CFG, "found traffic selector for %s: %R",
|
||||
local ? "us" : "other", selected);
|
||||
}
|
||||
}
|
||||
ts1->destroy(ts1);
|
||||
}
|
||||
i1->destroy(i1);
|
||||
i2->destroy(i2);
|
||||
}
|
||||
|
||||
/* remove any redundant traffic selectors in the list */
|
||||
i1 = result->create_iterator(result, TRUE);
|
||||
i2 = result->create_iterator(result, TRUE);
|
||||
while (i1->iterate(i1, (void**)&ts1))
|
||||
{
|
||||
while (i2->iterate(i2, (void**)&ts2))
|
||||
{
|
||||
if (ts1 != ts2)
|
||||
{
|
||||
if (ts2->is_contained_in(ts2, ts1))
|
||||
{
|
||||
i2->remove(i2);
|
||||
ts2->destroy(ts2);
|
||||
i1->reset(i1);
|
||||
break;
|
||||
}
|
||||
if (ts1->is_contained_in(ts1, ts2))
|
||||
{
|
||||
i1->remove(i1);
|
||||
ts1->destroy(ts1);
|
||||
i2->reset(i2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i1->destroy(i1);
|
||||
i2->destroy(i2);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of child_cfg_t.get_name
|
||||
*/
|
||||
static char* get_updown(private_child_cfg_t *this)
|
||||
{
|
||||
return this->updown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of child_cfg_t.get_name
|
||||
*/
|
||||
static bool get_hostaccess(private_child_cfg_t *this)
|
||||
{
|
||||
return this->hostaccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of child_cfg_t.get_name
|
||||
*/
|
||||
static u_int32_t get_lifetime(private_child_cfg_t *this, bool rekey)
|
||||
{
|
||||
if (rekey)
|
||||
{
|
||||
if (this->jitter == 0)
|
||||
{
|
||||
return this->rekeytime;
|
||||
}
|
||||
return this->rekeytime - (random() % this->jitter);
|
||||
}
|
||||
return this->lifetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of child_cfg_t.get_name
|
||||
*/
|
||||
static mode_t get_mode(private_child_cfg_t *this)
|
||||
{
|
||||
return this->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of child_cfg_t.get_name
|
||||
*/
|
||||
static void get_ref(private_child_cfg_t *this)
|
||||
{
|
||||
ref_get(&this->refcount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements child_cfg_t.destroy.
|
||||
*/
|
||||
static void destroy(private_child_cfg_t *this)
|
||||
{
|
||||
if (ref_put(&this->refcount))
|
||||
{
|
||||
this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
|
||||
this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
|
||||
this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
|
||||
if (this->updown)
|
||||
{
|
||||
free(this->updown);
|
||||
}
|
||||
free(this->name);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header-file
|
||||
*/
|
||||
child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
|
||||
u_int32_t rekeytime, u_int32_t jitter,
|
||||
char *updown, bool hostaccess, mode_t mode)
|
||||
{
|
||||
private_child_cfg_t *this = malloc_thing(private_child_cfg_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.get_name = (char* (*) (child_cfg_t*))get_name;
|
||||
this->public.add_traffic_selector = (void (*)(child_cfg_t*,bool,traffic_selector_t*))add_traffic_selector;
|
||||
this->public.get_traffic_selectors = (linked_list_t*(*)(child_cfg_t*,bool,linked_list_t*,host_t*))get_traffic_selectors;
|
||||
this->public.add_proposal = (void (*) (child_cfg_t*,proposal_t*))add_proposal;
|
||||
this->public.get_proposals = (linked_list_t* (*) (child_cfg_t*))get_proposals;
|
||||
this->public.select_proposal = (proposal_t* (*) (child_cfg_t*,linked_list_t*))select_proposal;
|
||||
this->public.get_updown = (char* (*) (child_cfg_t*))get_updown;
|
||||
this->public.get_hostaccess = (bool (*) (child_cfg_t*))get_hostaccess;
|
||||
this->public.get_mode = (mode_t (*) (child_cfg_t *))get_mode;
|
||||
this->public.get_lifetime = (u_int32_t (*) (child_cfg_t *,bool))get_lifetime;
|
||||
this->public.get_ref = (void (*) (child_cfg_t*))get_ref;
|
||||
this->public.destroy = (void (*) (child_cfg_t*))destroy;
|
||||
|
||||
/* apply init values */
|
||||
this->name = strdup(name);
|
||||
this->lifetime = lifetime;
|
||||
this->rekeytime = rekeytime;
|
||||
this->jitter = jitter;
|
||||
this->updown = updown ? strdup(updown) : NULL;
|
||||
this->hostaccess = hostaccess;
|
||||
this->mode = mode;
|
||||
|
||||
/* initialize private members*/
|
||||
this->refcount = 1;
|
||||
this->proposals = linked_list_create();
|
||||
this->my_ts = linked_list_create();
|
||||
this->other_ts = linked_list_create();
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
/**
|
||||
* @file child_cfg.h
|
||||
*
|
||||
* @brief Interface of child_cfg_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CHILD_CFG_H_
|
||||
#define CHILD_CFG_H_
|
||||
|
||||
typedef enum mode_t mode_t;
|
||||
typedef struct child_cfg_t child_cfg_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <config/proposal.h>
|
||||
#include <config/traffic_selector.h>
|
||||
|
||||
/**
|
||||
* @brief Mode of an CHILD_SA.
|
||||
*
|
||||
* These are equal to those defined in XFRM, so don't change.
|
||||
*
|
||||
* @ingroup child_cfg
|
||||
*/
|
||||
enum mode_t {
|
||||
/** transport mode, no inner address */
|
||||
MODE_TRANSPORT = 0,
|
||||
/** tunnel mode, inner and outer addresses */
|
||||
MODE_TUNNEL = 1,
|
||||
/** BEET mode, tunnel mode but fixed, bound inner addresses */
|
||||
MODE_BEET = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum names for mode_t.
|
||||
*/
|
||||
extern enum_name_t *mode_names;
|
||||
|
||||
/**
|
||||
* @brief A child_cfg_t defines the config template for a CHILD_SA.
|
||||
*
|
||||
* After creation, proposals and traffic selectors may be added to the config.
|
||||
* A child_cfg object is referenced multiple times, and is not thread save.
|
||||
* Reading from the object is save, adding things is not allowed when other
|
||||
* threads may access the object.
|
||||
* A reference counter handles the number of references hold to this config.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - child_cfg_create()
|
||||
*
|
||||
* @ingroup child_cfg
|
||||
*/
|
||||
struct child_cfg_t {
|
||||
|
||||
/**
|
||||
* @brief Get the name of the child_cfg.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return child_cfg's name
|
||||
*/
|
||||
char *(*get_name) (child_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Add a proposal to the list.
|
||||
*
|
||||
* The proposals are stored by priority, first added
|
||||
* is the most prefered.
|
||||
* After add, proposal is owned by child_cfg.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param proposal proposal to add
|
||||
*/
|
||||
void (*add_proposal) (child_cfg_t *this, proposal_t *proposal);
|
||||
|
||||
/**
|
||||
* @brief Get the list of proposals for the CHILD_SA.
|
||||
*
|
||||
* Resulting list and all of its proposals must be freed after use.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return list of proposals
|
||||
*/
|
||||
linked_list_t* (*get_proposals)(child_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Select a proposal from a supplied list.
|
||||
*
|
||||
* Returned propsal is newly created and must be destroyed after usage.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param proposals list from from wich proposals are selected
|
||||
* @return selected proposal, or NULL if nothing matches
|
||||
*/
|
||||
proposal_t* (*select_proposal)(child_cfg_t*this, linked_list_t *proposals);
|
||||
|
||||
/**
|
||||
* @brief Add a traffic selector to the config.
|
||||
*
|
||||
* Use the "local" parameter to add it for the local or the remote side.
|
||||
* After add, traffic selector is owned by child_cfg.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param local TRUE for local side, FALSE for remote
|
||||
* @param ts traffic_selector to add
|
||||
*/
|
||||
void (*add_traffic_selector)(child_cfg_t *this, bool local,
|
||||
traffic_selector_t *ts);
|
||||
|
||||
/**
|
||||
* @brief Get a list of traffic selectors to use for the CHILD_SA.
|
||||
*
|
||||
* The config contains two set of traffic selectors, one for the local
|
||||
* side, one for the remote side.
|
||||
* If a list with traffic selectors is supplied, these are used to narrow
|
||||
* down the traffic selector list to the greatest common divisor.
|
||||
* Some traffic selector may be "dymamic", meaning they are narrowed down
|
||||
* to a specific address (host-to-host or virtual-IP setups). Use
|
||||
* the "host" parameter to narrow such traffic selectors to that address.
|
||||
* Resulted list and its traffic selectors must be destroyed after use.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param local TRUE for TS on local side, FALSE for remote
|
||||
* @param supplied list with TS to select from, or NULL
|
||||
* @param host address to use for narrowing "dynamic" TS', or NULL
|
||||
* @return list containing the traffic selectors
|
||||
*/
|
||||
linked_list_t *(*get_traffic_selectors)(child_cfg_t *this, bool local,
|
||||
linked_list_t *supplied,
|
||||
host_t *host);
|
||||
|
||||
/**
|
||||
* @brief Get the updown script to run for the CHILD_SA.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return path to updown script
|
||||
*/
|
||||
char* (*get_updown)(child_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Should we allow access to the local host (gateway)?
|
||||
*
|
||||
* @param this calling object
|
||||
* @return value of hostaccess flag
|
||||
*/
|
||||
bool (*get_hostaccess) (child_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the lifetime of a CHILD_SA.
|
||||
*
|
||||
* If "rekey" is set to TRUE, a lifetime is returned before the first
|
||||
* rekeying should be started. If it is FALSE, the actual lifetime is
|
||||
* returned when the CHILD_SA must be deleted.
|
||||
* The rekey time automatically contains a jitter to avoid simlutaneous
|
||||
* rekeying.
|
||||
*
|
||||
* @param this child_cfg
|
||||
* @param rekey TRUE to get rekey time
|
||||
* @return lifetime in seconds
|
||||
*/
|
||||
u_int32_t (*get_lifetime) (child_cfg_t *this, bool rekey);
|
||||
|
||||
/**
|
||||
* @brief Get the mode to use for the CHILD_SA.
|
||||
*
|
||||
* The mode is either tunnel, transport or BEET. The peer must agree
|
||||
* on the method, fallback is tunnel mode.
|
||||
*
|
||||
* @param this child_cfg
|
||||
* @return lifetime in seconds
|
||||
*/
|
||||
mode_t (*get_mode) (child_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get a new reference.
|
||||
*
|
||||
* Get a new reference to this child_cfg by increasing
|
||||
* it's internal reference counter.
|
||||
* Do not call get_ref or any other function until you
|
||||
* already have a reference. Otherwise the object may get
|
||||
* destroyed while calling get_ref(),
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*get_ref) (child_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys the child_cfg object.
|
||||
*
|
||||
* Decrements the internal reference counter and
|
||||
* destroys the child_cfg when it reaches zero.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*destroy) (child_cfg_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create a configuration template for CHILD_SA setup.
|
||||
*
|
||||
* The "name" string gets cloned.
|
||||
* Lifetimes are in seconds. To prevent to peers to start rekeying at the
|
||||
* same time, a jitter may be specified. Rekeying of an SA starts at
|
||||
* (rekeytime - random(0, jitter)). You should specify
|
||||
* lifetime > rekeytime > jitter.
|
||||
* After a call to create, a reference is obtained (refcount = 1).
|
||||
*
|
||||
* @param name name of the child_cfg
|
||||
* @param lifetime lifetime after CHILD_SA expires and gets deleted
|
||||
* @param rekeytime time when rekeying should be initiated
|
||||
* @param jitter range of randomization time to remove from rekeytime
|
||||
* @param updown updown script to execute on up/down event
|
||||
* @param hostaccess TRUE to allow access to the local host
|
||||
* @param mode mode to propose for CHILD_SA, transport, tunnel or BEET
|
||||
* @return child_cfg_t object
|
||||
*
|
||||
* @ingroup child_cfg
|
||||
*/
|
||||
child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
|
||||
u_int32_t rekeytime, u_int32_t jitter,
|
||||
char *updown, bool hostaccess,
|
||||
mode_t mode);
|
||||
|
||||
#endif /* CHILD_CFG_H_ */
|
||||
@@ -1,404 +0,0 @@
|
||||
/**
|
||||
* @file connection.c
|
||||
*
|
||||
* @brief Implementation of connection_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* 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 <string.h>
|
||||
|
||||
#include <config/connections/connection.h>
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
|
||||
"CERT_ALWAYS_SEND",
|
||||
"CERT_SEND_IF_ASKED",
|
||||
"CERT_NEVER_SEND"
|
||||
);
|
||||
|
||||
typedef struct private_connection_t private_connection_t;
|
||||
|
||||
/**
|
||||
* Private data of an connection_t object
|
||||
*/
|
||||
struct private_connection_t {
|
||||
|
||||
/**
|
||||
* Public part
|
||||
*/
|
||||
connection_t public;
|
||||
|
||||
/**
|
||||
* Number of references hold by others to this connection
|
||||
*/
|
||||
refcount_t refcount;
|
||||
|
||||
/**
|
||||
* Name of the connection
|
||||
*/
|
||||
char *name;
|
||||
|
||||
/**
|
||||
* Does charon handle this connection? Or can he ignore it?
|
||||
*/
|
||||
bool ikev2;
|
||||
|
||||
/**
|
||||
* should we send a certificate request?
|
||||
*/
|
||||
cert_policy_t certreq_policy;
|
||||
|
||||
/**
|
||||
* should we send a certificates?
|
||||
*/
|
||||
cert_policy_t cert_policy;
|
||||
|
||||
/**
|
||||
* ID of us
|
||||
*/
|
||||
identification_t *my_id;
|
||||
|
||||
/**
|
||||
* Host information of my host.
|
||||
*/
|
||||
host_t *my_host;
|
||||
|
||||
/**
|
||||
* Host information of other host.
|
||||
*/
|
||||
host_t *other_host;
|
||||
|
||||
/**
|
||||
* Interval to send DPD liveness checks on inactivity
|
||||
*/
|
||||
u_int32_t dpd_delay;
|
||||
|
||||
/**
|
||||
* Number of retransmission sequences to send bevore giving up
|
||||
*/
|
||||
u_int32_t keyingtries;
|
||||
|
||||
/**
|
||||
* Supported proposals
|
||||
*/
|
||||
linked_list_t *proposals;
|
||||
|
||||
/**
|
||||
* Time before an SA gets invalid
|
||||
*/
|
||||
u_int32_t soft_lifetime;
|
||||
|
||||
/**
|
||||
* Time before an SA gets rekeyed
|
||||
*/
|
||||
u_int32_t hard_lifetime;
|
||||
|
||||
/**
|
||||
* Use full reauthentication instead of rekeying
|
||||
*/
|
||||
bool reauth;
|
||||
|
||||
/**
|
||||
* Time, which specifies the range of a random value
|
||||
* substracted from soft_lifetime.
|
||||
*/
|
||||
u_int32_t jitter;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.get_name.
|
||||
*/
|
||||
static char *get_name (private_connection_t *this)
|
||||
{
|
||||
return this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.is_ikev2.
|
||||
*/
|
||||
static bool is_ikev2 (private_connection_t *this)
|
||||
{
|
||||
return this->ikev2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.get_certreq_policy.
|
||||
*/
|
||||
static cert_policy_t get_certreq_policy (private_connection_t *this)
|
||||
{
|
||||
return this->certreq_policy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.get_cert_policy.
|
||||
*/
|
||||
static cert_policy_t get_cert_policy (private_connection_t *this)
|
||||
{
|
||||
return this->cert_policy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.get_my_host.
|
||||
*/
|
||||
static host_t *get_my_host (private_connection_t *this)
|
||||
{
|
||||
return this->my_host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.get_other_host.
|
||||
*/
|
||||
static host_t *get_other_host (private_connection_t *this)
|
||||
{
|
||||
return this->other_host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.get_proposals.
|
||||
*/
|
||||
static linked_list_t* get_proposals(private_connection_t *this)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
proposal_t *current;
|
||||
linked_list_t *proposals = linked_list_create();
|
||||
|
||||
iterator = this->proposals->create_iterator(this->proposals, TRUE);
|
||||
while (iterator->iterate(iterator, (void**)¤t))
|
||||
{
|
||||
current = current->clone(current);
|
||||
proposals->insert_last(proposals, (void*)current);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
|
||||
return proposals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.select_proposal.
|
||||
*/
|
||||
static proposal_t *select_proposal(private_connection_t *this, linked_list_t *proposals)
|
||||
{
|
||||
iterator_t *stored_iter, *supplied_iter;
|
||||
proposal_t *stored, *supplied, *selected;
|
||||
|
||||
stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
|
||||
supplied_iter = proposals->create_iterator(proposals, TRUE);
|
||||
|
||||
/* compare all stored proposals with all supplied. Stored ones are preferred. */
|
||||
while (stored_iter->iterate(stored_iter, (void**)&stored))
|
||||
{
|
||||
supplied_iter->reset(supplied_iter);
|
||||
|
||||
while (supplied_iter->iterate(supplied_iter, (void**)&supplied))
|
||||
{
|
||||
selected = stored->select(stored, supplied);
|
||||
if (selected)
|
||||
{
|
||||
/* they match, return */
|
||||
stored_iter->destroy(stored_iter);
|
||||
supplied_iter->destroy(supplied_iter);
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
|
||||
stored_iter->destroy(stored_iter);
|
||||
supplied_iter->destroy(supplied_iter);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.add_proposal.
|
||||
*/
|
||||
static void add_proposal(private_connection_t *this, proposal_t *proposal)
|
||||
{
|
||||
this->proposals->insert_last(this->proposals, proposal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.get_dpd_delay.
|
||||
*/
|
||||
static u_int32_t get_dpd_delay(private_connection_t *this)
|
||||
{
|
||||
return this->dpd_delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.get_keyingtries.
|
||||
*/
|
||||
static u_int32_t get_keyingtries(private_connection_t *this)
|
||||
{
|
||||
return this->keyingtries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.get_dh_group.
|
||||
*/
|
||||
static diffie_hellman_group_t get_dh_group(private_connection_t *this)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
proposal_t *proposal;
|
||||
algorithm_t *algo;
|
||||
diffie_hellman_group_t dh_group = MODP_NONE;
|
||||
|
||||
iterator = this->proposals->create_iterator(this->proposals, TRUE);
|
||||
while (iterator->iterate(iterator, (void**)&proposal))
|
||||
{
|
||||
if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo))
|
||||
{
|
||||
dh_group = algo->algorithm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return dh_group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.check_dh_group.
|
||||
*/
|
||||
static bool check_dh_group(private_connection_t *this, diffie_hellman_group_t dh_group)
|
||||
{
|
||||
iterator_t *prop_iter, *alg_iter;
|
||||
proposal_t *proposal;
|
||||
algorithm_t *algo;
|
||||
|
||||
prop_iter = this->proposals->create_iterator(this->proposals, TRUE);
|
||||
while (prop_iter->iterate(prop_iter, (void**)&proposal))
|
||||
{
|
||||
alg_iter = proposal->create_algorithm_iterator(proposal, DIFFIE_HELLMAN_GROUP);
|
||||
while (alg_iter->iterate(alg_iter, (void**)&algo))
|
||||
{
|
||||
if (algo->algorithm == dh_group)
|
||||
{
|
||||
prop_iter->destroy(prop_iter);
|
||||
alg_iter->destroy(alg_iter);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
alg_iter->destroy(alg_iter);
|
||||
}
|
||||
prop_iter->destroy(prop_iter);
|
||||
return FALSE;
|
||||
}
|
||||
/**
|
||||
* Implementation of connection_t.get_soft_lifetime
|
||||
*/
|
||||
static u_int32_t get_soft_lifetime(private_connection_t *this)
|
||||
{
|
||||
if (this->jitter == 0)
|
||||
{
|
||||
return this->soft_lifetime ;
|
||||
}
|
||||
return this->soft_lifetime - (random() % this->jitter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.get_hard_lifetime.
|
||||
*/
|
||||
static u_int32_t get_hard_lifetime(private_connection_t *this)
|
||||
{
|
||||
return this->hard_lifetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.get_reauth.
|
||||
*/
|
||||
static bool get_reauth(private_connection_t *this)
|
||||
{
|
||||
return this->reauth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.get_ref.
|
||||
*/
|
||||
static void get_ref(private_connection_t *this)
|
||||
{
|
||||
ref_get(&this->refcount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.destroy.
|
||||
*/
|
||||
static void destroy(private_connection_t *this)
|
||||
{
|
||||
if (ref_put(&this->refcount))
|
||||
{
|
||||
this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
|
||||
this->my_host->destroy(this->my_host);
|
||||
this->other_host->destroy(this->other_host);
|
||||
free(this->name);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
connection_t * connection_create(char *name, bool ikev2,
|
||||
cert_policy_t cert_policy,
|
||||
cert_policy_t certreq_policy,
|
||||
host_t *my_host, host_t *other_host,
|
||||
u_int32_t dpd_delay, bool reauth,
|
||||
u_int32_t keyingtries,
|
||||
u_int32_t hard_lifetime,
|
||||
u_int32_t soft_lifetime, u_int32_t jitter)
|
||||
{
|
||||
private_connection_t *this = malloc_thing(private_connection_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.get_name = (char*(*)(connection_t*))get_name;
|
||||
this->public.is_ikev2 = (bool(*)(connection_t*))is_ikev2;
|
||||
this->public.get_cert_policy = (cert_policy_t(*)(connection_t*))get_cert_policy;
|
||||
this->public.get_certreq_policy = (cert_policy_t(*)(connection_t*))get_certreq_policy;
|
||||
this->public.get_my_host = (host_t*(*)(connection_t*))get_my_host;
|
||||
this->public.get_other_host = (host_t*(*)(connection_t*))get_other_host;
|
||||
this->public.get_proposals = (linked_list_t*(*)(connection_t*))get_proposals;
|
||||
this->public.select_proposal = (proposal_t*(*)(connection_t*,linked_list_t*))select_proposal;
|
||||
this->public.add_proposal = (void(*)(connection_t*, proposal_t*)) add_proposal;
|
||||
this->public.get_dpd_delay = (u_int32_t(*)(connection_t*)) get_dpd_delay;
|
||||
this->public.get_reauth = (bool(*)(connection_t*)) get_reauth;
|
||||
this->public.get_keyingtries = (u_int32_t(*)(connection_t*)) get_keyingtries;
|
||||
this->public.get_dh_group = (diffie_hellman_group_t(*)(connection_t*)) get_dh_group;
|
||||
this->public.check_dh_group = (bool(*)(connection_t*,diffie_hellman_group_t)) check_dh_group;
|
||||
this->public.get_soft_lifetime = (u_int32_t (*) (connection_t *))get_soft_lifetime;
|
||||
this->public.get_hard_lifetime = (u_int32_t (*) (connection_t *))get_hard_lifetime;
|
||||
this->public.get_ref = (void(*)(connection_t*))get_ref;
|
||||
this->public.destroy = (void(*)(connection_t*))destroy;
|
||||
|
||||
/* private variables */
|
||||
this->refcount = 1;
|
||||
this->name = strdup(name);
|
||||
this->ikev2 = ikev2;
|
||||
this->cert_policy = cert_policy;
|
||||
this->certreq_policy = certreq_policy;
|
||||
this->my_host = my_host;
|
||||
this->other_host = other_host;
|
||||
this->dpd_delay = dpd_delay;
|
||||
this->reauth = reauth;
|
||||
this->keyingtries = keyingtries;
|
||||
this->hard_lifetime = hard_lifetime;
|
||||
this->soft_lifetime = soft_lifetime;
|
||||
this->jitter = jitter;
|
||||
|
||||
this->proposals = linked_list_create();
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -1,292 +0,0 @@
|
||||
/**
|
||||
* @file connection.h
|
||||
*
|
||||
* @brief Interface of connection_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CONNECTION_H_
|
||||
#define CONNECTION_H_
|
||||
|
||||
typedef enum cert_policy_t cert_policy_t;
|
||||
typedef struct connection_t connection_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <utils/host.h>
|
||||
#include <utils/linked_list.h>
|
||||
#include <utils/identification.h>
|
||||
#include <config/proposal.h>
|
||||
#include <crypto/diffie_hellman.h>
|
||||
|
||||
|
||||
/**
|
||||
* Certificate sending policy. This is also used for certificate
|
||||
* requests when using this definition for the other peer. If
|
||||
* it is CERT_NEVER_SEND, a certreq is omitted, otherwise its
|
||||
* included.
|
||||
*
|
||||
* @ingroup config
|
||||
*
|
||||
* @warning These definitions must be the same as in pluto/starter,
|
||||
* as they are sent over the stroke socket.
|
||||
*/
|
||||
enum cert_policy_t {
|
||||
/** always send certificates, even when not requested */
|
||||
CERT_ALWAYS_SEND = 0,
|
||||
/** send certificate upon cert request */
|
||||
CERT_SEND_IF_ASKED = 1,
|
||||
/** never send a certificate, even when requested */
|
||||
CERT_NEVER_SEND = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum strings for cert_policy_t
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
extern enum_name_t *cert_policy_names;
|
||||
|
||||
/**
|
||||
* @brief A connection_t defines the rules to set up an IKE_SA.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - connection_create()
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
struct connection_t {
|
||||
|
||||
/**
|
||||
* @brief Get my address as host_t object.
|
||||
*
|
||||
* Object is NOT getting cloned.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return host information as host_t object
|
||||
*/
|
||||
host_t *(*get_my_host) (connection_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get others address as host_t object.
|
||||
*
|
||||
* Object is NOT getting cloned.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return host information as host_t object
|
||||
*/
|
||||
host_t *(*get_other_host) (connection_t *this);
|
||||
|
||||
/**
|
||||
* @brief Returns a list of all supported proposals.
|
||||
*
|
||||
* Returned list and its proposals must be destroyed after usage.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return list containing all the proposals
|
||||
*/
|
||||
linked_list_t *(*get_proposals) (connection_t *this);
|
||||
|
||||
/**
|
||||
* @brief Adds a proposal to the list.
|
||||
*
|
||||
* The first added proposal has the highest priority, the last
|
||||
* added the lowest.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param proposal proposal to add
|
||||
*/
|
||||
void (*add_proposal) (connection_t *this, proposal_t *proposal);
|
||||
|
||||
/**
|
||||
* @brief Select a proposed from suggested proposals.
|
||||
*
|
||||
* Returned proposal must be destroyed after usage.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param proposals list of proposals to select from
|
||||
* @return selected proposal, or NULL if none matches.
|
||||
*/
|
||||
proposal_t *(*select_proposal) (connection_t *this, linked_list_t *proposals);
|
||||
|
||||
/**
|
||||
* @brief Get the DPD check interval.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return dpd_delay in seconds
|
||||
*/
|
||||
u_int32_t (*get_dpd_delay) (connection_t *this);
|
||||
|
||||
/**
|
||||
* @brief Should a full reauthentication be done instead of rekeying?
|
||||
*
|
||||
* @param this calling object
|
||||
* @return TRUE to use full reauthentication
|
||||
*/
|
||||
bool (*get_reauth) (connection_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the max number of retransmission sequences.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return max number of retransmission sequences
|
||||
*/
|
||||
u_int32_t (*get_keyingtries) (connection_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the connection name.
|
||||
*
|
||||
* Name must not be freed, since it points to
|
||||
* internal data.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return name of the connection
|
||||
*/
|
||||
char* (*get_name) (connection_t *this);
|
||||
|
||||
/**
|
||||
* @brief Check if the connection is marked as an IKEv2 connection.
|
||||
*
|
||||
* Since all connections (IKEv1+2) are loaded, but charon handles
|
||||
* only those marked with IKEv2, this flag can tell us if we must
|
||||
* ignore a connection on initiaton. Then pluto will do it for us.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return - TRUE, if this is an IKEv2 connection
|
||||
*/
|
||||
bool (*is_ikev2) (connection_t *this);
|
||||
|
||||
/**
|
||||
* @brief Should be sent a certificate request for this connection?
|
||||
*
|
||||
* A certificate request contains serials of our trusted CA certificates.
|
||||
* This flag says if such a request is sent on connection setup to
|
||||
* the peer. It should be omitted when CERT_SEND_NEVER, sended otherwise.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return certificate request sending policy
|
||||
*/
|
||||
cert_policy_t (*get_certreq_policy) (connection_t *this);
|
||||
|
||||
/**
|
||||
* @brief Should be sent a certificate for this connection?
|
||||
*
|
||||
* Return the policy used to send the certificate.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return certificate sending policy
|
||||
*/
|
||||
cert_policy_t (*get_cert_policy) (connection_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the DH group to use for connection initialization.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return dh group to use for initialization
|
||||
*/
|
||||
diffie_hellman_group_t (*get_dh_group) (connection_t *this);
|
||||
|
||||
/**
|
||||
* @brief Check if a suggested dh group is acceptable.
|
||||
*
|
||||
* If we guess a wrong DH group for IKE_SA_INIT, the other
|
||||
* peer will send us a offer. But is this acceptable for us?
|
||||
*
|
||||
* @param this calling object
|
||||
* @return TRUE if group acceptable
|
||||
*/
|
||||
bool (*check_dh_group) (connection_t *this, diffie_hellman_group_t dh_group);
|
||||
|
||||
/**
|
||||
* @brief Get the lifetime of a connection, before IKE_SA rekeying starts.
|
||||
*
|
||||
* A call to this function automatically adds a jitter to
|
||||
* avoid simultanous rekeying.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return lifetime in seconds
|
||||
*/
|
||||
u_int32_t (*get_soft_lifetime) (connection_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the lifetime of a connection, before IKE_SA gets deleted.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return lifetime in seconds
|
||||
*/
|
||||
u_int32_t (*get_hard_lifetime) (connection_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get a new reference to this connection.
|
||||
*
|
||||
* Get a new reference to this connection by increasing
|
||||
* it's internal reference counter.
|
||||
* Do not call get_ref or any other function until you
|
||||
* already have a reference. Otherwise the object may get
|
||||
* destroyed while calling get_ref(),
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*get_ref) (connection_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys a connection_t object.
|
||||
*
|
||||
* Decrements the internal reference counter and
|
||||
* destroys the connection when it reaches zero.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*destroy) (connection_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a connection_t object.
|
||||
*
|
||||
* Supplied hosts become owned by connection, so
|
||||
* do not modify or destroy them after a call to
|
||||
* connection_create(). Name gets cloned internally.
|
||||
* The retrasmit sequence number says how fast we give up when the peer
|
||||
* does not respond. A high value may bridge-over temporary connection
|
||||
* problems, a small value can detect dead peers faster.
|
||||
*
|
||||
* @param name connection identifier
|
||||
* @param ikev2 TRUE if this is an IKEv2 connection
|
||||
* @param cert_policy certificate send policy
|
||||
* @param cert_req_policy certificate request send policy
|
||||
* @param my_host host_t representing local address
|
||||
* @param other_host host_t representing remote address
|
||||
* @param dpd_delay interval of DPD liveness checks
|
||||
* @param reauth use full reauthentication instead of rekeying
|
||||
* @param keyingtries number of retransmit sequences to use
|
||||
* @param hard_lifetime lifetime before deleting an IKE_SA
|
||||
* @param soft_lifetime lifetime before rekeying an IKE_SA
|
||||
* @param jitter range of randomization time
|
||||
* @return connection_t object.
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
connection_t * connection_create(char *name, bool ikev2,
|
||||
cert_policy_t cert_pol, cert_policy_t req_pol,
|
||||
host_t *my_host, host_t *other_host,
|
||||
u_int32_t dpd_delay, bool reauth,
|
||||
u_int32_t keyingtries,
|
||||
u_int32_t hard_lifetime, u_int32_t soft_lifetime,
|
||||
u_int32_t jitter);
|
||||
|
||||
#endif /* CONNECTION_H_ */
|
||||
@@ -1,118 +0,0 @@
|
||||
/**
|
||||
* @file connection_store.h
|
||||
*
|
||||
* @brief Interface connection_store_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
#ifndef CONNECTION_STORE_H_
|
||||
#define CONNECTION_STORE_H_
|
||||
|
||||
typedef struct connection_store_t connection_store_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <config/connections/connection.h>
|
||||
#include <utils/iterator.h>
|
||||
|
||||
/**
|
||||
* @brief The interface for a store of connection_t's.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - stroke_create()
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
struct connection_store_t {
|
||||
|
||||
/**
|
||||
* @brief Returns a connection definition identified by two hosts.
|
||||
*
|
||||
* This call is usefull to get a connection identified by addresses.
|
||||
* It may be used after kernel request for traffic protection.
|
||||
* The returned connection gets created/cloned and therefore must
|
||||
* be destroyed after usage.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param my_id own address of connection
|
||||
* @param other_id others address of connection
|
||||
* @return
|
||||
* - connection_t, if found
|
||||
* - NULL otherwise
|
||||
*/
|
||||
connection_t *(*get_connection_by_hosts)(connection_store_t *this,
|
||||
host_t *my_host, host_t *other_host);
|
||||
|
||||
/**
|
||||
* @brief Returns a connection identified by its name.
|
||||
*
|
||||
* This call is usefull to get a connection identified its
|
||||
* name, as on an connection setup.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param name name of the connection to get
|
||||
* @return
|
||||
* - connection_t, if found
|
||||
* - NULL otherwise
|
||||
*/
|
||||
connection_t *(*get_connection_by_name) (connection_store_t *this, char *name);
|
||||
|
||||
/**
|
||||
* @brief Add a connection to the store.
|
||||
*
|
||||
* After a successful call, the connection is owned by the store and may
|
||||
* not be manipulated nor destroyed.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param connection connection to add
|
||||
* @return
|
||||
* - SUCCESS, or
|
||||
* - FAILED
|
||||
*/
|
||||
status_t (*add_connection) (connection_store_t *this, connection_t *connection);
|
||||
|
||||
/**
|
||||
* @brief Delete a connection from the store.
|
||||
*
|
||||
* Remove a connection from the connection store, identified
|
||||
* by the connections name.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param name name of the connection to delete
|
||||
* @return
|
||||
* - SUCCESS, or
|
||||
* - NOT_FOUND
|
||||
*/
|
||||
status_t (*delete_connection) (connection_store_t *this, char *name);
|
||||
|
||||
/**
|
||||
* @brief Get an iterator for the stored connections.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return iterator over all stored connections
|
||||
*/
|
||||
iterator_t* (*create_iterator) (connection_store_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys a connection_store_t object.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*destroy) (connection_store_t *this);
|
||||
};
|
||||
|
||||
#endif /* CONNECTION_STORE_H_ */
|
||||
@@ -1,237 +0,0 @@
|
||||
/**
|
||||
* @file local_connection_store.c
|
||||
*
|
||||
* @brief Implementation of local_connection_store_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006 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 <string.h>
|
||||
|
||||
#include "local_connection_store.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
|
||||
typedef struct private_local_connection_store_t private_local_connection_store_t;
|
||||
|
||||
/**
|
||||
* Private data of an local_connection_store_t object
|
||||
*/
|
||||
struct private_local_connection_store_t {
|
||||
|
||||
/**
|
||||
* Public part
|
||||
*/
|
||||
local_connection_store_t public;
|
||||
|
||||
/**
|
||||
* stored connection
|
||||
*/
|
||||
linked_list_t *connections;
|
||||
|
||||
/**
|
||||
* Mutex to exclusivly access connection list
|
||||
*/
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of connection_store_t.get_connection_by_hosts.
|
||||
*/
|
||||
static connection_t *get_connection_by_hosts(private_local_connection_store_t *this, host_t *my_host, host_t *other_host)
|
||||
{
|
||||
typedef enum {
|
||||
PRIO_UNDEFINED= 0x00,
|
||||
PRIO_ADDR_ANY= 0x01,
|
||||
PRIO_ADDR_MATCH= 0x02
|
||||
} prio_t;
|
||||
|
||||
prio_t best_prio = PRIO_UNDEFINED;
|
||||
|
||||
iterator_t *iterator;
|
||||
connection_t *candidate;
|
||||
connection_t *found = NULL;
|
||||
|
||||
DBG2(DBG_CFG, "looking for connection for host pair %H...%H",
|
||||
my_host, other_host);
|
||||
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
iterator = this->connections->create_iterator(this->connections, TRUE);
|
||||
/* determine closest matching connection */
|
||||
while (iterator->iterate(iterator, (void**)&candidate))
|
||||
{
|
||||
host_t *candidate_my_host;
|
||||
host_t *candidate_other_host;
|
||||
|
||||
candidate_my_host = candidate->get_my_host(candidate);
|
||||
candidate_other_host = candidate->get_other_host(candidate);
|
||||
|
||||
/* my_host addresses must match*/
|
||||
if (my_host->ip_equals(my_host, candidate_my_host))
|
||||
{
|
||||
prio_t prio = PRIO_UNDEFINED;
|
||||
|
||||
/* exact match of peer host address or wildcard address? */
|
||||
if (other_host->ip_equals(other_host, candidate_other_host))
|
||||
{
|
||||
prio |= PRIO_ADDR_MATCH;
|
||||
}
|
||||
else if (candidate_other_host->is_anyaddr(candidate_other_host))
|
||||
{
|
||||
prio |= PRIO_ADDR_ANY;
|
||||
}
|
||||
|
||||
DBG2(DBG_CFG, "candidate connection \"%s\": %H...%H (prio=%d)",
|
||||
candidate->get_name(candidate),
|
||||
candidate_my_host, candidate_other_host, prio);
|
||||
|
||||
if (prio > best_prio)
|
||||
{
|
||||
found = candidate;
|
||||
best_prio = prio;
|
||||
}
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
|
||||
if (found)
|
||||
{
|
||||
DBG2(DBG_CFG, "found matching connection \"%s\": %H...%H (prio=%d)",
|
||||
found->get_name(found), found->get_my_host(found),
|
||||
found->get_other_host(found), best_prio);
|
||||
|
||||
/* give out a new reference to it */
|
||||
found->get_ref(found);
|
||||
}
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_store_t.get_connection_by_name.
|
||||
*/
|
||||
static connection_t *get_connection_by_name(private_local_connection_store_t *this, char *name)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
connection_t *current, *found = NULL;
|
||||
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
iterator = this->connections->create_iterator(this->connections, TRUE);
|
||||
while (iterator->iterate(iterator, (void**)¤t))
|
||||
{
|
||||
if (strcmp(name, current->get_name(current)) == 0)
|
||||
{
|
||||
found = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
|
||||
if (found)
|
||||
{
|
||||
/* get a new reference for it */
|
||||
found->get_ref(found);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_store_t.delete_connection.
|
||||
*/
|
||||
static status_t delete_connection(private_local_connection_store_t *this, char *name)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
connection_t *current;
|
||||
bool found = FALSE;
|
||||
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
iterator = this->connections->create_iterator(this->connections, TRUE);
|
||||
while (iterator->iterate(iterator, (void **)¤t))
|
||||
{
|
||||
if (strcmp(current->get_name(current), name) == 0)
|
||||
{
|
||||
/* remove connection from list, and destroy it */
|
||||
iterator->remove(iterator);
|
||||
current->destroy(current);
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
if (found)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_store_t.add_connection.
|
||||
*/
|
||||
static status_t add_connection(private_local_connection_store_t *this, connection_t *connection)
|
||||
{
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
this->connections->insert_last(this->connections, connection);
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_store_t.create_iterator.
|
||||
*/
|
||||
static iterator_t* create_iterator(private_local_connection_store_t *this)
|
||||
{
|
||||
return this->connections->create_iterator_locked(this->connections,
|
||||
&this->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_store_t.destroy.
|
||||
*/
|
||||
static void destroy (private_local_connection_store_t *this)
|
||||
{
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
this->connections->destroy_offset(this->connections, offsetof(connection_t, destroy));
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
local_connection_store_t * local_connection_store_create(void)
|
||||
{
|
||||
private_local_connection_store_t *this = malloc_thing(private_local_connection_store_t);
|
||||
|
||||
this->public.connection_store.get_connection_by_hosts = (connection_t*(*)(connection_store_t*,host_t*,host_t*))get_connection_by_hosts;
|
||||
this->public.connection_store.get_connection_by_name = (connection_t*(*)(connection_store_t*,char*))get_connection_by_name;
|
||||
this->public.connection_store.delete_connection = (status_t(*)(connection_store_t*,char*))delete_connection;
|
||||
this->public.connection_store.add_connection = (status_t(*)(connection_store_t*,connection_t*))add_connection;
|
||||
this->public.connection_store.create_iterator = (iterator_t*(*)(connection_store_t*))create_iterator;
|
||||
this->public.connection_store.destroy = (void(*)(connection_store_t*))destroy;
|
||||
|
||||
/* private variables */
|
||||
this->connections = linked_list_create();
|
||||
pthread_mutex_init(&(this->mutex), NULL);
|
||||
|
||||
return (&this->public);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/**
|
||||
* @file local_connection_store.h
|
||||
*
|
||||
* @brief Interface of local_connection_store_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
#ifndef LOCAL_CONNECTION_H_
|
||||
#define LOCAL_CONNECTION_H_
|
||||
|
||||
typedef struct local_connection_store_t local_connection_store_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <config/connections/connection_store.h>
|
||||
|
||||
/**
|
||||
* @brief A connection_store_t implementation using a simple connection list.
|
||||
*
|
||||
* The local_connection_store_t class implements the connection_store_t interface
|
||||
* as simple as possible. connection_t's are stored in an in-memory list.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - local_connection_store_create()
|
||||
*
|
||||
* @todo Make thread-save first
|
||||
* @todo Add remove_connection method
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
struct local_connection_store_t {
|
||||
|
||||
/**
|
||||
* Implements connection_store_t interface
|
||||
*/
|
||||
connection_store_t connection_store;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a local_connection_store_t instance.
|
||||
*
|
||||
* @return connection store instance.
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
local_connection_store_t * local_connection_store_create(void);
|
||||
|
||||
#endif /* LOCAL_CONNECTION_H_ */
|
||||
@@ -0,0 +1,259 @@
|
||||
/**
|
||||
* @file ike_cfg.c
|
||||
*
|
||||
* @brief Implementation of ike_cfg_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* 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 "ike_cfg.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
typedef struct private_ike_cfg_t private_ike_cfg_t;
|
||||
|
||||
/**
|
||||
* Private data of an ike_cfg_t object
|
||||
*/
|
||||
struct private_ike_cfg_t {
|
||||
|
||||
/**
|
||||
* Public part
|
||||
*/
|
||||
ike_cfg_t public;
|
||||
|
||||
/**
|
||||
* Number of references hold by others to this ike_cfg
|
||||
*/
|
||||
refcount_t refcount;
|
||||
|
||||
/**
|
||||
* Address of local host
|
||||
*/
|
||||
host_t *my_host;
|
||||
|
||||
/**
|
||||
* Address of remote host
|
||||
*/
|
||||
host_t *other_host;
|
||||
|
||||
/**
|
||||
* should we send a certificate request?
|
||||
*/
|
||||
bool certreq;
|
||||
|
||||
/**
|
||||
* List of proposals to use
|
||||
*/
|
||||
linked_list_t *proposals;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of ike_cfg_t.certreq.
|
||||
*/
|
||||
static bool send_certreq(private_ike_cfg_t *this)
|
||||
{
|
||||
return this->certreq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of ike_cfg_t.get_my_host.
|
||||
*/
|
||||
static host_t *get_my_host (private_ike_cfg_t *this)
|
||||
{
|
||||
return this->my_host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of ike_cfg_t.get_other_host.
|
||||
*/
|
||||
static host_t *get_other_host (private_ike_cfg_t *this)
|
||||
{
|
||||
return this->other_host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of ike_cfg_t.add_proposal.
|
||||
*/
|
||||
static void add_proposal(private_ike_cfg_t *this, proposal_t *proposal)
|
||||
{
|
||||
this->proposals->insert_last(this->proposals, proposal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of ike_cfg_t.get_proposals.
|
||||
*/
|
||||
static linked_list_t* get_proposals(private_ike_cfg_t *this)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
proposal_t *current;
|
||||
linked_list_t *proposals = linked_list_create();
|
||||
|
||||
iterator = this->proposals->create_iterator(this->proposals, TRUE);
|
||||
while (iterator->iterate(iterator, (void**)¤t))
|
||||
{
|
||||
current = current->clone(current);
|
||||
proposals->insert_last(proposals, (void*)current);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
|
||||
return proposals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of ike_cfg_t.select_proposal.
|
||||
*/
|
||||
static proposal_t *select_proposal(private_ike_cfg_t *this,
|
||||
linked_list_t *proposals)
|
||||
{
|
||||
iterator_t *stored_iter, *supplied_iter;
|
||||
proposal_t *stored, *supplied, *selected;
|
||||
|
||||
stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
|
||||
supplied_iter = proposals->create_iterator(proposals, TRUE);
|
||||
|
||||
/* compare all stored proposals with all supplied. Stored ones are preferred.*/
|
||||
while (stored_iter->iterate(stored_iter, (void**)&stored))
|
||||
{
|
||||
supplied_iter->reset(supplied_iter);
|
||||
|
||||
while (supplied_iter->iterate(supplied_iter, (void**)&supplied))
|
||||
{
|
||||
selected = stored->select(stored, supplied);
|
||||
if (selected)
|
||||
{
|
||||
/* they match, return */
|
||||
stored_iter->destroy(stored_iter);
|
||||
supplied_iter->destroy(supplied_iter);
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
|
||||
stored_iter->destroy(stored_iter);
|
||||
supplied_iter->destroy(supplied_iter);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of ike_cfg_t.get_dh_group.
|
||||
*/
|
||||
static diffie_hellman_group_t get_dh_group(private_ike_cfg_t *this)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
proposal_t *proposal;
|
||||
algorithm_t *algo;
|
||||
diffie_hellman_group_t dh_group = MODP_NONE;
|
||||
|
||||
iterator = this->proposals->create_iterator(this->proposals, TRUE);
|
||||
while (iterator->iterate(iterator, (void**)&proposal))
|
||||
{
|
||||
if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo))
|
||||
{
|
||||
dh_group = algo->algorithm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return dh_group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of ike_cfg_t.check_dh_group.
|
||||
*/
|
||||
static bool check_dh_group(private_ike_cfg_t *this,
|
||||
diffie_hellman_group_t dh_group)
|
||||
{
|
||||
iterator_t *prop_iter, *alg_iter;
|
||||
proposal_t *proposal;
|
||||
algorithm_t *algo;
|
||||
|
||||
prop_iter = this->proposals->create_iterator(this->proposals, TRUE);
|
||||
while (prop_iter->iterate(prop_iter, (void**)&proposal))
|
||||
{
|
||||
alg_iter = proposal->create_algorithm_iterator(proposal,
|
||||
DIFFIE_HELLMAN_GROUP);
|
||||
while (alg_iter->iterate(alg_iter, (void**)&algo))
|
||||
{
|
||||
if (algo->algorithm == dh_group)
|
||||
{
|
||||
prop_iter->destroy(prop_iter);
|
||||
alg_iter->destroy(alg_iter);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
alg_iter->destroy(alg_iter);
|
||||
}
|
||||
prop_iter->destroy(prop_iter);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of ike_cfg_t.get_ref.
|
||||
*/
|
||||
static void get_ref(private_ike_cfg_t *this)
|
||||
{
|
||||
ref_get(&this->refcount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of ike_cfg_t.destroy.
|
||||
*/
|
||||
static void destroy(private_ike_cfg_t *this)
|
||||
{
|
||||
if (ref_put(&this->refcount))
|
||||
{
|
||||
this->proposals->destroy_offset(this->proposals,
|
||||
offsetof(proposal_t, destroy));
|
||||
this->my_host->destroy(this->my_host);
|
||||
this->other_host->destroy(this->other_host);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
ike_cfg_t *ike_cfg_create(bool certreq, host_t *my_host, host_t *other_host)
|
||||
{
|
||||
private_ike_cfg_t *this = malloc_thing(private_ike_cfg_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.send_certreq = (bool(*)(ike_cfg_t*))send_certreq;
|
||||
this->public.get_my_host = (host_t*(*)(ike_cfg_t*))get_my_host;
|
||||
this->public.get_other_host = (host_t*(*)(ike_cfg_t*))get_other_host;
|
||||
this->public.add_proposal = (void(*)(ike_cfg_t*, proposal_t*)) add_proposal;
|
||||
this->public.get_proposals = (linked_list_t*(*)(ike_cfg_t*))get_proposals;
|
||||
this->public.select_proposal = (proposal_t*(*)(ike_cfg_t*,linked_list_t*))select_proposal;
|
||||
this->public.get_dh_group = (diffie_hellman_group_t(*)(ike_cfg_t*)) get_dh_group;
|
||||
this->public.check_dh_group = (bool(*)(ike_cfg_t*,diffie_hellman_group_t)) check_dh_group;
|
||||
this->public.get_ref = (void(*)(ike_cfg_t*))get_ref;
|
||||
this->public.destroy = (void(*)(ike_cfg_t*))destroy;
|
||||
|
||||
/* private variables */
|
||||
this->refcount = 1;
|
||||
this->certreq = certreq;
|
||||
this->my_host = my_host;
|
||||
this->other_host = other_host;
|
||||
|
||||
this->proposals = linked_list_create();
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* @file ike_cfg.h
|
||||
*
|
||||
* @brief Interface of ike_cfg_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef IKE_CFG_H_
|
||||
#define IKE_CFG_H_
|
||||
|
||||
typedef struct ike_cfg_t ike_cfg_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <utils/host.h>
|
||||
#include <utils/linked_list.h>
|
||||
#include <utils/identification.h>
|
||||
#include <config/proposal.h>
|
||||
#include <crypto/diffie_hellman.h>
|
||||
|
||||
/**
|
||||
* @brief An ike_cfg_t defines the rules to set up an IKE_SA.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - ike_cfg_create()
|
||||
*
|
||||
* @ingroup ike_cfg
|
||||
*/
|
||||
struct ike_cfg_t {
|
||||
|
||||
/**
|
||||
* @brief Get own address.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return host information as host_t object
|
||||
*/
|
||||
host_t* (*get_my_host) (ike_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get peers address.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return host information as host_t object
|
||||
*/
|
||||
host_t* (*get_other_host) (ike_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Adds a proposal to the list.
|
||||
*
|
||||
* The first added proposal has the highest priority, the last
|
||||
* added the lowest.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param proposal proposal to add
|
||||
*/
|
||||
void (*add_proposal) (ike_cfg_t *this, proposal_t *proposal);
|
||||
|
||||
/**
|
||||
* @brief Returns a list of all supported proposals.
|
||||
*
|
||||
* Returned list and its proposals must be destroyed after use.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return list containing all the proposals
|
||||
*/
|
||||
linked_list_t* (*get_proposals) (ike_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Select a proposed from suggested proposals.
|
||||
*
|
||||
* Returned proposal must be destroyed after use.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param proposals list of proposals to select from
|
||||
* @return selected proposal, or NULL if none matches.
|
||||
*/
|
||||
proposal_t *(*select_proposal) (ike_cfg_t *this, linked_list_t *proposals);
|
||||
|
||||
/**
|
||||
* @brief Should we send a certificate request in IKE_SA_INIT?
|
||||
*
|
||||
* @param this calling object
|
||||
* @return certificate request sending policy
|
||||
*/
|
||||
bool (*send_certreq) (ike_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the DH group to use for IKE_SA setup.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return dh group to use for initialization
|
||||
*/
|
||||
diffie_hellman_group_t (*get_dh_group)(ike_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Check if a suggested DH group is acceptable.
|
||||
*
|
||||
* If we guess a wrong DH group for IKE_SA_INIT, the other
|
||||
* peer will send us a offer. But is this acceptable for us?
|
||||
*
|
||||
* @param this calling object
|
||||
* @return TRUE if group acceptable
|
||||
*/
|
||||
bool (*check_dh_group) (ike_cfg_t *this, diffie_hellman_group_t dh_group);
|
||||
|
||||
/**
|
||||
* @brief Get a new reference to this ike_cfg.
|
||||
*
|
||||
* Get a new reference to this ike_cfg by increasing
|
||||
* it's internal reference counter.
|
||||
* Do not call get_ref or any other function until you
|
||||
* already have a reference. Otherwise the object may get
|
||||
* destroyed while calling get_ref(),
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*get_ref) (ike_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys a ike_cfg_t object.
|
||||
*
|
||||
* Decrements the internal reference counter and
|
||||
* destroys the ike_cfg when it reaches zero.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*destroy) (ike_cfg_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a ike_cfg_t object.
|
||||
*
|
||||
* Supplied hosts become owned by ike_cfg, the name gets cloned.
|
||||
*
|
||||
* @param name ike_cfg identifier
|
||||
* @param certreq TRUE to send a certificate request
|
||||
* @param my_host host_t representing local address
|
||||
* @param other_host host_t representing remote address
|
||||
* @return ike_cfg_t object.
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
ike_cfg_t *ike_cfg_create(bool certreq, host_t *my_host, host_t *other_host);
|
||||
|
||||
#endif /* IKE_CFG_H_ */
|
||||
@@ -0,0 +1,470 @@
|
||||
/**
|
||||
* @file peer_cfg.c
|
||||
*
|
||||
* @brief Implementation of peer_cfg_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* 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 <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "peer_cfg.h"
|
||||
|
||||
#include <utils/linked_list.h>
|
||||
#include <utils/identification.h>
|
||||
|
||||
ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
|
||||
"CERT_ALWAYS_SEND",
|
||||
"CERT_SEND_IF_ASKED",
|
||||
"CERT_NEVER_SEND"
|
||||
);
|
||||
|
||||
ENUM(dpd_action_names, DPD_NONE, DPD_RESTART,
|
||||
"DPD_NONE",
|
||||
"DPD_CLEAR",
|
||||
"DPD_ROUTE",
|
||||
"DPD_RESTART"
|
||||
);
|
||||
|
||||
typedef struct private_peer_cfg_t private_peer_cfg_t;
|
||||
|
||||
/**
|
||||
* Private data of an peer_cfg_t object
|
||||
*/
|
||||
struct private_peer_cfg_t {
|
||||
|
||||
/**
|
||||
* Public part
|
||||
*/
|
||||
peer_cfg_t public;
|
||||
|
||||
/**
|
||||
* Number of references hold by others to this peer_cfg
|
||||
*/
|
||||
refcount_t refcount;
|
||||
|
||||
/**
|
||||
* Name of the peer_cfg, used to query it
|
||||
*/
|
||||
char *name;
|
||||
|
||||
/**
|
||||
* IKE version to use for initiation
|
||||
*/
|
||||
u_int ike_version;
|
||||
|
||||
/**
|
||||
* IKE config associated to this peer config
|
||||
*/
|
||||
ike_cfg_t *ike_cfg;
|
||||
|
||||
/**
|
||||
* list of child configs associated to this peer config
|
||||
*/
|
||||
linked_list_t *child_cfgs;
|
||||
|
||||
/**
|
||||
* mutex to lock access to list of child_cfgs
|
||||
*/
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
/**
|
||||
* id to use to identify us
|
||||
*/
|
||||
identification_t *my_id;
|
||||
|
||||
/**
|
||||
* allowed id for other
|
||||
*/
|
||||
identification_t *other_id;
|
||||
|
||||
/**
|
||||
* we have a cert issued by this CA
|
||||
*/
|
||||
identification_t *my_ca;
|
||||
|
||||
/**
|
||||
* we require the other end to have a cert issued by this CA
|
||||
*/
|
||||
identification_t *other_ca;
|
||||
|
||||
/**
|
||||
* should we send a certificate
|
||||
*/
|
||||
cert_policy_t cert_policy;
|
||||
|
||||
/**
|
||||
* Method to use for own authentication data
|
||||
*/
|
||||
auth_method_t auth_method;
|
||||
|
||||
/**
|
||||
* EAP type to use for peer authentication
|
||||
*/
|
||||
eap_type_t eap_type;
|
||||
|
||||
/**
|
||||
* number of tries after giving up if peer does not respond
|
||||
*/
|
||||
u_int32_t keyingtries;
|
||||
|
||||
/**
|
||||
* user reauthentication instead of rekeying
|
||||
*/
|
||||
bool use_reauth;
|
||||
|
||||
/**
|
||||
* Time before an SA gets invalid
|
||||
*/
|
||||
u_int32_t lifetime;
|
||||
|
||||
/**
|
||||
* Time before an SA gets rekeyed
|
||||
*/
|
||||
u_int32_t rekeytime;
|
||||
|
||||
/**
|
||||
* Time, which specifies the range of a random value
|
||||
* substracted from lifetime.
|
||||
*/
|
||||
u_int32_t jitter;
|
||||
|
||||
/**
|
||||
* What to do with an SA when other peer seams to be dead?
|
||||
*/
|
||||
bool dpd_delay;
|
||||
|
||||
/**
|
||||
* What to do with CHILDren when other peer seams to be dead?
|
||||
*/
|
||||
bool dpd_action;
|
||||
|
||||
/**
|
||||
* virtual IP to use locally
|
||||
*/
|
||||
host_t *my_virtual_ip;
|
||||
|
||||
/**
|
||||
* virtual IP to use remotly
|
||||
*/
|
||||
host_t *other_virtual_ip;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.get_name
|
||||
*/
|
||||
static char *get_name(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.get_ike_version
|
||||
*/
|
||||
static u_int get_ike_version(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->ike_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.get_ike_cfg
|
||||
*/
|
||||
static ike_cfg_t* get_ike_cfg(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->ike_cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.add_child_cfg.
|
||||
*/
|
||||
static void add_child_cfg(private_peer_cfg_t *this, child_cfg_t *child_cfg)
|
||||
{
|
||||
pthread_mutex_lock(&this->mutex);
|
||||
this->child_cfgs->insert_last(this->child_cfgs, child_cfg);
|
||||
pthread_mutex_unlock(&this->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.create_child_cfg_iterator.
|
||||
*/
|
||||
static iterator_t* create_child_cfg_iterator(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->child_cfgs->create_iterator_locked(this->child_cfgs,
|
||||
&this->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if child_cfg contains traffic selectors
|
||||
*/
|
||||
static bool contains_ts(child_cfg_t *child, bool mine, linked_list_t *ts,
|
||||
host_t *host)
|
||||
{
|
||||
linked_list_t *selected;
|
||||
bool contains = FALSE;
|
||||
|
||||
selected = child->get_traffic_selectors(child, mine, ts, host);
|
||||
contains = selected->get_count(selected);
|
||||
selected->destroy_offset(selected, offsetof(traffic_selector_t, destroy));
|
||||
return contains;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.select_child_cfg
|
||||
*/
|
||||
static child_cfg_t* select_child_cfg(private_peer_cfg_t *this,
|
||||
linked_list_t *my_ts,
|
||||
linked_list_t *other_ts,
|
||||
host_t *my_host, host_t *other_host)
|
||||
{
|
||||
child_cfg_t *current, *found = NULL;
|
||||
iterator_t *iterator;
|
||||
|
||||
iterator = create_child_cfg_iterator(this);
|
||||
while (iterator->iterate(iterator, (void**)¤t))
|
||||
{
|
||||
if (contains_ts(current, TRUE, my_ts, my_host) &&
|
||||
contains_ts(current, FALSE, other_ts, other_host))
|
||||
{
|
||||
found = current;
|
||||
found->get_ref(found);
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.get_my_id
|
||||
*/
|
||||
static identification_t *get_my_id(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->my_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.get_other_id
|
||||
*/
|
||||
static identification_t *get_other_id(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->other_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.get_my_ca
|
||||
*/
|
||||
static identification_t *get_my_ca(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->my_ca;
|
||||
}
|
||||
|
||||
static identification_t *get_other_ca(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->other_ca;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.get_cert_policy.
|
||||
*/
|
||||
static cert_policy_t get_cert_policy(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->cert_policy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.auth_method_t.
|
||||
*/
|
||||
static auth_method_t get_auth_method(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->auth_method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.get_eap_type.
|
||||
*/
|
||||
static eap_type_t get_eap_type(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->eap_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.get_keyingtries.
|
||||
*/
|
||||
static u_int32_t get_keyingtries(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->keyingtries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.get_soft_lifetime
|
||||
*/
|
||||
static u_int32_t get_lifetime(private_peer_cfg_t *this, bool rekey)
|
||||
{
|
||||
if (rekey)
|
||||
{
|
||||
if (this->jitter == 0)
|
||||
{
|
||||
return this->rekeytime;
|
||||
}
|
||||
return this->rekeytime - (random() % this->jitter);
|
||||
}
|
||||
return this->lifetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.use_reauth.
|
||||
*/
|
||||
static bool use_reauth(private_peer_cfg_t *this, bool rekey)
|
||||
{
|
||||
return this->use_reauth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements peer_cfg_t.get_dpd_delay
|
||||
*/
|
||||
static u_int32_t get_dpd_delay(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->dpd_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements peer_cfg_t.get_dpd_action
|
||||
*/
|
||||
static dpd_action_t get_dpd_action(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->dpd_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.get_virtual_ip.
|
||||
*/
|
||||
static host_t* get_virtual_ip(private_peer_cfg_t *this, host_t *suggestion)
|
||||
{
|
||||
if (suggestion == NULL)
|
||||
{
|
||||
if (this->my_virtual_ip)
|
||||
{
|
||||
return this->my_virtual_ip->clone(this->my_virtual_ip);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (this->other_virtual_ip)
|
||||
{
|
||||
return this->other_virtual_ip->clone(this->other_virtual_ip);
|
||||
}
|
||||
if (suggestion->is_anyaddr(suggestion))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return suggestion->clone(suggestion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements peer_cfg_t.get_ref.
|
||||
*/
|
||||
static void get_ref(private_peer_cfg_t *this)
|
||||
{
|
||||
ref_get(&this->refcount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements peer_cfg_t.destroy.
|
||||
*/
|
||||
static void destroy(private_peer_cfg_t *this)
|
||||
{
|
||||
if (ref_put(&this->refcount))
|
||||
{
|
||||
this->ike_cfg->destroy(this->ike_cfg);
|
||||
this->child_cfgs->destroy_offset(this->child_cfgs, offsetof(child_cfg_t, destroy));
|
||||
this->my_id->destroy(this->my_id);
|
||||
this->other_id->destroy(this->other_id);
|
||||
DESTROY_IF(this->my_ca);
|
||||
DESTROY_IF(this->other_ca);
|
||||
|
||||
DESTROY_IF(this->my_virtual_ip);
|
||||
DESTROY_IF(this->other_virtual_ip);
|
||||
free(this->name);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header-file
|
||||
*/
|
||||
peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
|
||||
identification_t *my_id, identification_t *other_id,
|
||||
identification_t *my_ca, identification_t *other_ca,
|
||||
cert_policy_t cert_policy, auth_method_t auth_method,
|
||||
eap_type_t eap_type, u_int32_t keyingtries,
|
||||
u_int32_t lifetime, u_int32_t rekeytime,
|
||||
u_int32_t jitter, bool reauth,
|
||||
u_int32_t dpd_delay, dpd_action_t dpd_action,
|
||||
host_t *my_virtual_ip, host_t *other_virtual_ip)
|
||||
{
|
||||
private_peer_cfg_t *this = malloc_thing(private_peer_cfg_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.get_name = (char* (*) (peer_cfg_t *))get_name;
|
||||
this->public.get_ike_version = (u_int(*) (peer_cfg_t *))get_ike_version;
|
||||
this->public.get_ike_cfg = (ike_cfg_t* (*) (peer_cfg_t *))get_ike_cfg;
|
||||
this->public.add_child_cfg = (void (*) (peer_cfg_t *, child_cfg_t*))add_child_cfg;
|
||||
this->public.create_child_cfg_iterator = (iterator_t* (*) (peer_cfg_t *))create_child_cfg_iterator;
|
||||
this->public.select_child_cfg = (child_cfg_t* (*) (peer_cfg_t *,linked_list_t*,linked_list_t*,host_t*,host_t*))select_child_cfg;
|
||||
this->public.get_my_id = (identification_t* (*)(peer_cfg_t*))get_my_id;
|
||||
this->public.get_other_id = (identification_t* (*)(peer_cfg_t *))get_other_id;
|
||||
this->public.get_my_ca = (identification_t* (*)(peer_cfg_t *))get_my_ca;
|
||||
this->public.get_other_ca = (identification_t* (*)(peer_cfg_t *))get_other_ca;
|
||||
this->public.get_cert_policy = (cert_policy_t (*) (peer_cfg_t *))get_cert_policy;
|
||||
this->public.get_auth_method = (auth_method_t (*) (peer_cfg_t *))get_auth_method;
|
||||
this->public.get_eap_type = (eap_type_t (*) (peer_cfg_t *))get_eap_type;
|
||||
this->public.get_keyingtries = (u_int32_t (*) (peer_cfg_t *))get_keyingtries;
|
||||
this->public.get_lifetime = (u_int32_t (*) (peer_cfg_t *, bool rekey))get_lifetime;
|
||||
this->public.use_reauth = (bool (*) (peer_cfg_t *))use_reauth;
|
||||
this->public.get_dpd_delay = (u_int32_t (*) (peer_cfg_t *))get_dpd_delay;
|
||||
this->public.get_dpd_action = (dpd_action_t (*) (peer_cfg_t *))get_dpd_action;
|
||||
this->public.get_virtual_ip = (host_t* (*) (peer_cfg_t *, host_t *))get_virtual_ip;
|
||||
this->public.get_ref = (void(*)(peer_cfg_t *))get_ref;
|
||||
this->public.destroy = (void(*)(peer_cfg_t *))destroy;
|
||||
|
||||
/* apply init values */
|
||||
this->name = strdup(name);
|
||||
this->ike_version = ike_version;
|
||||
this->ike_cfg = ike_cfg;
|
||||
this->child_cfgs = linked_list_create();
|
||||
pthread_mutex_init(&this->mutex, NULL);
|
||||
this->my_id = my_id;
|
||||
this->other_id = other_id;
|
||||
this->my_ca = my_ca;
|
||||
this->other_ca = other_ca;
|
||||
this->cert_policy = cert_policy;
|
||||
this->auth_method = auth_method;
|
||||
this->eap_type = eap_type;
|
||||
this->keyingtries = keyingtries;
|
||||
this->lifetime = lifetime;
|
||||
this->rekeytime = rekeytime;
|
||||
this->jitter = jitter;
|
||||
this->use_reauth = reauth;
|
||||
this->dpd_delay = dpd_delay;
|
||||
this->dpd_action = dpd_action;
|
||||
this->my_virtual_ip = my_virtual_ip;
|
||||
this->other_virtual_ip = other_virtual_ip;
|
||||
this->refcount = 1;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
/**
|
||||
* @file peer_cfg.h
|
||||
*
|
||||
* @brief Interface of peer_cfg_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PEER_CFG_H_
|
||||
#define PEER_CFG_H_
|
||||
|
||||
typedef enum dpd_action_t dpd_action_t;
|
||||
typedef enum cert_policy_t cert_policy_t;
|
||||
typedef struct peer_cfg_t peer_cfg_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <utils/identification.h>
|
||||
#include <config/traffic_selector.h>
|
||||
#include <config/proposal.h>
|
||||
#include <config/ike_cfg.h>
|
||||
#include <config/child_cfg.h>
|
||||
#include <sa/authenticators/authenticator.h>
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
|
||||
/**
|
||||
* Certificate sending policy. This is also used for certificate
|
||||
* requests when using this definition for the other peer. If
|
||||
* it is CERT_NEVER_SEND, a certreq is omitted, otherwise its
|
||||
* included.
|
||||
*
|
||||
* @ingroup config
|
||||
*
|
||||
* @warning These definitions must be the same as in pluto/starter,
|
||||
* as they are sent over the stroke socket.
|
||||
*/
|
||||
enum cert_policy_t {
|
||||
/** always send certificates, even when not requested */
|
||||
CERT_ALWAYS_SEND = 0,
|
||||
/** send certificate upon cert request */
|
||||
CERT_SEND_IF_ASKED = 1,
|
||||
/** never send a certificate, even when requested */
|
||||
CERT_NEVER_SEND = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum strings for cert_policy_t
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
extern enum_name_t *cert_policy_names;
|
||||
|
||||
/**
|
||||
* @brief Actions to take when a peer does not respond (dead peer detected).
|
||||
*
|
||||
* These values are the same as in pluto/starter, so do not modify them!
|
||||
*
|
||||
* @ingroup peer_cfg
|
||||
*/
|
||||
enum dpd_action_t {
|
||||
/** DPD disabled */
|
||||
DPD_NONE,
|
||||
/** remove CHILD_SAs without replacement */
|
||||
DPD_CLEAR,
|
||||
/** route the CHILD_SAs to resetup when needed */
|
||||
DPD_ROUTE,
|
||||
/** restart CHILD_SAs in a new IKE_SA, immediately */
|
||||
DPD_RESTART,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum names for dpd_action_t.
|
||||
*/
|
||||
extern enum_name_t *dpd_action_names;
|
||||
|
||||
/**
|
||||
* @brief Configuration of a peer, specified by IDs.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - peer_cfg_create()
|
||||
*
|
||||
* @ingroup peer_cfg
|
||||
*/
|
||||
struct peer_cfg_t {
|
||||
|
||||
/**
|
||||
* @brief Get the name of the peer_cfg.
|
||||
*
|
||||
* Returned object is not getting cloned.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return peer_cfg's name
|
||||
*/
|
||||
char* (*get_name) (peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the IKE version to use for initiating.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return IKE major version
|
||||
*/
|
||||
u_int (*get_ike_version)(peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the IKE config to use for initiaton.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return the IKE config to use
|
||||
*/
|
||||
ike_cfg_t* (*get_ike_cfg) (peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Attach a CHILD config.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param child_cfg CHILD config to add
|
||||
*/
|
||||
void (*add_child_cfg) (peer_cfg_t *this, child_cfg_t *child_cfg);
|
||||
|
||||
/**
|
||||
* @brief Create an iterator for all attached CHILD configs.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return an iterator over all CHILD configs.
|
||||
*/
|
||||
iterator_t* (*create_child_cfg_iterator) (peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Select a CHILD config from traffic selectors.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param my_ts TS for local side
|
||||
* @param other_ts TS for remote side
|
||||
* @param my_host host to narrow down dynamic TS for local side
|
||||
* @param other_host host to narrow down dynamic TS for remote side
|
||||
* @return selected CHILD config, or NULL if no match found
|
||||
*/
|
||||
child_cfg_t* (*select_child_cfg) (peer_cfg_t *this, linked_list_t *my_ts,
|
||||
linked_list_t *other_ts, host_t *my_host,
|
||||
host_t *other_host);
|
||||
|
||||
/**
|
||||
* @brief Get own ID.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return own id
|
||||
*/
|
||||
identification_t* (*get_my_id)(peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get peers ID.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return other id
|
||||
*/
|
||||
identification_t* (*get_other_id)(peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get own CA.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return own ca
|
||||
*/
|
||||
identification_t* (*get_my_ca)(peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get peers CA.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return other ca
|
||||
*/
|
||||
identification_t* (*get_other_ca)(peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Should be sent a certificate for this connection?
|
||||
*
|
||||
* @param this calling object
|
||||
* @return certificate sending policy
|
||||
*/
|
||||
cert_policy_t (*get_cert_policy) (peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the authentication method to use to authenticate us.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return authentication method
|
||||
*/
|
||||
auth_method_t (*get_auth_method) (peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the EAP type to use for peer authentication.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return authentication method
|
||||
*/
|
||||
eap_type_t (*get_eap_type) (peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the max number of retries after timeout.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return max number retries
|
||||
*/
|
||||
u_int32_t (*get_keyingtries) (peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the lifetime of a IKE_SA.
|
||||
*
|
||||
* If "rekey" is set to TRUE, a lifetime is returned before the first
|
||||
* rekeying should be started. If it is FALSE, the actual lifetime is
|
||||
* returned when the IKE_SA must be deleted.
|
||||
* The rekey time automatically contains a jitter to avoid simlutaneous
|
||||
* rekeying.
|
||||
*
|
||||
* @param this child_config
|
||||
* @param rekey TRUE to get rekey time
|
||||
* @return lifetime in seconds
|
||||
*/
|
||||
u_int32_t (*get_lifetime) (peer_cfg_t *this, bool rekey);
|
||||
|
||||
/**
|
||||
* @brief Should a full reauthentication be done instead of rekeying?
|
||||
*
|
||||
* @param this calling object
|
||||
* @return TRUE to use full reauthentication
|
||||
*/
|
||||
bool (*use_reauth) (peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the DPD check interval.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return dpd_delay in seconds
|
||||
*/
|
||||
u_int32_t (*get_dpd_delay) (peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief What should be done with a CHILD_SA, when other peer does not respond.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return dpd action
|
||||
*/
|
||||
dpd_action_t (*get_dpd_action) (peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get a virtual IP for the local or the remote host.
|
||||
*
|
||||
* By supplying NULL as IP, an IP for the local host is requested. It
|
||||
* may be %any or specific.
|
||||
* By supplying %any as host, an IP from the pool is selected to be
|
||||
* served to the peer.
|
||||
* If a specified host is supplied, it is checked if this address
|
||||
* is acceptable to serve to the peer. If so, it is returned. Otherwise,
|
||||
* an alternative IP is returned.
|
||||
* In any mode, this call may return NULL indicating virtual IP should
|
||||
* not be used.
|
||||
*
|
||||
* @param this peer_cfg
|
||||
* @param suggestion NULL, %any or specific, see description
|
||||
* @return clone of an IP to use, or NULL
|
||||
*/
|
||||
host_t* (*get_virtual_ip) (peer_cfg_t *this, host_t *suggestion);
|
||||
|
||||
/**
|
||||
* @brief Get a new reference.
|
||||
*
|
||||
* Get a new reference to this peer_cfg by increasing
|
||||
* it's internal reference counter.
|
||||
* Do not call get_ref or any other function until you
|
||||
* already have a reference. Otherwise the object may get
|
||||
* destroyed while calling get_ref(),
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*get_ref) (peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys the peer_cfg object.
|
||||
*
|
||||
* Decrements the internal reference counter and
|
||||
* destroys the peer_cfg when it reaches zero.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*destroy) (peer_cfg_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create a configuration object for IKE_AUTH and later.
|
||||
*
|
||||
* name-string gets cloned, ID's not.
|
||||
* Virtual IPs are used if they are != NULL. A %any host means the virtual
|
||||
* IP should be obtained from the other peer.
|
||||
* Lifetimes are in seconds. To prevent to peers to start rekeying at the
|
||||
* same time, a jitter may be specified. Rekeying of an SA starts at
|
||||
* (rekeylifetime - random(0, jitter)).
|
||||
*
|
||||
* @param name name of the peer_cfg
|
||||
* @param ike_version which IKE version we sould use for this peer
|
||||
* @param ike_cfg IKE config to use when acting as initiator
|
||||
* @param my_id identification_t for ourselves
|
||||
* @param other_id identification_t for the remote guy
|
||||
* @param my_ca CA to use for us
|
||||
* @param other_ca CA to use for other
|
||||
* @param cert_policy should we send a certificate payload?
|
||||
* @param auth_method auth method to use to authenticate us
|
||||
* @param eap_type EAP type to use for peer authentication
|
||||
* @param keyingtries how many keying tries should be done before giving up
|
||||
* @param lifetime lifetime before deleting an SA
|
||||
* @param rekeytime lifetime before rekeying an SA
|
||||
* @param jitter range of random to substract from rekeytime
|
||||
* @param use_reauth sould be done reauthentication instead of rekeying?
|
||||
* @param dpd_delay after how many seconds of inactivity to check DPD
|
||||
* @param dpd_action what to do with CHILD_SAs when detected a dead peer
|
||||
* @param my_virtual_ip virtual IP for local host, or NULL
|
||||
* @param other_virtual_ip virtual IP for remote host, or NULL
|
||||
* @return peer_cfg_t object
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
peer_cfg_t *peer_cfg_create(char *name, u_int ikev_version, ike_cfg_t *ike_cfg,
|
||||
identification_t *my_id, identification_t *other_id,
|
||||
identification_t *my_ca, identification_t *other_ca,
|
||||
cert_policy_t cert_policy, auth_method_t auth_method,
|
||||
eap_type_t eap_type, u_int32_t keyingtries,
|
||||
u_int32_t lifetime, u_int32_t rekeytime,
|
||||
u_int32_t jitter, bool use_reauth,
|
||||
u_int32_t dpd_delay, dpd_action_t dpd_action,
|
||||
host_t *my_virtual_ip, host_t *other_virtual_ip);
|
||||
|
||||
#endif /* PEER_CFG_H_ */
|
||||
@@ -1,282 +0,0 @@
|
||||
/**
|
||||
* @file local_policy_store.c
|
||||
*
|
||||
* @brief Implementation of local_policy_store_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006 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 <string.h>
|
||||
|
||||
#include "local_policy_store.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
|
||||
typedef struct private_local_policy_store_t private_local_policy_store_t;
|
||||
|
||||
/**
|
||||
* Private data of an local_policy_store_t object
|
||||
*/
|
||||
struct private_local_policy_store_t {
|
||||
|
||||
/**
|
||||
* Public part
|
||||
*/
|
||||
local_policy_store_t public;
|
||||
|
||||
/**
|
||||
* list of policy_t's
|
||||
*/
|
||||
linked_list_t *policies;
|
||||
|
||||
/**
|
||||
* Mutex to exclusivly access list
|
||||
*/
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of policy_store_t.add_policy.
|
||||
*/
|
||||
static void add_policy(private_local_policy_store_t *this, policy_t *policy)
|
||||
{
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
this->policies->insert_last(this->policies, (void*)policy);
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a policy contains traffic selectors
|
||||
*/
|
||||
static bool contains_traffic_selectors(policy_t *policy, bool mine,
|
||||
linked_list_t *ts, host_t *host)
|
||||
{
|
||||
linked_list_t *selected;
|
||||
bool contains = FALSE;
|
||||
|
||||
if (mine)
|
||||
{
|
||||
selected = policy->select_my_traffic_selectors(policy, ts, host);
|
||||
}
|
||||
else
|
||||
{
|
||||
selected = policy->select_other_traffic_selectors(policy, ts, host);
|
||||
}
|
||||
if (selected->get_count(selected))
|
||||
{
|
||||
contains = TRUE;
|
||||
}
|
||||
selected->destroy_offset(selected, offsetof(traffic_selector_t, destroy));
|
||||
return contains;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_store_t.get_policy.
|
||||
*/
|
||||
static policy_t *get_policy(private_local_policy_store_t *this,
|
||||
identification_t *my_id, identification_t *other_id,
|
||||
linked_list_t *my_ts, linked_list_t *other_ts,
|
||||
host_t *my_host, host_t *other_host)
|
||||
{
|
||||
typedef enum {
|
||||
PRIO_UNDEFINED = 0x00,
|
||||
PRIO_TS_MISMATCH = 0x01,
|
||||
PRIO_ID_ANY = 0x02,
|
||||
PRIO_ID_MATCH = PRIO_ID_ANY + MAX_WILDCARDS,
|
||||
} prio_t;
|
||||
|
||||
prio_t best_prio = PRIO_UNDEFINED;
|
||||
|
||||
iterator_t *iterator;
|
||||
policy_t *candidate;
|
||||
policy_t *found = NULL;
|
||||
traffic_selector_t *ts;
|
||||
|
||||
DBG1(DBG_CFG, "searching policy for '%D'...'%D'", my_id, other_id);
|
||||
iterator = my_ts->create_iterator(my_ts, TRUE);
|
||||
while (iterator->iterate(iterator, (void**)&ts))
|
||||
{
|
||||
DBG1(DBG_CFG, " local TS: %R", ts);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
iterator = other_ts->create_iterator(other_ts, TRUE);
|
||||
while (iterator->iterate(iterator, (void**)&ts))
|
||||
{
|
||||
DBG1(DBG_CFG, " remote TS: %R", ts);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
iterator = this->policies->create_iterator(this->policies, TRUE);
|
||||
|
||||
/* determine closest matching policy */
|
||||
while (iterator->iterate(iterator, (void**)&candidate))
|
||||
{
|
||||
identification_t *candidate_my_id;
|
||||
identification_t *candidate_other_id;
|
||||
int wildcards;
|
||||
|
||||
candidate_my_id = candidate->get_my_id(candidate);
|
||||
candidate_other_id = candidate->get_other_id(candidate);
|
||||
|
||||
/* my_id is either %any or if set must match exactly */
|
||||
if (candidate_my_id->matches(candidate_my_id, my_id, &wildcards))
|
||||
{
|
||||
prio_t prio = PRIO_UNDEFINED;
|
||||
|
||||
/* wildcard match for other_id */
|
||||
if (!other_id->matches(other_id, candidate_other_id, &wildcards))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
prio = PRIO_ID_MATCH - wildcards;
|
||||
|
||||
/* only accept if traffic selectors match */
|
||||
if (!contains_traffic_selectors(candidate, TRUE, my_ts, my_host) ||
|
||||
!contains_traffic_selectors(candidate, FALSE, other_ts, other_host))
|
||||
{
|
||||
DBG2(DBG_CFG, "candidate '%s' inacceptable due traffic "
|
||||
"selector mismatch", candidate->get_name(candidate));
|
||||
prio = PRIO_TS_MISMATCH;
|
||||
}
|
||||
|
||||
DBG2(DBG_CFG, "candidate policy '%s': '%D'...'%D' (prio=%d)",
|
||||
candidate->get_name(candidate),
|
||||
candidate_my_id, candidate_other_id, prio);
|
||||
|
||||
if (prio > best_prio)
|
||||
{
|
||||
found = candidate;
|
||||
best_prio = prio;
|
||||
}
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
|
||||
if (found)
|
||||
{
|
||||
DBG1(DBG_CFG, "found matching policy '%s': '%D'...'%D' (prio=%d)",
|
||||
found->get_name(found), found->get_my_id(found),
|
||||
found->get_other_id(found), best_prio);
|
||||
/* give out a new reference to it */
|
||||
found->get_ref(found);
|
||||
}
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_store_t.get_policy_by_name.
|
||||
*/
|
||||
static policy_t *get_policy_by_name(private_local_policy_store_t *this, char *name)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
policy_t *current, *found = NULL;
|
||||
|
||||
DBG2(DBG_CFG, "looking for policy '%s'", name);
|
||||
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
iterator = this->policies->create_iterator(this->policies, TRUE);
|
||||
while (iterator->iterate(iterator, (void **)¤t))
|
||||
{
|
||||
if (strcmp(current->get_name(current), name) == 0)
|
||||
{
|
||||
found = current;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
|
||||
/* give out a new reference */
|
||||
found->get_ref(found);
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_store_t.delete_policy.
|
||||
*/
|
||||
static status_t delete_policy(private_local_policy_store_t *this, char *name)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
policy_t *current;
|
||||
bool found = FALSE;
|
||||
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
iterator = this->policies->create_iterator(this->policies, TRUE);
|
||||
while (iterator->iterate(iterator, (void **)¤t))
|
||||
{
|
||||
if (strcmp(current->get_name(current), name) == 0)
|
||||
{
|
||||
/* remove policy from list, and destroy it */
|
||||
iterator->remove(iterator);
|
||||
current->destroy(current);
|
||||
found = TRUE;
|
||||
/* we do not break here, as there may be multipe policies */
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
if (found)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_store_t.create_iterator.
|
||||
*/
|
||||
static iterator_t* create_iterator(private_local_policy_store_t *this)
|
||||
{
|
||||
return this->policies->create_iterator_locked(this->policies,
|
||||
&this->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_store_t.destroy.
|
||||
*/
|
||||
static void destroy(private_local_policy_store_t *this)
|
||||
{
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
this->policies->destroy_offset(this->policies, offsetof(policy_t, destroy));
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
local_policy_store_t *local_policy_store_create(void)
|
||||
{
|
||||
private_local_policy_store_t *this = malloc_thing(private_local_policy_store_t);
|
||||
|
||||
this->public.policy_store.add_policy = (void (*) (policy_store_t*,policy_t*))add_policy;
|
||||
this->public.policy_store.get_policy = (policy_t* (*) (policy_store_t*,identification_t*,identification_t*,
|
||||
linked_list_t*,linked_list_t*,host_t*,host_t*))get_policy;
|
||||
this->public.policy_store.get_policy_by_name = (policy_t* (*) (policy_store_t*,char*))get_policy_by_name;
|
||||
this->public.policy_store.delete_policy = (status_t (*) (policy_store_t*,char*))delete_policy;
|
||||
this->public.policy_store.create_iterator = (iterator_t* (*) (policy_store_t*))create_iterator;
|
||||
this->public.policy_store.destroy = (void (*) (policy_store_t*))destroy;
|
||||
|
||||
/* private variables */
|
||||
this->policies = linked_list_create();
|
||||
pthread_mutex_init(&(this->mutex), NULL);
|
||||
|
||||
return (&this->public);
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/**
|
||||
* @file local_policy_store.h
|
||||
*
|
||||
* @brief Interface of local_policy_store_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
#ifndef LOCAL_POLICY_STORE_H_
|
||||
#define LOCAL_POLICY_STORE_H_
|
||||
|
||||
typedef struct local_policy_store_t local_policy_store_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <config/policies/policy_store.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief A policy_store_t implementation using a simple policy lists.
|
||||
*
|
||||
* The local_policy_store_t class implements the policy_store_t interface
|
||||
* as simple as possible. The policies are stored in a in-memory list.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - local_policy_store_create()
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
struct local_policy_store_t {
|
||||
|
||||
/**
|
||||
* Implements policy_store_t interface
|
||||
*/
|
||||
policy_store_t policy_store;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a local_policy_store_t instance.
|
||||
*
|
||||
* @return policy store instance.
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
local_policy_store_t *local_policy_store_create(void);
|
||||
|
||||
#endif /* LOCAL_POLICY_STORE_H_ */
|
||||
@@ -1,635 +0,0 @@
|
||||
/**
|
||||
* @file policy.c
|
||||
*
|
||||
* @brief Implementation of policy_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* 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 <time.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "policy.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <utils/linked_list.h>
|
||||
#include <utils/identification.h>
|
||||
|
||||
ENUM(dpd_action_names, DPD_NONE, DPD_RESTART,
|
||||
"DPD_NONE",
|
||||
"DPD_CLEAR",
|
||||
"DPD_ROUTE",
|
||||
"DPD_RESTART"
|
||||
);
|
||||
|
||||
ENUM(mode_names, MODE_TRANSPORT, MODE_BEET,
|
||||
"TRANSPORT",
|
||||
"TUNNEL",
|
||||
"2",
|
||||
"3",
|
||||
"BEET"
|
||||
);
|
||||
|
||||
typedef struct private_policy_t private_policy_t;
|
||||
|
||||
/**
|
||||
* Private data of an policy_t object
|
||||
*/
|
||||
struct private_policy_t {
|
||||
|
||||
/**
|
||||
* Public part
|
||||
*/
|
||||
policy_t public;
|
||||
|
||||
/**
|
||||
* Number of references hold by others to this policy
|
||||
*/
|
||||
refcount_t refcount;
|
||||
|
||||
/**
|
||||
* Name of the policy, used to query it
|
||||
*/
|
||||
char *name;
|
||||
|
||||
/**
|
||||
* id to use to identify us
|
||||
*/
|
||||
identification_t *my_id;
|
||||
|
||||
/**
|
||||
* allowed id for other
|
||||
*/
|
||||
identification_t *other_id;
|
||||
|
||||
/**
|
||||
* virtual IP to use locally
|
||||
*/
|
||||
host_t *my_virtual_ip;
|
||||
|
||||
/**
|
||||
* virtual IP to use remotly
|
||||
*/
|
||||
host_t *other_virtual_ip;
|
||||
|
||||
/**
|
||||
* Method to use for own authentication data
|
||||
*/
|
||||
auth_method_t auth_method;
|
||||
|
||||
/**
|
||||
* EAP type to use for peer authentication
|
||||
*/
|
||||
eap_type_t eap_type;
|
||||
|
||||
/**
|
||||
* we have a cert issued by this CA
|
||||
*/
|
||||
identification_t *my_ca;
|
||||
|
||||
/**
|
||||
* we require the other end to have a cert issued by this CA
|
||||
*/
|
||||
identification_t *other_ca;
|
||||
|
||||
/**
|
||||
* updown script
|
||||
*/
|
||||
char *updown;
|
||||
|
||||
/**
|
||||
* allow host access
|
||||
*/
|
||||
bool hostaccess;
|
||||
|
||||
/**
|
||||
* list for all proposals
|
||||
*/
|
||||
linked_list_t *proposals;
|
||||
|
||||
/**
|
||||
* list for traffic selectors for my site
|
||||
*/
|
||||
linked_list_t *my_ts;
|
||||
|
||||
/**
|
||||
* list for traffic selectors for others site
|
||||
*/
|
||||
linked_list_t *other_ts;
|
||||
|
||||
/**
|
||||
* Time before an SA gets invalid
|
||||
*/
|
||||
u_int32_t soft_lifetime;
|
||||
|
||||
/**
|
||||
* Time before an SA gets rekeyed
|
||||
*/
|
||||
u_int32_t hard_lifetime;
|
||||
|
||||
/**
|
||||
* Time, which specifies the range of a random value
|
||||
* substracted from soft_lifetime.
|
||||
*/
|
||||
u_int32_t jitter;
|
||||
|
||||
/**
|
||||
* What to do with an SA when other peer seams to be dead?
|
||||
*/
|
||||
bool dpd_action;
|
||||
|
||||
/**
|
||||
* Mode to propose for a initiated CHILD: tunnel/transport
|
||||
*/
|
||||
mode_t mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_name
|
||||
*/
|
||||
static char *get_name(private_policy_t *this)
|
||||
{
|
||||
return this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_my_id
|
||||
*/
|
||||
static identification_t *get_my_id(private_policy_t *this)
|
||||
{
|
||||
return this->my_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_other_id
|
||||
*/
|
||||
static identification_t *get_other_id(private_policy_t *this)
|
||||
{
|
||||
return this->other_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_my_ca
|
||||
*/
|
||||
static identification_t *get_my_ca(private_policy_t *this)
|
||||
{
|
||||
return this->my_ca;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_other_ca
|
||||
*/
|
||||
static identification_t *get_other_ca(private_policy_t *this)
|
||||
{
|
||||
return this->other_ca;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.auth_method_t.
|
||||
*/
|
||||
static auth_method_t get_auth_method(private_policy_t *this)
|
||||
{
|
||||
return this->auth_method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of connection_t.get_eap_type.
|
||||
*/
|
||||
static eap_type_t get_eap_type(private_policy_t *this)
|
||||
{
|
||||
return this->eap_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get traffic selectors, with wildcard-address update
|
||||
*/
|
||||
static linked_list_t *get_traffic_selectors(private_policy_t *this,
|
||||
linked_list_t *list, host_t *host)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
traffic_selector_t *current;
|
||||
linked_list_t *result = linked_list_create();
|
||||
|
||||
iterator = list->create_iterator(list, TRUE);
|
||||
|
||||
while (iterator->iterate(iterator, (void**)¤t))
|
||||
{
|
||||
/* we make a copy of the TS, this allows us to update wildcard
|
||||
* addresses in it. We won't pollute the shared policy. */
|
||||
current = current->clone(current);
|
||||
if (host)
|
||||
{
|
||||
current->set_address(current, host);
|
||||
}
|
||||
|
||||
result->insert_last(result, (void*)current);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_my_traffic_selectors
|
||||
*/
|
||||
static linked_list_t *get_my_traffic_selectors(private_policy_t *this, host_t *me)
|
||||
{
|
||||
return get_traffic_selectors(this, this->my_ts, me);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_other_traffic_selectors
|
||||
*/
|
||||
static linked_list_t *get_other_traffic_selectors(private_policy_t *this, host_t *other)
|
||||
{
|
||||
return get_traffic_selectors(this, this->other_ts, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Narrow traffic selectors, with wildcard-address update in "stored".
|
||||
*/
|
||||
static linked_list_t *select_traffic_selectors(private_policy_t *this,
|
||||
linked_list_t *stored,
|
||||
linked_list_t *supplied,
|
||||
host_t *host)
|
||||
{
|
||||
iterator_t *supplied_iter, *stored_iter, *i1, *i2;
|
||||
traffic_selector_t *supplied_ts, *stored_ts, *selected_ts, *ts1, *ts2;
|
||||
linked_list_t *selected = linked_list_create();
|
||||
|
||||
DBG2(DBG_CFG, "selecting traffic selectors");
|
||||
|
||||
stored_iter = stored->create_iterator(stored, TRUE);
|
||||
supplied_iter = supplied->create_iterator(supplied, TRUE);
|
||||
|
||||
/* iterate over all stored selectors */
|
||||
while (stored_iter->iterate(stored_iter, (void**)&stored_ts))
|
||||
{
|
||||
/* we make a copy of the TS, this allows us to update wildcard
|
||||
* addresses in it. We won't pollute the shared policy. */
|
||||
stored_ts = stored_ts->clone(stored_ts);
|
||||
if (host)
|
||||
{
|
||||
stored_ts->set_address(stored_ts, host);
|
||||
}
|
||||
|
||||
supplied_iter->reset(supplied_iter);
|
||||
/* iterate over all supplied traffic selectors */
|
||||
while (supplied_iter->iterate(supplied_iter, (void**)&supplied_ts))
|
||||
{
|
||||
DBG2(DBG_CFG, "stored %R <=> %R received",
|
||||
stored_ts, supplied_ts);
|
||||
|
||||
selected_ts = stored_ts->get_subset(stored_ts, supplied_ts);
|
||||
if (selected_ts)
|
||||
{
|
||||
/* got a match, add to list */
|
||||
selected->insert_last(selected, (void*)selected_ts);
|
||||
|
||||
DBG2(DBG_CFG, "found traffic selector for %s: %R",
|
||||
stored == this->my_ts ? "us" : "other", selected_ts);
|
||||
}
|
||||
}
|
||||
stored_ts->destroy(stored_ts);
|
||||
}
|
||||
stored_iter->destroy(stored_iter);
|
||||
supplied_iter->destroy(supplied_iter);
|
||||
|
||||
/* remove any redundant traffic selectors in the list */
|
||||
i1 = selected->create_iterator(selected, TRUE);
|
||||
i2 = selected->create_iterator(selected, TRUE);
|
||||
while (i1->iterate(i1, (void**)&ts1))
|
||||
{
|
||||
while (i2->iterate(i2, (void**)&ts2))
|
||||
{
|
||||
if (ts1 != ts2)
|
||||
{
|
||||
if (ts2->is_contained_in(ts2, ts1))
|
||||
{
|
||||
i2->remove(i2);
|
||||
ts2->destroy(ts2);
|
||||
i1->reset(i1);
|
||||
break;
|
||||
}
|
||||
if (ts1->is_contained_in(ts1, ts2))
|
||||
{
|
||||
i1->remove(i1);
|
||||
ts1->destroy(ts1);
|
||||
i2->reset(i2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i1->destroy(i1);
|
||||
i2->destroy(i2);
|
||||
|
||||
return selected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_policy_t.select_my_traffic_selectors
|
||||
*/
|
||||
static linked_list_t *select_my_traffic_selectors(private_policy_t *this,
|
||||
linked_list_t *supplied,
|
||||
host_t *me)
|
||||
{
|
||||
return select_traffic_selectors(this, this->my_ts, supplied, me);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_policy_t.select_other_traffic_selectors
|
||||
*/
|
||||
static linked_list_t *select_other_traffic_selectors(private_policy_t *this,
|
||||
linked_list_t *supplied,
|
||||
host_t* other)
|
||||
{
|
||||
return select_traffic_selectors(this, this->other_ts, supplied, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_proposal_iterator
|
||||
*/
|
||||
static linked_list_t *get_proposals(private_policy_t *this)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
proposal_t *current;
|
||||
linked_list_t *proposals = linked_list_create();
|
||||
|
||||
iterator = this->proposals->create_iterator(this->proposals, TRUE);
|
||||
while (iterator->iterate(iterator, (void**)¤t))
|
||||
{
|
||||
current = current->clone(current);
|
||||
proposals->insert_last(proposals, (void*)current);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
|
||||
return proposals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.select_proposal
|
||||
*/
|
||||
static proposal_t *select_proposal(private_policy_t *this, linked_list_t *proposals)
|
||||
{
|
||||
iterator_t *stored_iter, *supplied_iter;
|
||||
proposal_t *stored, *supplied, *selected;
|
||||
|
||||
stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
|
||||
supplied_iter = proposals->create_iterator(proposals, TRUE);
|
||||
|
||||
/* compare all stored proposals with all supplied. Stored ones are preferred. */
|
||||
while (stored_iter->iterate(stored_iter, (void**)&stored))
|
||||
{
|
||||
supplied_iter->reset(supplied_iter);
|
||||
while (supplied_iter->iterate(supplied_iter, (void**)&supplied))
|
||||
{
|
||||
selected = stored->select(stored, supplied);
|
||||
if (selected)
|
||||
{
|
||||
/* they match, return */
|
||||
stored_iter->destroy(stored_iter);
|
||||
supplied_iter->destroy(supplied_iter);
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
|
||||
stored_iter->destroy(stored_iter);
|
||||
supplied_iter->destroy(supplied_iter);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.add_authorities
|
||||
*/
|
||||
static void add_authorities(private_policy_t *this, identification_t *my_ca, identification_t *other_ca)
|
||||
{
|
||||
this->my_ca = my_ca;
|
||||
this->other_ca = other_ca;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_updown
|
||||
*/
|
||||
static char* get_updown(private_policy_t *this)
|
||||
{
|
||||
return this->updown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_hostaccess
|
||||
*/
|
||||
static bool get_hostaccess(private_policy_t *this)
|
||||
{
|
||||
return this->hostaccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements policy_t.get_dpd_action
|
||||
*/
|
||||
static dpd_action_t get_dpd_action(private_policy_t *this)
|
||||
{
|
||||
return this->dpd_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.add_my_traffic_selector
|
||||
*/
|
||||
static void add_my_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector)
|
||||
{
|
||||
this->my_ts->insert_last(this->my_ts, (void*)traffic_selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.add_other_traffic_selector
|
||||
*/
|
||||
static void add_other_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector)
|
||||
{
|
||||
this->other_ts->insert_last(this->other_ts, (void*)traffic_selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.add_proposal
|
||||
*/
|
||||
static void add_proposal(private_policy_t *this, proposal_t *proposal)
|
||||
{
|
||||
this->proposals->insert_last(this->proposals, (void*)proposal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_soft_lifetime
|
||||
*/
|
||||
static u_int32_t get_soft_lifetime(private_policy_t *this)
|
||||
{
|
||||
if (this->jitter == 0)
|
||||
{
|
||||
return this->soft_lifetime ;
|
||||
}
|
||||
return this->soft_lifetime - (random() % this->jitter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_hard_lifetime
|
||||
*/
|
||||
static u_int32_t get_hard_lifetime(private_policy_t *this)
|
||||
{
|
||||
return this->hard_lifetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_mode.
|
||||
*/
|
||||
static mode_t get_mode(private_policy_t *this)
|
||||
{
|
||||
return this->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of policy_t.get_virtual_ip.
|
||||
*/
|
||||
static host_t* get_virtual_ip(private_policy_t *this, host_t *suggestion)
|
||||
{
|
||||
if (suggestion == NULL)
|
||||
{
|
||||
if (this->my_virtual_ip)
|
||||
{
|
||||
return this->my_virtual_ip->clone(this->my_virtual_ip);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (this->other_virtual_ip)
|
||||
{
|
||||
return this->other_virtual_ip->clone(this->other_virtual_ip);
|
||||
}
|
||||
if (suggestion->is_anyaddr(suggestion))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return suggestion->clone(suggestion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements policy_t.get_ref.
|
||||
*/
|
||||
static void get_ref(private_policy_t *this)
|
||||
{
|
||||
ref_get(&this->refcount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements policy_t.destroy.
|
||||
*/
|
||||
static void destroy(private_policy_t *this)
|
||||
{
|
||||
if (ref_put(&this->refcount))
|
||||
{
|
||||
|
||||
this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
|
||||
this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
|
||||
this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
|
||||
|
||||
/* delete certification authorities */
|
||||
DESTROY_IF(this->my_ca);
|
||||
DESTROY_IF(this->other_ca);
|
||||
|
||||
/* delete updown script */
|
||||
if (this->updown)
|
||||
{
|
||||
free(this->updown);
|
||||
}
|
||||
|
||||
/* delete ids */
|
||||
this->my_id->destroy(this->my_id);
|
||||
this->other_id->destroy(this->other_id);
|
||||
DESTROY_IF(this->my_virtual_ip);
|
||||
DESTROY_IF(this->other_virtual_ip);
|
||||
|
||||
free(this->name);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header-file
|
||||
*/
|
||||
policy_t *policy_create(char *name, identification_t *my_id, identification_t *other_id,
|
||||
host_t *my_virtual_ip, host_t *other_virtual_ip,
|
||||
auth_method_t auth_method, eap_type_t eap_type,
|
||||
u_int32_t hard_lifetime, u_int32_t soft_lifetime,
|
||||
u_int32_t jitter, char *updown, bool hostaccess,
|
||||
mode_t mode, dpd_action_t dpd_action)
|
||||
{
|
||||
private_policy_t *this = malloc_thing(private_policy_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.get_name = (char* (*) (policy_t*))get_name;
|
||||
this->public.get_my_id = (identification_t* (*) (policy_t*))get_my_id;
|
||||
this->public.get_other_id = (identification_t* (*) (policy_t*))get_other_id;
|
||||
this->public.get_my_ca = (identification_t* (*) (policy_t*))get_my_ca;
|
||||
this->public.get_other_ca = (identification_t* (*) (policy_t*))get_other_ca;
|
||||
this->public.get_auth_method = (auth_method_t (*) (policy_t*)) get_auth_method;
|
||||
this->public.get_eap_type = (eap_type_t (*) (policy_t*)) get_eap_type;
|
||||
this->public.get_my_traffic_selectors = (linked_list_t* (*) (policy_t*,host_t*))get_my_traffic_selectors;
|
||||
this->public.get_other_traffic_selectors = (linked_list_t* (*) (policy_t*,host_t*))get_other_traffic_selectors;
|
||||
this->public.select_my_traffic_selectors = (linked_list_t* (*) (policy_t*,linked_list_t*,host_t*))select_my_traffic_selectors;
|
||||
this->public.select_other_traffic_selectors = (linked_list_t* (*) (policy_t*,linked_list_t*,host_t*))select_other_traffic_selectors;
|
||||
this->public.get_proposals = (linked_list_t* (*) (policy_t*))get_proposals;
|
||||
this->public.select_proposal = (proposal_t* (*) (policy_t*,linked_list_t*))select_proposal;
|
||||
this->public.add_my_traffic_selector = (void (*) (policy_t*,traffic_selector_t*))add_my_traffic_selector;
|
||||
this->public.add_other_traffic_selector = (void (*) (policy_t*,traffic_selector_t*))add_other_traffic_selector;
|
||||
this->public.add_proposal = (void (*) (policy_t*,proposal_t*))add_proposal;
|
||||
this->public.add_authorities = (void (*) (policy_t*,identification_t*,identification_t*))add_authorities;
|
||||
this->public.get_updown = (char* (*) (policy_t*))get_updown;
|
||||
this->public.get_hostaccess = (bool (*) (policy_t*))get_hostaccess;
|
||||
this->public.get_dpd_action = (dpd_action_t (*) (policy_t*))get_dpd_action;
|
||||
this->public.get_soft_lifetime = (u_int32_t (*) (policy_t *))get_soft_lifetime;
|
||||
this->public.get_hard_lifetime = (u_int32_t (*) (policy_t *))get_hard_lifetime;
|
||||
this->public.get_mode = (mode_t (*) (policy_t *))get_mode;
|
||||
this->public.get_virtual_ip = (host_t* (*)(policy_t*,host_t*))get_virtual_ip;
|
||||
this->public.get_ref = (void (*) (policy_t*))get_ref;
|
||||
this->public.destroy = (void (*) (policy_t*))destroy;
|
||||
|
||||
/* apply init values */
|
||||
this->name = strdup(name);
|
||||
this->my_id = my_id;
|
||||
this->other_id = other_id;
|
||||
this->my_virtual_ip = my_virtual_ip;
|
||||
this->other_virtual_ip = other_virtual_ip;
|
||||
this->auth_method = auth_method;
|
||||
this->eap_type = eap_type;
|
||||
this->hard_lifetime = hard_lifetime;
|
||||
this->soft_lifetime = soft_lifetime;
|
||||
this->jitter = jitter;
|
||||
this->updown = (updown == NULL) ? NULL : strdup(updown);
|
||||
this->hostaccess = hostaccess;
|
||||
this->dpd_action = dpd_action;
|
||||
this->mode = mode;
|
||||
|
||||
/* initialize private members*/
|
||||
this->refcount = 1;
|
||||
this->my_ca = NULL;
|
||||
this->other_ca = NULL;
|
||||
this->proposals = linked_list_create();
|
||||
this->my_ts = linked_list_create();
|
||||
this->other_ts = linked_list_create();
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -1,413 +0,0 @@
|
||||
/**
|
||||
* @file policy.h
|
||||
*
|
||||
* @brief Interface of policy_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef POLICY_H_
|
||||
#define POLICY_H_
|
||||
|
||||
typedef enum dpd_action_t dpd_action_t;
|
||||
typedef struct policy_t policy_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <utils/identification.h>
|
||||
#include <config/traffic_selector.h>
|
||||
#include <config/proposal.h>
|
||||
#include <sa/authenticators/authenticator.h>
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Actions to take when a peer does not respond (dead peer detected).
|
||||
*
|
||||
* These values are the same as in pluto/starter, so do not modify them!
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
enum dpd_action_t {
|
||||
/** DPD disabled */
|
||||
DPD_NONE,
|
||||
/** remove CHILD_SA without replacement */
|
||||
DPD_CLEAR,
|
||||
/** route the CHILD_SA to resetup when needed */
|
||||
DPD_ROUTE,
|
||||
/** restart CHILD_SA in a new IKE_SA, immediately */
|
||||
DPD_RESTART,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum names for dpd_action_t.
|
||||
*/
|
||||
extern enum_name_t *dpd_action_names;
|
||||
|
||||
/**
|
||||
* @brief Mode of an IPsec SA.
|
||||
*
|
||||
* These are equal to those defined in XFRM, so don't change.
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
enum mode_t {
|
||||
/** transport mode, no inner address */
|
||||
MODE_TRANSPORT = 0,
|
||||
/** tunnel mode, inner and outer addresses */
|
||||
MODE_TUNNEL = 1,
|
||||
/** BEET mode, tunnel mode but fixed, bound inner addresses */
|
||||
MODE_BEET = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum names for mode_t.
|
||||
*/
|
||||
extern enum_name_t *mode_names;
|
||||
|
||||
/**
|
||||
* @brief A policy_t defines the policies to apply to CHILD_SAs.
|
||||
*
|
||||
* The given two IDs identify a policy. These rules define how
|
||||
* child SAs may be set up and which traffic may be IPsec'ed.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - policy_create()
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
struct policy_t {
|
||||
|
||||
/**
|
||||
* @brief Get the name of the policy.
|
||||
*
|
||||
* Returned object is not getting cloned.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return policy's name
|
||||
*/
|
||||
char *(*get_name) (policy_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get own id.
|
||||
*
|
||||
* Returned object is not getting cloned.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return own id
|
||||
*/
|
||||
identification_t *(*get_my_id) (policy_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get peer id.
|
||||
*
|
||||
* Returned object is not getting cloned.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return other id
|
||||
*/
|
||||
identification_t *(*get_other_id) (policy_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get own ca.
|
||||
*
|
||||
* Returned object is not getting cloned.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return own ca
|
||||
*/
|
||||
identification_t *(*get_my_ca) (policy_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get peer ca.
|
||||
*
|
||||
* Returned object is not getting cloned.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return other ca
|
||||
*/
|
||||
identification_t *(*get_other_ca) (policy_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the authentication method to use.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return authentication method
|
||||
*/
|
||||
auth_method_t (*get_auth_method) (policy_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the EAP type to use for peer authentication.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return authentication method
|
||||
*/
|
||||
eap_type_t (*get_eap_type) (policy_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get configured traffic selectors for our site.
|
||||
*
|
||||
* Returns a list with all traffic selectors for the local
|
||||
* site. List and items must be destroyed after usage.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return list with traffic selectors
|
||||
*/
|
||||
linked_list_t *(*get_my_traffic_selectors) (policy_t *this, host_t *me);
|
||||
|
||||
/**
|
||||
* @brief Get configured traffic selectors for others site.
|
||||
*
|
||||
* Returns a list with all traffic selectors for the remote
|
||||
* site. List and items must be destroyed after usage.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return list with traffic selectors
|
||||
*/
|
||||
linked_list_t *(*get_other_traffic_selectors) (policy_t *this, host_t* other);
|
||||
|
||||
/**
|
||||
* @brief Select traffic selectors from a supplied list for local site.
|
||||
*
|
||||
* Resulted list and traffic selectors must be destroyed after usage.
|
||||
* As the traffic selectors may contain a wildcard address (0.0.0.0) for
|
||||
* addresses we don't know in previous, an address may be supplied to
|
||||
* replace these 0.0.0.0 addresses on-the-fly.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param supplied linked list with traffic selectors
|
||||
* @param me host address used by us
|
||||
* @return list containing the selected traffic selectors
|
||||
*/
|
||||
linked_list_t *(*select_my_traffic_selectors) (policy_t *this,
|
||||
linked_list_t *supplied,
|
||||
host_t *me);
|
||||
|
||||
/**
|
||||
* @brief Select traffic selectors from a supplied list for remote site.
|
||||
*
|
||||
* Resulted list and traffic selectors must be destroyed after usage.
|
||||
* As the traffic selectors may contain a wildcard address (0.0.0.0) for
|
||||
* addresses we don't know in previous, an address may be supplied to
|
||||
* replace these 0.0.0.0 addresses on-the-fly.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param supplied linked list with traffic selectors
|
||||
* @return list containing the selected traffic selectors
|
||||
*/
|
||||
linked_list_t *(*select_other_traffic_selectors) (policy_t *this,
|
||||
linked_list_t *supplied,
|
||||
host_t *other);
|
||||
|
||||
/**
|
||||
* @brief Get the list of internally stored proposals.
|
||||
*
|
||||
* policy_t does store proposals for AH/ESP, IKE proposals are in
|
||||
* the connection_t.
|
||||
* Resulting list and all of its proposals must be freed after usage.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return lists with proposals
|
||||
*/
|
||||
linked_list_t *(*get_proposals) (policy_t *this);
|
||||
|
||||
/**
|
||||
* @brief Select a proposal from a supplied list.
|
||||
*
|
||||
* Returned propsal is newly created and must be destroyed after usage.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param proposals list from from wich proposals are selected
|
||||
* @return selected proposal, or NULL if nothing matches
|
||||
*/
|
||||
proposal_t *(*select_proposal) (policy_t *this, linked_list_t *proposals);
|
||||
|
||||
/**
|
||||
* @brief Add a traffic selector to the list for local site.
|
||||
*
|
||||
* After add, traffic selector is owned by policy.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param traffic_selector traffic_selector to add
|
||||
*/
|
||||
void (*add_my_traffic_selector) (policy_t *this, traffic_selector_t *traffic_selector);
|
||||
|
||||
/**
|
||||
* @brief Add a traffic selector to the list for remote site.
|
||||
*
|
||||
* After add, traffic selector is owned by policy.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param traffic_selector traffic_selector to add
|
||||
*/
|
||||
void (*add_other_traffic_selector) (policy_t *this, traffic_selector_t *traffic_selector);
|
||||
|
||||
/**
|
||||
* @brief Add a proposal to the list.
|
||||
*
|
||||
* The proposals are stored by priority, first added
|
||||
* is the most prefered.
|
||||
* After add, proposal is owned by policy.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param proposal proposal to add
|
||||
*/
|
||||
void (*add_proposal) (policy_t *this, proposal_t *proposal);
|
||||
|
||||
/**
|
||||
* @brief Add certification authorities.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param my_ca issuer of my certificate
|
||||
* @param other_ca required issuer of the peer's certificate
|
||||
*/
|
||||
void (*add_authorities) (policy_t *this, identification_t *my_ca, identification_t *other_ca);
|
||||
|
||||
/**
|
||||
* @brief Get updown script
|
||||
*
|
||||
* @param this calling object
|
||||
* @return path to updown script
|
||||
*/
|
||||
char* (*get_updown) (policy_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get hostaccess flag
|
||||
*
|
||||
* @param this calling object
|
||||
* @return value of hostaccess flag
|
||||
*/
|
||||
bool (*get_hostaccess) (policy_t *this);
|
||||
|
||||
/**
|
||||
* @brief What should be done with a CHILD_SA, when other peer does not respond.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return dpd action
|
||||
*/
|
||||
dpd_action_t (*get_dpd_action) (policy_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the lifetime of a policy, before rekeying starts.
|
||||
*
|
||||
* A call to this function automatically adds a jitter to
|
||||
* avoid simultanous rekeying.
|
||||
*
|
||||
* @param this policy
|
||||
* @return lifetime in seconds
|
||||
*/
|
||||
u_int32_t (*get_soft_lifetime) (policy_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the lifetime of a policy, before SA gets deleted.
|
||||
*
|
||||
* @param this policy
|
||||
* @return lifetime in seconds
|
||||
*/
|
||||
u_int32_t (*get_hard_lifetime) (policy_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the mode to use for the CHILD_SA, tunnel, transport or BEET.
|
||||
*
|
||||
* @param this policy
|
||||
* @return lifetime in seconds
|
||||
*/
|
||||
mode_t (*get_mode) (policy_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get a virtual IP for the local or the remote host.
|
||||
*
|
||||
* By supplying NULL as IP, an IP for the local host is requested. It
|
||||
* may be %any or specific.
|
||||
* By supplying %any as host, an IP from the pool is selected to be
|
||||
* served to the peer.
|
||||
* If a specified host is supplied, it is checked if this address
|
||||
* is acceptable to serve to the peer. If so, it is returned. Otherwise,
|
||||
* an alternative IP is returned.
|
||||
* In any mode, this call may return NULL indicating virtual IP should
|
||||
* not be used.
|
||||
*
|
||||
* @param this policy
|
||||
* @param suggestion NULL, %any or specific, see description
|
||||
* @return clone of an IP to use, or NULL
|
||||
*/
|
||||
host_t* (*get_virtual_ip) (policy_t *this, host_t *suggestion);
|
||||
|
||||
/**
|
||||
* @brief Get a new reference.
|
||||
*
|
||||
* Get a new reference to this policy by increasing
|
||||
* it's internal reference counter.
|
||||
* Do not call get_ref or any other function until you
|
||||
* already have a reference. Otherwise the object may get
|
||||
* destroyed while calling get_ref(),
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*get_ref) (policy_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys the policy object.
|
||||
*
|
||||
* Decrements the internal reference counter and
|
||||
* destroys the policy when it reaches zero.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*destroy) (policy_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create a configuration object for IKE_AUTH and later.
|
||||
*
|
||||
* name-string gets cloned, ID's not.
|
||||
* Virtual IPs are used if they are != NULL. A %any host means the virtual
|
||||
* IP should be obtained from the other peer.
|
||||
* Lifetimes are in seconds. To prevent to peers to start rekeying at the
|
||||
* same time, a jitter may be specified. Rekeying of an SA starts at
|
||||
* (soft_lifetime - random(0, jitter)). After a successful rekeying,
|
||||
* the hard_lifetime limit counter is reset. You should specify
|
||||
* hard_lifetime > soft_lifetime > jitter.
|
||||
* After a call to create, a reference is obtained (refcount = 1).
|
||||
*
|
||||
* @param name name of the policy
|
||||
* @param my_id identification_t for ourselves
|
||||
* @param other_id identification_t for the remote guy
|
||||
* @param my_virtual_ip virtual IP for local host, or NULL
|
||||
* @param other_virtual_ip virtual IP for remote host, or NULL
|
||||
* @param auth_method Authentication method to use for our(!) auth data
|
||||
* @param eap_type EAP type to use for peer authentication
|
||||
* @param hard_lifetime lifetime before deleting an SA
|
||||
* @param soft_lifetime lifetime before rekeying an SA
|
||||
* @param jitter range of randomization time
|
||||
* @param updown updown script to execute on up/down event
|
||||
* @param hostaccess allow access to the host itself (used by the updown script)
|
||||
* @param mode mode to propose for CHILD_SA, transport, tunnel or BEET
|
||||
* @param dpd_action what to to with a CHILD_SA when other peer does not respond
|
||||
* @return policy_t object
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
policy_t *policy_create(char *name,
|
||||
identification_t *my_id, identification_t *other_id,
|
||||
host_t *my_virtual_ip, host_t *other_virtual_ip,
|
||||
auth_method_t auth_method, eap_type_t eap_type,
|
||||
u_int32_t hard_lifetime, u_int32_t soft_lifetime,
|
||||
u_int32_t jitter, char *updown, bool hostaccess,
|
||||
mode_t mode, dpd_action_t dpd_action);
|
||||
|
||||
#endif /* POLICY_H_ */
|
||||
@@ -1,119 +0,0 @@
|
||||
/**
|
||||
* @file policy_store.h
|
||||
*
|
||||
* @brief Interface policy_store_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
#ifndef POLICY_STORE_H_
|
||||
#define POLICY_STORE_H_
|
||||
|
||||
typedef struct policy_store_t policy_store_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <config/policies/policy.h>
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief The interface for a store of policy_t's.
|
||||
*
|
||||
* The store uses reference counting to manage their lifetime. Call
|
||||
* destroy() for a policy which is returned from the store after usage.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - stroke_create()
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
struct policy_store_t {
|
||||
|
||||
/**
|
||||
* @brief Returns a policy identified by two IDs and a set of traffic selectors.
|
||||
*
|
||||
* other_id must be fully qualified. my_id may be %any, as the
|
||||
* other peer may not include an IDr Request.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param my_id own ID of the policy
|
||||
* @param other_id others ID of the policy
|
||||
* @param my_ts traffic selectors requested for local host
|
||||
* @param other_ts traffic selectors requested for remote host
|
||||
* @param my_host host to use for wilcards in TS compare
|
||||
* @param other_host host to use for wildcards in TS compare
|
||||
* @return
|
||||
* - matching policy_t, if found
|
||||
* - NULL otherwise
|
||||
*/
|
||||
policy_t *(*get_policy) (policy_store_t *this,
|
||||
identification_t *my_id, identification_t *other_id,
|
||||
linked_list_t *my_ts, linked_list_t *other_ts,
|
||||
host_t *my_host, host_t* other_host);
|
||||
|
||||
/**
|
||||
* @brief Returns a policy identified by a connection name.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param name name of the policy
|
||||
* @return
|
||||
* - matching policy_t, if found
|
||||
* - NULL otherwise
|
||||
*/
|
||||
policy_t *(*get_policy_by_name) (policy_store_t *this, char *name);
|
||||
|
||||
/**
|
||||
* @brief Add a policy to the list.
|
||||
*
|
||||
* The policy is owned by the store after the call. Do
|
||||
* not modify nor free.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param policy policy to add
|
||||
*/
|
||||
void (*add_policy) (policy_store_t *this, policy_t *policy);
|
||||
|
||||
/**
|
||||
* @brief Delete a policy from the store.
|
||||
*
|
||||
* Remove a policy from the store identified by its name.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param policy policy to add
|
||||
* @return
|
||||
* - SUCCESS, or
|
||||
* - NOT_FOUND
|
||||
*/
|
||||
status_t (*delete_policy) (policy_store_t *this, char *name);
|
||||
|
||||
/**
|
||||
* @brief Get an iterator for the stored policies.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return iterator over all stored policies
|
||||
*/
|
||||
iterator_t* (*create_iterator) (policy_store_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys a policy_store_t object.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*destroy) (policy_store_t *this);
|
||||
};
|
||||
|
||||
#endif /*POLICY_STORE_H_*/
|
||||
@@ -167,6 +167,8 @@ static int print(FILE *stream, const struct printf_info *info,
|
||||
const void *const *args)
|
||||
{
|
||||
private_traffic_selector_t *this = *((private_traffic_selector_t**)(args[0]));
|
||||
linked_list_t *list = *((linked_list_t**)(args[0]));
|
||||
iterator_t *iterator;
|
||||
char addr_str[INET6_ADDRSTRLEN] = "";
|
||||
char *serv_proto = NULL;
|
||||
u_int8_t mask;
|
||||
@@ -179,6 +181,24 @@ static int print(FILE *stream, const struct printf_info *info,
|
||||
return fprintf(stream, "(null)");
|
||||
}
|
||||
|
||||
if (info->alt)
|
||||
{
|
||||
iterator = list->create_iterator(list, TRUE);
|
||||
while (iterator->iterate(iterator, (void**)&this))
|
||||
{
|
||||
/* call recursivly */
|
||||
written += fprintf(stream, "%R ", this);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return written;
|
||||
}
|
||||
|
||||
if (this->dynamic)
|
||||
{
|
||||
return fprintf(stream, "dynamic/%d",
|
||||
this->type == TS_IPV4_ADDR_RANGE ? 32 : 128);
|
||||
}
|
||||
|
||||
if (this->type == TS_IPV4_ADDR_RANGE)
|
||||
{
|
||||
inet_ntop(AF_INET, &this->from4, addr_str, sizeof(addr_str));
|
||||
|
||||
Reference in New Issue
Block a user