/*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
#include <daemon.h>
#include <collections/array.h>
+#include <processing/jobs/redirect_job.h>
typedef struct private_vici_control_t private_vici_control_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
*/
{
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);