Load test and suite specific connection configurations
authorMartin Willi <martin@revosec.ch>
Fri, 29 Oct 2010 08:34:08 +0000 (10:34 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 5 Jan 2011 15:45:40 +0000 (16:45 +0100)
src/conftest/Makefile.am
src/conftest/config.c [new file with mode: 0644]
src/conftest/config.h [new file with mode: 0644]
src/conftest/conftest.c
src/conftest/conftest.h

index 0b041a4..ce009e4 100644 (file)
@@ -2,7 +2,7 @@ ipsec_PROGRAMS = conftest
 
 AM_CFLAGS = -rdynamic
 
-conftest_SOURCES = conftest.c hooks/hook.h
+conftest_SOURCES = conftest.c conftest.h config.c config.h hooks/hook.h
 
 INCLUDES = \
        -I$(top_srcdir)/src/libstrongswan \
diff --git a/src/conftest/config.c b/src/conftest/config.c
new file mode 100644 (file)
index 0000000..1e70025
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#include <daemon.h>
+#include <conftest.h>
+
+typedef struct private_config_t private_config_t;
+
+/**
+ * Private data of an config_t object.
+ */
+struct private_config_t {
+
+       /**
+        * Public config_t interface.
+        */
+       config_t public;
+
+       /**
+        * List of loaded peer configs
+        */
+       linked_list_t *configs;
+};
+
+/**
+ * filter function for ike configs
+ */
+static bool ike_filter(void *data, peer_cfg_t **in, ike_cfg_t **out)
+{
+       *out = (*in)->get_ike_cfg(*in);
+       return TRUE;
+}
+
+METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
+       private_config_t *this, host_t *me, host_t *other)
+{
+
+       return enumerator_create_filter(
+                                                       this->configs->create_enumerator(this->configs),
+                                                       (void*)ike_filter, NULL, NULL);
+}
+
+METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
+       private_config_t *this, identification_t *me, identification_t *other)
+{
+       return this->configs->create_enumerator(this->configs);
+}
+
+METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
+       private_config_t *this, char *name)
+{
+       enumerator_t *e1, *e2;
+       peer_cfg_t *current, *found = NULL;
+       child_cfg_t *child;
+
+       e1 = this->configs->create_enumerator(this->configs);
+       while (e1->enumerate(e1, &current))
+       {
+               e2 = current->create_child_cfg_enumerator(current);
+               while (e2->enumerate(e2, &child))
+               {
+                       if (streq(child->get_name(child), name))
+                       {
+                               found = current;
+                               found->get_ref(found);
+                               break;
+                       }
+               }
+               e2->destroy(e2);
+               if (found)
+               {
+                       break;
+               }
+       }
+       e1->destroy(e1);
+       return found;
+}
+
+/**
+ * Load IKE config for a given section name
+ */
+static ike_cfg_t *load_ike_config(private_config_t *this,
+                                                                 settings_t *settings, char *config)
+{
+       enumerator_t *enumerator;
+       ike_cfg_t *ike_cfg;
+       proposal_t *proposal;
+       char *token;
+
+       ike_cfg = ike_cfg_create(TRUE, FALSE,
+               settings->get_str(settings, "configs.%s.lhost", "%any", config), 500,
+               settings->get_str(settings, "configs.%s.rhost", "%any", config), 500);
+       token = settings->get_str(settings, "configs.%s.proposal", NULL, config);
+       if (token)
+       {
+               enumerator = enumerator_create_token(token, ",", " ");
+               while (enumerator->enumerate(enumerator, &token))
+               {
+                       proposal = proposal_create_from_string(PROTO_IKE, token);
+                       if (proposal)
+                       {
+                               ike_cfg->add_proposal(ike_cfg, proposal);
+                       }
+                       else
+                       {
+                               DBG1(DBG_CFG, "parsing proposal '%s' failed, skipped", token);
+                       }
+               }
+               enumerator->destroy(enumerator);
+       }
+       else
+       {
+               ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+       }
+       return ike_cfg;
+}
+/**
+ * Load CHILD config for given section names
+ */
+static child_cfg_t *load_child_config(private_config_t *this,
+                                                       settings_t *settings, char *config, char *child)
+{
+       child_cfg_t *child_cfg;
+       lifetime_cfg_t lifetime = {};
+       enumerator_t *enumerator;
+       proposal_t *proposal;
+       traffic_selector_t *ts;
+       host_t *net;
+       char *token;
+       int bits;
+
+       child_cfg = child_cfg_create(child, &lifetime, NULL, FALSE,
+                                               settings->get_bool(settings, "configs.%s.%s.transport",
+                                                                                  FALSE, config, child),
+                                               ACTION_NONE, ACTION_NONE, FALSE, 0, 0, NULL, NULL);
+
+       token = settings->get_str(settings, "configs.%s.%s.proposal",
+                                                         NULL, config, child);
+       if (token)
+       {
+               enumerator = enumerator_create_token(token, ",", " ");
+               while (enumerator->enumerate(enumerator, &token))
+               {
+                       proposal = proposal_create_from_string(PROTO_ESP, token);
+                       if (proposal)
+                       {
+                               child_cfg->add_proposal(child_cfg, proposal);
+                       }
+                       else
+                       {
+                               DBG1(DBG_CFG, "parsing proposal '%s' failed, skipped", token);
+                       }
+               }
+               enumerator->destroy(enumerator);
+       }
+       else
+       {
+               child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+       }
+
+       token = settings->get_str(settings, "configs.%s.%s.lts", NULL, config);
+       if (token)
+       {
+               enumerator = enumerator_create_token(token, ",", " ");
+               while (enumerator->enumerate(enumerator, &token))
+               {
+                       net = host_create_from_subnet(token, &bits);
+                       if (net)
+                       {
+                               ts = traffic_selector_create_from_subnet(net, bits, 0, 0);
+                               child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
+                       }
+                       else
+                       {
+                               DBG1(DBG_CFG, "invalid local ts: %s, skipped", token);
+                       }
+               }
+               enumerator->destroy(enumerator);
+       }
+       else
+       {
+               ts = traffic_selector_create_dynamic(0, 0, 65535);
+               child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
+       }
+
+       token = settings->get_str(settings, "configs.%s.%s.rts", NULL, config);
+       if (token)
+       {
+               enumerator = enumerator_create_token(token, ",", " ");
+               while (enumerator->enumerate(enumerator, &token))
+               {
+                       net = host_create_from_subnet(token, &bits);
+                       if (net)
+                       {
+                               ts = traffic_selector_create_from_subnet(net, bits, 0, 0);
+                               child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
+                       }
+                       else
+                       {
+                               DBG1(DBG_CFG, "invalid remote ts: %s, skipped", token);
+                       }
+               }
+               enumerator->destroy(enumerator);
+       }
+       else
+       {
+               ts = traffic_selector_create_dynamic(0, 0, 65535);
+               child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
+       }
+       return child_cfg;
+}
+
+/**
+ * Load peer config for a given section name
+ */
+static peer_cfg_t *load_peer_config(private_config_t *this,
+                                                                       settings_t *settings, char *config)
+{
+       ike_cfg_t *ike_cfg;
+       peer_cfg_t *peer_cfg;
+       auth_cfg_t *auth;
+       child_cfg_t *child_cfg;
+       enumerator_t *enumerator;
+       identification_t *lid, *rid;
+       char *child;
+
+       ike_cfg = load_ike_config(this, settings, config);
+       peer_cfg = peer_cfg_create(config, 2, ike_cfg, CERT_ALWAYS_SEND,
+                                                          UNIQUE_NO, 1, 0, 0, 0, 0, TRUE, 0,
+                                                          NULL, NULL, FALSE, NULL, NULL);
+
+       auth = auth_cfg_create();
+       auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+       lid = identification_create_from_string(
+                               settings->get_str(settings, "configs.%s.lid", "%any", config));
+       auth->add(auth, AUTH_RULE_IDENTITY, lid);
+       peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
+
+       auth = auth_cfg_create();
+       auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+       rid = identification_create_from_string(
+                               settings->get_str(settings, "configs.%s.rid", "%any", config));
+       auth->add(auth, AUTH_RULE_IDENTITY, rid);
+       peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
+
+       DBG1(DBG_CFG, "loaded config %s: %Y - %Y", config, lid, rid);
+
+       enumerator = settings->create_section_enumerator(settings,
+                                                                                                        "configs.%s", config);
+       while (enumerator->enumerate(enumerator, &child))
+       {
+               child_cfg = load_child_config(this, settings, config, child);
+               peer_cfg->add_child_cfg(peer_cfg, child_cfg);
+       }
+       enumerator->destroy(enumerator);
+       return peer_cfg;
+}
+
+METHOD(config_t, load, void,
+       private_config_t *this, settings_t *settings)
+{
+       enumerator_t *enumerator;
+       char *config;
+
+       enumerator = settings->create_section_enumerator(settings, "configs");
+       while (enumerator->enumerate(enumerator, &config))
+       {
+               this->configs->insert_last(this->configs,
+                                                               load_peer_config(this, settings, config));
+       }
+       enumerator->destroy(enumerator);
+}
+
+METHOD(config_t, destroy, void,
+       private_config_t *this)
+{
+       this->configs->destroy_offset(this->configs, offsetof(peer_cfg_t, destroy));
+       free(this);
+}
+
+/**
+ * See header
+ */
+config_t *config_create()
+{
+       private_config_t *this;
+
+       INIT(this,
+               .public = {
+                       .backend = {
+                               .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
+                               .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
+                               .get_peer_cfg_by_name = _get_peer_cfg_by_name,
+                       },
+                       .load = _load,
+                       .destroy = _destroy,
+               },
+               .configs = linked_list_create(),
+       );
+
+       return &this->public;
+}
diff --git a/src/conftest/config.h b/src/conftest/config.h
new file mode 100644 (file)
index 0000000..2a62b9c
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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 config config
+ * @{ @ingroup conftest
+ */
+
+#ifndef CONFIG_H_
+#define CONFIG_H_
+
+typedef struct config_t config_t;
+
+#include <config/backend.h>
+
+/**
+ * Conftest IKE and CHILD config backend
+ */
+struct config_t {
+
+       /**
+        * Implements the backend_t interface.
+        */
+       backend_t backend;
+
+       /**
+        * Load configurations from a settings file.
+        *
+        * @param settings              settings file to load configs from
+        */
+       void (*load)(config_t *this, settings_t *settings);
+
+       /**
+        * Destroy a config_t.
+        */
+       void (*destroy)(config_t *this);
+};
+
+/**
+ * Create a config instance.
+ */
+config_t *config_create();
+
+#endif /** CONFIG_H_ @}*/
index 881db5d..9db59b0 100644 (file)
@@ -23,6 +23,7 @@
 #include <libgen.h>
 
 #include "conftest.h"
+#include "config.h"
 #include "hooks/hook.h"
 
 #include <threading/thread.h>
@@ -192,6 +193,12 @@ static void cleanup()
                hook->destroy(hook);
        }
        conftest->hooks->destroy(conftest->hooks);
+       if (conftest->config)
+       {
+               charon->backends->remove_backend(charon->backends,
+                                                                                &conftest->config->backend);
+               conftest->config->destroy(conftest->config);
+       }
        free(conftest->suite_dir);
        free(conftest->test_dir);
        free(conftest);
@@ -241,6 +248,7 @@ int main(int argc, char *argv[])
 
        lib->credmgr->add_set(lib->credmgr, &conftest->creds->set);
        conftest->hooks = linked_list_create();
+       conftest->config = config_create();
 
        atexit(cleanup);
 
@@ -292,6 +300,9 @@ int main(int argc, char *argv[])
        {
                return 1;
        }
+       charon->backends->add_backend(charon->backends, &conftest->config->backend);
+       conftest->config->load(conftest->config, conftest->suite);
+       conftest->config->load(conftest->config, conftest->test);
 
        /* set up thread specific handlers */
        action.sa_handler = segv_handler;
index 614248e..5fa2e37 100644 (file)
@@ -25,6 +25,8 @@
 #include <daemon.h>
 #include <credentials/sets/mem_cred.h>
 
+#include "config.h"
+
 typedef struct conftest_t conftest_t;
 
 /**
@@ -58,6 +60,11 @@ struct conftest_t {
        mem_cred_t *creds;
 
        /**
+        * Configurations loaded from config
+        */
+       config_t *config;
+
+       /**
         * Loaded hooks
         */
        linked_list_t *hooks;