]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
vici: Add support for mediation extension
authorTobias Brunner <tobias@strongswan.org>
Tue, 7 Feb 2017 11:04:30 +0000 (12:04 +0100)
committerTobias Brunner <tobias@strongswan.org>
Thu, 16 Feb 2017 18:24:09 +0000 (19:24 +0100)
src/libcharon/plugins/vici/vici_config.c
src/swanctl/swanctl.opt

index b9f6b79b1d8d64114ff5d6e9ccdad6f33595b773..12497ec5eefa9550abf65fce791d3201c3b28ae1 100644 (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,
index 7eb0885c857c6e0040e8f243c644240bfd5130fe..cd2d9142ddb84af5f01a4675ea6501c368b52a59 100644 (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.