]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
Added a hook to narrow traffic selectors for CHILD_SAs
authorMartin Willi <martin@revosec.ch>
Tue, 13 Jul 2010 06:39:19 +0000 (08:39 +0200)
committerMartin Willi <martin@revosec.ch>
Tue, 13 Jul 2010 08:26:07 +0000 (10:26 +0200)
src/libcharon/bus/bus.c
src/libcharon/bus/bus.h
src/libcharon/bus/listeners/listener.h
src/libcharon/sa/tasks/child_create.c

index 6a9fcce022786eb2156e3db5a81fe772268b3436..97d09c40a57589a4850d044e39e996e3b4c74149 100644 (file)
@@ -640,6 +640,38 @@ METHOD(bus_t, authorize, bool,
        return success;
 }
 
+METHOD(bus_t, narrow, void,
+       private_bus_t *this, child_sa_t *child_sa, narrow_hook_t type,
+       linked_list_t *local, linked_list_t *remote)
+{
+       enumerator_t *enumerator;
+       ike_sa_t *ike_sa;
+       entry_t *entry;
+       bool keep;
+
+       ike_sa = this->thread_sa->get(this->thread_sa);
+
+       this->mutex->lock(this->mutex);
+       enumerator = this->listeners->create_enumerator(this->listeners);
+       while (enumerator->enumerate(enumerator, &entry))
+       {
+               if (entry->calling || !entry->listener->narrow)
+               {
+                       continue;
+               }
+               entry->calling++;
+               keep = entry->listener->narrow(entry->listener, ike_sa, child_sa,
+                                                                          type, local, remote);
+               entry->calling--;
+               if (!keep)
+               {
+                       unregister_listener(this, entry, enumerator);
+               }
+       }
+       enumerator->destroy(enumerator);
+       this->mutex->unlock(this->mutex);
+}
+
 METHOD(bus_t, destroy, void,
        private_bus_t *this)
 {
@@ -676,6 +708,7 @@ bus_t *bus_create()
                        .child_updown = _child_updown,
                        .child_rekey = _child_rekey,
                        .authorize = _authorize,
+                       .narrow = _narrow,
                        .destroy = _destroy,
                },
                .listeners = linked_list_create(),
index 8cf392eae03144e4dd8c9a38a5034097dde88a6d..df555d83e3f74503ba60a4cb79fa223f98a1b57d 100644 (file)
@@ -22,6 +22,7 @@
 #define BUS_H_
 
 typedef enum alert_t alert_t;
+typedef enum narrow_hook_t narrow_hook_t;
 typedef struct bus_t bus_t;
 
 #include <stdarg.h>
@@ -85,6 +86,31 @@ enum alert_t {
        ALERT_SHUTDOWN_SIGNAL,
 };
 
+/**
+ * Kind of narrow hook.
+ *
+ * There is a non-authenticated (IKE_AUTH) and a authenticated
+ * (CREATE_CHILD_SA) narrowing hook for the initiator. Only one of these
+ * hooks is invoked before the exchange.
+ * To verify the traffic selectors negotiated, each PRE hook has a POST
+ * counterpart that follows. POST hooks are invoked with an authenticated peer.
+ * It is usually not a good idea to narrow in the POST hooks,
+ * as the resulting traffic selector is not negotiated and results
+ * in non-matching policies.
+ */
+enum narrow_hook_t {
+       /** invoked as initiator before exchange, peer is not yet authenticated */
+       NARROW_INITIATOR_PRE_NOAUTH,
+       /** invoked as initiator before exchange, peer is authenticated */
+       NARROW_INITIATOR_PRE_AUTH,
+       /** invoked as responder during exchange, peer is authenticated */
+       NARROW_RESPONDER,
+       /** invoked as initiator after exchange, follows a INITIATOR_PRE_NOAUTH */
+       NARROW_INITIATOR_POST_NOAUTH,
+       /** invoked as initiator after exchange, follows a INITIATOR_PRE_AUTH */
+       NARROW_INITIATOR_POST_AUTH,
+};
+
 /**
  * The bus receives events and sends them to all registered listeners.
  *
@@ -216,6 +242,17 @@ struct bus_t {
         */
        bool (*authorize)(bus_t *this, bool final);
 
+       /**
+        * CHILD_SA traffic selector narrowing hook.
+        *
+        * @param child_sa      CHILD_SA set up with these traffic selectors
+        * @param type          type of hook getting invoked
+        * @param local         list of local traffic selectors to narrow
+        * @param remote        list of remote traffic selectors to narrow
+        */
+       void (*narrow)(bus_t *this, child_sa_t *child_sa, narrow_hook_t type,
+                                  linked_list_t *local, linked_list_t *remote);
+
        /**
         * IKE_SA keymat hook.
         *
index 9a51a2ef4c0546af2bd58cdb28f57d68818a0bb3..45c61c0c04de239f4338300222088434b82c7b5a 100644 (file)
@@ -173,6 +173,21 @@ struct listener_t {
         */
        bool (*authorize)(listener_t *this, ike_sa_t *ike_sa,
                                          bool final, bool *success);
+
+       /**
+        * CHILD_SA traffic selector narrowing hook.
+        *
+        * This hook is invoked for each CHILD_SA and allows plugins to modify
+        * the traffic selector list negotiated for this CHILD_SA.
+        *
+        * @param ike_sa        IKE_SA the created CHILD_SA is created in
+        * @param child_sa      CHILD_SA set up with these traffic selectors
+        * @param type          type of hook getting invoked
+        * @param local         list of local traffic selectors to narrow
+        * @param remote        list of remote traffic selectors to narrow
+        */
+       bool (*narrow)(listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+                               narrow_hook_t type, linked_list_t *local, linked_list_t *remote);
 };
 
 #endif /** LISTENER_H_ @}*/
index ed468ec9c26121d6ec07c98e1117c69398ca22a4..9928110407206919baa7fc5eabe360c05e9a2615 100644 (file)
@@ -273,7 +273,8 @@ static void schedule_inactivity_timeout(private_child_create_t *this)
  * - INVALID_ARG: diffie hellman group inacceptable
  * - NOT_FOUND: TS inacceptable
  */
-static status_t select_and_install(private_child_create_t *this, bool no_dh)
+static status_t select_and_install(private_child_create_t *this,
+                                                                  bool no_dh, bool ike_auth)
 {
        status_t status, status_i, status_o;
        chunk_t nonce_i, nonce_r;
@@ -364,6 +365,25 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
        other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
                                                                                                   other_vip);
 
+       if (this->initiator)
+       {
+               if (ike_auth)
+               {
+                       charon->bus->narrow(charon->bus, this->child_sa,
+                                                               NARROW_INITIATOR_POST_NOAUTH, my_ts, other_ts);
+               }
+               else
+               {
+                       charon->bus->narrow(charon->bus, this->child_sa,
+                                                               NARROW_INITIATOR_POST_AUTH, my_ts, other_ts);
+               }
+       }
+       else
+       {
+               charon->bus->narrow(charon->bus, this->child_sa,
+                                                       NARROW_RESPONDER, my_ts, other_ts);
+       }
+
        if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
        {
                my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
@@ -848,6 +868,17 @@ static status_t build_i(private_child_create_t *this, message_t *message)
                add_ipcomp_notify(this, message, IPCOMP_DEFLATE);
        }
 
+       if (message->get_exchange_type(message) == IKE_AUTH)
+       {
+               charon->bus->narrow(charon->bus, this->child_sa,
+                                                       NARROW_INITIATOR_PRE_NOAUTH, this->tsi, this->tsr);
+       }
+       else
+       {
+               charon->bus->narrow(charon->bus, this->child_sa,
+                                                       NARROW_INITIATOR_PRE_AUTH, this->tsi, this->tsr);
+       }
+
        build_payloads(this, message);
 
        this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
@@ -914,7 +945,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
        peer_cfg_t *peer_cfg;
        payload_t *payload;
        enumerator_t *enumerator;
-       bool no_dh = TRUE;
+       bool no_dh = TRUE, ike_auth = FALSE;
 
        switch (message->get_exchange_type(message))
        {
@@ -934,6 +965,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
                        {       /* wait until all authentication round completed */
                                return NEED_MORE;
                        }
+                       ike_auth = TRUE;
                default:
                        break;
        }
@@ -1016,7 +1048,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
                }
        }
 
-       switch (select_and_install(this, no_dh))
+       switch (select_and_install(this, no_dh, ike_auth))
        {
                case SUCCESS:
                        break;
@@ -1064,7 +1096,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
 {
        enumerator_t *enumerator;
        payload_t *payload;
-       bool no_dh = TRUE;
+       bool no_dh = TRUE, ike_auth = FALSE;
 
        switch (message->get_exchange_type(message))
        {
@@ -1079,6 +1111,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
                        {       /* wait until all authentication round completed */
                                return NEED_MORE;
                        }
+                       ike_auth = TRUE;
                default:
                        break;
        }
@@ -1159,7 +1192,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
                return SUCCESS;
        }
 
-       if (select_and_install(this, no_dh) == SUCCESS)
+       if (select_and_install(this, no_dh, ike_auth) == SUCCESS)
        {
                DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
                         "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",