Mercurial > hg > waaad
view waaad/security.c @ 328:502470023dc5
Fix possible issue in sec_getmodules
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Thu, 19 Mar 2009 13:27:07 +0900 |
parents | efbca5bc0d9f |
children | e86dba02630a |
line wrap: on
line source
/********************************************************************************************************* * 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. * *********************************************************************************************************/ /* Security module. * * See security.h and security-api.h for more information on the functions and types involved. */ #include "waaad-internal.h" /* Type of a security module list item = sec_mod_hdl_t */ typedef struct { uti_list_t links; /* List is ordered by module's insecid. the "o" field of the list points to the sec_module_t of this item. */ int peers; /* Number of peers using this module */ } _smh_t; #define _SMH( _o ) ((_smh_t *)( _o )) #define _SM( _smh ) ((sec_module_t *)( _LIST(_smh)->o )) /* The mutex to protect the list */ static pthread_mutex_t smh_lock = PTHREAD_MUTEX_INITIALIZER; /* The list sentinel */ static uti_list_t smh_senti; /* Initialize the module */ int sec_init ( void ) { TRACE_ENTRY( "" ); uti_list_init(&smh_senti, NULL); return 0; } /* End of the module */ int sec_fini ( void ) { TRACE_ENTRY( "" ); /* Unregister any remaining module */ while (! IS_LIST_EMPTY( &smh_senti ) ) { CHECK_FCT( sec_unregister((sec_mod_hdl_t *)smh_senti.next) ); } return 0; } /* Increment a refcount of a module */ int sec_modlink(sec_mod_hdl_t * module) { TRACE_ENTRY( "%p" ); /* Get the mutex */ CHECK_POSIX( pthread_mutex_lock(&smh_lock) ); _SMH(module)->peers ++ ; /* Release the mutex */ CHECK_POSIX( pthread_mutex_unlock(&smh_lock) ); return 0; } /* Decrement a refcount of a module */ int sec_modunlink(sec_mod_hdl_t * module) { TRACE_ENTRY( "%p" ); /* Get the mutex */ CHECK_POSIX( pthread_mutex_lock(&smh_lock) ); _SMH(module)->peers -- ; /* This counter is just an indication, we don't use it to free the module when no more user remains. */ /* Release the mutex */ CHECK_POSIX( pthread_mutex_unlock(&smh_lock) ); return 0; } /* Find a module by its insecid */ int sec_module(uint32_t insecid, _sec_item_t *module) { uti_list_t * li; TRACE_ENTRY( "%d %p", insecid, module ); CHECK_PARAMS( module != NULL ); memset(module, 0, sizeof(_sec_item_t)); /* Get the mutex */ CHECK_POSIX( pthread_mutex_lock(&smh_lock) ); /* Seach a corresponding module */ for (li = smh_senti.next; li != &smh_senti; li = li->next) { if (_SM(li)->sec_insecid < insecid) continue; if (_SM(li)->sec_insecid > insecid) break; /* We found it */ uti_list_init(_LIST(module), _SM(li)); module->hdl= (sec_mod_hdl_t *) li; /* increment the refcount of this module */ _SMH(li)->peers ++; break; } /* Release the mutex */ CHECK_POSIX( pthread_mutex_unlock(&smh_lock) ); return (module->hdl == NULL) ? ENOENT : 0; } /* Return the module corresponding to a handler */ int sec_getmodfromhdl(sec_mod_hdl_t * hdl, sec_module_t ** mod) { CHECK_PARAMS( hdl && mod ); *mod = _SM(hdl); return 0; } /* Create a list of _sec_item_t: modules able to handle a peer */ int sec_getmodules(char * diamid, sSA * sa, uti_list_t *modules) { int ret = 0; uti_list_t * li; TRACE_ENTRY( "%s %p %p", diamid, sa, modules ); CHECK_PARAMS( diamid && sa && modules ); /* Initialize the module list */ uti_list_init(modules, NULL); /* Get the mutex */ CHECK_POSIX( pthread_mutex_lock(&smh_lock) ); /* For each module */ for (li = smh_senti.next; li != &smh_senti; li = li->next) { _sec_item_t * new; uti_list_t * prev; int prio; /* Get the priority of this module */ ret = _SM(li)->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", _SM(li)->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)", _SM(li)->sec_insecid, diamid, prio); continue; } /* Create a new element */ CHECK_MALLOC_DO( new = (_sec_item_t *) malloc(sizeof(_sec_item_t)), { ret = ENOMEM; goto failed; } ); memset(new, 0, sizeof(_sec_item_t)); uti_list_init(&new->chain, _SM(li)); new->prio = prio; new->hdl = _SMH(li); /* Ok, then save this new element in the returned module list. the list is in decreasing prio order */ for (prev = modules; (prev->next != modules) && (((_sec_item_t *)(prev->next))->prio > prio); prev = prev->next) /* just loop */; /* then insert */ uti_list_insert_after(prev, _LIST(new)); } /* Release the mutex */ CHECK_POSIX( pthread_mutex_unlock(&smh_lock) ); return 0; failed: CHECK_POSIX( pthread_mutex_unlock(&smh_lock) ); return ret; } /* Register a new module. */ int sec_register ( sec_module_t * module, sec_mod_hdl_t ** handler ) { int ret=0, already=0; uti_list_t * prev = &smh_senti; _smh_t * new = NULL; TRACE_ENTRY( "%p %p", module, handler ); /* First check the parameters are valid */ CHECK_PARAMS( handler && module && module->sec_is_supported_peer && module->sec_send_protect && module->sec_recv_unprotect ); *handler = NULL; /* Create a new entry */ CHECK_MALLOC( new = (_smh_t *) malloc(sizeof(_smh_t)) ); memset(new, 0, sizeof(_smh_t)); uti_list_init(&new->links, (void *)module); /* Get the list mutex */ CHECK_POSIX_DO( ret = pthread_mutex_lock(&smh_lock), { free(new); return ret; } ); /* Search the location in the list */ while ((prev->next != &smh_senti) && (_SM(prev->next)->sec_insecid < module->sec_insecid)) prev = prev->next; /* Check we don't have an extension with equal insecid already */ if ((prev->next != &smh_senti) && (_SM(prev->next)->sec_insecid == module->sec_insecid)) { log_error("More than one security extension with Inband-Security-Id value '%d' is registering.\n", 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 */ uti_list_insert_after(prev, &new->links); } /* Release the mutex */ CHECK_POSIX( pthread_mutex_unlock(&smh_lock) ); 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 cnt; TRACE_ENTRY( "%p", handle ); CHECK_PARAMS( handle ); /* Lock the list */ CHECK_POSIX( pthread_mutex_lock(&smh_lock) ); cnt = _SMH(handle)->peers; if (cnt == 0) { /* Unlink the element */ uti_list_unlink(_LIST(handle)); } /* Release the mutex */ CHECK_POSIX( pthread_mutex_unlock(&smh_lock) ); if (cnt != 0) { TRACE_DEBUG(INFO, "Cannot unregister the module, it is still referenced by some peers"); return EBUSY; } /* Free the element */ free(handle); return 0; }