experimental P2P-NAT-T for IKEv2 merged back from branch

This commit is contained in:
Tobias Brunner
2007-10-03 15:10:41 +00:00
parent 99670c3714
commit d5cc175833
41 changed files with 5114 additions and 31 deletions
+10
View File
@@ -273,6 +273,16 @@ AC_ARG_ENABLE(
)
AM_CONDITIONAL(USE_MANAGER, test x$manager = xtrue)
AC_ARG_ENABLE(
[p2p],
AS_HELP_STRING([--enable-p2p],[enable peer-to-peer NAT traversal (default is NO).]),
[if test x$enableval = xyes; then
p2p=true
AC_DEFINE(P2P)
fi]
)
AM_CONDITIONAL(USE_P2P, test x$p2p = xtrue)
AC_ARG_ENABLE(
[integrity-test],
AS_HELP_STRING([--enable-integrity-test],[enable the integrity test of the crypto library (default is NO).]),
+8
View File
@@ -85,6 +85,14 @@ sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
sa/tasks/ike_reauth.c sa/tasks/ike_reauth.h \
sa/tasks/task.c sa/tasks/task.h
if USE_P2P
charon_SOURCES += encoding/payloads/endpoint_notify.c encoding/payloads/endpoint_notify.h \
processing/jobs/initiate_mediation_job.c processing/jobs/initiate_mediation_job.h \
processing/jobs/mediation_job.c processing/jobs/mediation_job.h \
sa/connect_manager.c sa/connect_manager.h \
sa/mediation_manager.c sa/mediation_manager.h \
sa/tasks/ike_p2p.c sa/tasks/ike_p2p.h
endif
INCLUDES = -I${linuxdir} -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon -I$(top_srcdir)/src/stroke
AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DIPSEC_DIR=\"${ipsecdir}\" -DIPSEC_PIDDIR=\"${piddir}\" \
+66 -1
View File
@@ -6,6 +6,7 @@
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -175,6 +176,24 @@ struct private_peer_cfg_t {
* virtual IP to use remotly
*/
host_t *other_virtual_ip;
#ifdef P2P
/**
* Is this a mediation connection?
*/
bool p2p_mediation;
/**
* Name of the mediation connection to mediate through
*/
peer_cfg_t *p2p_mediated_by;
/**
* ID of our peer at the mediation server (= leftid of the peer's conn with
* the mediation server)
*/
identification_t *peer_id;
#endif /* P2P */
};
/**
@@ -413,6 +432,36 @@ static host_t* get_other_virtual_ip(private_peer_cfg_t *this, host_t *suggestion
return suggestion->clone(suggestion);
}
#ifdef P2P
/**
* Implementation of peer_cfg_t.is_mediation.
*/
static bool is_mediation(private_peer_cfg_t *this)
{
return this->p2p_mediation;
}
/**
* Implementation of peer_cfg_t.get_mediated_by.
*/
static peer_cfg_t* get_mediated_by(private_peer_cfg_t *this)
{
if (this->p2p_mediated_by) {
this->p2p_mediated_by->get_ref(this->p2p_mediated_by);
return this->p2p_mediated_by;
}
return NULL;
}
/**
* Implementation of peer_cfg_t.get_peer_id.
*/
static identification_t* get_peer_id(private_peer_cfg_t *this)
{
return this->peer_id;
}
#endif /* P2P */
/**
* Implements peer_cfg_t.get_ref.
*/
@@ -436,6 +485,10 @@ static void destroy(private_peer_cfg_t *this)
DESTROY_IF(this->other_ca);
DESTROY_IF(this->my_virtual_ip);
DESTROY_IF(this->other_virtual_ip);
#ifdef P2P
DESTROY_IF(this->p2p_mediated_by);
DESTROY_IF(this->peer_id);
#endif /* P2P */
ietfAttr_list_destroy(this->groups);
free(this->name);
free(this);
@@ -454,7 +507,9 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
u_int32_t rekeytime, u_int32_t jitter,
bool reauth, bool mobike,
u_int32_t dpd_delay, dpd_action_t dpd_action,
host_t *my_virtual_ip, host_t *other_virtual_ip)
host_t *my_virtual_ip, host_t *other_virtual_ip,
bool p2p_mediation, peer_cfg_t *p2p_mediated_by,
identification_t *peer_id)
{
private_peer_cfg_t *this = malloc_thing(private_peer_cfg_t);
@@ -483,6 +538,11 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
this->public.get_other_virtual_ip = (host_t* (*) (peer_cfg_t *, host_t *))get_other_virtual_ip;
this->public.get_ref = (void(*)(peer_cfg_t *))get_ref;
this->public.destroy = (void(*)(peer_cfg_t *))destroy;
#ifdef P2P
this->public.is_mediation = (bool (*) (peer_cfg_t *))is_mediation;
this->public.get_mediated_by = (peer_cfg_t* (*) (peer_cfg_t *))get_mediated_by;
this->public.get_peer_id = (identification_t* (*) (peer_cfg_t *))get_peer_id;
#endif /* P2P */
/* apply init values */
this->name = strdup(name);
@@ -509,6 +569,11 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
this->my_virtual_ip = my_virtual_ip;
this->other_virtual_ip = other_virtual_ip;
this->refcount = 1;
#ifdef P2P
this->p2p_mediation = p2p_mediation;
this->p2p_mediated_by = p2p_mediated_by;
this->peer_id = peer_id;
#endif /* P2P */
return &this->public;
}
+38 -1
View File
@@ -6,6 +6,7 @@
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -314,6 +315,37 @@ struct peer_cfg_t {
* @return clone of an IP to use
*/
host_t* (*get_other_virtual_ip) (peer_cfg_t *this, host_t *suggestion);
#ifdef P2P
/**
* @brief Is this a mediation connection?
*
* @param this peer_cfg
* @return TRUE, if this is a mediation connection
*/
bool (*is_mediation) (peer_cfg_t *this);
/**
* @brief Get peer_cfg of the connection this one is mediated through.
*
* @param this peer_cfg
* @return reference to peer_cfg of the mediation connection
*/
peer_cfg_t* (*get_mediated_by) (peer_cfg_t *this);
/**
* @brief Get the id of the other peer at the mediation server.
*
* This is the leftid of the peer's connection with the mediation server.
*
* If it is not configured, it is assumed to be the same as the right id
* of this connection.
*
* @param this peer_cfg
* @return the id of the other peer
*/
identification_t* (*get_peer_id) (peer_cfg_t *this);
#endif /* P2P */
/**
* @brief Get a new reference.
@@ -370,6 +402,9 @@ struct peer_cfg_t {
* @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
* @param p2p_mediation TRUE if this is a mediation connection
* @param p2p_mediated_by name of the mediation connection to mediate through
* @param peer_id ID that identifies our peer at the mediation server
* @return peer_cfg_t object
*
* @ingroup config
@@ -383,6 +418,8 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ikev_version, ike_cfg_t *ike_cfg,
u_int32_t rekeytime, u_int32_t jitter,
bool reauth, bool mobike,
u_int32_t dpd_delay, dpd_action_t dpd_action,
host_t *my_virtual_ip, host_t *other_virtual_ip);
host_t *my_virtual_ip, host_t *other_virtual_ip,
bool p2p_mediation, peer_cfg_t *p2p_mediated_by,
identification_t *peer_id);
#endif /* PEER_CFG_H_ */
@@ -6,6 +6,7 @@
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2006-2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -228,10 +229,12 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
{
ike_cfg_t *ike_cfg;
peer_cfg_t *peer_cfg;
peer_cfg_t *mediated_by_cfg = NULL;
child_cfg_t *child_cfg;
identification_t *my_id, *other_id;
identification_t *my_ca = NULL;
identification_t *other_ca = NULL;
identification_t *peer_id = NULL;
bool my_ca_same = FALSE;
bool other_ca_same =FALSE;
host_t *my_host, *other_host, *my_subnet, *other_subnet;
@@ -253,7 +256,12 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
pop_string(msg, &msg->add_conn.algorithms.esp);
DBG2(DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike);
DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp);
pop_string(msg, &msg->add_conn.p2p.mediated_by);
pop_string(msg, &msg->add_conn.p2p.peerid);
DBG2(DBG_CFG, " p2p_mediation=%s", msg->add_conn.p2p.mediation ? "yes" : "no");
DBG2(DBG_CFG, " p2p_mediated_by=%s", msg->add_conn.p2p.mediated_by);
DBG2(DBG_CFG, " p2p_peerid=%s", msg->add_conn.p2p.peerid);
my_host = msg->add_conn.me.address?
host_create_from_string(msg->add_conn.me.address, IKE_PORT) : NULL;
if (my_host == NULL)
@@ -320,6 +328,49 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
goto destroy_hosts;
}
#ifdef P2P
if (msg->add_conn.p2p.mediation && msg->add_conn.p2p.mediated_by)
{
DBG1(DBG_CFG, "a mediation connection cannot be a"
" mediated connection at the same time, aborting");
goto destroy_ids;
}
if (msg->add_conn.p2p.mediated_by)
{
mediated_by_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, msg->add_conn.p2p.mediated_by);
if (!mediated_by_cfg)
{
DBG1(DBG_CFG, "mediation connection '%s' not found, aborting",
msg->add_conn.p2p.mediated_by);
goto destroy_ids;
}
if (!mediated_by_cfg->is_mediation(mediated_by_cfg))
{
DBG1(DBG_CFG, "connection '%s' as referred to by '%s' is"
"no mediation connection, aborting",
msg->add_conn.p2p.mediated_by, msg->add_conn.name);
goto destroy_ids;
}
}
if (msg->add_conn.p2p.peerid)
{
peer_id = identification_create_from_string(msg->add_conn.p2p.peerid);
if (!peer_id)
{
DBG1(DBG_CFG, "invalid peer ID: %s\n", msg->add_conn.p2p.peerid);
goto destroy_ids;
}
}
else
#endif /* P2P */
{
// no peer ID supplied, assume right ID
peer_id = other_id->clone(other_id);
}
my_subnet = host_create_from_string(msg->add_conn.me.subnet ?
msg->add_conn.me.subnet : msg->add_conn.me.address, IKE_PORT);
if (my_subnet == NULL)
@@ -513,6 +564,8 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
other_host->destroy(other_host);
other_id->destroy(other_id);
other_ca->destroy(other_ca);
peer_id->destroy(peer_id);
DESTROY_IF(mediated_by_cfg);
ietfAttr_list_destroy(my_groups);
ietfAttr_list_destroy(other_groups);
}
@@ -568,9 +621,9 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
msg->add_conn.rekey.tries, msg->add_conn.rekey.ike_lifetime,
msg->add_conn.rekey.ike_lifetime - msg->add_conn.rekey.margin,
msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
msg->add_conn.rekey.reauth, msg->add_conn.mobike,
msg->add_conn.dpd.delay, msg->add_conn.dpd.action,
my_vip, other_vip);
msg->add_conn.rekey.reauth, msg->add_conn.mobike,
msg->add_conn.dpd.delay, msg->add_conn.dpd.action, my_vip, other_vip,
msg->add_conn.p2p.mediation, mediated_by_cfg, peer_id);
}
child_cfg = child_cfg_create(
@@ -632,6 +685,8 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
destroy_ids:
my_id->destroy(my_id);
other_id->destroy(other_id);
DESTROY_IF(mediated_by_cfg);
DESTROY_IF(peer_id);
destroy_hosts:
my_host->destroy(my_host);
+12 -2
View File
@@ -5,8 +5,8 @@
*
*/
/*
* Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
/* Copyright (C) 2006-2007 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -177,6 +177,10 @@ static void destroy(private_daemon_t *this)
DESTROY_IF(this->public.kernel_interface);
DESTROY_IF(this->public.scheduler);
DESTROY_IF(this->public.interfaces);
#ifdef P2P
DESTROY_IF(this->public.connect_manager);
DESTROY_IF(this->public.mediation_manager);
#endif /* P2P */
DESTROY_IF(this->public.backends);
DESTROY_IF(this->public.credentials);
DESTROY_IF(this->public.sender);
@@ -337,6 +341,12 @@ static bool initialize(private_daemon_t *this, bool syslog, level_t levels[])
this->public.socket = socket_create(IKEV2_UDP_PORT, IKEV2_NATT_PORT);
this->public.sender = sender_create();
this->public.receiver = receiver_create();
#ifdef P2P
this->public.connect_manager = connect_manager_create();
this->public.mediation_manager = mediation_manager_create();
#endif /* P2P */
return TRUE;
}
+19 -1
View File
@@ -6,7 +6,8 @@
*/
/*
* Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
* Copyright (C) 2006-2007 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -42,6 +43,11 @@ typedef struct daemon_t daemon_t;
#include <sa/ike_sa_manager.h>
#include <config/backend_manager.h>
#ifdef P2P
#include <sa/connect_manager.h>
#include <sa/mediation_manager.h>
#endif /* P2P */
/**
* @defgroup charon charon
*
@@ -427,6 +433,18 @@ struct daemon_t {
*/
interface_manager_t *interfaces;
#ifdef P2P
/**
* Connect manager
*/
connect_manager_t *connect_manager;
/**
* Mediation manager
*/
mediation_manager_t *mediation_manager;
#endif /* P2P */
/**
* @brief Shut down the daemon.
*
+28
View File
@@ -150,9 +150,15 @@ static payload_rule_t ike_auth_i_payload_rules[] = {
{CERTIFICATE,0,1,TRUE,FALSE},
{CERTIFICATE_REQUEST,0,1,TRUE,FALSE},
{ID_RESPONDER,0,1,TRUE,FALSE},
#ifdef P2P
{SECURITY_ASSOCIATION,0,1,TRUE,FALSE},
{TRAFFIC_SELECTOR_INITIATOR,0,1,TRUE,FALSE},
{TRAFFIC_SELECTOR_RESPONDER,0,1,TRUE,FALSE},
#else
{SECURITY_ASSOCIATION,1,1,TRUE,FALSE},
{TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE,FALSE},
{TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE,FALSE},
#endif /* P2P */
{CONFIGURATION,0,1,TRUE,FALSE},
{VENDOR_ID,0,10,TRUE,FALSE},
};
@@ -223,6 +229,24 @@ static payload_rule_t create_child_sa_r_payload_rules[] = {
{VENDOR_ID,0,10,TRUE,FALSE},
};
#ifdef P2P
/**
* Message rule for P2P_CONNECT from initiator.
*/
static payload_rule_t p2p_connect_i_payload_rules[] = {
{NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,TRUE},
{ID_PEER,1,1,TRUE,FALSE},
{VENDOR_ID,0,10,TRUE,FALSE}
};
/**
* Message rule for P2P_CONNECT from responder.
*/
static payload_rule_t p2p_connect_r_payload_rules[] = {
{NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,TRUE},
{VENDOR_ID,0,10,TRUE,FALSE}
};
#endif /* P2P */
/**
* Message rules, defines allowed payloads.
@@ -236,6 +260,10 @@ static message_rule_t message_rules[] = {
{INFORMATIONAL,FALSE,TRUE,(sizeof(informational_r_payload_rules)/sizeof(payload_rule_t)),informational_r_payload_rules},
{CREATE_CHILD_SA,TRUE,TRUE,(sizeof(create_child_sa_i_payload_rules)/sizeof(payload_rule_t)),create_child_sa_i_payload_rules},
{CREATE_CHILD_SA,FALSE,TRUE,(sizeof(create_child_sa_r_payload_rules)/sizeof(payload_rule_t)),create_child_sa_r_payload_rules},
#ifdef P2P
{P2P_CONNECT,TRUE,TRUE,(sizeof(p2p_connect_i_payload_rules)/sizeof(payload_rule_t)),p2p_connect_i_payload_rules},
{P2P_CONNECT,FALSE,TRUE,(sizeof(p2p_connect_r_payload_rules)/sizeof(payload_rule_t)),p2p_connect_r_payload_rules},
#endif /* P2P */
};
@@ -0,0 +1,422 @@
/**
* @file endpoint_notify.c
*
* @brief Implementation of endpoint_notify_t.
*
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "endpoint_notify.h"
#include <math.h>
#include <daemon.h>
typedef struct private_endpoint_notify_t private_endpoint_notify_t;
/**
* Private data of an notify_payload_t object.
*
*/
struct private_endpoint_notify_t {
/**
* Public endpoint_notify_t interface.
*/
endpoint_notify_t public;
/**
* Priority
*/
u_int32_t priority;
/**
* Family
*/
p2p_endpoint_family_t family;
/**
* Endpoint type
*/
p2p_endpoint_type_t type;
/**
* Endpoint
*/
host_t *endpoint;
/**
* Base (used for server reflexive endpoints)
*/
host_t *base;
};
/* Notification data:
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Priority !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Family ! Type ! Port !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! IP Address (variable)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Helper functions to parse integer values
*/
static status_t parse_uint8(u_int8_t **cur, u_int8_t *top, u_int8_t *val)
{
if (*cur + sizeof(u_int8_t) > top)
{
return FAILED;
}
*val = *(u_int8_t*)*cur;
*cur += sizeof(u_int8_t);
return SUCCESS;
}
static status_t parse_uint16(u_int8_t **cur, u_int8_t *top, u_int16_t *val)
{
if (*cur + sizeof(u_int16_t) > top)
{
return FAILED;
}
*val = ntohs(*(u_int16_t*)*cur);
*cur += sizeof(u_int16_t);
return SUCCESS;
}
static status_t parse_uint32(u_int8_t **cur, u_int8_t *top, u_int32_t *val)
{
if (*cur + sizeof(u_int32_t) > top)
{
return FAILED;
}
*val = ntohl(*(u_int32_t*)*cur);
*cur += sizeof(u_int32_t);
return SUCCESS;
}
/**
* Parses the notification data of a P2P_ENDPOINT notify
*/
static status_t parse_notification_data(private_endpoint_notify_t *this, chunk_t data)
{
u_int8_t family, type, addr_family;
u_int16_t port;
chunk_t addr;
u_int8_t *cur = data.ptr;
u_int8_t *top = data.ptr + data.len;
DBG3(DBG_IKE, "p2p_endpoint_data %B", &data);
if (parse_uint32(&cur, top, &this->priority) != SUCCESS)
{
DBG1(DBG_IKE, "failed to parse P2P_ENDPOINT: invalid priority");
return FAILED;
}
if (parse_uint8(&cur, top, &family) != SUCCESS || family >= MAX_FAMILY)
{
DBG1(DBG_IKE, "failed to parse P2P_ENDPOINT: invalid family");
return FAILED;
}
this->family = (p2p_endpoint_family_t)family;
if (parse_uint8(&cur, top, &type) != SUCCESS || type >= MAX_TYPE)
{
DBG1(DBG_IKE, "failed to parse P2P_ENDPOINT: invalid type");
return FAILED;
}
this->type = (p2p_endpoint_type_t)type;
addr_family = AF_INET;
addr.len = 4;
switch(this->family)
{
case NO_FAMILY:
this->endpoint = NULL;
break;
case IPv6:
addr_family = AF_INET6;
addr.len = 16;
// fall-through
case IPv4:
if (parse_uint16(&cur, top, &port) != SUCCESS)
{
DBG1(DBG_IKE, "failed to parse P2P_ENDPOINT: invalid port");
return FAILED;
}
if (cur + addr.len > top)
{
DBG1(DBG_IKE, "failed to parse P2P_ENDPOINT: invalid IP address");
return FAILED;
}
addr.ptr = cur;
this->endpoint = host_create_from_chunk(addr_family, addr, port);
break;
}
return SUCCESS;
}
/**
* Generates the notification data of a P2P_ENDPOINT notify
*/
static chunk_t build_notification_data(private_endpoint_notify_t *this)
{
chunk_t prio_chunk, family_chunk, type_chunk, port_chunk, addr_chunk;
chunk_t data;
u_int32_t prio;
u_int16_t port;
u_int8_t family, type;
prio = htonl(this->priority);
prio_chunk = chunk_from_thing(prio);
family = this->family;
family_chunk = chunk_from_thing(family);
type = this->type;
type_chunk = chunk_from_thing(type);
if (this->endpoint)
{
port = htons(this->endpoint->get_port(this->endpoint));
addr_chunk = this->endpoint->get_address(this->endpoint);
}
else
{
port = 0;
addr_chunk = chunk_empty;
}
port_chunk = chunk_from_thing(port);
// data = prio | family | type | port | addr
data = chunk_cat("ccccc", prio_chunk, family_chunk, type_chunk,
port_chunk, addr_chunk);
DBG3(DBG_IKE, "p2p_endpoint_data %B", &data);
return data;
}
/**
* Implementation of endpoint_notify_t.build_notify
*/
static notify_payload_t *build_notify(private_endpoint_notify_t *this)
{
chunk_t data;
notify_payload_t *notify;
notify = notify_payload_create();
notify->set_notify_type(notify, P2P_ENDPOINT);
data = build_notification_data(this);
notify->set_notification_data(notify, data);
chunk_free(&data);
return notify;
}
/**
* Implementation of endpoint_notify_t.get_priority.
*/
static u_int32_t get_priority(private_endpoint_notify_t *this)
{
return this->priority;
}
/**
* Implementation of endpoint_notify_t.set_priority.
*/
static void set_priority(private_endpoint_notify_t *this, u_int32_t priority)
{
return this->priority = priority;
}
/**
* Implementation of endpoint_notify_t.get_type.
*/
static p2p_endpoint_type_t get_type(private_endpoint_notify_t *this)
{
return this->type;
}
/**
* Implementation of endpoint_notify_t.get_family.
*/
static p2p_endpoint_family_t get_family(private_endpoint_notify_t *this)
{
return this->family;
}
/**
* Implementation of endpoint_notify_t.get_host.
*/
static host_t *get_host(private_endpoint_notify_t *this)
{
return this->endpoint;
}
/**
* Implementation of endpoint_notify_t.get_base.
*/
static host_t *get_base(private_endpoint_notify_t *this)
{
return (!this->base) ? this->endpoint : this->base;
}
/**
* Implementation of endpoint_notify_t.clone.
*/
static endpoint_notify_t *_clone(private_endpoint_notify_t *this)
{
private_endpoint_notify_t *clone = (private_endpoint_notify_t*)endpoint_notify_create();
clone->priority = this->priority;
clone->type = this->type;
clone->family = this->family;
if (this->endpoint)
{
clone->endpoint = this->endpoint->clone(this->endpoint);
}
if (this->base)
{
clone->base = this->base->clone(this->base);
}
return &clone->public;
}
/**
* Implementation of endpoint_notify_t.destroy.
*/
static status_t destroy(private_endpoint_notify_t *this)
{
DESTROY_IF(this->endpoint);
free(this);
return SUCCESS;
}
/*
* Described in header
*/
endpoint_notify_t *endpoint_notify_create()
{
private_endpoint_notify_t *this = malloc_thing(private_endpoint_notify_t);
/* public functions */
this->public.get_priority = (u_int32_t (*) (endpoint_notify_t *)) get_priority;
this->public.set_priority = (void (*) (endpoint_notify_t *, u_int32_t)) set_priority;
this->public.get_type = (p2p_endpoint_type_t (*) (endpoint_notify_t *)) get_type;
this->public.get_family = (p2p_endpoint_family_t (*) (endpoint_notify_t *)) get_family;
this->public.get_host = (host_t *(*) (endpoint_notify_t *)) get_host;
this->public.get_base = (host_t *(*) (endpoint_notify_t *)) get_base;
this->public.build_notify = (notify_payload_t *(*) (endpoint_notify_t *)) build_notify;
this->public.clone = (endpoint_notify_t *(*) (endpoint_notify_t *)) _clone;
this->public.destroy = (void (*) (endpoint_notify_t *)) destroy;
/* set default values of the fields */
this->priority = 0;
this->family = NO_FAMILY;
this->type = NO_TYPE;
this->endpoint = NULL;
this->base = NULL;
return &this->public;
}
/**
* Described in header
*/
endpoint_notify_t *endpoint_notify_create_from_host(p2p_endpoint_type_t type, host_t *host, host_t *base)
{
private_endpoint_notify_t *this = (private_endpoint_notify_t*)endpoint_notify_create();
this->type = type;
switch(type)
{
case HOST:
this->priority = pow(2, 16) * P2P_PRIO_HOST;
break;
case SERVER_REFLEXIVE:
this->priority = pow(2, 16) * P2P_PRIO_SERVER;
break;
case PEER_REFLEXIVE:
this->priority = pow(2, 16) * P2P_PRIO_PEER;
break;
case RELAYED:
this->priority = pow(2, 16) * P2P_PRIO_RELAY;
break;
}
this->priority += 65535;
if (!host) {
return &this->public;
}
switch(host->get_family(host))
{
case AF_INET:
this->family = IPv4;
break;
case AF_INET6:
this->family = IPv6;
break;
default:
// unsupported family type, we do not set the hsot (family is set to NO_FAMILY)
return &this->public;
}
this->endpoint = host->clone(host);
if (base)
{
this->base = base->clone(base);
}
return &this->public;
}
/**
* Described in header
*/
endpoint_notify_t *endpoint_notify_create_from_payload(notify_payload_t *notify)
{
if (notify->get_notify_type(notify) != P2P_ENDPOINT)
{
return NULL;
}
private_endpoint_notify_t *this = (private_endpoint_notify_t*)endpoint_notify_create();
chunk_t data = notify->get_notification_data(notify);
if (parse_notification_data(this, data) != SUCCESS)
{
destroy(this);
return NULL;
}
return &this->public;
}
@@ -0,0 +1,185 @@
/**
* @file endpoint_notify.h
*
* @brief Interface of endpoint_notify_t.
*
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef ENDPOINT_NOTIFY_H_
#define ENDPOINT_NOTIFY_H_
#define P2P_PRIO_HOST 255
#define P2P_PRIO_SERVER 100
#define P2P_PRIO_PEER 120
#define P2P_PRIO_RELAY 0
typedef enum p2p_endpoint_family_t p2p_endpoint_family_t;
typedef enum p2p_endpoint_type_t p2p_endpoint_type_t;
typedef struct endpoint_notify_t endpoint_notify_t;
#include <encoding/payloads/notify_payload.h>
enum p2p_endpoint_family_t {
NO_FAMILY = 0,
IPv4 = 1,
IPv6 = 2,
MAX_FAMILY = 3
};
enum p2p_endpoint_type_t {
NO_TYPE = 0,
HOST = 1,
SERVER_REFLEXIVE = 2,
PEER_REFLEXIVE = 3,
RELAYED = 4,
MAX_TYPE = 5
};
/**
* @brief Class representing a P2P_ENDPOINT notify. In fact it's not
* the notify per se, but the notification data of that notify that is
* handled with this class.
*
* @b Constructors:
* - endpoint_notify_create()
* - endpoint_notify_create_from_host()
*
* @ingroup payloads
*/
struct endpoint_notify_t {
/**
* @brief Returns the priority of this endpoint.
*
* @param this object
* @return priority
*/
u_int32_t (*get_priority) (endpoint_notify_t *this);
/**
* @brief Sets the priority of this endpoint.
*
* @param this object
* @param priority priority
*/
void (*set_priority) (endpoint_notify_t *this, u_int32_t priority);
/**
* @brief Returns the endpoint type of this endpoint.
*
* @param this object
* @return endpoint type
*/
p2p_endpoint_type_t (*get_type) (endpoint_notify_t *this);
/**
* @brief Returns the endpoint family of this endpoint.
*
* @param this object
* @return endpoint family
*/
p2p_endpoint_family_t (*get_family) (endpoint_notify_t *this);
/**
* @brief Returns the host of this endpoint.
*
* @param this object
* @return host
*/
host_t *(*get_host) (endpoint_notify_t *this);
/**
* @brief Returns the base of this endpoint.
*
* If this is not a SERVER_REFLEXIVE endpoint, the returned host is the same
* as the one returned by get_host.
*
* @param this object
* @return host
*/
host_t *(*get_base) (endpoint_notify_t *this);
/**
* @brief Generates a notification payload from this endpoint.
*
* @param this object
* @return built notify_payload_t
*/
notify_payload_t *(*build_notify) (endpoint_notify_t *this);
/**
* @brief Clones an endpoint_notify_t object.
*
* @param this endpoint_notify_t object to clone
* @return cloned object
*/
endpoint_notify_t *(*clone) (endpoint_notify_t *this);
/**
* @brief Destroys an endpoint_notify_t object.
*
* @param this endpoint_notify_t object to destroy
*/
void (*destroy) (endpoint_notify_t *this);
};
/**
* @brief Creates an empty endpoint_notify_t object.
*
* @return created endpoint_notify_t object
*
* @ingroup payloads
*/
endpoint_notify_t *endpoint_notify_create(void);
/**
* @brief Creates an endpoint_notify_t object from a host.
*
* @param type the endpoint type
* @param host host to base the notify on (gets cloned)
* @param base base of the endpoint, applies only to reflexive endpoints (gets cloned)
* @return created endpoint_notify_t object
*
* @ingroup payloads
*/
endpoint_notify_t *endpoint_notify_create_from_host(p2p_endpoint_type_t type, host_t *host, host_t *base);
/**
* @brief Creates an endpoint_notify_t object from a notify payload.
*
* @param notify the notify payload
* @return - created endpoint_notify_t object
* - NULL if invalid payload
* @ingroup payloads
*/
endpoint_notify_t *endpoint_notify_create_from_payload(notify_payload_t *notify);
#endif /*ENDPOINT_NOTIFY_H_*/
+20 -2
View File
@@ -6,6 +6,7 @@
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -109,7 +110,13 @@ ENUM_NEXT(exchange_type_names, IKE_SA_INIT, INFORMATIONAL, EXCHANGE_TYPE_UNDEFIN
"IKE_AUTH",
"CREATE_CHILD_SA",
"INFORMATIONAL");
#ifdef P2P
ENUM_NEXT(exchange_type_names, P2P_CONNECT, P2P_CONNECT, INFORMATIONAL,
"P2P_CONNECT");
ENUM_END(exchange_type_names, P2P_CONNECT);
#else
ENUM_END(exchange_type_names, INFORMATIONAL);
#endif /* P2P */
/**
* Encoding rules to parse or generate a IKEv2-Header.
@@ -172,12 +179,23 @@ encoding_rule_t ike_header_encodings[] = {
*/
static status_t verify(private_ike_header_t *this)
{
if ((this->exchange_type < IKE_SA_INIT) || (this->exchange_type > INFORMATIONAL))
if ((this->exchange_type < IKE_SA_INIT) ||
((this->exchange_type > INFORMATIONAL)
#ifdef P2P
&& (this->exchange_type != P2P_CONNECT)
#endif /* P2P */
))
{
/* unsupported exchange type */
return FAILED;
}
if (this->initiator_spi == 0)
if (this->initiator_spi == 0
#ifdef P2P
// we allow zero spi for INFORMATIONAL exchanges, to allow P2P connectivity checks
&& this->exchange_type != INFORMATIONAL
#endif /* P2P */
)
{
/* initiator spi not set */
return FAILED;
+9 -2
View File
@@ -6,6 +6,7 @@
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -70,7 +71,7 @@ enum exchange_type_t{
/**
* EXCHANGE_TYPE_UNDEFINED. In private space, since not a official message type.
*/
EXCHANGE_TYPE_UNDEFINED = 240,
EXCHANGE_TYPE_UNDEFINED = 255,
/**
* IKE_SA_INIT.
@@ -90,7 +91,13 @@ enum exchange_type_t{
/**
* INFORMATIONAL.
*/
INFORMATIONAL = 37
INFORMATIONAL = 37,
#ifdef P2P
/**
* P2P_CONNECT
*/
P2P_CONNECT = 240
#endif /* P2P */
};
/**
+41 -1
View File
@@ -6,7 +6,8 @@
*/
/*
* Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
* Copyright (C) 2006-2007 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -56,7 +57,13 @@ ENUM_NEXT(notify_type_names, SINGLE_PAIR_REQUIRED, UNEXPECTED_NAT_DETECTED, AUTH
"INVALID_SELECTORS",
"UNACCEPTABLE_ADDRESSES",
"UNEXPECTED_NAT_DETECTED");
#ifdef P2P
ENUM_NEXT(notify_type_names, P2P_CONNECT_FAILED, P2P_CONNECT_FAILED, UNEXPECTED_NAT_DETECTED,
"P2P_CONNECT_FAILED");
ENUM_NEXT(notify_type_names, INITIAL_CONTACT, AUTH_LIFETIME, P2P_CONNECT_FAILED,
#else
ENUM_NEXT(notify_type_names, INITIAL_CONTACT, AUTH_LIFETIME, UNEXPECTED_NAT_DETECTED,
#endif /* P2P */
"INITIAL_CONTACT",
"SET_WINDOW_SIZE",
"ADDITIONAL_TS_POSSIBLE",
@@ -79,7 +86,20 @@ ENUM_NEXT(notify_type_names, INITIAL_CONTACT, AUTH_LIFETIME, UNEXPECTED_NAT_DETE
"AUTH_LIFETIME");
ENUM_NEXT(notify_type_names, EAP_ONLY_AUTHENTICATION, EAP_ONLY_AUTHENTICATION, AUTH_LIFETIME,
"EAP_ONLY_AUTHENTICATION");
#ifdef P2P
ENUM_NEXT(notify_type_names, USE_BEET_MODE, USE_BEET_MODE, EAP_ONLY_AUTHENTICATION,
"USE_BEET_MODE");
ENUM_NEXT(notify_type_names, P2P_MEDIATION, P2P_RESPONSE, USE_BEET_MODE,
"P2P_MEDIATION",
"P2P_ENDPOINT",
"P2P_CALLBACK",
"P2P_SESSIONID",
"P2P_SESSIONKEY",
"P2P_RESPONSE");
ENUM_END(notify_type_names, P2P_RESPONSE);
#else
ENUM_END(notify_type_names, EAP_ONLY_AUTHENTICATION);
#endif /* P2P */
ENUM_BEGIN(notify_type_short_names, UNSUPPORTED_CRITICAL_PAYLOAD, UNSUPPORTED_CRITICAL_PAYLOAD,
@@ -108,7 +128,13 @@ ENUM_NEXT(notify_type_short_names, SINGLE_PAIR_REQUIRED, UNEXPECTED_NAT_DETECTED
"INVAL_SEL",
"UNACCEPT_ADDR",
"UNEXPECT_NAT");
#ifdef P2P
ENUM_NEXT(notify_type_short_names, P2P_CONNECT_FAILED, P2P_CONNECT_FAILED, UNEXPECTED_NAT_DETECTED,
"P2P_CONN_FAIL");
ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, AUTH_LIFETIME, P2P_CONNECT_FAILED,
#else
ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, AUTH_LIFETIME, UNEXPECTED_NAT_DETECTED,
#endif /* P2P */
"INIT_CONTACT",
"SET_WINSIZE",
"ADD_TS_POSS",
@@ -131,7 +157,20 @@ ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, AUTH_LIFETIME, UNEXPECTED_NA
"AUTH_LFT");
ENUM_NEXT(notify_type_short_names, EAP_ONLY_AUTHENTICATION, EAP_ONLY_AUTHENTICATION, AUTH_LIFETIME,
"EAP_ONLY");
#ifdef P2P
ENUM_NEXT(notify_type_short_names, USE_BEET_MODE, USE_BEET_MODE, EAP_ONLY_AUTHENTICATION,
"BEET_MODE");
ENUM_NEXT(notify_type_short_names, P2P_MEDIATION, P2P_RESPONSE, USE_BEET_MODE,
"P2P_MED",
"P2P_EP",
"P2P_CB",
"P2P_SID",
"P2P_SKEY",
"P2P_R");
ENUM_END(notify_type_short_names, P2P_RESPONSE);
#else
ENUM_END(notify_type_short_names, EAP_ONLY_AUTHENTICATION);
#endif /* P2P */
typedef struct private_notify_payload_t private_notify_payload_t;
@@ -303,6 +342,7 @@ static status_t verify(private_notify_payload_t *this)
}
break;
}
// FIXME: check size of P2P-NAT-T payloads
default:
/* TODO: verify */
break;
+15 -1
View File
@@ -6,7 +6,8 @@
*/
/*
* Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
* Copyright (C) 2006-2007 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -67,6 +68,10 @@ enum notify_type_t {
INVALID_SELECTORS = 39,
UNACCEPTABLE_ADDRESSES = 40,
UNEXPECTED_NAT_DETECTED = 41,
#ifdef P2P
/* P2P-NAT-T, private use */
P2P_CONNECT_FAILED = 8192,
#endif /* P2P */
/* notify status messages */
INITIAL_CONTACT = 16384,
SET_WINDOW_SIZE = 16385,
@@ -94,6 +99,15 @@ enum notify_type_t {
EAP_ONLY_AUTHENTICATION = 40960,
/* BEET mode, not even a draft yet. private use */
USE_BEET_MODE = 40961,
#ifdef P2P
/* P2P-NAT-T, private use */
P2P_MEDIATION = 40962,
P2P_ENDPOINT = 40963,
P2P_CALLBACK = 40964,
P2P_SESSIONID = 40965,
P2P_SESSIONKEY = 40966,
P2P_RESPONSE = 40967
#endif /* P2P */
};
/**
+16
View File
@@ -64,7 +64,13 @@ ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, N
"ENCRYPTED",
"CONFIGURATION",
"EXTENSIBLE_AUTHENTICATION");
#ifdef P2P
ENUM_NEXT(payload_type_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
"ID_PEER");
ENUM_NEXT(payload_type_names, HEADER, UNKNOWN_PAYLOAD, ID_PEER,
#else
ENUM_NEXT(payload_type_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTICATION,
#endif /* P2P */
"HEADER",
"PROPOSAL_SUBSTRUCTURE",
"TRANSFORM_SUBSTRUCTURE",
@@ -94,7 +100,13 @@ ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICAT
"E",
"CP",
"EAP");
#ifdef P2P
ENUM_NEXT(payload_type_short_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
"IDp");
ENUM_NEXT(payload_type_short_names, HEADER, UNKNOWN_PAYLOAD, ID_PEER,
#else
ENUM_NEXT(payload_type_short_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTICATION,
#endif /* P2P */
"HDR",
"PROP",
"TRANS",
@@ -127,6 +139,10 @@ payload_t *payload_create(payload_type_t type)
return (payload_t*)id_payload_create(ID_INITIATOR);
case ID_RESPONDER:
return (payload_t*)id_payload_create(ID_RESPONDER);
#ifdef P2P
case ID_PEER:
return (payload_t*)id_payload_create(ID_PEER);
#endif /* P2P */
case AUTHENTICATION:
return (payload_t*)auth_payload_create();
case CERTIFICATE:
+9
View File
@@ -6,6 +6,7 @@
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -126,6 +127,14 @@ enum payload_type_t{
*/
EXTENSIBLE_AUTHENTICATION = 48,
#ifdef P2P
/**
* Identification payload for peers in P2P-NAT-T has a value from
* the PRIVATE USE space.
*/
ID_PEER = 128,
#endif /* P2P */
/**
* Header has a value of PRIVATE USE space.
*
@@ -0,0 +1,253 @@
/**
* @file initiate_mediation_job.c
*
* @brief Implementation of initiate_mediation_job_t.
*
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "initiate_mediation_job.h"
#include <sa/ike_sa.h>
#include <daemon.h>
typedef struct private_initiate_mediation_job_t private_initiate_mediation_job_t;
/**
* Private data of an initiate_mediation_job_t Object
*/
struct private_initiate_mediation_job_t {
/**
* public initiate_mediation_job_t interface
*/
initiate_mediation_job_t public;
/**
* ID of the IKE_SA of the mediated connection.
*/
ike_sa_id_t *mediated_sa_id;
/**
* Child config of the CHILD_SA of the mediated connection.
*/
child_cfg_t *mediated_child;
/**
* ID of the IKE_SA of the mediation connection.
*/
ike_sa_id_t *mediation_sa_id;
};
/**
* Implements job_t.destroy.
*/
static void destroy(private_initiate_mediation_job_t *this)
{
DESTROY_IF(this->mediation_sa_id);
DESTROY_IF(this->mediated_sa_id);
DESTROY_IF(this->mediated_child);
free(this);
}
/**
* Callback to handle initiation of mediation connection
*/
static bool initiate_callback(private_initiate_mediation_job_t *this, signal_t signal, level_t level,
ike_sa_t *ike_sa, char *format, va_list args)
{
if (signal == CHILD_UP_SUCCESS)
{
// mediation connection is up
this->mediation_sa_id = ike_sa->get_id(ike_sa);
this->mediation_sa_id = this->mediation_sa_id->clone(this->mediation_sa_id);
return FALSE;
}
return TRUE;
}
/**
* Implementation of job_t.execute.
*/
static void initiate(private_initiate_mediation_job_t *this)
{//FIXME: check the logging
ike_sa_t *mediated_sa, *mediation_sa;
peer_cfg_t *mediated_cfg, *mediation_cfg;
mediated_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
this->mediated_sa_id);
if (mediated_sa)
{
mediated_cfg = mediated_sa->get_peer_cfg(mediated_sa);
mediated_cfg->get_ref(mediated_cfg); // get_peer_cfg returns an internal object
charon->ike_sa_manager->checkin(charon->ike_sa_manager, mediated_sa);
mediation_cfg = mediated_cfg->get_mediated_by(mediated_cfg);
if (charon->connect_manager->check_and_register(charon->connect_manager,
mediation_cfg->get_my_id(mediation_cfg),
mediated_cfg->get_peer_id(mediated_cfg),
this->mediated_sa_id, this->mediated_child))
{
mediated_cfg->destroy(mediated_cfg);
mediation_cfg->destroy(mediation_cfg);
charon->bus->set_sa(charon->bus, mediated_sa); // this pointer should still be valid
DBG1(DBG_IKE, "mediation with the same peer is already in progress, queued");
destroy(this);
return;
}
mediation_cfg->get_ref(mediation_cfg); // we need an additional reference because initiate consumes one
// this function call blocks until the connection is up or failed
// we do not check the status, but NEED_MORE would be returned on success
// because the registered callback returns FALSE then
// this->mediation_sa_id is set in the callback
charon->interfaces->initiate(charon->interfaces,
mediation_cfg, NULL, (interface_manager_cb_t)initiate_callback, this);
if (!this->mediation_sa_id)
{
DBG1(DBG_JOB, "initiating mediation connection '%s' failed",
mediation_cfg->get_name(mediation_cfg));
mediation_cfg->destroy(mediation_cfg);
mediated_cfg->destroy(mediated_cfg);
charon->bus->set_sa(charon->bus, mediated_sa); // this pointer should still be valid
SIG(IKE_UP_FAILED, "mediation failed");
destroy(this);
return;
}
mediation_cfg->destroy(mediation_cfg);
mediation_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
this->mediation_sa_id);
if (mediation_sa)
{
if (mediation_sa->initiate_mediation(mediation_sa, mediated_cfg) != SUCCESS)
{
DBG1(DBG_JOB, "initiating mediated connection '%s' failed",
mediated_cfg->get_name(mediated_cfg));
mediated_cfg->destroy(mediated_cfg);
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, mediation_sa);
charon->bus->set_sa(charon->bus, mediated_sa); // this pointer should still be valid
SIG(IKE_UP_FAILED, "mediation failed");
destroy(this);
return;
}
charon->ike_sa_manager->checkin(charon->ike_sa_manager, mediation_sa);
}
mediated_cfg->destroy(mediated_cfg);
}
destroy(this);
}
/**
* Implementation of job_t.execute.
*/
static void reinitiate(private_initiate_mediation_job_t *this)
{//FIXME: check the logging
ike_sa_t *mediated_sa, *mediation_sa;
peer_cfg_t *mediated_cfg;
mediated_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
this->mediated_sa_id);
if (mediated_sa)
{
mediated_cfg = mediated_sa->get_peer_cfg(mediated_sa);
mediated_cfg->get_ref(mediated_cfg); // get_peer_cfg returns an internal object
charon->ike_sa_manager->checkin(charon->ike_sa_manager, mediated_sa);
mediation_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
this->mediation_sa_id);
if (mediation_sa)
{
if (mediation_sa->initiate_mediation(mediation_sa, mediated_cfg) != SUCCESS)
{
DBG1(DBG_JOB, "initiating mediated connection '%s' failed",
mediated_cfg->get_name(mediated_cfg));
mediated_cfg->destroy(mediated_cfg);
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, mediation_sa);
charon->bus->set_sa(charon->bus, mediated_sa); // this pointer should still be valid
SIG(IKE_UP_FAILED, "mediation failed");
destroy(this);
return;
}
charon->ike_sa_manager->checkin(charon->ike_sa_manager, mediation_sa);
}
mediated_cfg->destroy(mediated_cfg);
}
destroy(this);
}
/**
* Creates an empty job
*/
static private_initiate_mediation_job_t *initiate_mediation_job_create_empty()
{
private_initiate_mediation_job_t *this = malloc_thing(private_initiate_mediation_job_t);
/* interface functions */
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
/* private variables */
this->mediation_sa_id = NULL;
this->mediated_sa_id = NULL;
this->mediated_child = NULL;
return this;
}
/*
* Described in header
*/
initiate_mediation_job_t *initiate_mediation_job_create(ike_sa_id_t *ike_sa_id,
child_cfg_t *child_cfg)
{
private_initiate_mediation_job_t *this = initiate_mediation_job_create_empty();
this->public.job_interface.execute = (void (*) (job_t *)) initiate;
this->mediated_sa_id = ike_sa_id->clone(ike_sa_id);
child_cfg->get_ref(child_cfg);
this->mediated_child = child_cfg;
return &this->public;
}
/*
* Described in header
*/
initiate_mediation_job_t *reinitiate_mediation_job_create(ike_sa_id_t *mediation_sa_id,
ike_sa_id_t *mediated_sa_id)
{
private_initiate_mediation_job_t *this = initiate_mediation_job_create_empty();
this->public.job_interface.execute = (void (*) (job_t *)) reinitiate;
this->mediation_sa_id = mediation_sa_id->clone(mediation_sa_id);
this->mediated_sa_id = mediated_sa_id->clone(mediated_sa_id);
return &this->public;
}
@@ -0,0 +1,74 @@
/**
* @file initiate_mediation_job.h
*
* @brief Interface of initiate_mediation_job_t.
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef INITIATE_MEDIATION_JOB_H_
#define INITIATE_MEDIATION_JOB_H_
typedef struct initiate_mediation_job_t initiate_mediation_job_t;
#include <processing/jobs/job.h>
#include <config/child_cfg.h>
#include <sa/ike_sa_id.h>
/**
* @brief Class representing a INITIATE_MEDIATION Job.
*
* This job will initiate a mediation on behalf of a mediated connection.
* If required the mediation connection is established.
*
* @b Constructors:
* - initiate_mediation_job_create()
*
* @ingroup jobs
*/
struct initiate_mediation_job_t {
/**
* implements job_t interface
*/
job_t job_interface;
};
/**
* @brief Creates a job of type INITIATE_MEDIATION.
*
* @param ike_sa_id identification of the ike_sa as ike_sa_id_t object (gets cloned)
* @param child_cfg child config of the child_sa (gets cloned)
* @return job object
*
* @ingroup jobs
*/
initiate_mediation_job_t *initiate_mediation_job_create(ike_sa_id_t *ike_sa_id,
child_cfg_t *child_cfg);
/**
* @brief Creates a special job of type INITIATE_MEDIATION that reinitiates a
* specific connection.
*
* @param mediation_sa_id identification of the mediation sa (gets cloned)
* @param mediated_sa_id identification of the mediated sa (gets cloned)
* @return job object
*
* @ingroup jobs
*/
initiate_mediation_job_t *reinitiate_mediation_job_create(ike_sa_id_t *mediation_sa_id,
ike_sa_id_t *mediated_sa_id);
#endif /*INITIATE_MEDIATION_JOB_H_*/
+203
View File
@@ -0,0 +1,203 @@
/**
* @file mediation_job.c
*
* @brief Implementation of mediation_job_t.
*
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "mediation_job.h"
#include <encoding/payloads/endpoint_notify.h>
#include <daemon.h>
typedef struct private_mediation_job_t private_mediation_job_t;
/**
* Private data of an mediation_job_t Object
*/
struct private_mediation_job_t {
/**
* public mediation_job_t interface
*/
mediation_job_t public;
/**
* ID of target peer.
*/
identification_t *target;
/**
* ID of the source peer.
*/
identification_t *source;
/**
* P2P_SESSIONID
*/
chunk_t session_id;
/**
* P2P_SESSIONKEY
*/
chunk_t session_key;
/**
* Submitted endpoints
*/
linked_list_t *endpoints;
/**
* Is this a callback job?
*/
bool callback;
/**
* Is this a response?
*/
bool response;
};
/**
* Implements job_t.destroy.
*/
static void destroy(private_mediation_job_t *this)
{
DESTROY_IF(this->target);
DESTROY_IF(this->source);
chunk_free(&this->session_id);
chunk_free(&this->session_key);
DESTROY_OFFSET_IF(this->endpoints, offsetof(endpoint_notify_t, destroy));
free(this);
}
/**
* Implementation of job_t.execute.
*/
static void execute(private_mediation_job_t *this)
{
ike_sa_id_t *target_sa_id;
target_sa_id = charon->mediation_manager->check(charon->mediation_manager, this->target);
if (target_sa_id)
{
ike_sa_t *target_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
target_sa_id);
if (target_sa)
{
if (this->callback)
{
// send callback to a peer
if (target_sa->callback(target_sa, this->source) != SUCCESS)
{
DBG1(DBG_JOB, "callback for '%D' to '%D' failed",
this->source, this->target);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa);
destroy(this);
return;
}
}
else
{
// normal mediation between two peers
if (target_sa->relay(target_sa, this->source, this->session_id,
this->session_key, this->endpoints, this->response) != SUCCESS)
{
DBG1(DBG_JOB, "mediation between '%D' and '%D' failed",
this->source, this->target);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa);
// FIXME: notify the initiator
destroy(this);
return;
}
}
charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa);
}
else
{
DBG1(DBG_JOB, "mediation between '%D' and '%D' failed: "
"SA not found", this->source, this->target);
}
}
else
{
DBG1(DBG_JOB, "mediation between '%D' and '%D' failed: "
"peer is not online anymore", this->source, this->target);
}
destroy(this);
}
/**
* Creates an empty mediation job
*/
static private_mediation_job_t *mediation_job_create_empty()
{
private_mediation_job_t *this = malloc_thing(private_mediation_job_t);
/* interface functions */
this->public.job_interface.execute = (void (*) (job_t *)) execute;
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
/* private variables */
this->target = NULL;
this->source = NULL;
this->callback = FALSE;
this->session_id = chunk_empty;
this->session_key = chunk_empty;
this->endpoints = NULL;
this->response = FALSE;
return this;
}
/*
* Described in header
*/
mediation_job_t *mediation_job_create(identification_t *peer_id,
identification_t *requester, chunk_t session_id, chunk_t session_key,
linked_list_t *endpoints, bool response)
{
private_mediation_job_t *this = mediation_job_create_empty();
this->target = peer_id->clone(peer_id);
this->source = requester->clone(requester);
this->session_id = chunk_clone(session_id);
this->session_key = chunk_clone(session_key);
this->endpoints = endpoints->clone_offset(endpoints, offsetof(endpoint_notify_t, clone));
this->response = response;
return &this->public;
}
/*
* Described in header
*/
mediation_job_t *mediation_callback_job_create(identification_t *requester,
identification_t *peer_id)
{
private_mediation_job_t *this = mediation_job_create_empty();
this->target = requester->clone(requester);
this->source = peer_id->clone(peer_id);
this->callback = TRUE;
return &this->public;
}
@@ -0,0 +1,84 @@
/**
* @file mediation_job.h
*
* @brief Interface of mediation_job_t.
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef MEDIATION_JOB_H_
#define MEDIATION_JOB_H_
typedef struct mediation_job_t mediation_job_t;
#include <library.h>
#include <processing/jobs/job.h>
#include <utils/identification.h>
#include <utils/linked_list.h>
/**
* @brief Class representing a MEDIATION Job.
*
* This job handles the mediation on the mediation server.
*
* @b Constructors:
* - mediation_job_create()
*
* @ingroup jobs
*/
struct mediation_job_t {
/**
* implements job_t interface
*/
job_t job_interface;
};
/**
* @brief Creates a job of type MEDIATION.
*
* Parameters get cloned.
*
* @param peer_id ID of the requested peer
* @param requester ID of the requesting peer
* @param session_id content of P2P_SESSIONID (could be NULL)
* @param session_key content of P2P_SESSIONKEY
* @param endpoints list of submitted endpoints
* @param response TRUE if this is a response
* @return job object
*
* @ingroup jobs
*/
mediation_job_t *mediation_job_create(identification_t *peer_id,
identification_t *requester, chunk_t session_id, chunk_t session_key,
linked_list_t *endpoints, bool response);
/**
* @brief Creates a special job of type MEDIATION that is used to send a callback
* notification to a peer.
*
* Parameters get cloned.
*
* @param requester ID of the waiting peer
* @param peer_id ID of the requested peer
* @return job object
*
* @ingroup jobs
*/
mediation_job_t *mediation_callback_job_create(identification_t *requester,
identification_t *peer_id);
#endif /*MEDIATION_JOB_H_*/
@@ -59,6 +59,22 @@ static void execute(private_process_message_job_t *this)
{
ike_sa_t *ike_sa;
#ifdef P2P
// if this is an unencrypted INFORMATIONAL exchange it is likely a
// connectivity check
if (this->message->get_exchange_type(this->message) == INFORMATIONAL &&
this->message->get_first_payload_type(this->message) != ENCRYPTED)
{
// theoretically this could also be an error message see RFC 4306, section 1.5.
DBG1(DBG_NET, "received unencrypted informational: from %#H to %#H",
this->message->get_source(this->message),
this->message->get_destination(this->message));
charon->connect_manager->process_check(charon->connect_manager, this->message);
destroy(this);
return;
}
#endif /* P2P */
ike_sa = charon->ike_sa_manager->checkout_by_message(charon->ike_sa_manager,
this->message);
if (ike_sa)
File diff suppressed because it is too large Load Diff
+131
View File
@@ -0,0 +1,131 @@
/**
* @file connect_manager.h
*
* @brief Interface of connect_manager_t.
*
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef CONNECT_MANAGER_H_
#define CONNECT_MANAGER_H_
typedef struct connect_manager_t connect_manager_t;
#include <encoding/message.h>
#include <config/child_cfg.h>
#include <sa/ike_sa_id.h>
#include <utils/identification.h>
/**
* @brief The connection manager is responsible for establishing a direct
* connection with another peer.
*
* @b Constructors:
* - connect_manager_create()
*
* @ingroup sa
*/
struct connect_manager_t {
/**
* @brief Checks if a there is already a mediated connection registered
* between two peers.
*
* @param this the manager object
* @param id my id
* @param peer_id the other peer's id
* @param mediated_sa the IKE_SA ID of the mediated connection
* @param child the CHILD_SA config of the mediated connection
* @returns
* - TRUE, if there was already a mediated connection registered
* - FALSE, otherwise
*/
bool (*check_and_register) (connect_manager_t *this,
identification_t *id, identification_t *peer_id,
ike_sa_id_t *mediated_sa, child_cfg_t *child);
/**
* @brief Checks if there are waiting connections with a specific peer.
* If so, reinitiate them.
*
* @param this the manager object
* @param id my id
* @param peer_id the other peer's id
*/
void (*check_and_initiate) (connect_manager_t *this, ike_sa_id_t *mediation_sa,
identification_t *id, identification_t *peer_id);
/**
* @brief Creates a checklist and sets the initiator's data.
*
* @param this the manager object
* @param initiator ID of the initiator
* @param responder ID of the responder
* @param session_id the session ID provided by the initiator
* @param key the initiator's key
* @param endpoints the initiator's endpoints
* @param is_initiator TRUE, if the caller of this method is the initiator
* FALSE, otherwise
* @returns
* SUCCESS
*/
status_t (*set_initiator_data) (connect_manager_t *this,
identification_t *initiator, identification_t *responder,
chunk_t session_id, chunk_t key, linked_list_t *endpoints, bool is_initiator);
/**
* @brief Updates a checklist and sets the responder's data. The checklist's
* state is advanced to WAITING which means that checks will be sent.
*
* @param this the manager object
* @param session_id the session ID
* @param chunk_t the responder's key
* @param endpoints the responder's endpoints
* @returns
* - NOT_FOUND, if the checklist has not been found
* - SUCCESS, otherwise
*/
status_t (*set_responder_data) (connect_manager_t *this,
chunk_t session_id, chunk_t key, linked_list_t *endpoints);
/**
* @brief Processes a connectivity check
*
* @param this the manager object
* @param message the received message
*/
void (*process_check) (connect_manager_t *this, message_t *message);
/**
* @brief Destroys the manager with all data.
*
* @param this the manager object
*/
void (*destroy) (connect_manager_t *this);
};
/**
* @brief Create a manager.
*
* @returns connect_manager_t object
*
* @ingroup sa
*/
connect_manager_t *connect_manager_create(void);
#endif /*CONNECT_MANAGER_H_*/
+155 -8
View File
@@ -6,7 +6,8 @@
*/
/*
* Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
* Copyright (C) 2006-2007 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -65,6 +66,9 @@
#include <processing/jobs/send_keepalive_job.h>
#include <processing/jobs/rekey_ike_sa_job.h>
#ifdef P2P
#include <sa/tasks/ike_p2p.h>
#endif
#ifndef RESOLV_CONF
#define RESOLV_CONF "/etc/resolv.conf"
@@ -130,6 +134,13 @@ struct private_ike_sa_t {
*/
host_t *other_host;
#ifdef P2P
/**
* Server reflexive host
*/
host_t *server_reflexive_host;
#endif /* P2P */
/**
* Identification used for us
*/
@@ -855,6 +866,92 @@ static void send_notify_response(private_ike_sa_t *this, message_t *request,
response->destroy(response);
}
#ifdef P2P
/**
* Implementation of ike_sa_t.get_server_reflexive_host.
*/
static host_t *get_server_reflexive_host(private_ike_sa_t *this)
{
return this->server_reflexive_host;
}
/**
* Implementation of ike_sa_t.set_server_reflexive_host.
*/
static void set_server_reflexive_host(private_ike_sa_t *this, host_t *host)
{
DESTROY_IF(this->server_reflexive_host);
this->server_reflexive_host = host;
}
/**
* Implementation of ike_sa_t.respond
*/
static status_t respond(private_ike_sa_t *this, identification_t *peer_id,
chunk_t session_id)
{
ike_p2p_t *task = ike_p2p_create(&this->public, TRUE);
task->respond(task, peer_id, session_id);
this->task_manager->queue_task(this->task_manager, (task_t*)task);
return this->task_manager->initiate(this->task_manager);
}
/**
* Implementation of ike_sa_t.callback
*/
static status_t callback(private_ike_sa_t *this, identification_t *peer_id)
{
ike_p2p_t *task = ike_p2p_create(&this->public, TRUE);
task->callback(task, peer_id);
this->task_manager->queue_task(this->task_manager, (task_t*)task);
return this->task_manager->initiate(this->task_manager);
}
/**
* Implementation of ike_sa_t.relay
*/
static status_t relay(private_ike_sa_t *this, identification_t *requester,
chunk_t session_id, chunk_t session_key, linked_list_t *endpoints, bool response)
{
ike_p2p_t *task = ike_p2p_create(&this->public, TRUE);
task->relay(task, requester, session_id, session_key, endpoints, response);
this->task_manager->queue_task(this->task_manager, (task_t*)task);
return this->task_manager->initiate(this->task_manager);
}
/**
* Implementation of ike_sa_t.initiate_mediation
*/
static status_t initiate_mediation(private_ike_sa_t *this, peer_cfg_t *mediated_cfg)
{
ike_p2p_t *task = ike_p2p_create(&this->public, TRUE);
task->connect(task, mediated_cfg->get_peer_id(mediated_cfg));
this->task_manager->queue_task(this->task_manager, (task_t*)task);
return this->task_manager->initiate(this->task_manager);
}
/**
* Implementation of ike_sa_t.initiate_mediated
*/
static status_t initiate_mediated(private_ike_sa_t *this, host_t *me, host_t *other,
linked_list_t *childs)
{
this->my_host = me->clone(me);
this->other_host = other->clone(other);
task_t *task;
child_cfg_t *child_cfg;
iterator_t *iterator = childs->create_iterator(childs, TRUE);
while (iterator->iterate(iterator, (void**)&child_cfg))
{
task = (task_t*)child_create_create(&this->public, child_cfg);
this->task_manager->queue_task(this->task_manager, task);
}
iterator->destroy(iterator);
return this->task_manager->initiate(this->task_manager);
}
#endif /* P2P */
/**
* Implementation of ike_sa_t.initiate.
*/
@@ -864,7 +961,11 @@ static status_t initiate(private_ike_sa_t *this, child_cfg_t *child_cfg)
if (this->state == IKE_CREATED)
{
if (this->other_host->is_anyaddr(this->other_host))
if (this->other_host->is_anyaddr(this->other_host)
#ifdef P2P
&& !this->peer_cfg->get_mediated_by(this->peer_cfg)
#endif /* P2P */
)
{
child_cfg->destroy(child_cfg);
SIG(IKE_UP_START, "initiating IKE_SA");
@@ -887,11 +988,36 @@ static status_t initiate(private_ike_sa_t *this, child_cfg_t *child_cfg)
task = (task_t*)ike_mobike_create(&this->public, TRUE);
this->task_manager->queue_task(this->task_manager, task);
}
#ifdef P2P
task = (task_t*)ike_p2p_create(&this->public, TRUE);
this->task_manager->queue_task(this->task_manager, task);
#endif /* P2P */
}
#ifdef P2P
if (this->peer_cfg->get_mediated_by(this->peer_cfg))
{
// mediated connection, initiate mediation process
job_t *job = (job_t*)initiate_mediation_job_create(this->ike_sa_id, child_cfg);
child_cfg->destroy(child_cfg);
charon->processor->queue_job(charon->processor, job);
return SUCCESS;
}
else if (this->peer_cfg->is_mediation(this->peer_cfg))
{
if (this->state == IKE_ESTABLISHED)
{// FIXME: we should try to find a better solution to this
SIG(CHILD_UP_SUCCESS, "mediation connection is already up and running");
}
}
else
#endif /* P2P */
{
// normal IKE_SA with CHILD_SA
task = (task_t*)child_create_create(&this->public, child_cfg);
child_cfg->destroy(child_cfg);
this->task_manager->queue_task(this->task_manager, task);
}
task = (task_t*)child_create_create(&this->public, child_cfg);
child_cfg->destroy(child_cfg);
this->task_manager->queue_task(this->task_manager, task);
return this->task_manager->initiate(this->task_manager);
}
@@ -900,7 +1026,7 @@ static status_t initiate(private_ike_sa_t *this, child_cfg_t *child_cfg)
* Implementation of ike_sa_t.acquire.
*/
static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
{
{// FIXME: P2P-NAT-T
child_cfg_t *child_cfg;
iterator_t *iterator;
child_sa_t *current, *child_sa = NULL;
@@ -1224,7 +1350,7 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
* Implementation of ike_sa_t.retransmit.
*/
static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
{
{// FIXME: P2P-NAT-T
this->time.outbound = time(NULL);
if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS)
{
@@ -2047,6 +2173,15 @@ static void destroy(private_ike_sa_t *this)
offsetof(host_t, destroy));
this->additional_addresses->destroy_offset(this->additional_addresses,
offsetof(host_t, destroy));
#ifdef P2P
if (this->peer_cfg && this->peer_cfg->is_mediation(this->peer_cfg) &&
!this->ike_sa_id->is_initiator(this->ike_sa_id))
{
// mediation server
charon->mediation_manager->remove(charon->mediation_manager, this->ike_sa_id);
}
DESTROY_IF(this->server_reflexive_host);
#endif /* P2P */
DESTROY_IF(this->my_host);
DESTROY_IF(this->other_host);
@@ -2129,6 +2264,15 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.set_virtual_ip = (void (*)(ike_sa_t*,bool,host_t*))set_virtual_ip;
this->public.get_virtual_ip = (host_t* (*)(ike_sa_t*,bool))get_virtual_ip;
this->public.add_dns_server = (void (*)(ike_sa_t*,host_t*))add_dns_server;
#ifdef P2P
this->public.get_server_reflexive_host = (host_t* (*)(ike_sa_t*)) get_server_reflexive_host;
this->public.set_server_reflexive_host = (void (*)(ike_sa_t*,host_t*)) set_server_reflexive_host;
this->public.initiate_mediation = (status_t (*)(ike_sa_t*,peer_cfg_t*)) initiate_mediation;
this->public.initiate_mediated = (status_t (*)(ike_sa_t*,host_t*,host_t*,linked_list_t*)) initiate_mediated;
this->public.relay = (status_t (*)(ike_sa_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool)) relay;
this->public.callback = (status_t (*)(ike_sa_t*,identification_t*)) callback;
this->public.respond = (status_t (*)(ike_sa_t*,identification_t*,chunk_t)) respond;
#endif /* P2P */
/* initialize private fields */
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
@@ -2163,6 +2307,9 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->additional_addresses = linked_list_create();
this->pending_updates = 0;
this->keyingtry = 0;
#ifdef P2P
this->server_reflexive_host = NULL;
#endif /* P2P */
return &this->public;
}
+92 -1
View File
@@ -6,7 +6,8 @@
*/
/*
* Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
* Copyright (C) 2006-2007 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -452,6 +453,96 @@ struct ike_sa_t {
* @param updates number of pending updates
*/
void (*set_pending_updates)(ike_sa_t *this, u_int32_t updates);
#ifdef P2P
/**
* @brief Get the server reflexive host.
*
* @param this calling object
* @return server reflexive host
*/
host_t* (*get_server_reflexive_host) (ike_sa_t *this);
/**
* @brief Set the server reflexive host.
*
* @param this calling object
* @param host server reflexive host
*/
void (*set_server_reflexive_host) (ike_sa_t *this, host_t *host);
/**
* @brief Initiate the mediation of a mediated connection (i.e. initiate a
* P2P_CONNECT exchange).
*
* @param this calling object
* @param mediated_cfg peer_cfg of the mediated connection
* @return
* - SUCCESS if initialization started
* - DESTROY_ME if initialization failed
*/
status_t (*initiate_mediation) (ike_sa_t *this, peer_cfg_t *mediated_cfg);
/**
* @brief Initiate the mediated connection
*
* @param this calling object
* @param me local endpoint (gets cloned)
* @param other remote endpoint (gets cloned)
* @param childs linked list of child_cfg_t of CHILD_SAs (gets cloned)
* @return
* - SUCCESS if initialization started
* - DESTROY_ME if initialization failed
*/
status_t (*initiate_mediated) (ike_sa_t *this, host_t *me, host_t *other,
linked_list_t *childs);
/**
* @brief Relay data from one peer to another (i.e. initiate a
* P2P_CONNECT exchange).
*
* Data is cloned.
*
* @param this calling object
* @param requester ID of the requesting peer
* @param session_id data of the P2P_SESSIONID payload
* @param session_key data of the P2P_SESSIONKEY payload
* @param endpoints endpoints
* @param response TRUE if this is a response
* @return
* - SUCCESS if relay started
* - DESTROY_ME if relay failed
*/
status_t (*relay) (ike_sa_t *this, identification_t *requester, chunk_t session_id,
chunk_t session_key, linked_list_t *endpoints, bool response);
/**
* @brief Send a callback to a peer.
*
* Data is cloned.
*
* @param this calling object
* @param peer_id ID of the other peer
* @return
* - SUCCESS if response started
* - DESTROY_ME if response failed
*/
status_t (*callback) (ike_sa_t *this, identification_t *peer_id);
/**
* @brief Respond to a P2P_CONNECT request.
*
* Data is cloned.
*
* @param this calling object
* @param peer_id ID of the other peer
* @param session_id the session ID supplied by the initiator
* @return
* - SUCCESS if response started
* - DESTROY_ME if response failed
*/
status_t (*respond) (ike_sa_t *this, identification_t *peer_id, chunk_t session_id);
#endif /* P2P */
/**
* @brief Initiate a new connection.
+343
View File
@@ -0,0 +1,343 @@
/**
* @file mediation_manager.c
*
* @brief Implementation of mediation_manager_t.
*
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "mediation_manager.h"
#include <pthread.h>
#include <daemon.h>
#include <utils/linked_list.h>
#include <processing/jobs/mediation_job.h>
typedef struct peer_t peer_t;
/**
* An entry in the linked list.
*/
struct peer_t {
/** id of the peer */
identification_t *id;
/** sa id of the peer, NULL if offline */
ike_sa_id_t *ike_sa_id;
/** list of peer ids that reuested this peer */
linked_list_t *requested_by;
};
/**
* Implementation of peer_t.destroy.
*/
static void peer_destroy(peer_t *this)
{
DESTROY_IF(this->id);
DESTROY_IF(this->ike_sa_id);
this->requested_by->destroy_offset(this->requested_by, offsetof(identification_t, destroy));
free(this);
}
/**
* Creates a new entry for the list.
*/
static peer_t *peer_create(identification_t *id, ike_sa_id_t* ike_sa_id)
{
peer_t *this = malloc_thing(peer_t);
/* clone everything */
this->id = id->clone(id);
this->ike_sa_id = ike_sa_id ? ike_sa_id->clone(ike_sa_id) : NULL;
this->requested_by = linked_list_create();
return this;
}
typedef struct private_mediation_manager_t private_mediation_manager_t;
/**
* Additional private members of mediation_manager_t.
*/
struct private_mediation_manager_t {
/**
* Public interface of mediation_manager_t.
*/
mediation_manager_t public;
/**
* Lock for exclusivly accessing the manager.
*/
pthread_mutex_t mutex;
/**
* Linked list with state entries.
*/
linked_list_t *peers;
};
/**
* Registers a peer's ID at another peer, if it is not yet registered
*/
static void register_peer(peer_t *peer, identification_t *peer_id)
{
iterator_t *iterator;
identification_t *current;
iterator = peer->requested_by->create_iterator(peer->requested_by, TRUE);
while (iterator->iterate(iterator, (void**)&current))
{
if (peer_id->equals(peer_id, current))
{
iterator->destroy(iterator);
return;
}
}
iterator->destroy(iterator);
peer->requested_by->insert_last(peer->requested_by, peer_id->clone(peer_id));
}
/**
* Get a peer_t object by a peer's id
*/
static status_t get_peer_by_id(private_mediation_manager_t *this,
identification_t *id, peer_t **peer)
{
iterator_t *iterator;
peer_t *current;
status_t status = NOT_FOUND;
iterator = this->peers->create_iterator(this->peers, TRUE);
while (iterator->iterate(iterator, (void**)&current))
{
if (id->equals(id, current->id))
{
if (peer)
{
*peer = current;
}
status = SUCCESS;
break;
}
}
iterator->destroy(iterator);
return status;
}
/**
* Check if a given peer is registered at other peers. If so, remove it there
* and then remove peers completely that are not online and have no registered
* peers.
*/
static void unregister_peer(private_mediation_manager_t *this, identification_t *peer_id)
{
iterator_t *iterator, *iterator_r;
peer_t *peer;
identification_t *registered;
iterator = this->peers->create_iterator(this->peers, TRUE);
while (iterator->iterate(iterator, (void**)&peer))
{
iterator_r = peer->requested_by->create_iterator(peer->requested_by, TRUE);
while (iterator_r->iterate(iterator_r, (void**)&registered))
{
if (peer_id->equals(peer_id, registered))
{
iterator_r->remove(iterator_r);
registered->destroy(registered);
break;
}
}
iterator_r->destroy(iterator_r);
if (!peer->ike_sa_id && !peer->requested_by->get_count(peer->requested_by))
{
iterator->remove(iterator);
peer_destroy(peer);
break;
}
}
iterator->destroy(iterator);
}
/**
* Implementation of mediation_manager_t.remove
*/
static void remove_sa(private_mediation_manager_t *this, ike_sa_id_t *ike_sa_id)
{
iterator_t *iterator;
peer_t *peer;
pthread_mutex_lock(&(this->mutex));
iterator = this->peers->create_iterator(this->peers, TRUE);
while (iterator->iterate(iterator, (void**)&peer))
{
if (ike_sa_id->equals(ike_sa_id, peer->ike_sa_id))
{
iterator->remove(iterator);
unregister_peer(this, peer->id);
peer_destroy(peer);
break;
}
}
iterator->destroy(iterator);
pthread_mutex_unlock(&(this->mutex));
}
/**
* Implementation of mediation_manager_t.update_sa_id
*/
static void update_sa_id(private_mediation_manager_t *this, identification_t *peer_id, ike_sa_id_t *ike_sa_id)
{
iterator_t *iterator;
peer_t *peer;
bool found = FALSE;
pthread_mutex_lock(&(this->mutex));
iterator = this->peers->create_iterator(this->peers, TRUE);
while (iterator->iterate(iterator, (void**)&peer))
{
if (peer_id->equals(peer_id, peer->id))
{
DESTROY_IF(peer->ike_sa_id);
found = TRUE;
break;
}
}
iterator->destroy(iterator);
if (!found)
{
DBG2(DBG_IKE, "adding peer '%D'", peer_id);
peer = peer_create(peer_id, NULL);
this->peers->insert_last(this->peers, peer);
}
DBG2(DBG_IKE, "changing registered IKE_SA ID of peer '%D'", peer_id);
peer->ike_sa_id = ike_sa_id ? ike_sa_id->clone(ike_sa_id) : NULL;
// send callbacks to registered peers
identification_t *requester;
while(peer->requested_by->remove_last(peer->requested_by, (void**)&requester) == SUCCESS)
{
job_t *job = (job_t*)mediation_callback_job_create(requester, peer_id);
charon->processor->queue_job(charon->processor, job);
}
pthread_mutex_unlock(&(this->mutex));
}
/**
* Implementation of mediation_manager_t.check.
*/
static ike_sa_id_t *check(private_mediation_manager_t *this,
identification_t *peer_id)
{
peer_t *peer;
ike_sa_id_t *ike_sa_id;
pthread_mutex_lock(&(this->mutex));
if (get_peer_by_id(this, peer_id, &peer) != SUCCESS)
{
pthread_mutex_unlock(&(this->mutex));
return NULL;
}
ike_sa_id = peer->ike_sa_id;
pthread_mutex_unlock(&(this->mutex));
return ike_sa_id;
}
/**
* Implementation of mediation_manager_t.check_and_register.
*/
static ike_sa_id_t *check_and_register(private_mediation_manager_t *this,
identification_t *peer_id, identification_t *requester)
{
peer_t *peer;
ike_sa_id_t *ike_sa_id;
pthread_mutex_lock(&(this->mutex));
if (get_peer_by_id(this, peer_id, &peer) != SUCCESS)
{
DBG2(DBG_IKE, "adding peer %D", peer_id);
peer = peer_create(peer_id, NULL);
this->peers->insert_last(this->peers, peer);
}
if (!peer->ike_sa_id)
{
// the peer is not online
DBG2(DBG_IKE, "requested peer '%D' is offline, registering peer '%D'", peer_id, requester);
register_peer(peer, requester);
pthread_mutex_unlock(&(this->mutex));
return NULL;
}
ike_sa_id = peer->ike_sa_id;
pthread_mutex_unlock(&(this->mutex));
return ike_sa_id;
}
/**
* Implementation of mediation_manager_t.destroy.
*/
static void destroy(private_mediation_manager_t *this)
{
pthread_mutex_lock(&(this->mutex));
this->peers->destroy_function(this->peers, (void*)peer_destroy);
pthread_mutex_unlock(&(this->mutex));
pthread_mutex_destroy(&(this->mutex));
free(this);
}
/*
* Described in header.
*/
mediation_manager_t *mediation_manager_create()
{
private_mediation_manager_t *this = malloc_thing(private_mediation_manager_t);
this->public.destroy = (void(*)(mediation_manager_t*))destroy;
this->public.remove = (void(*)(mediation_manager_t*,ike_sa_id_t*))remove_sa;
this->public.update_sa_id = (void(*)(mediation_manager_t*,identification_t*,ike_sa_id_t*))update_sa_id;
this->public.check = (ike_sa_id_t*(*)(mediation_manager_t*,identification_t*))check;
this->public.check_and_register = (ike_sa_id_t*(*)(mediation_manager_t*,identification_t*,identification_t*))check_and_register;
this->peers = linked_list_create();
pthread_mutex_init(&(this->mutex), NULL);
return (mediation_manager_t*)this;
}
+104
View File
@@ -0,0 +1,104 @@
/**
* @file mediation_manager.h
*
* @brief Interface of mediation_manager_t.
*
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef MEDIATION_MANAGER_H_
#define MEDIATION_MANAGER_H_
typedef struct mediation_manager_t mediation_manager_t;
#include <sa/ike_sa_id.h>
#include <utils/identification.h>
/**
* @brief The mediation manager is responsible for managing currently online
* peers and registered requests for offline peers on the mediation server.
*
* @b Constructors:
* - mediation_manager_create()
*
* @ingroup sa
*/
struct mediation_manager_t {
/**
* @brief Remove the IKE_SA of a peer.
*
* @param this the manager object
* @param ike_sa_id the IKE_SA ID of the peer's SA
*/
void (*remove) (mediation_manager_t* this, ike_sa_id_t *ike_sa_id);
/**
* @brief Update the ike_sa_id that is assigned to a peer's ID. If the peer
* is new, it gets a new record assigned.
*
* @param this the manager object
* @param peer_id the peer's ID
* @param ike_sa_id the IKE_SA ID of the peer's SA
*/
void (*update_sa_id) (mediation_manager_t* this, identification_t *peer_id,
ike_sa_id_t *ike_sa_id);
/**
* @brief Checks if a specific peer is online.
*
* @param this the manager object
* @param peer_id the peer's ID
* @returns
* - IKE_SA ID of the peer's SA.
* - NULL, if the peer is not online.
*/
ike_sa_id_t* (*check) (mediation_manager_t* this,
identification_t *peer_id);
/**
* @brief Checks if a specific peer is online and registers the requesting
* peer if it is not.
*
* @param this the manager object
* @param peer_id the peer's ID
* @param requester the requesters ID
* @returns
* - IKE_SA ID of the peer's SA.
* - NULL, if the peer is not online.
*/
ike_sa_id_t* (*check_and_register) (mediation_manager_t* this,
identification_t *peer_id, identification_t *requester);
/**
* @brief Destroys the manager with all data.
*
* @param this the manager object
*/
void (*destroy) (mediation_manager_t *this);
};
/**
* @brief Create a manager.
*
* @returns mediation_manager_t object
*
* @ingroup sa
*/
mediation_manager_t *mediation_manager_create(void);
#endif /*MEDIATION_MANAGER_H_*/
+31 -1
View File
@@ -6,6 +6,7 @@
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -40,6 +41,10 @@
#include <encoding/payloads/delete_payload.h>
#include <processing/jobs/retransmit_job.h>
#ifdef P2P
#include <sa/tasks/ike_p2p.h>
#endif
typedef struct exchange_t exchange_t;
/**
@@ -323,6 +328,13 @@ static status_t build_request(private_task_manager_t *this)
exchange = IKE_SA_INIT;
activate_task(this, IKE_NATD);
activate_task(this, IKE_CERT);
#ifdef P2P
/* this task has to be activated before the IKE_AUTHENTICATE
* task, because that task pregenerates the packet after
* which no payloads can be added to the message anymore.
*/
activate_task(this, IKE_P2P);
#endif /* P2P */
activate_task(this, IKE_AUTHENTICATE);
activate_task(this, IKE_CONFIG);
activate_task(this, CHILD_CREATE);
@@ -370,6 +382,13 @@ static status_t build_request(private_task_manager_t *this)
exchange = INFORMATIONAL;
break;
}
#ifdef P2P
if (activate_task(this, IKE_P2P))
{
exchange = P2P_CONNECT;
break;
}
#endif /* P2P */
case IKE_REKEYING:
if (activate_task(this, IKE_DELETE))
{
@@ -668,6 +687,10 @@ static status_t process_request(private_task_manager_t *this,
this->passive_tasks->insert_last(this->passive_tasks, task);
task = (task_t*)ike_cert_create(this->ike_sa, FALSE);
this->passive_tasks->insert_last(this->passive_tasks, task);
#ifdef P2P
task = (task_t*)ike_p2p_create(this->ike_sa, FALSE);
this->passive_tasks->insert_last(this->passive_tasks, task);
#endif /* P2P */
task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
this->passive_tasks->insert_last(this->passive_tasks, task);
task = (task_t*)ike_config_create(this->ike_sa, FALSE);
@@ -679,7 +702,7 @@ static status_t process_request(private_task_manager_t *this,
break;
}
case CREATE_CHILD_SA:
{
{//FIXME: we should prevent this on mediation connections
bool notify_found = FALSE, ts_found = FALSE;
iterator = message->get_payload_iterator(message);
while (iterator->iterate(iterator, (void**)&payload))
@@ -787,6 +810,13 @@ static status_t process_request(private_task_manager_t *this,
this->passive_tasks->insert_last(this->passive_tasks, task);
break;
}
#ifdef P2P
case P2P_CONNECT:
{
task = (task_t*)ike_p2p_create(this->ike_sa, FALSE);
this->passive_tasks->insert_last(this->passive_tasks, task);
}
#endif /* P2P */
default:
break;
}
+17 -2
View File
@@ -91,7 +91,7 @@ static chunk_t generate_natd_hash(private_ike_natd_t *this,
u_int64_t spi_i, spi_r;
u_int16_t port;
/* prepare all requred chunks */
/* prepare all required chunks */
spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
spi_r = ike_sa_id->get_responder_spi(ike_sa_id);
spi_i_chunk.ptr = (void*)&spi_i;
@@ -258,8 +258,23 @@ static status_t process_i(private_ike_natd_t *this, message_t *message)
if (message->get_exchange_type(message) == IKE_SA_INIT)
{
peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
#ifdef P2P
/* if we are on a mediated connection we have already switched to
* port 4500 and the correct destination port is already configured,
* therefore we must not switch again */
if (peer_cfg->get_mediated_by(peer_cfg))
{
return SUCCESS;
}
#endif /* P2P */
if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY) ||
#ifdef P2P
/* if we are on a mediation connection we swith to port 4500 even
* if no NAT is detected. */
peer_cfg->is_mediation(peer_cfg) ||
#endif /* P2P */
/* if peer supports NAT-T, we switch to port 4500 even
* if no NAT is detected. MOBIKE requires this. */
(peer_cfg->use_mobike(peer_cfg) &&
+851
View File
@@ -0,0 +1,851 @@
/**
* @file ike_p2p.c
*
* @brief Implementation of the ike_p2p task.
*
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "ike_p2p.h"
#include <string.h>
#include <daemon.h>
#include <config/peer_cfg.h>
#include <encoding/payloads/id_payload.h>
#include <encoding/payloads/notify_payload.h>
#include <encoding/payloads/endpoint_notify.h>
#include <processing/jobs/mediation_job.h>
#define P2P_SESSIONID_LEN 8
#define P2P_SESSIONKEY_LEN 16
// FIXME: proposed values
#define P2P_SESSIONID_MIN_LEN 4
#define P2P_SESSIONID_MAX_LEN 16
#define P2P_SESSIONKEY_MIN_LEN 8
#define P2P_SESSIONKEY_MAX_LEN 64
typedef struct private_ike_p2p_t private_ike_p2p_t;
/**
* Private members of a ike_p2p_t task.
*/
struct private_ike_p2p_t {
/**
* Public methods and task_t interface.
*/
ike_p2p_t public;
/**
* Assigned IKE_SA.
*/
ike_sa_t *ike_sa;
/**
* Are we the initiator?
*/
bool initiator;
/**
* Is this a mediation connection?
*/
bool mediation;
/**
* Is this the response from another peer?
*/
bool response;
/**
* Gathered endpoints
*/
linked_list_t *local_endpoints;
/**
* Parsed endpoints
*/
linked_list_t *remote_endpoints;
/**
* Did the peer request a callback?
*/
bool callback;
/**
* Did the connect fail?
*/
bool failed;
/**
* Was there anything wrong with the payloads?
*/
bool invalid_syntax;
/**
* The requested peer
*/
identification_t *peer_id;
/**
* Received ID used for connectivity checks
*/
chunk_t session_id;
/**
* Received key used for connectivity checks
*/
chunk_t session_key;
/**
* Peer config of the mediated connection
*/
peer_cfg_t *mediated_cfg;
};
// -----------------------------------------------------------------------------
/**
* Adds a list of endpoints as notifies to a given message
*/
static void add_endpoints_to_message(message_t *message, linked_list_t *endpoints)
{
iterator_t *iterator;
endpoint_notify_t *endpoint;
iterator = endpoints->create_iterator(endpoints, TRUE);
while (iterator->iterate(iterator, (void**)&endpoint))
{
message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
}
iterator->destroy(iterator);
}
/**
* Gathers endpoints and adds them to the current message
*/
static void gather_and_add_endpoints(private_ike_p2p_t *this, message_t *message)
{
iterator_t *iterator;
host_t *addr, *host;
u_int16_t port;
// get the port that is used to communicate with the ms
host = this->ike_sa->get_my_host(this->ike_sa);
port = host->get_port(host);
iterator = charon->kernel_interface->create_address_iterator(
charon->kernel_interface);
while (iterator->iterate(iterator, (void**)&addr))
{
host = addr->clone(addr);
host->set_port(host, port);
this->local_endpoints->insert_last(this->local_endpoints,
endpoint_notify_create_from_host(HOST, host, NULL));
host->destroy(host);
}
iterator->destroy(iterator);
host = this->ike_sa->get_server_reflexive_host(this->ike_sa);
if (host)
{
this->local_endpoints->insert_last(this->local_endpoints,
endpoint_notify_create_from_host(SERVER_REFLEXIVE, host,
this->ike_sa->get_my_host(this->ike_sa)));
}
add_endpoints_to_message(message, this->local_endpoints);
}
/**
* read notifys from message and evaluate them
*/
static void process_payloads(private_ike_p2p_t *this, message_t *message)
{
iterator_t *iterator;
payload_t *payload;
iterator = message->get_payload_iterator(message);
while (iterator->iterate(iterator, (void**)&payload))
{
if (payload->get_type(payload) != NOTIFY)
{
continue;
}
notify_payload_t *notify = (notify_payload_t*)payload;
switch (notify->get_notify_type(notify))
{
case P2P_CONNECT_FAILED:
{
DBG2(DBG_IKE, "received P2P_CONNECT_FAILED notify");
this->failed = TRUE;
break;
}
case P2P_MEDIATION:
{
DBG2(DBG_IKE, "received P2P_MEDIATION notify");
this->mediation = TRUE;
break;
}
case P2P_ENDPOINT:
{
endpoint_notify_t *endpoint = endpoint_notify_create_from_payload(notify);
if (!endpoint)
{
DBG1(DBG_IKE, "received invalid P2P_ENDPOINT notify");
break;
}
DBG2(DBG_IKE, "received P2P_ENDPOINT notify");
this->remote_endpoints->insert_last(this->remote_endpoints, endpoint);
break;
}
case P2P_CALLBACK:
{
DBG2(DBG_IKE, "received P2P_CALLBACK notify");
this->callback = TRUE;
break;
}
case P2P_SESSIONID:
{
chunk_free(&this->session_id);
this->session_id = chunk_clone(notify->get_notification_data(notify));
DBG3(DBG_IKE, "received p2p_sessionid %B", &this->session_id);
break;
}
case P2P_SESSIONKEY:
{
chunk_free(&this->session_key);
this->session_key = chunk_clone(notify->get_notification_data(notify));
DBG4(DBG_IKE, "received p2p_sessionkey %B", &this->session_key);
break;
}
case P2P_RESPONSE:
{
DBG2(DBG_IKE, "received P2P_RESPONSE notify");
this->response = TRUE;
break;
}
default:
break;
}
}
iterator->destroy(iterator);
}
// -----------------------------------------------------------------------------
/**
* Implementation of task_t.process for initiator
*/
static status_t build_i(private_ike_p2p_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
case IKE_SA_INIT:
{
peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
if (peer_cfg->is_mediation(peer_cfg))
{
DBG2(DBG_IKE, "adding P2P_MEDIATION");
message->add_notify(message, FALSE, P2P_MEDIATION, chunk_empty);
}
else
{
return SUCCESS;
}
break;
}
case IKE_AUTH:
{
if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_HERE))
{
endpoint_notify_t *endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE, NULL, NULL);
message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
endpoint->destroy(endpoint);
}
break;
}
case P2P_CONNECT:
{
id_payload_t *id_payload;
randomizer_t *rand = randomizer_create();
id_payload = id_payload_create_from_identification(ID_PEER, this->peer_id);
message->add_payload(message, (payload_t*)id_payload);
if (!this->response)
{
// only the initiator creates a session ID. the responder returns
// the session ID that it received from the initiator
if (rand->allocate_pseudo_random_bytes(rand,
P2P_SESSIONID_LEN, &this->session_id) != SUCCESS)
{
DBG1(DBG_IKE, "unable to generate session ID for P2P_CONNECT");
rand->destroy(rand);
return FAILED;
}
}
if (rand->allocate_pseudo_random_bytes(rand,
P2P_SESSIONKEY_LEN, &this->session_key) != SUCCESS)
{
DBG1(DBG_IKE, "unable to generate session key for P2P_CONNECT");
rand->destroy(rand);
return FAILED;
}
rand->destroy(rand);
message->add_notify(message, FALSE, P2P_SESSIONID, this->session_id);
message->add_notify(message, FALSE, P2P_SESSIONKEY, this->session_key);
if (this->response)
{
message->add_notify(message, FALSE, P2P_RESPONSE, chunk_empty);
}
else
{
// FIXME: should we make that configurable
message->add_notify(message, FALSE, P2P_CALLBACK, chunk_empty);
}
gather_and_add_endpoints(this, message);
break;
}
}
return NEED_MORE;
}
/**
* Implementation of task_t.process for responder
*/
static status_t process_r(private_ike_p2p_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
case P2P_CONNECT:
{
id_payload_t *id_payload;
id_payload = (id_payload_t*)message->get_payload(message, ID_PEER);
if (!id_payload)
{
DBG1(DBG_IKE, "received P2P_CONNECT without ID_PEER payload, aborting");
break;
}
this->peer_id = id_payload->get_identification(id_payload);
process_payloads(this, message);
if (this->callback)
{
DBG1(DBG_IKE, "received P2P_CALLBACK for '%D'", this->peer_id);
break;
}
if (!this->session_id.ptr)
{
DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONID notify, aborting");
this->invalid_syntax = TRUE;
break;
}
if (!this->session_key.ptr)
{
DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONKEY notify, aborting");
this->invalid_syntax = TRUE;
break;
}
if (!this->remote_endpoints->get_count(this->remote_endpoints))
{
DBG1(DBG_IKE, "received P2P_CONNECT without any P2P_ENDPOINT payloads, aborting");
this->invalid_syntax = TRUE;
break;
}
DBG1(DBG_IKE, "received P2P_CONNECT");
break;
}
}
return NEED_MORE;
}
/**
* Implementation of task_t.build for responder
*/
static status_t build_r(private_ike_p2p_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
case P2P_CONNECT:
{
if (this->invalid_syntax)
{
message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty);
break;
}
if (this->callback)
{
charon->connect_manager->check_and_initiate(charon->connect_manager,
this->ike_sa->get_id(this->ike_sa),
this->ike_sa->get_my_id(this->ike_sa), this->peer_id);
return SUCCESS;
}
if (this->response)
{
// FIXME: handle result of set_responder_data
// as initiator, upon receiving a response from another peer,
// update the checklist and start sending checks
charon->connect_manager->set_responder_data(charon->connect_manager,
this->session_id, this->session_key, this->remote_endpoints);
}
else
{
// FIXME: handle result of set_initiator_data
// as responder, create a checklist with the initiator's data
charon->connect_manager->set_initiator_data(charon->connect_manager,
this->peer_id, this->ike_sa->get_my_id(this->ike_sa),
this->session_id, this->session_key, this->remote_endpoints,
FALSE);
if (this->ike_sa->respond(this->ike_sa, this->peer_id,
this->session_id) != SUCCESS)
{
return FAILED;
}
}
break;
}
}
return SUCCESS;
}
/**
* Implementation of task_t.process for initiator
*/
static status_t process_i(private_ike_p2p_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
case IKE_SA_INIT:
{
process_payloads(this, message);
if (!this->mediation)
{
DBG1(DBG_IKE, "server did not return a P2P_MEDIATION, aborting");
return FAILED;
}
return NEED_MORE;
}
case IKE_AUTH:
{
process_payloads(this, message);
//FIXME: we should update the server reflexive endpoint somehow, if mobike notices a change
endpoint_notify_t *reflexive;
if (this->remote_endpoints->get_first(this->remote_endpoints, (void**)&reflexive) == SUCCESS &&
reflexive->get_type(reflexive) == SERVER_REFLEXIVE)
{//FIXME: should we accept this endpoint even if we did not send a request?
host_t *endpoint = reflexive->get_host(reflexive);
DBG2(DBG_IKE, "received server reflexive endpoint %#H", endpoint);
this->ike_sa->set_server_reflexive_host(this->ike_sa, endpoint->clone(endpoint));
}
// FIXME: what if it failed? e.g. AUTH failure
SIG(CHILD_UP_SUCCESS, "established mediation connection without CHILD_SA successfully");
break;
}
case P2P_CONNECT:
{
process_payloads(this, message);
if (this->failed)
{
DBG1(DBG_IKE, "peer '%D' is not online", this->peer_id);
// FIXME: notify the mediated connection (job?)
// FIXME: probably delete the created checklist, at least as responder
}
else
{
if (this->response)
{
// FIXME: handle result of set_responder_data
// as responder, we update the checklist and start sending checks
charon->connect_manager->set_responder_data(charon->connect_manager,
this->session_id, this->session_key, this->local_endpoints);
}
else
{
// FIXME: handle result of set_initiator_data
// as initiator, we create a checklist and set the initiator's data
charon->connect_manager->set_initiator_data(charon->connect_manager,
this->ike_sa->get_my_id(this->ike_sa), this->peer_id,
this->session_id, this->session_key, this->local_endpoints,
TRUE);
}
}
break;
}
}
return SUCCESS;
}
// -----------------------------------------------------------------------------
/**
* Implementation of task_t.process for initiator (mediation server)
*/
static status_t build_i_ms(private_ike_p2p_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
case P2P_CONNECT:
{
id_payload_t *id_payload = id_payload_create_from_identification(ID_PEER, this->peer_id);
message->add_payload(message, (payload_t*)id_payload);
if (this->callback)
{
message->add_notify(message, FALSE, P2P_CALLBACK, chunk_empty);
}
else
{
notify_payload_t *notify;
if (this->response)
{
message->add_notify(message, FALSE, P2P_RESPONSE, chunk_empty);
}
message->add_notify(message, FALSE, P2P_SESSIONID, this->session_id);
message->add_notify(message, FALSE, P2P_SESSIONKEY, this->session_key);
add_endpoints_to_message(message, this->remote_endpoints);
}
break;
}
}
return NEED_MORE;
}
/**
* Implementation of task_t.process for responder (mediation server)
*/
static status_t process_r_ms(private_ike_p2p_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
case IKE_SA_INIT:
{
process_payloads(this, message);
return this->mediation ? NEED_MORE : SUCCESS;
}
case IKE_AUTH:
{
process_payloads(this, message);
break;
}
case P2P_CONNECT:
{
id_payload_t *id_payload;
id_payload = (id_payload_t*)message->get_payload(message, ID_PEER);
if (!id_payload)
{
DBG1(DBG_IKE, "received P2P_CONNECT without ID_PEER payload, aborting");
this->invalid_syntax = TRUE;
break;
}
this->peer_id = id_payload->get_identification(id_payload);
process_payloads(this, message);
if (!this->session_id.ptr)
{
DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONID notify, aborting");
this->invalid_syntax = TRUE;
break;
}
if (!this->session_key.ptr)
{
DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONKEY notify, aborting");
this->invalid_syntax = TRUE;
break;
}
if (!this->remote_endpoints->get_count(this->remote_endpoints))
{
DBG1(DBG_IKE, "received P2P_CONNECT without any P2P_ENDPOINT payloads, aborting");
this->invalid_syntax = TRUE;
break;
}
break;
}
}
return NEED_MORE;
}
/**
* Implementation of task_t.build for responder (mediation server)
*/
static status_t build_r_ms(private_ike_p2p_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
case IKE_SA_INIT:
{
message->add_notify(message, FALSE, P2P_MEDIATION, chunk_empty);
return NEED_MORE;
}
case IKE_AUTH:
{
endpoint_notify_t *endpoint;
if (this->remote_endpoints->get_first(this->remote_endpoints, (void**)&endpoint) == SUCCESS &&
endpoint->get_type(endpoint) == SERVER_REFLEXIVE)
{
host_t *host = this->ike_sa->get_other_host(this->ike_sa);
DBG2(DBG_IKE, "received request for a server reflexive endpoint "
"sending: %#H", host);
endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE, host, NULL);
message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
}
charon->mediation_manager->update_sa_id(charon->mediation_manager,
this->ike_sa->get_other_id(this->ike_sa),
this->ike_sa->get_id(this->ike_sa));
SIG(CHILD_UP_SUCCESS, "established mediation connection without CHILD_SA successfully");
break;
}
case P2P_CONNECT:
{
if (this->invalid_syntax)
{
message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty);
break;
}
ike_sa_id_t *peer_sa;
if (this->callback)
{
peer_sa = charon->mediation_manager->check_and_register(charon->mediation_manager,
this->peer_id, this->ike_sa->get_other_id(this->ike_sa));
}
else
{
peer_sa = charon->mediation_manager->check(charon->mediation_manager,
this->peer_id);
}
if (!peer_sa)
{
// the peer is not online
message->add_notify(message, TRUE, P2P_CONNECT_FAILED, chunk_empty);
break;
}
job_t *job = (job_t*)mediation_job_create(this->peer_id,
this->ike_sa->get_other_id(this->ike_sa), this->session_id,
this->session_key, this->remote_endpoints, this->response);
charon->processor->queue_job(charon->processor, job);
break;
}
}
return SUCCESS;
}
/**
* Implementation of task_t.process for initiator (mediation server)
*/
static status_t process_i_ms(private_ike_p2p_t *this, message_t *message)
{
switch(message->get_exchange_type(message))
{
case P2P_CONNECT:
{
break;
}
}
return SUCCESS;
}
// -----------------------------------------------------------------------------
/**
* Implementation of ike_p2p.connect
*/
static void p2p_connect(private_ike_p2p_t *this, identification_t *peer_id)
{
this->peer_id = peer_id->clone(peer_id);
}
/**
* Implementation of ike_p2p.respond
*/
static void p2p_respond(private_ike_p2p_t *this, identification_t *peer_id,
chunk_t session_id)
{
this->peer_id = peer_id->clone(peer_id);
this->session_id = chunk_clone(session_id);
this->response = TRUE;
}
/**
* Implementation of ike_p2p.callback
*/
static void p2p_callback(private_ike_p2p_t *this, identification_t *peer_id)
{
this->peer_id = peer_id->clone(peer_id);
this->callback = TRUE;
}
/**
* Implementation of ike_p2p.relay
*/
static void relay(private_ike_p2p_t *this, identification_t *requester, chunk_t session_id,
chunk_t session_key, linked_list_t *endpoints, bool response)
{
this->peer_id = requester->clone(requester);
this->session_id = chunk_clone(session_id);
this->session_key = chunk_clone(session_key);
this->remote_endpoints = endpoints->clone_offset(endpoints, offsetof(endpoint_notify_t, clone));
this->response = response;
}
/**
* Implementation of task_t.get_type
*/
static task_type_t get_type(private_ike_p2p_t *this)
{
return IKE_P2P;
}
/**
* Implementation of task_t.migrate
*/
static void migrate(private_ike_p2p_t *this, ike_sa_t *ike_sa)
{
this->ike_sa = ike_sa;
}
/**
* Implementation of task_t.destroy
*/
static void destroy(private_ike_p2p_t *this)
{
DESTROY_IF(this->peer_id);
chunk_free(&this->session_id);
chunk_free(&this->session_key);
this->local_endpoints->destroy_offset(this->local_endpoints, offsetof(endpoint_notify_t, destroy));
this->remote_endpoints->destroy_offset(this->remote_endpoints, offsetof(endpoint_notify_t, destroy));
DESTROY_IF(this->mediated_cfg);
free(this);
}
/*
* Described in header.
*/
ike_p2p_t *ike_p2p_create(ike_sa_t *ike_sa, bool initiator)
{
private_ike_p2p_t *this = malloc_thing(private_ike_p2p_t);
this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
this->public.task.destroy = (void(*)(task_t*))destroy;
ike_sa_id_t *id = ike_sa->get_id(ike_sa);
if (id->is_initiator(id))
{
if (initiator)
{
this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
}
else
{
this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
}
}
else
{
// mediation server
if (initiator)
{
this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_ms;
this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_ms;
}
else
{
this->public.task.build = (status_t(*)(task_t*,message_t*))build_r_ms;
this->public.task.process = (status_t(*)(task_t*,message_t*))process_r_ms;
}
}
this->public.connect = (void(*)(ike_p2p_t*,identification_t*))p2p_connect;
this->public.respond = (void(*)(ike_p2p_t*,identification_t*,chunk_t))p2p_respond;
this->public.callback = (void(*)(ike_p2p_t*,identification_t*))p2p_callback;
this->public.relay = (void(*)(ike_p2p_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool))relay;
this->ike_sa = ike_sa;
this->initiator = initiator;
this->peer_id = NULL;
this->session_id = chunk_empty;
this->session_key = chunk_empty;
this->local_endpoints = linked_list_create();
this->remote_endpoints = linked_list_create();
this->mediation = FALSE;
this->response = FALSE;
this->callback = FALSE;
this->failed = FALSE;
this->invalid_syntax = FALSE;
this->mediated_cfg = NULL;
return &this->public;
}
+110
View File
@@ -0,0 +1,110 @@
/**
* @file ike_p2p.h
*
* @brief Interface ike_p2p_t.
*
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef IKE_P2P_H_
#define IKE_P2P_H_
typedef struct ike_p2p_t ike_p2p_t;
#include <library.h>
#include <sa/ike_sa.h>
#include <sa/tasks/task.h>
/**
* @brief Task of type IKE_P2P, detects and handles P2P-NAT-T extensions.
*
* This tasks handles the P2P_MEDIATION notify exchange to setup a mediation
* connection, allows to initiate mediated connections using P2P_CONNECT
* exchanges and to request reflexive addresses from the mediation server using
* P2P_ENDPOINT notifies.
*
* @note This task has to be activated before the IKE_AUTH task, because that
* task generates the IKE_SA_INIT message so that no more payloads can be added
* to it afterwards.
*
* @b Constructors:
* - ike_p2p_create()
*
* @ingroup tasks
*/
struct ike_p2p_t {
/**
* Implements the task_t interface
*/
task_t task;
/**
* @brief Initiates a connection with another peer (i.e. sends a P2P_CONNECT
* to the mediation server)
*
* @param this object
* @param peer_id ID of the other peer (gets cloned)
*/
void (*connect)(ike_p2p_t *this, identification_t *peer_id);
/**
* @brief Responds to a P2P_CONNECT from another peer (i.e. sends a P2P_CONNECT
* to the mediation server)
*
* @param this object
* @param peer_id ID of the other peer (gets cloned)
* @param session_id the session ID as provided by the initiator (gets cloned)
*/
void (*respond)(ike_p2p_t *this, identification_t *peer_id, chunk_t session_id);
/**
* @brief Sends a P2P_CALLBACK to a peer that previously requested another peer.
*
* @param this object
* @param peer_id ID of the other peer (gets cloned)
*/
void (*callback)(ike_p2p_t *this, identification_t *peer_id);
/**
* @brief Relays data to another peer (i.e. sends a P2P_CONNECT to the peer)
*
* Data gets cloned.
*
* @param this object
* @param requester ID of the requesting peer
* @param session_id content of the P2P_SESSIONID notify
* @param session_key content of the P2P_SESSIONKEY notify
* @param endpoints endpoints
* @param response TRUE if this is a response
*/
void (*relay)(ike_p2p_t *this, identification_t *requester, chunk_t session_id,
chunk_t session_key, linked_list_t *endpoints, bool response);
};
/**
* @brief Create a new ike_p2p task.
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE if taks is initiated by us
* @return ike_p2p task to handle by the task_manager
*/
ike_p2p_t *ike_p2p_create(ike_sa_t *ike_sa, bool initiator);
#endif /*IKE_P2P_H_*/
+4
View File
@@ -6,6 +6,7 @@
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -33,6 +34,9 @@ ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
"IKE_REAUTH",
"IKE_DELETE",
"IKE_DPD",
#ifdef P2P
"IKE_P2P",
#endif /* P2P */
"CHILD_CREATE",
"CHILD_DELETE",
"CHILD_REKEY",
+5
View File
@@ -6,6 +6,7 @@
*/
/*
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -56,6 +57,10 @@ enum task_type_t {
IKE_DELETE,
/** liveness check */
IKE_DPD,
#ifdef P2P
/** handle P2P-NAT-T stuff */
IKE_P2P,
#endif /* P2P */
/** establish a CHILD_SA within an IKE_SA */
CHILD_CREATE,
/** delete an established CHILD_SA */
+4
View File
@@ -1,4 +1,5 @@
/* automatic handling of confread struct arguments
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2006 Andreas Steffen
* Hochschule fuer Technik Rapperswil, Switzerland
*
@@ -210,6 +211,9 @@ static const token_info_t token_info[] =
{ ARG_ENUM, offsetof(starter_conn_t, dpd_action), LST_dpd_action },
{ ARG_MISC, 0, NULL /* KW_MODECONFIG */ },
{ ARG_MISC, 0, NULL /* KW_XAUTH */ },
{ ARG_ENUM, offsetof(starter_conn_t, p2p_mediation), LST_bool },
{ ARG_STR, offsetof(starter_conn_t, p2p_mediated_by), NULL },
{ ARG_STR, offsetof(starter_conn_t, p2p_peerid), NULL },
/* ca section keywords */
{ ARG_STR, offsetof(starter_ca_t, name), NULL },
+8 -1
View File
@@ -1,5 +1,8 @@
/* strongSwan IPsec config file parser
* Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
* Copyright (C) 2007 Tobias Brunner
* Hochschule fuer Technik Rapperswil
* Copyright (C) 2001-2002 Mathieu Lafon
* Arkoon Network Security
*
* 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
@@ -125,6 +128,10 @@ struct starter_conn {
time_t dpd_timeout;
dpd_action_t dpd_action;
int dpd_count;
bool p2p_mediation;
char *p2p_mediated_by;
char *p2p_peerid;
starter_conn_t *next;
};
+30
View File
@@ -779,6 +779,36 @@ Accepted values are
and
.B client
(the default).
.SS "CONN PARAMETERS: PEER-TO-PEER"
The following parameters are relevant to Peer-to-Peer NAT-T operation
only.
.TP 14
.B p2p_mediation
whether this connection is a P2P mediation connection, ie. whether this
connection is used to mediate other connections. Mediation connections
create no child SA. Acceptable values are
.B no
(the default) and
.BR yes .
.TP
.B p2p_mediated_by
the name of the connection to mediate this connection through. If given,
the connection will be mediated through the named mediation connection.
The mediation connection must set
.BR p2p_mediation=yes .
.TP
.B p2p_peerid
ID as which the peer is known to the mediation server, ie. which the other
end of this connection uses as its
.B leftid
on its connection to the mediation server. This is the ID we request the
mediation server to mediate us with. If
.B p2p_peerid
is not given, the
.B rightid
of this connection will be used as peer ID.
.SH "CA SECTIONS"
This are optional sections that can be used to assign special
parameters to a Certification Authority (CA). These parameters are not
+5 -1
View File
@@ -1,4 +1,5 @@
/* strongSwan keywords
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2005 Andreas Steffen
* Hochschule fuer Technik Rapperswil, Switzerland
*
@@ -87,9 +88,12 @@ typedef enum {
KW_DPDACTION,
KW_MODECONFIG,
KW_XAUTH,
KW_P2P_MEDIATION,
KW_P2P_MEDIATED_BY,
KW_P2P_PEERID,
#define KW_CONN_FIRST KW_CONN_SETUP
#define KW_CONN_LAST KW_XAUTH
#define KW_CONN_LAST KW_P2P_PEERID
/* ca section keywords */
KW_CA_NAME,
+4
View File
@@ -1,5 +1,6 @@
%{
/* strongSwan keywords
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2005 Andreas Steffen
* Hochschule fuer Technik Rapperswil, Switzerland
*
@@ -76,6 +77,9 @@ dpdtimeout, KW_DPDTIMEOUT
dpdaction, KW_DPDACTION
modeconfig, KW_MODECONFIG
xauth, KW_XAUTH
p2p_mediation, KW_P2P_MEDIATION
p2p_mediated_by, KW_P2P_MEDIATED_BY
p2p_peerid, KW_P2P_PEERID
cacert, KW_CACERT
ldaphost, KW_LDAPHOST
ldapbase, KW_LDAPBASE
+6 -1
View File
@@ -1,5 +1,7 @@
/* Stroke for charon is the counterpart to whack from pluto
* Copyright (C) 2006 Martin Willi - Hochschule fuer Technik Rapperswil
* Copyright (C) 2007 Tobias Brunner
* 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
@@ -233,6 +235,9 @@ int starter_stroke_add_conn(starter_conn_t *conn)
msg.add_conn.algorithms.esp = push_string(&msg, conn->esp);
msg.add_conn.dpd.delay = conn->dpd_delay;
msg.add_conn.dpd.action = conn->dpd_action;
msg.add_conn.p2p.mediation = conn->p2p_mediation;
msg.add_conn.p2p.mediated_by = push_string(&msg, conn->p2p_mediated_by);
msg.add_conn.p2p.peerid = push_string(&msg, conn->p2p_peerid);
starter_stroke_add_end(&msg, &msg.add_conn.me, &conn->left);
starter_stroke_add_end(&msg, &msg.add_conn.other, &conn->right);
+7 -1
View File
@@ -1,5 +1,7 @@
/* Stroke for charon is the counterpart to whack from pluto
* Copyright (C) 2006 Martin Willi - Hochschule fuer Technik Rapperswil
* Copyright (C) 2007 Tobias Brunner
* 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
@@ -125,6 +127,10 @@ static int add_connection(char *name,
msg.add_conn.dpd.delay = 0;
msg.add_conn.dpd.action = 1;
msg.add_conn.p2p.mediation = 0;
msg.add_conn.p2p.mediated_by = NULL;
msg.add_conn.p2p.peerid = NULL;
msg.add_conn.me.id = push_string(&msg, my_id);
msg.add_conn.me.address = push_string(&msg, my_addr);
msg.add_conn.me.subnet = push_string(&msg, my_net);
+5
View File
@@ -200,6 +200,11 @@ struct stroke_msg_t {
time_t delay;
int action;
} dpd;
struct {
int mediation;
char *mediated_by;
char *peerid;
} p2p;
stroke_end_t me, other;
} add_conn;