vici: Add support for mediation extension

This commit is contained in:
Tobias Brunner 2017-02-07 12:04:30 +01:00
parent ed96fe72cf
commit f927ba975b
2 changed files with 109 additions and 1 deletions

View File

@ -2,7 +2,7 @@
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
* Copyright (C) 2015-2016 Tobias Brunner
* Copyright (C) 2015-2017 Tobias Brunner
* Copyright (C) 2015-2016 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
@ -318,6 +318,11 @@ typedef struct {
uint64_t over_time;
uint64_t rand_time;
uint8_t dscp;
#ifdef ME
bool mediation;
char *mediated_by;
identification_t *peer_id;
#endif /* ME */
} peer_data_t;
/**
@ -405,6 +410,14 @@ static void log_peer_data(peer_data_t *data)
DBG2(DBG_CFG, " over_time = %llu", data->over_time);
DBG2(DBG_CFG, " rand_time = %llu", data->rand_time);
DBG2(DBG_CFG, " proposals = %#P", data->proposals);
#ifdef ME
DBG2(DBG_CFG, " mediation = %u", data->mediation);
if (data->mediated_by)
{
DBG2(DBG_CFG, " mediated_by = %s", data->mediated_by);
DBG2(DBG_CFG, " mediation_peer = %Y", data->peer_id);
}
#endif /* ME */
if (data->vips->get_count(data->vips))
{
@ -449,6 +462,10 @@ static void free_peer_data(peer_data_t *data)
free(data->pools);
free(data->local_addrs);
free(data->remote_addrs);
#ifdef ME
free(data->mediated_by);
DESTROY_IF(data->peer_id);
#endif /* ME */
}
/**
@ -1397,6 +1414,24 @@ CALLBACK(parse_hosts, bool,
return TRUE;
}
#ifdef ME
/**
* Parse peer ID
*/
CALLBACK(parse_peer_id, bool,
identification_t **out, chunk_t v)
{
char buf[BUF_LEN];
if (!vici_stringify(v, buf, sizeof(buf)))
{
return FALSE;
}
*out = identification_create_from_string(buf);
return TRUE;
}
#endif /* ME */
CALLBACK(cert_kv, bool,
cert_data_t *cert, vici_message_t *message, char *name, chunk_t value)
{
@ -1531,6 +1566,11 @@ CALLBACK(peer_kv, bool,
{ "rekey_time", parse_time, &peer->rekey_time },
{ "over_time", parse_time, &peer->over_time },
{ "rand_time", parse_time, &peer->rand_time },
#ifdef ME
{ "mediation", parse_bool, &peer->mediation },
{ "mediated_by", parse_string, &peer->mediated_by },
{ "mediation_peer", parse_peer_id, &peer->peer_id },
#endif /* ME */
};
return parse_rules(rules, countof(rules), name, value,
@ -2260,6 +2300,42 @@ CALLBACK(config_sn, bool,
peer.rand_time = min(peer.over_time, peer.rand_time / 2);
}
#ifdef ME
if (peer.mediation && peer.mediated_by)
{
DBG1(DBG_CFG, "a mediation connection cannot be a mediated connection "
"at the same time, config discarded");
free_peer_data(&peer);
return FALSE;
}
if (peer.mediation)
{ /* force unique connections for mediation connections */
peer.unique = UNIQUE_REPLACE;
}
else if (peer.mediated_by)
{ /* fallback to remote identity of first auth round if peer_id is not
* given explicitly */
auth_cfg_t *cfg;
if (!peer.peer_id &&
peer.remote->get_first(peer.remote, (void**)&cfg) == SUCCESS)
{
peer.peer_id = cfg->get(cfg, AUTH_RULE_IDENTITY);
if (peer.peer_id)
{
peer.peer_id = peer.peer_id->clone(peer.peer_id);
}
else
{
DBG1(DBG_CFG, "mediation peer missing for mediated connection, "
"config discarded");
free_peer_data(&peer);
return FALSE;
}
}
}
#endif /* ME */
log_peer_data(&peer);
ike_cfg = ike_cfg_create(peer.version, peer.send_certreq, peer.encap,
@ -2281,6 +2357,14 @@ CALLBACK(config_sn, bool,
.dpd = peer.dpd_delay,
.dpd_timeout = peer.dpd_timeout,
};
#ifdef ME
cfg.mediation = peer.mediation;
if (peer.mediated_by)
{
cfg.mediated_by = peer.mediated_by;
cfg.peer_id = peer.peer_id->clone(peer.peer_id);
}
#endif /* ME */
peer_cfg = peer_cfg_create(name, ike_cfg, &cfg);
while (peer.local->remove_first(peer.local,

View File

@ -264,6 +264,30 @@ connections.<conn>.pools =
other configuration attributes from. Each name references a pool by name
from either the **pools** section or an external pool.
connections.<conn>.mediation = no
Whether this connection is a mediation connection.
Whether this connection is a mediation connection, that is, whether this
connection is used to mediate other connections using the IKEv2 Mediation
Extension. Mediation connections create no CHILD_SA.
connections.<conn>.mediated_by =
The name of the connection to mediate this connection through.
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 have **mediation** enabled.
connections.<conn>.mediation_peer =
Identity under which the peer is registered at the mediation server.
Identity under which the peer is registered at the mediation server, that
is, the IKE identity the other end of this connection uses as its local
identity on its connection to the mediation server. This is the identity we
request the mediation server to mediate us with. Only relevant on
connections that set **mediated_by**. If it is not given, the remote IKE
identity of the first authentication round of this connection will be used.
connections.<conn>.local<suffix> {}
Section for a local authentication round.