[Asterisk-code-review] res_rtp_asterisk: implement ACL mechanism for ICE and STUN addresses. (asterisk[13])

Jaco Kroon asteriskteam at digium.com
Wed Nov 27 09:55:33 CST 2019


Jaco Kroon has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/13309 )


Change subject: res_rtp_asterisk: implement ACL mechanism for ICE and STUN addresses.
......................................................................

res_rtp_asterisk: implement ACL mechanism for ICE and STUN addresses.

A pure blacklist is not good enough, we need a whitelist mechanism as
well, and the simplest way to do that is to re-use existing ACL
infrastructure.

Without this patch some of my systems would attempt to load ~300
addresses into an ICE response.  With this patch it just provides
the two intended addresses.

Change-Id: Id57a8df51fcfd3bd85ea67c489c85c6c3ecd7b30
Signed-off-by: Jaco Kroon <jaco at uls.co.za>
---
M configs/samples/rtp.conf.sample
M res/res_rtp_asterisk.c
2 files changed, 84 insertions(+), 6 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/09/13309/1

diff --git a/configs/samples/rtp.conf.sample b/configs/samples/rtp.conf.sample
index a94707e..bb806d3 100644
--- a/configs/samples/rtp.conf.sample
+++ b/configs/samples/rtp.conf.sample
@@ -76,6 +76,13 @@
 ;
 ; stun_blacklist =
 ;
+; As an alternative to the stun_blacklist you can also use named ACLs.  Note
+; that both the stun_blacklist and the ACL needs to allow the address.
+;
+; stun_acl = named_acl
+; stun_deny = 0.0.0.0/0
+; stun_permit = 1.2.3.4/32
+;
 ; Hostname or address for the TURN server to be used as a relay. The port
 ; number is optional. If omitted the default value of 3478 will be used.
 ; This option is disabled by default.
@@ -102,6 +109,13 @@
 ;
 ; ice_blacklist =
 ;
+; As an alternative to the ice_blacklist you can also use named ACLs.  Note
+; that both the ice_blacklist and the ACL needs to allow the address.
+;
+; ice_acl = named_acl
+; ice_deny = 0.0.0.0/0
+; ice_permit = 1.2.3.4/32
+;
 ; The MTU to use for DTLS packet fragmentation. This option is set to 1200
 ; by default. The minimum MTU is 256.
 ; dtls_mtu = 1200
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 8154c2c..fa3c836 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -81,6 +81,7 @@
 #include "asterisk/test.h"
 #ifdef HAVE_PJPROJECT
 #include "asterisk/res_pjproject.h"
+#include "asterisk/security_events.h"
 #endif
 
 #define MAX_TIMESTAMP_SKEW	640
@@ -199,14 +200,18 @@
 static int turnport = DEFAULT_TURN_PORT;
 static pj_str_t turnusername;
 static pj_str_t turnpassword;
+static struct stasis_subscription *acl_change_sub = NULL;
 
 static struct ast_ha *ice_blacklist = NULL;    /*!< Blacklisted ICE networks */
 static ast_rwlock_t ice_blacklist_lock = AST_RWLOCK_INIT_VALUE;
 
+static struct ast_acl_list *ice_acl = NULL;
+
 /*! Blacklisted networks for STUN requests */
 static struct ast_ha *stun_blacklist = NULL;
 static ast_rwlock_t stun_blacklist_lock = AST_RWLOCK_INIT_VALUE;
 
+static struct ast_acl_list *stun_acl = NULL;
 
 /*! \brief Pool factory used by pjlib to allocate memory. */
 static pj_caching_pool cachingpool;
@@ -2961,6 +2966,38 @@
 }
 
 #ifdef HAVE_PJPROJECT
+static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message);
+
+/*!
+ * \internal
+ * \brief Resets and loads an ACL from the configuration
+ *
+ * \return Nothing
+ */
+static void rtp_load_acl(struct ast_config *cfg, const char* section, const char* prefix, struct ast_acl_list **acl)
+{
+	static const char *sense[] = { "acl", "deny", "permit", NULL };
+
+	int acl_subscription_flag = 0, i;
+	const char *val;
+	char* opt;
+	*acl = ast_free_acl_list(*acl);
+
+	for (i = 0; sense[i]; ++i) {
+		ast_asprintf(&opt, "%s%s", prefix, *sense);
+		if ((val = ast_variable_retrieve(cfg, "general", opt))) {
+			ast_append_acl(sense[i], val, acl, NULL, &acl_subscription_flag);
+		}
+	}
+
+	if (acl_subscription_flag && !acl_change_sub) {
+		acl_change_sub = stasis_subscribe(ast_security_topic(),
+			acl_change_stasis_cb, NULL);
+		stasis_subscription_accept_message_type(acl_change_sub, ast_named_acl_change_type());
+		stasis_subscription_set_filter(acl_change_sub, STASIS_SUBSCRIPTION_FILTER_SELECTIVE);
+	}
+}
+
 /*!
  * \internal
  * \brief Checks an address against the ICE blacklist
@@ -2972,11 +3009,12 @@
  */
 static int rtp_address_is_ice_blacklisted(const pj_sockaddr_t *address)
 {
-	char buf[PJ_INET6_ADDRSTRLEN];
 	struct ast_sockaddr saddr;
 	int result = 1;
 
-	ast_sockaddr_parse(&saddr, pj_sockaddr_print(address, buf, sizeof(buf), 0), 0);
+	if (ice_acl && ast_apply_acl(ice_acl, address, "RTP ICE ACL: ") == AST_SENSE_DENY) {
+		return result;
+	}
 
 	ast_rwlock_rdlock(&ice_blacklist_lock);
 	if (!ice_blacklist || (ast_apply_ha(ice_blacklist, &saddr) == AST_SENSE_ALLOW)) {
@@ -3003,6 +3041,10 @@
 {
 	int result = 1;
 
+	if (stun_acl && ast_apply_acl(stun_acl, addr, "RTP STUN ACL: ") == AST_SENSE_DENY) {
+		return result;
+	}
+
 	ast_rwlock_rdlock(&stun_blacklist_lock);
 	if (!stun_blacklist
 		|| ast_apply_ha(stun_blacklist, addr) == AST_SENSE_ALLOW) {
@@ -6673,11 +6715,11 @@
 }
 #endif
 
-static int rtp_reload(int reload)
+static int rtp_reload(int reload, int by_external_config)
 {
 	struct ast_config *cfg;
 	const char *s;
-	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
+	struct ast_flags config_flags = { (reload && !by_external_config) ? CONFIG_FLAG_FILEUNCHANGED : 0 };
 
 #ifdef HAVE_PJPROJECT
 	struct ast_variable *var;
@@ -6852,11 +6894,19 @@
 	}
 	AST_RWLIST_UNLOCK(&host_candidates);
 
+	acl_change_sub = stasis_unsubscribe_and_join(acl_change_sub);
+
 	/* Read ICE blacklist configuration lines */
 	blacklist_config_load(cfg, "ice_blacklist", &ice_blacklist_lock, &ice_blacklist);
 
+	/* Read ICE ACL configuration lines */
+	rtp_load_acl(cfg, "general", "ice_", &ice_acl);
+
 	/* Read STUN blacklist configuration lines */
 	blacklist_config_load(cfg, "stun_blacklist", &stun_blacklist_lock, &stun_blacklist);
+
+	/* Read STUN ACL configuration lines */
+	rtp_load_acl(cfg, "general", "stun_", &stun_acl);
 #endif
 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
 	if ((s = ast_variable_retrieve(cfg, "general", "dtls_mtu"))) {
@@ -6881,7 +6931,7 @@
 
 static int reload_module(void)
 {
-	rtp_reload(1);
+	rtp_reload(1, 0);
 	return 0;
 }
 
@@ -6899,6 +6949,16 @@
 	ast_pjproject_caching_pool_destroy(&cachingpool);
 	pj_shutdown();
 }
+
+static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
+{
+	if (stasis_message_type(message) != ast_named_acl_change_type()) {
+		return;
+	}
+
+	/* There is no simple way to just reload the ACLs, so just execute a forced reload. */
+	rtp_reload(1, 1);
+}
 #endif
 
 static int load_module(void)
@@ -6979,7 +7039,7 @@
 		return AST_MODULE_LOAD_DECLINE;
 	}
 
-	rtp_reload(0);
+	rtp_reload(0, 0);
 
 	return AST_MODULE_LOAD_SUCCESS;
 }
@@ -6999,6 +7059,10 @@
 	host_candidate_overrides_clear();
 	pj_thread_register_check();
 	rtp_terminate_pjproject();
+
+	acl_change_sub = stasis_unsubscribe_and_join(acl_change_sub);
+	ice_acl = ast_free_acl_list(ice_acl);
+	stun_acl = ast_free_acl_list(stun_acl);
 #endif
 
 	return 0;

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/13309
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 13
Gerrit-Change-Id: Id57a8df51fcfd3bd85ea67c489c85c6c3ecd7b30
Gerrit-Change-Number: 13309
Gerrit-PatchSet: 1
Gerrit-Owner: Jaco Kroon <jaco at uls.co.za>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20191127/57d1e797/attachment.html>


More information about the asterisk-code-review mailing list