Mercurial > hg > waaad
changeset 102:b9085fed408e
Security module implemented, to be tested
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Thu, 24 Jul 2008 18:29:32 +0900 |
parents | 54c7f5120aa5 |
children | 5c9a4c18d414 |
files | include/waaad/security-api.h waaad/security.c waaad/security.h waaad/tests/Makefile.am waaad/tests/testsec.c |
diffstat | 5 files changed, 470 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/include/waaad/security-api.h Wed Jul 23 11:32:40 2008 +0900 +++ b/include/waaad/security-api.h Thu Jul 24 18:29:32 2008 +0900 @@ -265,6 +265,7 @@ * 0 : The module is registered. * EINVAL : A parameter is invalid. * ENOMEM : Not enough memory to complete the operation + * EALREADY : Another module is already registered with the same sec_insecid value. */ int sec_register ( sec_module_t * module, sec_mod_hdl_t ** handler );
--- a/waaad/security.c Wed Jul 23 11:32:40 2008 +0900 +++ b/waaad/security.c Thu Jul 24 18:29:32 2008 +0900 @@ -38,39 +38,373 @@ * See security.h and security-api.h for more information on the functions and types involved. */ +#include <pthread.h> #include <errno.h> +#include <string.h> +#include <assert.h> #include "waaad-internal.h" + +/* Type of a security module list item = sec_mod_hdl_t */ +typedef struct _sm_ { + struct _sm_ *next; /* The next in the list. List is ordered by module's insecid */ + struct _sm_ *prev; /* The prev in the list. */ + sec_module_t *sm; /* Pointer to the extension's module */ + int peers; /* Number of peers using this module */ +} _sm_t; + +#define LI_init( _li ) { \ + (_li)->next = (_li); \ + (_li)->prev = (_li); \ +} + +#define LI_isempty( _li ) ( (_li)->next == (_li) ) + +#define LI_remove( _li ) { \ + (_li)->next->prev = (_li)->prev; \ + (_li)->prev->next = (_li)->next; \ + (_li)->next = (_li); \ + (_li)->prev = (_li); \ +} + +#define LI_addafter( _ref, _li ) { \ + assert(LI_isempty( _li )); \ + (_li)->next = (_ref)->next; \ + (_li)->prev = (_ref); \ + (_ref)->next->prev = (_li); \ + (_ref)->next = (_li); \ +} + + +/* The mutex to protect the list */ +static pthread_mutex_t sm_lock; + +/* The list sentinel */ +static _sm_t sm_senti; + + + /* Initialize the module */ int sec_init ( void ) { + int ret = 0; + TRACE_ENTRY( "" ); - TRACE_DEBUG (INFO, "@@@ Not implemented yet." ); + + memset(&sm_senti, 0, sizeof(sm_senti)); + + LI_init(&sm_senti); + + ret = pthread_mutex_init(&sm_lock, NULL); + if (ret != 0) { + TRACE_DEBUG(INFO, "pthread_mutex_lock failed: %s", strerror(ret)); + return ret; + } + return 0; } /* End of the module */ int sec_fini ( void ) { + int ret = 0; + TRACE_ENTRY( "" ); - TRACE_DEBUG (INFO, "@@@ Not implemented yet." ); + + /* Unregister any remaining module */ + while (! LI_isempty( &sm_senti ) ) { + ret = sec_unregister((sec_mod_hdl_t *)sm_senti.next); + if (ret != 0) { + TRACE_DEBUG(INFO, "sec_unregister failed: %s", strerror(ret)); + return ret; + } + } + + ret = pthread_mutex_destroy(&sm_lock); + if (ret != 0) { + TRACE_DEBUG(INFO, "pthread_mutex_destroy failed: %s", strerror(ret)); + return ret; + } + + return 0; +} + +/* Increment a refcount of a module */ +int sec_modlink(sec_mod_hdl_t * module) +{ + int ret = 0; + _sm_t * h = (_sm_t *)module; + + TRACE_ENTRY( "%p" ); + + /* Get the mutex */ + ret = pthread_mutex_lock(&sm_lock); + if (ret != 0) { + TRACE_DEBUG(INFO, "pthread_mutex_lock failed: %s", strerror(ret)); + return ret; + } + + h->peers ++ ; + + /* Release the mutex */ + ret = pthread_mutex_unlock(&sm_lock); + if (ret != 0) { + TRACE_DEBUG(INFO, "pthread_mutex_unlock failed: %s", strerror(ret)); + return ret; + } + + return 0; +} + + +/* Decrement a refcount of a module */ +int sec_modunlink(sec_mod_hdl_t * module) +{ + int ret = 0; + _sm_t * h = (_sm_t *)module; + + TRACE_ENTRY( "%p" ); + + /* Get the mutex */ + ret = pthread_mutex_lock(&sm_lock); + if (ret != 0) { + TRACE_DEBUG(INFO, "pthread_mutex_lock failed: %s", strerror(ret)); + return ret; + } + + h->peers -- ; + + /* Release the mutex */ + ret = pthread_mutex_unlock(&sm_lock); + if (ret != 0) { + TRACE_DEBUG(INFO, "pthread_mutex_unlock failed: %s", strerror(ret)); + return ret; + } + return 0; } + +/* Destroy a list of _sec_item_t */ +int sec_freemodules(_sec_item_t * modules) +{ + int ret = 0; + _sec_item_t *l = modules; + + TRACE_ENTRY( "%p" ); + + while (l != NULL) { + _sec_item_t *i = l; + l = l->next; + ret = sec_modunlink(i->hdl); + if (ret != 0) { + TRACE_DEBUG(INFO, "sec_modunlink failed: %s", strerror(ret)); + return ret; + } + free(i); + } + + return 0; +} + +/* Create a list of _sec_item_t */ +int sec_getmodules(char * diamid, struct sockaddr * sa, _sec_item_t **modules) +{ + int ret = 0; + int prio; + _sec_item_t sentinel = { .next = NULL }; + _sm_t * mod; + + TRACE_ENTRY( "%s %p %p", diamid, sa, modules ); + + if (!diamid || !sa || !modules) { + TRACE_DEBUG(INFO, "Invalid parameter"); + return EINVAL; + } + + *modules = NULL; + + /* Get the mutex */ + ret = pthread_mutex_lock(&sm_lock); + if (ret != 0) { + TRACE_DEBUG(INFO, "pthread_mutex_lock failed: %s", strerror(ret)); + return ret; + } + + /* For each module */ + for (mod = sm_senti.next; mod != &sm_senti; mod = mod->next) { + _sec_item_t * new; + _sec_item_t * prev; + + /* Get the priority of this module */ + ret = mod->sm->sec_is_supported_peer(diamid, sa, &prio); + if (ret != 0) { + TRACE_DEBUG(INFO, "The security module with insecid: $d failed to give a priority to peer %s: %s", + mod->sm->sec_insecid, diamid, strerror(ret)); + continue; + } + + /* does that module handle this peer? */ + if (prio < 0) { + TRACE_DEBUG(FULL, "Security module with insecid: $d will not handle peer %s (%d)", + mod->sm->sec_insecid, diamid, prio); + continue; + } + + /* Create a new element */ + new = (_sec_item_t *) malloc(sizeof(_sec_item_t)); + if (new == NULL) { + log_error("Memory allocation failed: %s\n", strerror(errno)); + TRACE_DEBUG(INFO, "malloc failed"); + ret = ENOMEM; + goto failed; + } + + memset(new, 0, sizeof(_sec_item_t)); + + new->prio = prio; + new->sm = mod->sm; + new->hdl = (sec_mod_hdl_t *) mod; + /* increment the refcount of this module */ + mod->peers ++; + + /* Ok, then put it in the list. the list is in decreasing order */ + for (prev = &sentinel; (prev->next != NULL) && (prev->next->prio > prio); prev = prev->next); + + new->next = prev->next; + prev->next = new; + } + + /* Release the mutex */ + ret = pthread_mutex_unlock(&sm_lock); + if (ret != 0) { + TRACE_DEBUG(INFO, "pthread_mutex_unlock failed: %s", strerror(ret)); + return ret; + } + + /* Save the reference to be returned */ + *modules = sentinel.next; + + return 0; + +failed: + (void)pthread_mutex_unlock(&sm_lock); + + /* destroy the temporary list */ + (void)sec_freemodules(sentinel.next); + + return ret; +} /* Register a new module. */ int sec_register ( sec_module_t * module, sec_mod_hdl_t ** handler ) { + int ret=0, already=0; + _sm_t * prev = &sm_senti; + _sm_t * new = NULL; + TRACE_ENTRY( "%p %p", module, handler ); - TRACE_DEBUG (INFO, "@@@ %s: not implemented yet.", __FUNCTION__ ); - return ENOTSUP; + + /* First check the parameters are valid */ + if ( !handler + || !module + || !module->sec_is_supported_peer + || !module->sec_send_protect + || !module->sec_recv_unprotect ) { + TRACE_DEBUG(INFO, "Invalid parameter"); + return EINVAL; + } + + *handler = NULL; + + /* Create a new entry */ + new = (_sm_t *) malloc(sizeof(_sm_t)); + if (new == NULL) { + log_error("Memory allocation failed: %s\n", strerror(errno)); + TRACE_DEBUG(INFO, "malloc failed"); + return ENOMEM; + } + memset(new, 0, sizeof(_sm_t)); + new->sm = module; + LI_init(new); + + /* Get the list mutex */ + ret = pthread_mutex_lock(&sm_lock); + if (ret != 0) { + TRACE_DEBUG(INFO, "pthread_mutex_lock failed: %s", strerror(ret)); + free(new); + return ret; + } + + /* Search the location in the list */ + while ((prev->next != &sm_senti) && (prev->next->sm->sec_insecid < module->sec_insecid)) + prev = prev->next; + + /* Check we don't have an equal extension already */ + if ((prev->next != &sm_senti) && (prev->next->sm->sec_insecid == module->sec_insecid)) { + TRACE_DEBUG(INFO, "A module with the same Inband-Security-Id value has been found."); + already = 1; + free(new); + } else { + /* Insert in the list */ + LI_addafter(prev, new); + } + + /* Release the mutex */ + ret = pthread_mutex_unlock(&sm_lock); + if (ret != 0) { + TRACE_DEBUG(INFO, "pthread_mutex_unlock failed: %s", strerror(ret)); + return ret; + } + + if (already) + return EALREADY; + + *handler = (sec_mod_hdl_t *)new; + return 0; } /* Remove a registered module. */ int sec_unregister ( sec_mod_hdl_t * handle ) { + int ret=0, cnt; + _sm_t * h = (_sm_t *)handle; + TRACE_ENTRY( "%p", handle ); - TRACE_DEBUG (INFO, "@@@ %s: not implemented yet.", __FUNCTION__ ); - return ENOTSUP; + + if (handle == NULL) { + TRACE_DEBUG(INFO, "Invalid parameter"); + return EINVAL; + } + + /* Lock the list */ + ret = pthread_mutex_lock(&sm_lock); + if (ret != 0) { + TRACE_DEBUG(INFO, "pthread_mutex_lock failed: %s", strerror(ret)); + return ret; + } + + cnt = h->peers; + if (cnt == 0) { + /* Unlink the element */ + LI_remove(h); + } + + /* Release the mutex */ + ret = pthread_mutex_unlock(&sm_lock); + if (ret != 0) { + TRACE_DEBUG(INFO, "pthread_mutex_unlock failed: %s", strerror(ret)); + return ret; + } + + if (cnt != 0) { + TRACE_DEBUG(INFO, "Cannot unregister the module, it is still referenced by some peers"); + return EBUSY; + } + + /* Free the element */ + free(h); + + return 0; }
--- a/waaad/security.h Wed Jul 23 11:32:40 2008 +0900 +++ b/waaad/security.h Thu Jul 24 18:29:32 2008 +0900 @@ -46,6 +46,15 @@ /* Include the API definitions for the module */ #include <waaad/security-api.h> +/* For daemon's internal use only */ +typedef struct _sec_item { + int prio; /* priority of this module -- only to build the list ordered */ + sec_module_t *sm; /* pointer to the security module data */ + sec_mod_hdl_t *hdl; /* pointer to the security module handle */ + struct _sec_item *next; /* The next module available to this peer with lesser priority, if any, or NULL. */ +} _sec_item_t; + + /* The following functions are called only from the daemon */ /* @@ -78,5 +87,70 @@ */ int sec_fini ( void ); +/* + * FUNCTION: sec_getmodules + * + * PARAMETERS: + * diamid : diameter identity of the peer. + * sa : Information about the location and port of the peer. + * modules: upon success, the security modules available for this peer. + * + * DESCRIPTION: + * Get a list of security modules available to a peer, ordered by priority. + * The list must be freed with sec_freemodules. + * If the peer makes a successful CER/CEA exchange with one of the modules, it must call + * sec_modlink on its hdl; then call sec_modunlink when it does not need it anymore. + * + * RETURN VALUE: + * 0 : List created properly + * !0 : an error occurred + */ +int sec_getmodules(char * diamid, struct sockaddr * sa, _sec_item_t **modules); + +/* + * FUNCTION: sec_freemodules + * + * PARAMETERS: + * modules: The list of security modules to free. + * + * DESCRIPTION: + * Release a list of modules returned by sec_getmodules. + * + * RETURN VALUE: + * 0 : List freed properly + * !0 : an error occurred + */ +int sec_freemodules(_sec_item_t * modules); + +/* + * FUNCTION: sec_modlink + * + * PARAMETERS: + * module: A security module to lock for use in a peer, after successful CER/CEA. + * + * DESCRIPTION: + * Increment a refcount on a module. + * + * RETURN VALUE: + * 0 : OK + * !0 : an error occurred + */ +int sec_modlink(sec_mod_hdl_t * module); + +/* + * FUNCTION: sec_modunlink + * + * PARAMETERS: + * module: A security module to unlock after use in a peer. + * + * DESCRIPTION: + * Decrement a refcount on a module. + * + * RETURN VALUE: + * 0 : OK + * !0 : an error occurred + */ +int sec_modunlink(sec_mod_hdl_t * module); + #endif /* _SECURITY_H */
--- a/waaad/tests/Makefile.am Wed Jul 23 11:32:40 2008 +0900 +++ b/waaad/tests/Makefile.am Thu Jul 24 18:29:32 2008 +0900 @@ -39,6 +39,9 @@ # Testing the sessions: testsess_SOURCES = testsess.c tests.h $(WAAADSOURCES) -check_PROGRAMS = testdict testmesg testmeq testsess +# Testing the security: +testsec_SOURCES = testsec.c tests.h $(WAAADSOURCES) + +check_PROGRAMS = testdict testmesg testmeq testsess testsec TESTS = $(check_PROGRAMS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/waaad/tests/testsec.c Thu Jul 24 18:29:32 2008 +0900 @@ -0,0 +1,51 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis <sdecugis@nict.go.jp> * +* * +* Copyright (c) 2008, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +#include "tests.h" + +/* Test for the security module */ + + +/* Main test routine */ +int main(int argc, char *argv[]) +{ + + /* First, initialize the daemon modules */ + INIT_WAAAD(); + + /* That's all for the tests yet */ + PASSTEST(); +} +