]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
Moved X509 ipAddrBlock checking to the addrblock plugin
authorMartin Willi <martin@revosec.ch>
Tue, 13 Jul 2010 07:19:39 +0000 (09:19 +0200)
committerMartin Willi <martin@revosec.ch>
Tue, 13 Jul 2010 08:26:07 +0000 (10:26 +0200)
src/libcharon/plugins/addrblock/Makefile.am
src/libcharon/plugins/addrblock/addrblock_narrow.c [new file with mode: 0644]
src/libcharon/plugins/addrblock/addrblock_narrow.h [new file with mode: 0644]
src/libcharon/plugins/addrblock/addrblock_plugin.c
src/libcharon/sa/tasks/child_create.c

index d844674ffba09d6d41bb16e4c628c9364625f3bd..50d0457f868bf4502b3c7368e8a5abf70406de6e 100644 (file)
@@ -12,6 +12,7 @@ endif
 
 libstrongswan_addrblock_la_SOURCES = \
        addrblock_plugin.h addrblock_plugin.c \
+       addrblock_narrow.h addrblock_narrow.c \
        addrblock_validator.h addrblock_validator.c
 
 libstrongswan_addrblock_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/addrblock/addrblock_narrow.c b/src/libcharon/plugins/addrblock/addrblock_narrow.c
new file mode 100644 (file)
index 0000000..f85fa78
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ * Copyright (C) 2009 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "addrblock_narrow.h"
+
+#include <daemon.h>
+#include <credentials/certificates/x509.h>
+
+typedef struct private_addrblock_narrow_t private_addrblock_narrow_t;
+
+/**
+ * Private data of an addrblock_narrow_t object.
+ */
+struct private_addrblock_narrow_t {
+
+       /**
+        * Public addrblock_narrow_t interface.
+        */
+       addrblock_narrow_t public;
+};
+
+/**
+ * Check if the negotiated TS list is acceptable by X509 ipAddrBlock constraints
+ */
+static bool check_constraints(ike_sa_t *ike_sa, linked_list_t *list)
+{
+       auth_cfg_t *auth;
+       enumerator_t *auth_enum;
+       certificate_t *cert = NULL;
+
+       auth_enum = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE);
+       while (auth_enum->enumerate(auth_enum, &auth))
+       {
+               cert = auth->get(auth, AUTH_HELPER_SUBJECT_CERT);
+               if (cert)
+               {
+                       break;
+               }
+       }
+       auth_enum->destroy(auth_enum);
+
+       if (cert && cert->get_type(cert) == CERT_X509)
+       {
+               x509_t *x509 = (x509_t*)cert;
+
+               if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
+               {
+                       enumerator_t *enumerator, *block_enum;
+                       traffic_selector_t *ts, *block_ts;
+
+                       DBG1(DBG_IKE, "checking certificate-based traffic selector "
+                                                 "constraints [RFC 3779]");
+                       enumerator = list->create_enumerator(list);
+                       while (enumerator->enumerate(enumerator, &ts))
+                       {
+                               bool contained = FALSE;
+
+                               block_enum = x509->create_ipAddrBlock_enumerator(x509);
+                               while (block_enum->enumerate(block_enum, &block_ts))
+                               {
+                                       if (ts->is_contained_in(ts, block_ts))
+                                       {
+                                               DBG1(DBG_IKE, "  TS %R is contained in address block"
+                                                                         " constraint %R", ts, block_ts);
+                                               contained = TRUE;
+                                               break;
+                                       }
+                               }
+                               block_enum->destroy(block_enum);
+
+                               if (!contained)
+                               {
+                                       DBG1(DBG_IKE, "  TS %R is not contained in any"
+                                                                 " address block constraint", ts);
+                                       enumerator->destroy(enumerator);
+                                       return FALSE;
+                               }
+                       }
+                       enumerator->destroy(enumerator);
+               }
+       }
+       return TRUE;
+}
+
+/**
+ * Delete all traffic selectors in a list
+ */
+static void flush_ts_list(linked_list_t *list)
+{
+       traffic_selector_t *ts;
+
+       while (list->remove_last(list, (void**)&ts) == SUCCESS)
+       {
+               ts->destroy(ts);
+       }
+}
+
+METHOD(listener_t, narrow, bool,
+       private_addrblock_narrow_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+       narrow_hook_t type, linked_list_t *local, linked_list_t *remote)
+{
+       switch (type)
+       {
+               case NARROW_RESPONDER:
+               case NARROW_INITIATOR_POST_AUTH:
+               case NARROW_INITIATOR_POST_NOAUTH:
+                       if (!check_constraints(ike_sa, remote))
+                       {
+                               flush_ts_list(local);
+                               flush_ts_list(remote);
+                       }
+                       break;
+               default:
+                       break;
+       }
+       return TRUE;
+}
+
+METHOD(addrblock_narrow_t, destroy, void,
+       private_addrblock_narrow_t *this)
+{
+       free(this);
+}
+
+/**
+ * See header
+ */
+addrblock_narrow_t *addrblock_narrow_create()
+{
+       private_addrblock_narrow_t *this;
+
+       INIT(this,
+               .public = {
+                       .listener.narrow = _narrow,
+                       .destroy = _destroy,
+               },
+       );
+
+       return &this->public;
+}
diff --git a/src/libcharon/plugins/addrblock/addrblock_narrow.h b/src/libcharon/plugins/addrblock/addrblock_narrow.h
new file mode 100644 (file)
index 0000000..9ab32e6
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup addrblock_narrow addrblock_narrow
+ * @{ @ingroup addrblock
+ */
+
+#ifndef ADDRBLOCK_NARROW_H_
+#define ADDRBLOCK_NARROW_H_
+
+#include <bus/listeners/listener.h>
+
+typedef struct addrblock_narrow_t addrblock_narrow_t;
+
+/**
+ * Listener that checks traffic selectors against addrblock constraints.
+ */
+struct addrblock_narrow_t {
+
+       /**
+        * Implements listener_t.
+        */
+       listener_t listener;
+
+       /**
+        * Destroy a addrblock_narrow_t.
+        */
+       void (*destroy)(addrblock_narrow_t *this);
+};
+
+/**
+ * Create a addrblock_narrow instance.
+ */
+addrblock_narrow_t *addrblock_narrow_create();
+
+#endif /** ADDRBLOCK_NARROW_H_ @}*/
index 6c1ef73e487d4b82a7dcf43198629d7bd18a79b4..1c407035d023a4fa848e6eb99b357a414f6a2418 100644 (file)
 
 #include "addrblock_plugin.h"
 
-#include <library.h>
+#include <daemon.h>
+
 #include "addrblock_validator.h"
+#include "addrblock_narrow.h"
 
 typedef struct private_addrblock_plugin_t private_addrblock_plugin_t;
 
@@ -34,12 +36,19 @@ struct private_addrblock_plugin_t {
         * Validator implementation instance.
         */
        addrblock_validator_t *validator;
+
+       /**
+        * Listener to check TS list
+        */
+       addrblock_narrow_t *narrower;
 };
 
 METHOD(plugin_t, destroy, void,
        private_addrblock_plugin_t *this)
 {
+       charon->bus->remove_listener(charon->bus, &this->narrower->listener);
        lib->credmgr->remove_validator(lib->credmgr, &this->validator->validator);
+       this->narrower->destroy(this->narrower);
        this->validator->destroy(this->validator);
        free(this);
 }
@@ -54,8 +63,10 @@ plugin_t *addrblock_plugin_create()
        INIT(this,
                .public.plugin.destroy = _destroy,
                .validator = addrblock_validator_create(),
+               .narrower = addrblock_narrow_create(),
        );
        lib->credmgr->add_validator(lib->credmgr, &this->validator->validator);
+       charon->bus->add_listener(charon->bus, &this->narrower->listener);
 
        return &this->public.plugin;
 }
index 9928110407206919baa7fc5eabe360c05e9a2615..1113e473ba4881216bb688ff58918be4c41791e6 100644 (file)
@@ -438,66 +438,6 @@ static status_t select_and_install(private_child_create_t *this,
                }
        }
 
-       /* check for any certificate-based IP address block constraints */
-       if (this->mode == MODE_BEET || this->mode == MODE_TUNNEL)
-       {
-               auth_cfg_t *auth;
-               enumerator_t *auth_enum;
-               certificate_t *cert = NULL;
-
-               auth_enum = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, FALSE);
-               while (auth_enum->enumerate(auth_enum, &auth))
-               {
-                       cert = auth->get(auth, AUTH_HELPER_SUBJECT_CERT);
-                       if (cert)
-                       {
-                               break;
-                       }
-               }
-               auth_enum->destroy(auth_enum);
-
-               if (cert && cert->get_type(cert) == CERT_X509)
-               {
-                       x509_t *x509 = (x509_t*)cert;
-
-                       if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
-                       {
-                               enumerator_t *enumerator, *block_enum;
-                               traffic_selector_t *ts, *block_ts;
-
-                               DBG1(DBG_IKE, "checking certificate-based traffic selector "
-                                                         "constraints [RFC 3779]");
-                               enumerator = other_ts->create_enumerator(other_ts);
-                               while (enumerator->enumerate(enumerator, &ts))
-                               {
-                                       bool contained = FALSE;
-
-                                       block_enum = x509->create_ipAddrBlock_enumerator(x509);
-                                       while (block_enum->enumerate(block_enum, &block_ts))
-                                       {
-                                               if (ts->is_contained_in(ts, block_ts))
-                                               {
-                                                       DBG1(DBG_IKE, "  TS %R is contained in address block"
-                                                                                 " constraint %R", ts, block_ts);
-                                                       contained = TRUE;
-                                                       break;
-                                               }
-                                       }
-                                       block_enum->destroy(block_enum);
-
-                                       if (!contained)
-                                       {
-                                               DBG1(DBG_IKE, "  TS %R is not contained in any"
-                                                                         " address block constraint", ts);
-                                               enumerator->destroy(enumerator);
-                                               return FAILED;
-                                       }
-                               }
-                               enumerator->destroy(enumerator);
-                       }
-               }
-       }
-
        this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
        this->child_sa->set_ipcomp(this->child_sa, this->ipcomp);
        this->child_sa->set_mode(this->child_sa, this->mode);