diff options
Diffstat (limited to 'src/charon-tkm')
-rw-r--r-- | src/charon-tkm/Makefile.in | 2 | ||||
-rw-r--r-- | src/charon-tkm/src/charon-tkm.c | 47 | ||||
-rw-r--r-- | src/charon-tkm/src/tkm/tkm_id_manager.c | 48 | ||||
-rw-r--r-- | src/charon-tkm/src/tkm/tkm_id_manager.h | 20 | ||||
-rw-r--r-- | src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 8 | ||||
-rw-r--r-- | src/charon-tkm/src/tkm/tkm_keymat.c | 19 | ||||
-rw-r--r-- | src/charon-tkm/src/tkm/tkm_private_key.c | 3 | ||||
-rw-r--r-- | src/charon-tkm/src/tkm/tkm_public_key.c | 3 | ||||
-rw-r--r-- | src/charon-tkm/tests/id_manager_tests.c | 97 | ||||
-rw-r--r-- | src/charon-tkm/tests/kernel_sad_tests.c | 4 |
10 files changed, 201 insertions, 50 deletions
diff --git a/src/charon-tkm/Makefile.in b/src/charon-tkm/Makefile.in index 258f33b0f..c2762f031 100644 --- a/src/charon-tkm/Makefile.in +++ b/src/charon-tkm/Makefile.in @@ -161,9 +161,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index a4d4d0cf5..7f014237a 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2017 Tobias Brunner * Copyright (C) 2012 Reto Buerki * Copyright (C) 2012 Adrian-Ken Rueegsegger - * Hochschule fuer Technik Rapperswil + * HSR 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 @@ -24,6 +24,7 @@ #include <sys/types.h> #include <unistd.h> #include <libgen.h> +#include <fcntl.h> #include <errno.h> #include <daemon.h> @@ -50,6 +51,11 @@ static tkm_listener_t *listener; /** + * Name of the daemon + */ +static char *dmn_name; + +/** * PID file, in which charon-tkm stores its process id */ static char *pidfile_name = NULL; @@ -186,8 +192,11 @@ static bool check_pidfile() pid = atoi(buf); } fclose(pidfile); + pidfile = NULL; if (pid && kill(pid, 0) == 0) - { /* such a process is running */ + { + DBG1(DBG_DMN, "%s already running ('%s' exists)", dmn_name, + pidfile_name); return TRUE; } } @@ -199,13 +208,31 @@ static bool check_pidfile() pidfile = fopen(pidfile_name, "w"); if (pidfile) { - ignore_result(fchown(fileno(pidfile), + int fd; + + fd = fileno(pidfile); + if (fd == -1) + { + DBG1(DBG_DMN, "unable to determine fd for '%s'", pidfile_name); + return TRUE; + } + if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) + { + DBG1(DBG_LIB, "setting FD_CLOEXEC for '%s' failed: %s", + pidfile_name, strerror(errno)); + } + ignore_result(fchown(fd, lib->caps->get_uid(lib->caps), lib->caps->get_gid(lib->caps))); fprintf(pidfile, "%d\n", getpid()); fflush(pidfile); + return FALSE; + } + else + { + DBG1(DBG_DMN, "unable to create pidfile '%s'", pidfile_name); + return TRUE; } - return FALSE; } /** @@ -221,15 +248,15 @@ static void unlink_pidfile() { ignore_result(ftruncate(fileno(pidfile), 0)); fclose(pidfile); + unlink(pidfile_name); } - unlink(pidfile_name); } + /** * Main function, starts TKM backend. */ int main(int argc, char *argv[]) { - char *dmn_name; if (argc > 0 && strlen(argv[0]) > 0) { dmn_name = basename(argv[0]); @@ -322,8 +349,6 @@ int main(int argc, char *argv[]) if (check_pidfile()) { - DBG1(DBG_DMN, "%s already running (\"%s\" exists)", dmn_name, - pidfile_name); goto deinit; } @@ -372,8 +397,6 @@ int main(int argc, char *argv[]) /* main thread goes to run loop */ run(); - unlink_pidfile(); - free(pidfile_name); status = 0; charon->bus->remove_listener(charon->bus, &listener->listener); listener->destroy(listener); @@ -384,6 +407,8 @@ deinit: destroy_dh_mapping(); libcharon_deinit(); tkm_deinit(); + unlink_pidfile(); + free(pidfile_name); library_deinit(); return status; } diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.c b/src/charon-tkm/src/tkm/tkm_id_manager.c index d8ff6753f..9a2ede03e 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.c +++ b/src/charon-tkm/src/tkm/tkm_id_manager.c @@ -43,7 +43,7 @@ struct private_tkm_id_manager_t { /** * Per-kind array of free context ids */ - bool* ctxids[TKM_CTX_MAX]; + int* ctxids[TKM_CTX_MAX]; /** * Per-kind context limits. @@ -85,9 +85,9 @@ METHOD(tkm_id_manager_t, acquire_id, int, this->locks[kind]->write_lock(this->locks[kind]); for (j = 0; j < this->limits[kind]; j++) { - if (!this->ctxids[kind][j]) + if (this->ctxids[kind][j] == 0) { - this->ctxids[kind][j] = true; + this->ctxids[kind][j] = 1; id = j + 1; break; } @@ -103,24 +103,55 @@ METHOD(tkm_id_manager_t, acquire_id, int, return id; } -METHOD(tkm_id_manager_t, release_id, bool, +METHOD(tkm_id_manager_t, acquire_ref, bool, + private_tkm_id_manager_t * const this, const tkm_context_kind_t kind, + const int ref_id) +{ + const int idx = ref_id - 1; + + if (!is_valid_kind(kind)) + { + DBG1(DBG_LIB, "tried to acquire reference for invalid context kind '%d'", + kind); + return FALSE; + } + + if (ref_id < 1 || (uint64_t)ref_id > this->limits[kind]) + { + DBG1(DBG_LIB, "tried to acquire reference for context id %d out of " + "bounds (max %llu)", ref_id, this->limits[kind]); + return FALSE; + } + + this->locks[kind]->write_lock(this->locks[kind]); + this->ctxids[kind][idx]++; + this->locks[kind]->unlock(this->locks[kind]); + + return TRUE; +} + +METHOD(tkm_id_manager_t, release_id, int, private_tkm_id_manager_t * const this, const tkm_context_kind_t kind, const int id) { const int idx = id - 1; + int refcount = 0; if (!is_valid_kind(kind)) { DBG1(DBG_LIB, "tried to release id %d for invalid context kind '%d'", id, kind); - return FALSE; + return -1; } this->locks[kind]->write_lock(this->locks[kind]); - this->ctxids[kind][idx] = false; + if (this->ctxids[kind][idx] > 0) + { + refcount = --this->ctxids[kind][idx]; + } this->locks[kind]->unlock(this->locks[kind]); - return TRUE; + return refcount; } @@ -147,6 +178,7 @@ tkm_id_manager_t *tkm_id_manager_create(const tkm_limits_t limits) INIT(this, .public = { .acquire_id = _acquire_id, + .acquire_ref = _acquire_ref, .release_id = _release_id, .destroy = _destroy, }, @@ -155,7 +187,7 @@ tkm_id_manager_t *tkm_id_manager_create(const tkm_limits_t limits) for (i = 0; i < TKM_CTX_MAX; i++) { this->limits[i] = limits[i]; - this->ctxids[i] = calloc(limits[i], sizeof(bool)); + this->ctxids[i] = calloc(limits[i], sizeof(int)); this->locks[i] = rwlock_create(RWLOCK_TYPE_DEFAULT); DBG2(DBG_LIB, "%N initialized, %llu slot(s)", tkm_context_kind_names, i, limits[i]); diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.h b/src/charon-tkm/src/tkm/tkm_id_manager.h index 0fc9ff8ef..1c48b57f1 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.h +++ b/src/charon-tkm/src/tkm/tkm_id_manager.h @@ -74,15 +74,27 @@ struct tkm_id_manager_t { const tkm_context_kind_t kind); /** + * Acquire reference to given context id for a specific context kind. + * + * @param kind kind of context id + * @param ref_id id to acquire a reference for + * @return TRUE if reference could be acquired, + * FALSE otherwise + */ + bool (*acquire_ref)(tkm_id_manager_t * const this, + const tkm_context_kind_t kind, + const int ref_id); + + /** * Release a previously acquired context id. * * @param kind kind of context id to release * @param id id to release - * @return TRUE if id was released, FALSE otherwise + * @return current refcount if id was released, -1 otherwise */ - bool (*release_id)(tkm_id_manager_t * const this, - const tkm_context_kind_t kind, - const int id); + int (*release_id)(tkm_id_manager_t * const this, + const tkm_context_kind_t kind, + const int id); /** * Destroy a tkm_id_manager instance. diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index 5decde92b..48dd40aa5 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -134,6 +134,12 @@ METHOD(kernel_ipsec_t, add_sa, status_t, } esa_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ESA); + if (esa_id == 0) + { + DBG1(DBG_KNL, "unable to acquire esa context id"); + goto esa_id_failure; + } + if (!tkm->sad->insert(tkm->sad, esa_id, data->reqid, local, peer, spi_loc, spi_rem, id->proto)) { @@ -193,9 +199,11 @@ METHOD(kernel_ipsec_t, add_sa, status_t, return SUCCESS; failure: + ike_esa_reset(esa_id); tkm->sad->remove(tkm->sad, esa_id); sad_failure: tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_ESA, esa_id); +esa_id_failure: chunk_free(&esa.nonce_i); chunk_free(&esa.nonce_r); return FAILED; diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index a24760445..ed5366c2c 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -279,8 +279,15 @@ METHOD(keymat_v2_t, derive_ike_keys, bool, } isa_info = *((isa_info_t *)(rekey_skd.ptr)); DBG1(DBG_IKE, "deriving IKE keys (parent_isa: %llu, ae: %llu, nc: %llu," - "dh: %llu, spi_loc: %llx, spi_rem: %llx)", isa_info.parent_isa_id, + " dh: %llu, spi_loc: %llx, spi_rem: %llx)", isa_info.parent_isa_id, isa_info.ae_id, nc_id, dh_id, spi_loc, spi_rem); + + if (!tkm->idmgr->acquire_ref(tkm->idmgr, TKM_CTX_AE, isa_info.ae_id)) + { + DBG1(DBG_IKE, "unable to acquire reference for ae: %llu", + isa_info.ae_id); + return FALSE; + } this->ae_ctx_id = isa_info.ae_id; res = ike_isa_create_child(this->isa_ctx_id, isa_info.parent_isa_id, 1, dh_id, nc_id, nonce_rem, this->initiator, @@ -416,11 +423,6 @@ METHOD(keymat_v2_t, get_skd, pseudo_random_function_t, *skd = chunk_create((u_char *)isa_info, sizeof(isa_info_t)); - /* - * remove ae context id, since control has now been handed over to the new - * IKE SA keymat - */ - this->ae_ctx_id = 0; return PRF_HMAC_SHA2_512; } @@ -462,11 +464,12 @@ METHOD(keymat_t, destroy, void, /* only reset ae context if set */ if (this->ae_ctx_id != 0) { - if (ike_ae_reset(this->ae_ctx_id) != TKM_OK) + int count; + count = tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_AE, this->ae_ctx_id); + if (count == 0 && ike_ae_reset(this->ae_ctx_id) != TKM_OK) { DBG1(DBG_IKE, "failed to reset AE context %d", this->ae_ctx_id); } - tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_AE, this->ae_ctx_id); } DESTROY_IF(this->hash_algorithms); diff --git a/src/charon-tkm/src/tkm/tkm_private_key.c b/src/charon-tkm/src/tkm/tkm_private_key.c index db57ec1c7..891b579ee 100644 --- a/src/charon-tkm/src/tkm/tkm_private_key.c +++ b/src/charon-tkm/src/tkm/tkm_private_key.c @@ -14,6 +14,7 @@ * for more details. */ +#include <library.h> #include <utils/debug.h> #include <tkm/constants.h> #include <tkm/client.h> @@ -58,7 +59,7 @@ METHOD(private_key_t, get_type, key_type_t, } METHOD(private_key_t, sign, bool, - private_tkm_private_key_t *this, signature_scheme_t scheme, + private_tkm_private_key_t *this, signature_scheme_t scheme, void *params, chunk_t data, chunk_t *signature) { signature_type sig; diff --git a/src/charon-tkm/src/tkm/tkm_public_key.c b/src/charon-tkm/src/tkm/tkm_public_key.c index 9ebdc29e6..2a14a9bdd 100644 --- a/src/charon-tkm/src/tkm/tkm_public_key.c +++ b/src/charon-tkm/src/tkm/tkm_public_key.c @@ -14,6 +14,7 @@ * for more details. */ +#include <library.h> #include <utils/debug.h> #include "tkm_public_key.h" @@ -53,7 +54,7 @@ METHOD(public_key_t, get_type, key_type_t, } METHOD(public_key_t, verify, bool, - private_tkm_public_key_t *this, signature_scheme_t scheme, + private_tkm_public_key_t *this, signature_scheme_t scheme, void *params, chunk_t data, chunk_t signature) { return TRUE; diff --git a/src/charon-tkm/tests/id_manager_tests.c b/src/charon-tkm/tests/id_manager_tests.c index 8157496ca..fb5e56a05 100644 --- a/src/charon-tkm/tests/id_manager_tests.c +++ b/src/charon-tkm/tests/id_manager_tests.c @@ -84,21 +84,85 @@ START_TEST(test_acquire_id_same) } END_TEST -START_TEST(test_release_id) +START_TEST(test_acquire_ref) { int i, id = 0; - bool released = false; + bool acquired = false; + tkm_id_manager_t *idmgr = tkm_id_manager_create(limits); + + for (i = 0; i < TKM_CTX_MAX; i++) + { + id = idmgr->acquire_id(idmgr, i); + acquired = idmgr->acquire_ref(idmgr, i, id); + fail_unless(acquired, "Error acquiring reference context kind %d", i); + + /* Reset test variable */ + acquired = false; + } + + idmgr->destroy(idmgr); +} +END_TEST + +START_TEST(test_acquire_ref_invalid_kind) +{ + bool acquired; + tkm_id_manager_t *idmgr = tkm_id_manager_create(limits); + + acquired = idmgr->acquire_ref(idmgr, TKM_CTX_MAX, 1); + fail_if(acquired, "Acquired reference for invalid context kind %d", TKM_CTX_MAX); + + /* Reset test variable */ + acquired = 0; + + acquired = idmgr->acquire_ref(idmgr, -1, 1); + fail_if(acquired, "Acquired reference for invalid context kind %d", -1); + + idmgr->destroy(idmgr); +} +END_TEST + +START_TEST(test_acquire_ref_invalid_id) +{ + int i; + bool acquired; + tkm_id_manager_t *idmgr = tkm_id_manager_create(limits); + + for (i = 0; i < TKM_CTX_MAX; i++) + { + acquired = idmgr->acquire_ref(idmgr, i, -1); + fail_if(acquired, + "Acquired reference for negative id of context kind %d", i); + + /* Reset test variable */ + acquired = false; + + acquired = idmgr->acquire_ref(idmgr, i, limits[i] + 1); + fail_if(acquired, + "Acquired reference exceeding limit of context kind %d", i); + + /* Reset test variable */ + acquired = false; + } + + idmgr->destroy(idmgr); +} +END_TEST + +START_TEST(test_release_id) +{ + int i, count, id = 0; tkm_id_manager_t *idmgr = tkm_id_manager_create(limits); for (i = 0; i < TKM_CTX_MAX; i++) { id = idmgr->acquire_id(idmgr, i); - released = idmgr->release_id(idmgr, i, id); + count = idmgr->release_id(idmgr, i, id); - fail_unless(released, "Error releasing id of context kind %d", i); + fail_unless(count == 0, "Error releasing id of context kind %d", i); - /* Reset released variable */ - released = FALSE; + /* Reset count variable */ + count = 0; } idmgr->destroy(idmgr); @@ -107,17 +171,17 @@ END_TEST START_TEST(test_release_id_invalid_kind) { - bool released = TRUE; + int count = 0; tkm_id_manager_t *idmgr = tkm_id_manager_create(limits); - released = idmgr->release_id(idmgr, TKM_CTX_MAX, 1); - fail_if(released, "Released id for invalid context kind %d", TKM_CTX_MAX); + count = idmgr->release_id(idmgr, TKM_CTX_MAX, 1); + fail_if(count >= 0, "Released id for invalid context kind %d", TKM_CTX_MAX); /* Reset test variable */ - released = TRUE; + count = 0; - released = idmgr->release_id(idmgr, -1, 1); - fail_if(released, "Released id for invalid context kind %d", -1); + count = idmgr->release_id(idmgr, -1, 1); + fail_if(count >= 0, "Released id for invalid context kind %d", -1); idmgr->destroy(idmgr); } @@ -125,11 +189,11 @@ END_TEST START_TEST(test_release_id_nonexistent) { - bool released = FALSE; + int count = 0; tkm_id_manager_t *idmgr = tkm_id_manager_create(limits); - released = idmgr->release_id(idmgr, TKM_CTX_NONCE, 1); - fail_unless(released, "Release of nonexistent id failed"); + count = idmgr->release_id(idmgr, TKM_CTX_NONCE, 1); + fail_unless(count == 0, "Release of nonexistent id failed"); idmgr->destroy(idmgr); } @@ -150,6 +214,9 @@ Suite *make_id_manager_tests() tcase_add_test(tc, test_acquire_id); tcase_add_test(tc, test_acquire_id_invalid_kind); tcase_add_test(tc, test_acquire_id_same); + tcase_add_test(tc, test_acquire_ref); + tcase_add_test(tc, test_acquire_ref_invalid_kind); + tcase_add_test(tc, test_acquire_ref_invalid_id); suite_add_tcase(s, tc); tc = tcase_create("release"); diff --git a/src/charon-tkm/tests/kernel_sad_tests.c b/src/charon-tkm/tests/kernel_sad_tests.c index 39d8a790a..59ff77b68 100644 --- a/src/charon-tkm/tests/kernel_sad_tests.c +++ b/src/charon-tkm/tests/kernel_sad_tests.c @@ -123,11 +123,11 @@ START_TEST(test_remove) tkm_kernel_sad_t *sad = tkm_kernel_sad_create(); fail_unless(sad->insert(sad, 23, 54, addr, addr, 27, 42, 50), "Error inserting SAD entry"); - fail_unless(sad->get_esa_id(sad, addr, addr, 42, 50) == 23, + fail_unless(sad->get_esa_id(sad, addr, addr, 42, 50, FALSE) == 23, "Error getting esa id"); fail_unless(sad->remove(sad, 23), "Error removing SAD entry"); - fail_unless(sad->get_esa_id(sad, addr, addr, 42, 50) == 0, + fail_unless(sad->get_esa_id(sad, addr, addr, 42, 50, FALSE) == 0, "Got esa id for removed SAD entry"); sad->destroy(sad); addr->destroy(addr); |