diff --git a/src/modules/permissions/doc/permissions_admin.xml b/src/modules/permissions/doc/permissions_admin.xml index 315a70c8329..500dc486270 100644 --- a/src/modules/permissions/doc/permissions_admin.xml +++ b/src/modules/permissions/doc/permissions_admin.xml @@ -254,7 +254,7 @@ 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. @@ -1185,12 +1185,12 @@ if ($var(group) != -1) {
- <function moreinfo="none">allow_trusted([src_ip_pvar, proto_pvar])</function> + <function moreinfo="none">allow_trusted([src_ip_pvar, proto_pvar, uri_pvar])</function> 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 1 if a match is found as described in @@ -1200,7 +1200,7 @@ if ($var(group) != -1) { matching peer to AVP peer_tag_avp. - 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". diff --git a/src/modules/permissions/hash.c b/src/modules/permissions/hash.c index 14121b620fb..b771ba164d1 100644 --- a/src/modules/permissions/hash.c +++ b/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 diff --git a/src/modules/permissions/hash.h b/src/modules/permissions/hash.h index 047c3f604b4..1c28fbb1c4f 100644 --- a/src/modules/permissions/hash.h +++ b/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); /* diff --git a/src/modules/permissions/permissions.c b/src/modules/permissions/permissions.c index 810874e12bb..707ccd315b7 100644 --- a/src/modules/permissions/permissions.c +++ b/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, diff --git a/src/modules/permissions/trusted.c b/src/modules/permissions/trusted.c index f953338d96a..7150aa803da 100644 --- a/src/modules/permissions/trusted.c +++ b/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) { diff --git a/src/modules/permissions/trusted.h b/src/modules/permissions/trusted.h index 485165b784d..a37a1623551 100644 --- a/src/modules/permissions/trusted.h +++ b/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);