From: Andreas Steffen Date: Wed, 10 Nov 2010 09:57:01 +0000 (+0100) Subject: read IMC/IMV configurations from /etc/tnc_config X-Git-Tag: 4.5.1~539 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7ead19a700a4c8afe2e838876fec309c59a03692;p=thirdparty%2Fstrongswan.git read IMC/IMV configurations from /etc/tnc_config --- diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc.c b/src/libcharon/plugins/tnc_imc/tnc_imc.c index e0f06e57df..fa5e2e499e 100644 --- a/src/libcharon/plugins/tnc_imc/tnc_imc.c +++ b/src/libcharon/plugins/tnc_imc/tnc_imc.c @@ -32,6 +32,11 @@ struct private_tnc_imc_t { */ imc_t public; + /** + * Path of loaded IMC + */ + char *path; + /** * Name of loaded IMC */ @@ -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; } diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c index d78c92a259..f8761672f0 100644 --- a/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c +++ b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c @@ -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); diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c b/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c index 05d7b7ace3..683efc10b6 100644 --- a/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c +++ b/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c @@ -17,7 +17,128 @@ #include "tnc_imc_manager.h" #include "tnc_imc.h" +#include +#include +#include +#include +#include +#include + #include +#include + +/** + * 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; } diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv.c b/src/libcharon/plugins/tnc_imv/tnc_imv.c index f04ecc71ed..29161f5134 100644 --- a/src/libcharon/plugins/tnc_imv/tnc_imv.c +++ b/src/libcharon/plugins/tnc_imv/tnc_imv.c @@ -32,6 +32,11 @@ struct private_tnc_imv_t { */ imv_t public; + /** + * Path of loaded IMV + */ + char *path; + /** * Name of loaded IMV */ @@ -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; } diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c index 9e4bc50d7e..00060bbce5 100644 --- a/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c @@ -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); diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c b/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c index 49321051f8..54162656b8 100644 --- a/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c @@ -17,7 +17,128 @@ #include "tnc_imv_manager.h" #include "tnc_imv.h" +#include +#include +#include +#include +#include +#include + #include +#include + +/** + * 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; }