From: Tobias Brunner Date: Tue, 28 Apr 2015 15:45:52 +0000 (+0200) Subject: vici: Add redirect command X-Git-Tag: 5.4.0dr8~12^2~12 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=43b46b26ea1eac87e6e4189c5ef3b92ccb885c66;p=thirdparty%2Fstrongswan.git vici: Add redirect command This allows redirecting IKE_SAs by multiple different selectors, if none are given all SAs are redirected. --- diff --git a/src/libcharon/plugins/vici/README.md b/src/libcharon/plugins/vici/README.md index 773ef1aa5c..d084883104 100644 --- a/src/libcharon/plugins/vici/README.md +++ b/src/libcharon/plugins/vici/README.md @@ -289,6 +289,21 @@ Terminates an SA while streaming _control-log_ events. The default timeout of 0 waits indefinitely for a result, and a timeout value of -1 returns a result immediately. +### redirect() ### + +Redirect a client-initiated IKE_SA to another gateway. Only for IKEv2 and if +supported by the peer. + + { + ike = + ike-id = + peer-ip = + peer-id = + } => { + success = + errmsg = + } + ### install() ### Install a trap, drop or bypass policy defined by a CHILD_SA config. diff --git a/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Session.pm b/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Session.pm index 5252296cfe..78197136ae 100644 --- a/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Session.pm +++ b/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Session.pm @@ -36,6 +36,10 @@ sub terminate { return request_vars_res('terminate', @_); } +sub redirect { + return request_vars_res('redirect', @_); +} + sub install { return request_vars_res('install', @_); } diff --git a/src/libcharon/plugins/vici/python/vici/session.py b/src/libcharon/plugins/vici/python/vici/session.py index 283e3d13d7..66de8590a9 100644 --- a/src/libcharon/plugins/vici/python/vici/session.py +++ b/src/libcharon/plugins/vici/python/vici/session.py @@ -53,6 +53,14 @@ class Session(object): """ return self.handler.streamed_request("terminate", "control-log", sa) + def redirect(self, sa): + """Redirect an IKE_SA. + + :param sa: the SA to redirect + :type sa: dict + """ + self.handler.request("redirect", sa) + def install(self, policy): """Install a trap, drop or bypass policy defined by a CHILD_SA config. diff --git a/src/libcharon/plugins/vici/ruby/lib/vici.rb b/src/libcharon/plugins/vici/ruby/lib/vici.rb index f8169add07..018f507661 100644 --- a/src/libcharon/plugins/vici/ruby/lib/vici.rb +++ b/src/libcharon/plugins/vici/ruby/lib/vici.rb @@ -504,6 +504,12 @@ module Vici "control-log", &block)) end + ## + # Redirect an IKE_SA. + def redirect(options) + check_success(@transp.request("redirect", Message.new(options))) + end + ## # Install a shunt/route policy. def install(policy) diff --git a/src/libcharon/plugins/vici/vici_control.c b/src/libcharon/plugins/vici/vici_control.c index 87794d24dd..7bcab0e86e 100644 --- a/src/libcharon/plugins/vici/vici_control.c +++ b/src/libcharon/plugins/vici/vici_control.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2015 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2014 Martin Willi * Copyright (C) 2014 revosec AG * @@ -20,6 +23,7 @@ #include #include +#include typedef struct private_vici_control_t private_vici_control_t; @@ -356,6 +360,118 @@ CALLBACK(terminate, vici_message_t*, return builder->finalize(builder); } +CALLBACK(redirect, vici_message_t*, + private_vici_control_t *this, char *name, u_int id, vici_message_t *request) +{ + enumerator_t *sas; + char *ike, *peer_ip, *peer_id, *gw, *errmsg = NULL; + u_int ike_id, current, found = 0; + identification_t *gateway, *identity = NULL; + host_t *address = NULL; + ike_sa_t *ike_sa; + vici_builder_t *builder; + + ike = request->get_str(request, NULL, "ike"); + ike_id = request->get_int(request, 0, "ike-id"); + peer_ip = request->get_str(request, NULL, "peer-ip"); + peer_id = request->get_str(request, NULL, "peer-id"); + gw = request->get_str(request, NULL, "gateway"); + + if (!gw || !(gateway = identification_create_from_string(gw))) + { + return send_reply(this, "missing target gateway"); + } + switch (gateway->get_type(gateway)) + { + case ID_IPV4_ADDR: + case ID_IPV6_ADDR: + case ID_FQDN: + break; + default: + return send_reply(this, "unsupported gateway identity"); + } + if (peer_ip) + { + address = host_create_from_string(peer_ip, 0); + if (!address) + { + return send_reply(this, "invalid peer IP selector"); + } + DBG1(DBG_CFG, "vici redirect IKE_SAs with src %H to %Y", address, + gateway); + } + if (peer_id) + { + identity = identification_create_from_string(peer_id); + if (!identity) + { + DESTROY_IF(address); + return send_reply(this, "invalid peer identity selector"); + } + DBG1(DBG_CFG, "vici redirect IKE_SAs with ID '%Y' to %Y", identity, + gateway); + } + if (ike_id) + { + DBG1(DBG_CFG, "vici redirect IKE_SA #%d to %Y", ike_id, gateway); + } + if (ike) + { + DBG1(DBG_CFG, "vici redirect IKE_SA '%s' to %Y", ike, gateway); + } + if (!peer_ip && !peer_id && !ike && !ike_id) + { + DBG1(DBG_CFG, "vici redirect all IKE_SAs to %Y", gateway); + } + + sas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE); + while (sas->enumerate(sas, &ike_sa)) + { + if (ike_sa->get_version(ike_sa) != IKEV2) + { + continue; + } + current = ike_sa->get_unique_id(ike_sa); + if (ike_id && ike_id != current) + { + continue; + } + if (ike && !streq(ike, ike_sa->get_name(ike_sa))) + { + continue; + } + if (address && + !address->ip_equals(address, ike_sa->get_other_host(ike_sa))) + { + continue; + } + if (identity && + !identity->equals(identity, ike_sa->get_other_eap_id(ike_sa))) + { + continue; + } + lib->processor->queue_job(lib->processor, + (job_t*)redirect_job_create(ike_sa->get_id(ike_sa), gateway)); + found++; + } + sas->destroy(sas); + + builder = vici_builder_create(); + if (!found) + { + errmsg = "no matching SAs to redirect found"; + } + builder->add_kv(builder, "success", errmsg ? "no" : "yes"); + if (errmsg) + { + builder->add_kv(builder, "errmsg", "%s", errmsg); + } + gateway->destroy(gateway); + DESTROY_IF(identity); + DESTROY_IF(address); + return builder->finalize(builder); +} + /** * Find reqid of an existing CHILD_SA */ @@ -498,6 +614,7 @@ static void manage_commands(private_vici_control_t *this, bool reg) { manage_command(this, "initiate", initiate, reg); manage_command(this, "terminate", terminate, reg); + manage_command(this, "redirect", redirect, reg); manage_command(this, "install", install, reg); manage_command(this, "uninstall", uninstall, reg); manage_command(this, "reload-settings", reload_settings, reg);