changeset 162:79768bf7d208

Completed whitelist extension
author Sebastien Decugis <sdecugis@nict.go.jp>
date Tue, 26 Jan 2010 13:23:03 +0900
parents 645ff1487c23
children 547f30e9a8ae
files doc/acl_wl.conf.sample extensions/acl_wl/CMakeLists.txt extensions/acl_wl/acl_wl.c extensions/acl_wl/aw_tree.c freeDiameter/p_ce.c include/freeDiameter/freeDiameter.h
diffstat 6 files changed, 62 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- 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.
 
--- 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})
--- 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);
--- 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;
 }
--- 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 */
--- 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.
"Welcome to our mercurial repository"