Skip to content

Commit

Permalink
Merge pull request #1584 from rromrrom/allow_trusted_3
Browse files Browse the repository at this point in the history
permissions: Improve From pattern matching in kamailio permissions mo…
  • Loading branch information
miconda committed Jul 11, 2018
2 parents bfb1f5a + caaef04 commit ad2425c
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 46 deletions.
8 changes: 4 additions & 4 deletions src/modules/permissions/doc/permissions_admin.xml
Expand Up @@ -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>
Expand Down Expand Up @@ -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"/>
Expand All @@ -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".
Expand Down
22 changes: 9 additions & 13 deletions src/modules/permissions/hash.c
Expand Up @@ -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;
Expand All @@ -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");
Expand All @@ -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;
}
Expand Down Expand Up @@ -327,6 +322,7 @@ int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
count++;
}
}

if (!count)
return -1;
else
Expand Down
4 changes: 2 additions & 2 deletions src/modules/permissions/hash.h
Expand Up @@ -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);


/*
Expand Down
2 changes: 2 additions & 0 deletions src/modules/permissions/permissions.c
Expand Up @@ -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,
Expand Down
98 changes: 71 additions & 27 deletions src/modules/permissions/trusted.c
Expand Up @@ -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;
Expand All @@ -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");
Expand All @@ -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) &&
Expand All @@ -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)) {
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down
5 changes: 5 additions & 0 deletions src/modules/permissions/trusted.h
Expand Up @@ -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);

Expand Down

0 comments on commit ad2425c

Please sign in to comment.