Преглед на файлове

permissions: Improve From pattern matching in kamailio permissions module

- allow_trusted() now can take optional parameter of value to match.
- provided parameter will be used instead of From header in match_res() and match_hash_table()
- documentation extended with 3-arguments allow_trusted() function description
Roman Romanchenko преди 7 години
родител
ревизия
caaef0457e

+ 4 - 4
src/modules/permissions/doc/permissions_admin.xml

@@ -254,7 +254,7 @@
 		<listitem>
 		<listitem>
 			<para>
 			<para>
 			regular expression is either empty (NULL in
 			regular expression is either empty (NULL in
-			database) or matches the From URI of request.
+			database) or matches the request's From (or optionally provided) URI.
 			</para>
 			</para>
 		</listitem>
 		</listitem>
 		</itemizedlist>
 		</itemizedlist>
@@ -1185,12 +1185,12 @@ if ($var(group) != -1) {
 	</section>
 	</section>
 	<section id ="permissions.f.allow_trusted">
 	<section id ="permissions.f.allow_trusted">
 		<title>
 		<title>
-		<function moreinfo="none">allow_trusted([src_ip_pvar, proto_pvar])</function>
+		<function moreinfo="none">allow_trusted([src_ip_pvar, proto_pvar, uri_pvar])</function>
 		</title>
 		</title>
 		<para>
 		<para>
 		Checks based either on request's source address and transport
 		Checks based either on request's source address and transport
 		protocol or source address and transport protocol given
 		protocol or source address and transport protocol given
-		in pvar arguments, and From URI of request
+		in pvar arguments, and From URI of request (or uri_pvar if provided)
 		if request can be trusted without
 		if request can be trusted without
 		authentication.  Returns <quote>1</quote> if a match is found
 		authentication.  Returns <quote>1</quote> if a match is found
 		as described in <xref linkend="sec-trusted-requests"/>
 		as described in <xref linkend="sec-trusted-requests"/>
@@ -1200,7 +1200,7 @@ if ($var(group) != -1) {
 		matching peer to AVP peer_tag_avp.
 		matching peer to AVP peer_tag_avp.
 		</para>
 		</para>
 		<para>
 		<para>
-		Source address and transport protocol given in pvar
+		Source address, transport protocol and uri given in pvar
 		arguments must be in string format.  Valid transport
 		arguments must be in string format.  Valid transport
 		protocol values are (ignoring case) "any", "udp, "tcp", "tls",
 		protocol values are (ignoring case) "any", "udp, "tcp", "tls",
 		"ws", "wss" and "sctp".
 		"ws", "wss" and "sctp".

+ 9 - 13
src/modules/permissions/hash.c

@@ -250,10 +250,10 @@ int hash_table_insert(struct trusted_list** table, char* src_ip,
  * Returns number of matches or -1 if none matched.
  * Returns number of matches or -1 if none matched.
  */
  */
 int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
 int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
-		char *src_ip_c_str, int proto)
+		char *src_ip_c_str, int proto, char *uri)
 {
 {
-	str uri, ruri;
-	char uri_string[MAX_URI_SIZE + 1];
+	LM_DBG("match_hash_table src_ip: %s, proto: %d, uri: %s\n", src_ip_c_str, proto, uri);
+	str ruri;
 	char ruri_string[MAX_URI_SIZE + 1];
 	char ruri_string[MAX_URI_SIZE + 1];
 	regex_t preg;
 	regex_t preg;
 	struct trusted_list *np;
 	struct trusted_list *np;
@@ -266,14 +266,6 @@ int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
 
 
 	if (IS_SIP(msg))
 	if (IS_SIP(msg))
 	{
 	{
-		if (parse_from_header(msg) < 0) return -1;
-		uri = get_from(msg)->uri;
-		if (uri.len > MAX_URI_SIZE) {
-			LM_ERR("from URI too large\n");
-			return -1;
-		}
-		memcpy(uri_string, uri.s, uri.len);
-		uri_string[uri.len] = (char)0;
 		ruri = msg->first_line.u.request.uri;
 		ruri = msg->first_line.u.request.uri;
 		if (ruri.len > MAX_URI_SIZE) {
 		if (ruri.len > MAX_URI_SIZE) {
 			LM_ERR("message has Request URI too large\n");
 			LM_ERR("message has Request URI too large\n");
@@ -288,15 +280,18 @@ int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
 				(strncmp(np->src_ip.s, src_ip.s, src_ip.len) == 0) &&
 				(strncmp(np->src_ip.s, src_ip.s, src_ip.len) == 0) &&
 				((np->proto == PROTO_NONE) || (proto == PROTO_NONE) ||
 				((np->proto == PROTO_NONE) || (proto == PROTO_NONE) ||
 				(np->proto == proto))) {
 				(np->proto == proto))) {
+
+			LM_DBG("match_hash_table: %d, %s, %s, %s\n", np->proto, (np->pattern ? np->pattern : "null"), (np->ruri_pattern ? np->ruri_pattern : "null"), (np->tag.s ? np->tag.s : "null"));
+
 			if (IS_SIP(msg)) {
 			if (IS_SIP(msg)) {
 				if (np->pattern) {
 				if (np->pattern) {
 					if (regcomp(&preg, np->pattern, REG_NOSUB)) {
 					if (regcomp(&preg, np->pattern, REG_NOSUB)) {
 						LM_ERR("invalid regular expression\n");
 						LM_ERR("invalid regular expression\n");
-						if (!np->ruri_pattern) {
+						if (!np->pattern) {
 							continue;
 							continue;
 						}
 						}
 					}
 					}
-					if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
+					if (regexec(&preg, uri, 0, (regmatch_t *)0, 0)) {
 						regfree(&preg);
 						regfree(&preg);
 						continue;
 						continue;
 					}
 					}
@@ -327,6 +322,7 @@ int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
 			count++;
 			count++;
 		}
 		}
 	}
 	}
+
 	if (!count)
 	if (!count)
 		return -1;
 		return -1;
 	else
 	else

+ 2 - 2
src/modules/permissions/hash.h

@@ -85,10 +85,10 @@ int hash_table_insert(struct trusted_list** hash_table, char* src_ip,
 
 
 /*
 /*
  * Check if an entry exists in hash table that has given src_ip and protocol
  * Check if an entry exists in hash table that has given src_ip and protocol
- * value and pattern or ruri_pattern that matches to From URI.
+ * value and pattern or ruri_pattern that matches to provided URI.
  */
  */
 int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
 int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
-		char *scr_ip, int proto);
+		char *scr_ip, int proto, char *uri);
 
 
 
 
 /*
 /*

+ 2 - 0
src/modules/permissions/permissions.c

@@ -141,6 +141,8 @@ static cmd_export_t cmds[] = {
 		ANY_ROUTE},
 		ANY_ROUTE},
 	{"allow_trusted",  (cmd_function)allow_trusted_2,  2, fixup_spve_spve,
 	{"allow_trusted",  (cmd_function)allow_trusted_2,  2, fixup_spve_spve,
 		fixup_free_spve_spve, ANY_ROUTE},
 		fixup_free_spve_spve, ANY_ROUTE},
+	{"allow_trusted",  (cmd_function)allow_trusted_3,  3, fixup_spve_all,
+		fixup_free_spve_all, ANY_ROUTE},
 	{"allow_uri",      (cmd_function)allow_uri, 2, double_fixup, 0,
 	{"allow_uri",      (cmd_function)allow_uri, 2, double_fixup, 0,
 		REQUEST_ROUTE | FAILURE_ROUTE},
 		REQUEST_ROUTE | FAILURE_ROUTE},
 	{"allow_address",  (cmd_function)w_allow_address, 3, fixup_allow_address,
 	{"allow_address",  (cmd_function)w_allow_address, 3, fixup_allow_address,

+ 71 - 27
src/modules/permissions/trusted.c

@@ -354,16 +354,15 @@ static inline int match_proto(const char *proto_string, int proto_int)
 
 
 	return 0;
 	return 0;
 }
 }
-
 /*
 /*
  * Matches from uri against patterns returned from database.  Returns number
  * Matches from uri against patterns returned from database.  Returns number
  * of matches or -1 if none of the patterns match.
  * of matches or -1 if none of the patterns match.
  */
  */
-static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
+static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r, char* uri)
 {
 {
 	int i, tag_avp_type;
 	int i, tag_avp_type;
-	str uri, ruri;
-	char uri_string[MAX_URI_SIZE+1];
+	str ruri;
+
 	char ruri_string[MAX_URI_SIZE+1];
 	char ruri_string[MAX_URI_SIZE+1];
 	db_row_t* row;
 	db_row_t* row;
 	db_val_t* val;
 	db_val_t* val;
@@ -372,14 +371,6 @@ static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
 	int count = 0;
 	int count = 0;
 
 
 	if (IS_SIP(msg)) {
 	if (IS_SIP(msg)) {
-		if (parse_from_header(msg) < 0) return -1;
-		uri = get_from(msg)->uri;
-		if (uri.len > MAX_URI_SIZE) {
-			LM_ERR("message has From URI too large\n");
-			return -1;
-		}
-		memcpy(uri_string, uri.s, uri.len);
-		uri_string[uri.len] = (char)0;
 		ruri = msg->first_line.u.request.uri;
 		ruri = msg->first_line.u.request.uri;
 		if (ruri.len > MAX_URI_SIZE) {
 		if (ruri.len > MAX_URI_SIZE) {
 			LM_ERR("message has Request URI too large\n");
 			LM_ERR("message has Request URI too large\n");
@@ -392,6 +383,8 @@ static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
 
 
 	row = RES_ROWS(_r);
 	row = RES_ROWS(_r);
 
 
+	LM_DBG("match_res: row numbers %d\n",  RES_ROW_N(_r));
+
 	for(i = 0; i < RES_ROW_N(_r); i++) {
 	for(i = 0; i < RES_ROW_N(_r); i++) {
 		val = ROW_VALUES(row + i);
 		val = ROW_VALUES(row + i);
 		if ((ROW_N(row + i) == 4) &&
 		if ((ROW_N(row + i) == 4) &&
@@ -404,6 +397,8 @@ static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
 				(VAL_NULL(val + 3) ||
 				(VAL_NULL(val + 3) ||
 				((VAL_TYPE(val + 3) == DB1_STRING) && !VAL_NULL(val + 3))))
 				((VAL_TYPE(val + 3) == DB1_STRING) && !VAL_NULL(val + 3))))
 		{
 		{
+			LM_DBG("match_res: %s, %s, %s, %s\n", VAL_STRING(val), VAL_STRING(val + 1), VAL_STRING(val + 2), VAL_STRING(val + 3));
+
 			if (IS_SIP(msg)) {
 			if (IS_SIP(msg)) {
 				if (!VAL_NULL(val + 1)) {
 				if (!VAL_NULL(val + 1)) {
 					if (regcomp(&preg, (char *)VAL_STRING(val + 1), REG_NOSUB)) {
 					if (regcomp(&preg, (char *)VAL_STRING(val + 1), REG_NOSUB)) {
@@ -412,7 +407,7 @@ static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
 							continue;
 							continue;
 						}
 						}
 					}
 					}
-					if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
+					if (regexec(&preg, uri, 0, (regmatch_t *)0, 0)) {
 						regfree(&preg);
 						regfree(&preg);
 						continue;
 						continue;
 					}
 					}
@@ -444,19 +439,17 @@ static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
 			count++;
 			count++;
 		}
 		}
 	}
 	}
-	if (!count)
-		return -1;
-	else
-		return count;
-}
 
 
+	return (count == 0 ? -1 : count);
+}
 
 
 /*
 /*
  * Checks based on given source IP address and protocol, and From URI
  * Checks based on given source IP address and protocol, and From URI
  * of request if request can be trusted without authentication.
  * of request if request can be trusted without authentication.
  */
  */
-int allow_trusted(struct sip_msg* msg, char *src_ip, int proto)
+int allow_trusted(struct sip_msg* msg, char *src_ip, int proto, char *uri)
 {
 {
+	LM_DBG("allow_trusted src_ip: %s, proto: %d, uri: %s\n", src_ip, proto, uri);
 	int result;
 	int result;
 	db1_res_t* res = NULL;
 	db1_res_t* res = NULL;
 
 
@@ -498,11 +491,11 @@ int allow_trusted(struct sip_msg* msg, char *src_ip, int proto)
 			return -1;
 			return -1;
 		}
 		}
 
 
-		result = match_res(msg, proto, res);
+		result = match_res(msg, proto, res, uri);
 		perm_dbf.free_result(db_handle, res);
 		perm_dbf.free_result(db_handle, res);
 		return result;
 		return result;
 	} else {
 	} else {
-		return match_hash_table(*hash_table, msg, src_ip, proto);
+		return match_hash_table(*hash_table, msg, src_ip, proto, uri);
 	}
 	}
 }
 }
 
 
@@ -513,16 +506,29 @@ int allow_trusted(struct sip_msg* msg, char *src_ip, int proto)
  */
  */
 int allow_trusted_0(struct sip_msg* _msg, char* str1, char* str2)
 int allow_trusted_0(struct sip_msg* _msg, char* str1, char* str2)
 {
 {
-	return allow_trusted(_msg, ip_addr2a(&(_msg->rcv.src_ip)),
-			_msg->rcv.proto);
-}
+	str uri;
+	char uri_string[MAX_URI_SIZE+1];
+
+	if (IS_SIP(_msg)) {
+		if (parse_from_header(_msg) < 0) return -1;
+		uri = get_from(_msg)->uri;
+		if (uri.len > MAX_URI_SIZE) {
+			LM_ERR("message has From URI too large\n");
+			return -1;
+		}
 
 
+		memcpy(uri_string, uri.s, uri.len);
+		uri_string[uri.len] = (char)0;
+	}
+
+	return allow_trusted(_msg, ip_addr2a(&(_msg->rcv.src_ip)), _msg->rcv.proto, uri_string);
+}
 
 
 /*
 /*
  * Checks based on source address and protocol given in pvar arguments and
  * Checks based on source address and protocol given in pvar arguments and
- * and requests's From URI, if request can be trusted without authentication.
+ * provided uri, if request can be trusted without authentication.
  */
  */
-int allow_trusted_2(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp)
+int allow_trusted_1(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp, char *uri_string)
 {
 {
 	str src_ip, proto;
 	str src_ip, proto;
 	int proto_int;
 	int proto_int;
@@ -576,12 +582,50 @@ int allow_trusted_2(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp)
 			goto error;
 			goto error;
 	}
 	}
 
 
-	return allow_trusted(_msg, src_ip.s, proto_int);
+	return allow_trusted(_msg, src_ip.s, proto_int, uri_string);
 error:
 error:
 	LM_ERR("unknown protocol %.*s\n", proto.len, proto.s);
 	LM_ERR("unknown protocol %.*s\n", proto.len, proto.s);
 	return -1;
 	return -1;
 }
 }
 
 
+/*
+ * Checks based on source address and protocol given in pvar arguments and
+ * and requests's From URI, if request can be trusted without authentication.
+ */
+int allow_trusted_2(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp)
+{
+	str uri;
+	char uri_string[MAX_URI_SIZE+1];
+
+	if (IS_SIP(_msg)) {
+		if (parse_from_header(_msg) < 0) return -1;
+		uri = get_from(_msg)->uri;
+		if (uri.len > MAX_URI_SIZE) {
+			LM_ERR("message has From URI too large\n");
+			return -1;
+		}
+
+		memcpy(uri_string, uri.s, uri.len);
+		uri_string[uri.len] = (char)0;
+	}
+
+	return allow_trusted_1(_msg, _src_ip_sp, _proto_sp, uri_string);
+}
+
+/*
+ * Checks based on source address and protocol given in pvar arguments and
+ * and requests's From URI, if request can be trusted without authentication.
+ */
+int allow_trusted_3(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp, char *_uri)
+{
+	str uri;
+	if (_uri==NULL || (fixup_get_svalue(_msg, (gparam_p)_uri, &uri) != 0)) {
+		LM_ERR("uri param does not exist or has no value\n");
+		return -1;
+	}
+
+	return allow_trusted_1(_msg, _src_ip_sp, _proto_sp, uri.s);
+}
 
 
 int reload_trusted_table_cmd(void)
 int reload_trusted_table_cmd(void)
 {
 {

+ 5 - 0
src/modules/permissions/trusted.h

@@ -75,6 +75,11 @@ int allow_trusted_0(struct sip_msg* _msg, char* str1, char* str2);
  */
  */
 int allow_trusted_2(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp);
 int allow_trusted_2(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp);
 
 
+/*
+ * Checks based on source address and protocol given in pvar arguments and
+ * provided URI, if request can be trusted without authentication.
+ */
+int allow_trusted_3(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp, char* uri);
 
 
 int reload_trusted_table_cmd(void);
 int reload_trusted_table_cmd(void);