Selaa lähdekoodia

Merge pull request #1584 from rromrrom/allow_trusted_3

permissions: Improve From pattern matching in kamailio permissions mo…
Daniel-Constantin Mierla 7 vuotta sitten
vanhempi
commit
ad2425c34e

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

@@ -254,7 +254,7 @@
 		<listitem>
 			<para>
 			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>
 		</listitem>
 		</itemizedlist>
@@ -1185,12 +1185,12 @@ if ($var(group) != -1) {
 	</section>
 	<section id ="permissions.f.allow_trusted">
 		<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>
 		<para>
 		Checks based either on request's source address and transport
 		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
 		authentication.  Returns <quote>1</quote> if a match is found
 		as described in <xref linkend="sec-trusted-requests"/>
@@ -1200,7 +1200,7 @@ if ($var(group) != -1) {
 		matching peer to AVP peer_tag_avp.
 		</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
 		protocol values are (ignoring case) "any", "udp, "tcp", "tls",
 		"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.
  */
 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];
 	regex_t preg;
 	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 (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;
 		if (ruri.len > MAX_URI_SIZE) {
 			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) &&
 				((np->proto == PROTO_NONE) || (proto == PROTO_NONE) ||
 				(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 (np->pattern) {
 					if (regcomp(&preg, np->pattern, REG_NOSUB)) {
 						LM_ERR("invalid regular expression\n");
-						if (!np->ruri_pattern) {
+						if (!np->pattern) {
 							continue;
 						}
 					}
-					if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
+					if (regexec(&preg, uri, 0, (regmatch_t *)0, 0)) {
 						regfree(&preg);
 						continue;
 					}
@@ -327,6 +322,7 @@ int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
 			count++;
 		}
 	}
+
 	if (!count)
 		return -1;
 	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
- * 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,
-		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},
 	{"allow_trusted",  (cmd_function)allow_trusted_2,  2, fixup_spve_spve,
 		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,
 		REQUEST_ROUTE | FAILURE_ROUTE},
 	{"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;
 }
-
 /*
  * Matches from uri against patterns returned from database.  Returns number
  * 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;
-	str uri, ruri;
-	char uri_string[MAX_URI_SIZE+1];
+	str ruri;
+
 	char ruri_string[MAX_URI_SIZE+1];
 	db_row_t* row;
 	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;
 
 	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;
 		if (ruri.len > MAX_URI_SIZE) {
 			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);
 
+	LM_DBG("match_res: row numbers %d\n",  RES_ROW_N(_r));
+
 	for(i = 0; i < RES_ROW_N(_r); i++) {
 		val = ROW_VALUES(row + i);
 		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_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 (!VAL_NULL(val + 1)) {
 					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;
 						}
 					}
-					if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
+					if (regexec(&preg, uri, 0, (regmatch_t *)0, 0)) {
 						regfree(&preg);
 						continue;
 					}
@@ -444,19 +439,17 @@ static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
 			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
  * 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;
 	db1_res_t* res = NULL;
 
@@ -498,11 +491,11 @@ int allow_trusted(struct sip_msg* msg, char *src_ip, int proto)
 			return -1;
 		}
 
-		result = match_res(msg, proto, res);
+		result = match_res(msg, proto, res, uri);
 		perm_dbf.free_result(db_handle, res);
 		return result;
 	} 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)
 {
-	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
- * 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;
 	int proto_int;
@@ -576,12 +582,50 @@ int allow_trusted_2(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp)
 			goto error;
 	}
 
-	return allow_trusted(_msg, src_ip.s, proto_int);
+	return allow_trusted(_msg, src_ip.s, proto_int, uri_string);
 error:
 	LM_ERR("unknown protocol %.*s\n", proto.len, proto.s);
 	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)
 {

+ 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);
 
+/*
+ * 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);