read IMC/IMV configurations from /etc/tnc_config
authorAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 10 Nov 2010 09:57:01 +0000 (10:57 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 10 Nov 2010 09:57:01 +0000 (10:57 +0100)
src/libcharon/plugins/tnc_imc/tnc_imc.c
src/libcharon/plugins/tnc_imc/tnc_imc_manager.c
src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c
src/libcharon/plugins/tnc_imv/tnc_imv.c
src/libcharon/plugins/tnc_imv/tnc_imv_manager.c
src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c

index e0f06e5..fa5e2e4 100644 (file)
@@ -33,6 +33,11 @@ struct private_tnc_imc_t {
        imc_t public;
 
        /**
+        * Path of loaded IMC
+        */
+       char *path;
+
+       /**
         * Name of loaded IMC
         */
        char *name;
@@ -129,13 +134,14 @@ METHOD(imc_t, destroy, void,
        dlclose(this->handle);
        free(this->supported_types);
        free(this->name);
+       free(this->path);
        free(this);
 }
 
 /**
  * Described in header.
  */
-imc_t* tnc_imc_create(char* name, char *filename)
+imc_t* tnc_imc_create(char *name, char *path)
 {
        private_tnc_imc_t *this;
 
@@ -148,25 +154,23 @@ imc_t* tnc_imc_create(char* name, char *filename)
                        .type_supported = _type_supported,
                        .destroy = _destroy,
         },
+               .name = name,
+               .path = path,
        );
 
-       this->handle = dlopen(filename, RTLD_NOW);
+       this->handle = dlopen(path, RTLD_NOW);
        if (!this->handle)
        {
-               DBG1(DBG_TNC, "IMC '%s' failed to load from '%s': %s",
-                                          name, filename, dlerror());
+               DBG1(DBG_TNC, "IMC \"%s\" failed to load: %s", name, dlerror());
                free(this);
                return NULL;
        }
 
-       /* we do not store or free dlopen() this->handles, leak_detective requires
-        * the modules to keep loaded until leak report */
-
        this->public.initialize = dlsym(this->handle, "TNC_IMC_Initialize");
        if (!this->public.initialize)
     {
                DBG1(DBG_TNC, "could not resolve TNC_IMC_Initialize in %s: %s\n",
-                                          filename, dlerror());
+                                          path, dlerror());
                dlclose(this->handle);
                free(this);
                return NULL;
@@ -177,7 +181,7 @@ imc_t* tnc_imc_create(char* name, char *filename)
        if (!this->public.begin_handshake)
     {
                DBG1(DBG_TNC, "could not resolve TNC_IMC_BeginHandshake in %s: %s\n",
-                                          filename, dlerror());
+                                          path, dlerror());
                dlclose(this->handle);
                free(this);
                return NULL;
@@ -193,12 +197,11 @@ imc_t* tnc_imc_create(char* name, char *filename)
     if (!this->public.provide_bind_function)
        {
                DBG1(DBG_TNC, "could not resolve TNC_IMC_ProvideBindFunction in %s: %s\n",
-                                         filename, dlerror());
+                                         path, dlerror());
                dlclose(this->handle);
                free(this);
                return NULL;
        }
-       this->name = strdup(name);
 
        return &this->public;
 }
index d78c92a..f876167 100644 (file)
@@ -55,8 +55,7 @@ METHOD(imc_manager_t, add, bool,
        if (imc->initialize(imc->get_id(imc), TNC_IFIMC_VERSION_1,
                        TNC_IFIMC_VERSION_1, &version) != TNC_RESULT_SUCCESS)
        {
-               DBG1(DBG_TNC, "could not initialize IMC '%s'",
-                                          imc->get_name(imc));
+               DBG1(DBG_TNC, "IMC \"%s\" failed to initialize", imc->get_name(imc));
                return FALSE;
        }
        this->imcs->insert_last(this->imcs, imc);
@@ -65,7 +64,7 @@ METHOD(imc_manager_t, add, bool,
     if (imc->provide_bind_function(imc->get_id(imc), TNC_TNCC_BindFunction)
                        != TNC_RESULT_SUCCESS)
        {
-               DBG1(DBG_TNC, "could not provide bind function for IMC '%s'",
+               DBG1(DBG_TNC, "IMC \"%s\" failed to obtain bind function",
                                           imc->get_name(imc));
                this->imcs->remove_last(this->imcs, (void**)&imc);
                return FALSE;
@@ -202,7 +201,7 @@ METHOD(imc_manager_t, destroy, void,
                if (imc->terminate &&
                        imc->terminate(imc->get_id(imc)) != TNC_RESULT_SUCCESS)
                {
-                       DBG1(DBG_TNC, "IMC '%s' not terminated successfully",
+                       DBG1(DBG_TNC, "IMC \"%s\" not terminated successfully",
                                                   imc->get_name(imc));
                }
                imc->destroy(imc);
index 05d7b7a..683efc1 100644 (file)
 #include "tnc_imc_manager.h"
 #include "tnc_imc.h"
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
 #include <daemon.h>
+#include <utils/lexparser.h>
+
+/**
+ * load IMCs from a configuration file
+ */
+static bool load_imcs(char *filename)
+{
+       int fd, line_nr = 0;
+       chunk_t src, line;
+       struct stat sb;
+       void *addr;
+
+       DBG1(DBG_TNC, "loading IMCs from '%s'", filename);
+       fd = open(filename, O_RDONLY);
+       if (fd == -1)
+       {
+               DBG1(DBG_TNC, "opening configuration file '%s' failed: %s", filename,
+                        strerror(errno));
+               return FALSE;
+       }
+       if (fstat(fd, &sb) == -1)
+       {
+               DBG1(DBG_LIB, "getting file size of '%s' failed: %s", filename,
+                        strerror(errno));
+               close(fd);
+               return FALSE;
+       }
+       addr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+       if (addr == MAP_FAILED)
+       {
+               DBG1(DBG_LIB, "mapping '%s' failed: %s", filename, strerror(errno));
+               close(fd);
+               return FALSE;
+       }
+       src = chunk_create(addr, sb.st_size);
+
+       while (fetchline(&src, &line))
+       {
+               char *name, *path;
+               chunk_t token;
+               imc_t *imc;
+
+               line_nr++;
+
+               /* skip comments or empty lines */
+               if (*line.ptr == '#' || !eat_whitespace(&line))
+               {
+                       continue;
+               }
+
+               /* determine keyword */
+               if (!extract_token(&token, ' ', &line))
+               {
+                       DBG1(DBG_TNC, "line %d: keyword must be followed by a space",
+                                                  line_nr);
+                       return FALSE;
+               }
+
+               /* only interested in IMCs */
+               if (!match("IMC", &token))
+               {
+                       continue;
+               }
+
+               /* advance to the IMC name and extract it */
+               if (!extract_token(&token, '"', &line) ||
+                       !extract_token(&token, '"', &line))
+               {
+                       DBG1(DBG_TNC, "line %d: IMC name must be set in double quotes",
+                                                  line_nr);
+                       return FALSE;
+               }
+
+               /* copy the IMC name */
+               name = malloc(token.len + 1);
+               memcpy(name, token.ptr, token.len);
+               name[token.len] = '\0';
+
+               /* advance to the IMC path and extract it */
+               if (!eat_whitespace(&line))
+               {
+                       DBG1(DBG_TNC, "line %d: IMC path is missing", line_nr);
+                       free(name);
+                       return FALSE;
+               }
+               if (!extract_token(&token, ' ', &line))
+               {
+                       token = line;
+               }
+
+               /* copy the IMC path */
+               path = malloc(token.len + 1);
+               memcpy(path, token.ptr, token.len);
+               path[token.len] = '\0';
+
+               /* load and register IMC instance */
+               imc = tnc_imc_create(name, path);
+               if (!imc)
+               {
+                       free(name);
+                       free(path);
+                       return FALSE;
+               }
+               if (!charon->imcs->add(charon->imcs, imc))
+               {
+                       imc->destroy(imc);
+                       return FALSE;
+               }
+               DBG1(DBG_TNC, "IMC \"%s\" loaded from '%s'", name, path);
+       }
+       munmap(addr, sb.st_size);
+       close(fd);
+       return TRUE;
+}
 
 METHOD(plugin_t, destroy, void,
        tnc_imc_plugin_t *this)
@@ -31,9 +152,8 @@ METHOD(plugin_t, destroy, void,
  */
 plugin_t *tnc_imc_plugin_create()
 {
-       char *tnc_config, *pref_lang, *name, *filename;
+       char *tnc_config, *pref_lang;
        tnc_imc_plugin_t *this;
-       imc_t *imc;
 
        INIT(this,
                .plugin = {
@@ -49,27 +169,12 @@ plugin_t *tnc_imc_plugin_create()
        /* Create IMC manager */
        charon->imcs = tnc_imc_manager_create();
 
-       /**
-        * Create, register and initialize IMCs
-        * Abort if one of the IMCs fails to initialize successfully
-        */
+       /* Load IMCs and abort if not all instances initalize successfully */
+       if (!load_imcs(tnc_config))
        {
-               name = "Dummy";
-               filename = "/usr/local/lib/libdummyimc.so";
-               imc = tnc_imc_create(name, filename);
-               if (!imc)
-               {
-                       charon->imcs->destroy(charon->imcs);
-                       free(this);
-                       return NULL;
-               }
-               if (!charon->imcs->add(charon->imcs, imc))
-               {
-                       imc->destroy(imc);
-                       charon->imcs->destroy(charon->imcs);
-                       free(this);
-                       return NULL;
-               }
+               charon->imcs->destroy(charon->imcs);
+               free(this);
+               return NULL;
        }
        return &this->plugin;
 }
index f04ecc7..29161f5 100644 (file)
@@ -33,6 +33,11 @@ struct private_tnc_imv_t {
        imv_t public;
 
        /**
+        * Path of loaded IMV
+        */
+       char *path;
+
+       /**
         * Name of loaded IMV
         */
        char *name;
@@ -129,13 +134,14 @@ METHOD(imv_t, destroy, void,
        dlclose(this->handle);
        free(this->supported_types);
        free(this->name);
+       free(this->path);
        free(this);
 }
 
 /**
  * Described in header.
  */
-imv_t* tnc_imv_create(char *name, char *filename)
+imv_t* tnc_imv_create(char *name, char *path)
 {
        private_tnc_imv_t *this;
 
@@ -148,13 +154,14 @@ imv_t* tnc_imv_create(char *name, char *filename)
                        .type_supported = _type_supported,
                        .destroy = _destroy,
         },
+               .name = name,
+               .path = path,
        );
 
-       this->handle = dlopen(filename, RTLD_NOW);
+       this->handle = dlopen(path, RTLD_NOW);
        if (!this->handle)
        {
-               DBG1(DBG_TNC, "IMV '%s' failed to load from '%s': %s",
-                                          name, filename, dlerror());
+               DBG1(DBG_TNC, "IMV \"%s\" failed to load: %s", name, dlerror());
                free(this);
                return NULL;
        }
@@ -163,7 +170,7 @@ imv_t* tnc_imv_create(char *name, char *filename)
        if (!this->public.initialize)
     {
                DBG1(DBG_TNC, "could not resolve TNC_IMV_Initialize in %s: %s\n",
-                                          filename, dlerror());
+                                          path, dlerror());
                dlclose(this->handle);
                free(this);
                return NULL;
@@ -175,7 +182,7 @@ imv_t* tnc_imv_create(char *name, char *filename)
        if (!this->public.solicit_recommendation)
     {
                DBG1(DBG_TNC, "could not resolve TNC_IMV_SolicitRecommendation in %s: %s\n",
-                                          filename, dlerror());
+                                          path, dlerror());
                dlclose(this->handle);
                free(this);
                return NULL;
@@ -191,12 +198,11 @@ imv_t* tnc_imv_create(char *name, char *filename)
     if (!this->public.provide_bind_function)
        {
                DBG1(DBG_TNC, "could not resolve TNC_IMV_ProvideBindFunction in %s: %s\n",
-                                         filename, dlerror());
+                                         path, dlerror());
                dlclose(this->handle);
                free(this);
                return NULL;
        }
-       this->name = strdup(name);
 
        return &this->public;
 }
index 9e4bc50..00060bb 100644 (file)
@@ -55,8 +55,7 @@ METHOD(imv_manager_t, add, bool,
        if (imv->initialize(imv->get_id(imv), TNC_IFIMV_VERSION_1,
                TNC_IFIMV_VERSION_1, &version) != TNC_RESULT_SUCCESS)
        {
-               DBG1(DBG_TNC, "could not initialize IMV '%s'",
-                                          imv->get_name(imv));
+               DBG1(DBG_TNC, "IMV \"%s\" failed to initialize", imv->get_name(imv));
                return FALSE;
        }
        this->imvs->insert_last(this->imvs, imv);
@@ -65,7 +64,7 @@ METHOD(imv_manager_t, add, bool,
     if (imv->provide_bind_function(imv->get_id(imv), TNC_TNCS_BindFunction)
                        != TNC_RESULT_SUCCESS)
        {
-               DBG1(DBG_TNC, "could not provide bind function for IMV '%s'",
+               DBG1(DBG_TNC, "IMV \"%s\" could failed to obtain bind function",
                                           imv->get_name(imv));
                this->imvs->remove_last(this->imvs, (void**)&imv);
                return FALSE;
@@ -202,7 +201,7 @@ METHOD(imv_manager_t, destroy, void,
                if (imv->terminate &&
                        imv->terminate(imv->get_id(imv)) != TNC_RESULT_SUCCESS)
                {
-                       DBG1(DBG_TNC, "IMV '%s' not terminated successfully",
+                       DBG1(DBG_TNC, "IMV \"%s\" not terminated successfully",
                                                   imv->get_name(imv));
                }
                imv->destroy(imv);
index 4932105..5416265 100644 (file)
 #include "tnc_imv_manager.h"
 #include "tnc_imv.h"
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
 #include <daemon.h>
+#include <utils/lexparser.h>
+
+/**
+ * load IMVs from a configuration file
+ */
+static bool load_imvs(char *filename)
+{
+       int fd, line_nr = 0;
+       chunk_t src, line;
+       struct stat sb;
+       void *addr;
+
+       DBG1(DBG_TNC, "loading IMVs from '%s'", filename);
+       fd = open(filename, O_RDONLY);
+       if (fd == -1)
+       {
+               DBG1(DBG_TNC, "opening configuration file '%s' failed: %s", filename,
+                        strerror(errno));
+               return FALSE;
+       }
+       if (fstat(fd, &sb) == -1)
+       {
+               DBG1(DBG_LIB, "getting file size of '%s' failed: %s", filename,
+                        strerror(errno));
+               close(fd);
+               return FALSE;
+       }
+       addr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+       if (addr == MAP_FAILED)
+       {
+               DBG1(DBG_LIB, "mapping '%s' failed: %s", filename, strerror(errno));
+               close(fd);
+               return FALSE;
+       }
+       src = chunk_create(addr, sb.st_size);
+
+       while (fetchline(&src, &line))
+       {
+               char *name, *path;
+               chunk_t token;
+               imv_t *imv;
+
+               line_nr++;
+
+               /* skip comments or empty lines */
+               if (*line.ptr == '#' || !eat_whitespace(&line))
+               {
+                       continue;
+               }
+
+               /* determine keyword */
+               if (!extract_token(&token, ' ', &line))
+               {
+                       DBG1(DBG_TNC, "line %d: keyword must be followed by a space",
+                                                  line_nr);
+                       return FALSE;
+               }
+
+               /* only interested in IMVs */
+               if (!match("IMV", &token))
+               {
+                       continue;
+               }
+
+               /* advance to the IMV name and extract it */
+               if (!extract_token(&token, '"', &line) ||
+                       !extract_token(&token, '"', &line))
+               {
+                       DBG1(DBG_TNC, "line %d: IMV name must be set in double quotes",
+                                                  line_nr);
+                       return FALSE;
+               }
+
+               /* copy the IMV name */
+               name = malloc(token.len + 1);
+               memcpy(name, token.ptr, token.len);
+               name[token.len] = '\0';
+
+               /* advance to the IMV path and extract it */
+               if (!eat_whitespace(&line))
+               {
+                       DBG1(DBG_TNC, "line %d: IMV path is missing", line_nr);
+                       free(name);
+                       return FALSE;
+               }
+               if (!extract_token(&token, ' ', &line))
+               {
+                       token = line;
+               }
+
+               /* copy the IMV path */
+               path = malloc(token.len + 1);
+               memcpy(path, token.ptr, token.len);
+               path[token.len] = '\0';
+
+               /* load and register IMV instance */
+               imv = tnc_imv_create(name, path);
+               if (!imv)
+               {
+                       free(name);
+                       free(path);
+                       return FALSE;
+               }
+               if (!charon->imvs->add(charon->imvs, imv))
+               {
+                       imv->destroy(imv);
+                       return FALSE;
+               }
+               DBG1(DBG_TNC, "IMV \"%s\" loaded from '%s'", name, path);
+       }
+       munmap(addr, sb.st_size);
+       close(fd);
+       return TRUE;
+}
 
 METHOD(plugin_t, destroy, void,
        tnc_imv_plugin_t *this)
@@ -31,9 +152,8 @@ METHOD(plugin_t, destroy, void,
  */
 plugin_t *tnc_imv_plugin_create()
 {
-       char *tnc_config, *name, *filename;
+       char *tnc_config;
        tnc_imv_plugin_t *this;
-       imv_t *imv;
 
        INIT(this,
                .plugin = {
@@ -47,28 +167,12 @@ plugin_t *tnc_imv_plugin_create()
        /* Create IMV manager */
        charon->imvs = tnc_imv_manager_create();
 
-       /**
-        * Create, register and initialize IMVs
-        * Abort if one of the IMVs fails to initialize successfully
-        */
+       /* Load IMVs and abort if not all instances initalize successfully */
+       if (!load_imvs(tnc_config))
        {
-               name = "Dummy";
-               filename = "/usr/local/lib/libdummyimv.so";
-               imv = tnc_imv_create(name, filename);
-
-               if (!imv)
-               {
-                       charon->imvs->destroy(charon->imvs);
-                       free(this);
-                       return NULL;
-               }
-               if (!charon->imvs->add(charon->imvs, imv))
-               {
-                       imv->destroy(imv);
-                       charon->imvs->destroy(charon->imvs);
-                       free(this);
-                       return NULL;
-               }
+               charon->imvs->destroy(charon->imvs);
+               free(this);
+               return NULL;
        }
        return &this->plugin;
 }