# HG changeset patch # User Sebastien Decugis # Date 1264479783 -32400 # Node ID 79768bf7d208f185aee4d3ee608442896fc9f399 # Parent 645ff1487c23015f34c733d8a587685bd1fd03f7 Completed whitelist extension diff -r 645ff1487c23 -r 79768bf7d208 doc/acl_wl.conf.sample --- a/doc/acl_wl.conf.sample Mon Jan 25 19:07:29 2010 +0900 +++ b/doc/acl_wl.conf.sample Tue Jan 26 13:23:03 2010 +0900 @@ -15,4 +15,5 @@ # ALLOW_IPSEC : we accept implicitly protected connection with with peer (Inband-Security-Id = IPSec) # It is specified for example as: # ALLOW_IPSEC vpn.example.net vpn2.example.net *.vpn.example.net +# These flag take effect from their position, until the end of the line. diff -r 645ff1487c23 -r 79768bf7d208 extensions/acl_wl/CMakeLists.txt --- a/extensions/acl_wl/CMakeLists.txt Mon Jan 25 19:07:29 2010 +0900 +++ b/extensions/acl_wl/CMakeLists.txt Tue Jan 26 13:23:03 2010 +0900 @@ -7,7 +7,7 @@ SET_SOURCE_FILES_PROPERTIES(lex.aw_conf.c aw_conf.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}") # List of source files -SET( APP_TEST_SRC +SET( ACL_WL_SRC acl_wl.h acl_wl.c aw_tree.c @@ -17,4 +17,4 @@ ) # Compile as a module -FD_ADD_EXTENSION(acl_wl ${APP_TEST_SRC}) +FD_ADD_EXTENSION(acl_wl ${ACL_WL_SRC}) diff -r 645ff1487c23 -r 79768bf7d208 extensions/acl_wl/acl_wl.c --- a/extensions/acl_wl/acl_wl.c Mon Jan 25 19:07:29 2010 +0900 +++ b/extensions/acl_wl/acl_wl.c Tue Jan 26 13:23:03 2010 +0900 @@ -70,35 +70,57 @@ } /* Now, if we did not specify any flag, reject */ + if (res == 0) { + TRACE_DEBUG(INFO, "Peer '%s' rejected, only TLS-protected connection is whitelisted.", info->pi_diamid); + /* We don't actually set *auth = -1, leave space for a further extension to validate the peer */ + return 0; + } - + /* Check the Inband-Security-Id value */ + res &= info->runtime.pir_isi; + if (res == 0) { + TRACE_DEBUG(INFO, "Peer '%s' rejected, remotely advertised Inband-Security-Id is not compatible with whitelist flags.", info->pi_diamid); + /* We don't actually set *auth = -1, leave space for a further extension to validate the peer */ + return 0; + } + + /* Ok, the peer is whitelisted */ + *auth = 1; + + /* Now, configure the peer for the authorized mechanism */ + if ((res & PI_SEC_NONE) && (res & PI_SEC_TLS_OLD)) + res = PI_SEC_NONE; /* If we authorized it, we must have an IPsec tunnel setup, no need for TLS in this case */ + + /* Save information about the security mechanism to use after CER/CEA exchange */ + info->config.pic_flags.sec = res; + return 0; } /* entry point */ static int aw_entry(char * conffile) { TRACE_ENTRY("%p", conffile); - CHECK_PARAMS(conffile); /* Parse configuration file */ CHECK_FCT( aw_conf_handle(conffile) ); TRACE_DEBUG(INFO, "Extension ACL_wl initialized with configuration: '%s'", conffile); - aw_tree_dump(); + if (TRACE_BOOL(ANNOYING)) { + aw_tree_dump(); + } /* Register the validator function */ - + CHECK_FCT( fd_peer_validate_register ( aw_validate ) ); + return 0; } /* Unload */ void fd_ext_fini(void) { - /* Unregister the validator function */ - /* Destroy the tree */ - + aw_tree_destroy(); } EXTENSION_ENTRY("acl_wl", aw_entry); diff -r 645ff1487c23 -r 79768bf7d208 extensions/acl_wl/aw_tree.c --- a/extensions/acl_wl/aw_tree.c Mon Jan 25 19:07:29 2010 +0900 +++ b/extensions/acl_wl/aw_tree.c Tue Jan 26 13:23:03 2010 +0900 @@ -229,7 +229,7 @@ /* Check if we have a '*' element already that overlapses */ ti = (struct tree_item *)(senti->next); if (ti->str == NULL) { - fd_log_debug("[acl_wl] Warning: entry '%s' is superseeded by a generic entry at level %d, ignoring.\n", name, lbl); + fd_log_debug("[acl_wl] Warning: entry '%s' is superseeded by a generic entry at label %d, ignoring.\n", name, lbl + 1); return 0; } @@ -286,7 +286,7 @@ /* Check we don't have a '*' entry already */ ti = (struct tree_item *)(senti->next); if (ti->str == NULL) { - fd_log_debug("[acl_wl] Warning: entry '%s' is superseeded by a generic entry at level 0, ignoring.\n", name); + fd_log_debug("[acl_wl] Warning: entry '%s' is superseeded by a generic entry at label 1, ignoring.\n", name); return 0; } @@ -366,7 +366,7 @@ /* Check if we have a '*' element */ ti = (struct tree_item *)(senti->next); if (ti->str == NULL) { - TRACE_DEBUG(FULL, "[acl_wl] %s matched at level %d with a generic entry.", name, lbl); + TRACE_DEBUG(ANNOYING, "[acl_wl] %s matched at label %d with a generic entry.", name, lbl + 1); *result = ti->flags; return 0; } @@ -406,7 +406,7 @@ if (!ti->leaf) return 0; - TRACE_DEBUG(FULL, "[acl_wl] %s matched exactly.", name); + TRACE_DEBUG(ANNOYING, "[acl_wl] %s matched exactly.", name); *result = ti->flags; return 0; } diff -r 645ff1487c23 -r 79768bf7d208 freeDiameter/p_ce.c --- a/freeDiameter/p_ce.c Mon Jan 25 19:07:29 2010 +0900 +++ b/freeDiameter/p_ce.c Tue Jan 26 13:23:03 2010 +0900 @@ -781,12 +781,31 @@ } } - /* Do we send ISI back ? */ + /* Do we agree on ISI ? */ if ( ! fd_cnx_getTLS(peer->p_cnxctx) ) { - if (peer->p_hdr.info.config.pic_flags.sec & PI_SEC_NONE) - isi = PI_SEC_NONE; /* Maybe we should also look at peer->p_hdr.info.runtime.pir_isi here ? */ - else + /* In case of responder, the validate callback must have set the config.pic_flags.sec value already */ + if (!peer->p_hdr.info.config.pic_flags.sec) { + /* The peer did not send the Inband-Security-Id AVP, reject */ + TRACE_DEBUG(INFO, "No security mechanism advertised by peer '%s', sending DIAMETER_NO_COMMON_SECURITY", peer->p_hdr.info.pi_diamid); + ec = "DIAMETER_NO_COMMON_SECURITY"; + fatal = 1; + goto error_abort; + } + + /* Now, check if we agree on the value IPsec */ + if ((peer->p_hdr.info.config.pic_flags.sec & PI_SEC_NONE) && (peer->p_hdr.info.runtime.pir_isi & PI_SEC_NONE)) { + isi = PI_SEC_NONE; + } else if ((peer->p_hdr.info.config.pic_flags.sec & PI_SEC_TLS_OLD) && (peer->p_hdr.info.runtime.pir_isi & PI_SEC_TLS_OLD)) { isi = PI_SEC_TLS_OLD; + } + + /* If we did not find an agreement */ + if (!isi) { + TRACE_DEBUG(INFO, "No common security mechanism with '%s', sending DIAMETER_NO_COMMON_SECURITY", peer->p_hdr.info.pi_diamid); + ec = "DIAMETER_NO_COMMON_SECURITY"; + fatal = 1; + goto error_abort; + } } /* Reply a CEA */ diff -r 645ff1487c23 -r 79768bf7d208 include/freeDiameter/freeDiameter.h --- a/include/freeDiameter/freeDiameter.h Mon Jan 25 19:07:29 2010 +0900 +++ b/include/freeDiameter/freeDiameter.h Tue Jan 26 13:23:03 2010 +0900 @@ -302,7 +302,7 @@ int fd_peer_getbyid( char * diamid, struct peer_hdr ** peer ); /* - * FUNCTION: peer_validate_register + * FUNCTION: fd_peer_validate_register * * PARAMETERS: * peer_validate : Callback as defined bellow. @@ -341,6 +341,8 @@ * structure as parameter (with pir_cert_list set) and returns 0 if the credentials are correct, * or an error code otherwise. If the error code is received, the connection is closed and the * peer is destroyed. + * Note that freeDiameter already achieves some usual checks. The callback may be used to enforce + * additional restrictions. * * RETURN VALUE: * 0 : The authorization decision has been written in the location pointed by auth.