Hello,
I have written a patch to add checking for the Request-URI.
Please see attached diff.
I hope you consider pushing this code upstream.
Thanks,
Emmanuel

On Wed, May 6, 2015 at 12:14 PM, Vik Killa <vipki...@gmail.com> wrote:

> Hello,
> We would like to match specific calls based on two factors:
> 1. the source IP address
> 2. the Request URI
>
> I see in the permissions module, it is possible to match based on the
> Source IP + the From URI.
> We need two match both in order to return the appropriate 'tag' attribute
> from table.
>
> Would anyone know of a way to accomplish this?
>
>
> Also, I noticed that matching source IP + from uri, you cannot control
> which result is returned by permissions module based on regular expression.
> In other words if more than one match is made, permissions module seems to
> return the first result.
>
> Thank you and I look forward to your response.
> V
>
> _______________________________________________
> SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list
> sr-users@lists.sip-router.org
> http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
>
>
diff --git a/modules/permissions/hash.c b/modules/permissions/hash.c
index 7b11ebd..97e0578 100644
--- a/modules/permissions/hash.c
+++ b/modules/permissions/hash.c
@@ -22,6 +22,7 @@
 
 #include <sys/types.h>
 #include <regex.h>
+#include "parse_config.h"
 #include "../../mem/shm_mem.h"
 #include "../../parser/parse_from.h"
 #include "../../ut.h"
@@ -116,11 +117,11 @@ void free_hash_table(struct trusted_list** table)
 
 
 /* 
- * Add <src_ip, proto, pattern, tag> into hash table, where proto is integer
+ * Add <src_ip, proto, pattern, ruri_pattern, tag> into hash table, where 
proto is integer
  * representation of string argument proto.
  */
 int hash_table_insert(struct trusted_list** table, char* src_ip, 
-               char* proto, char* pattern, char* tag)
+               char* proto, char* pattern, char* ruri_pattern, char* tag)
 {
        struct trusted_list *np;
        unsigned int hash_val;
@@ -178,14 +179,28 @@ int hash_table_insert(struct trusted_list** table, char* 
src_ip,
        } else {
                np->pattern = 0;
        }
+       
+       if (ruri_pattern) {
+               np->ruri_pattern = (char *) shm_malloc(strlen(ruri_pattern)+1);
+               if (np->ruri_pattern == NULL) {
+                       LM_CRIT("cannot allocate shm memory for ruri_pattern 
string\n");
+                       shm_free(np->src_ip.s);
+                       shm_free(np);
+                       return -1;
+               }
+               (void) strcpy(np->ruri_pattern, ruri_pattern);
+       } else {
+               np->ruri_pattern = 0;
+       }
 
        if (tag) {
                np->tag.len = strlen(tag);
                np->tag.s = (char *) shm_malloc((np->tag.len) + 1);
                if (np->tag.s == NULL) {
-                       LM_CRIT("cannot allocate shm memory for pattern 
string\n");
+                       LM_CRIT("cannot allocate shm memory for pattern or 
ruri_pattern string\n");
                        shm_free(np->src_ip.s);
                        shm_free(np->pattern);
+                       shm_free(np->ruri_pattern);
                        shm_free(np);
                        return -1;
                }
@@ -220,9 +235,23 @@ int match_hash_table(struct trusted_list** table, struct 
sip_msg* msg,
        int_str val;
        int count = 0;
 
+       int len;
+       static char ruri_str[EXPRESSION_LENGTH+1];
+       
+       len = msg->parsed_uri.user.len + msg->parsed_uri.host.len + 5;
+       if (len > EXPRESSION_LENGTH) {
+               LM_ERR("Request URI is too long: %d chars\n", len);
+               return -1;
+       }
+       strcpy(ruri_str, "sip:");
+       memcpy(ruri_str + 4, msg->parsed_uri.user.s, msg->parsed_uri.user.len);
+       ruri_str[msg->parsed_uri.user.len + 4] = '@';
+       memcpy(ruri_str + msg->parsed_uri.user.len + 5, msg->parsed_uri.host.s, 
msg->parsed_uri.host.len);
+       ruri_str[len] = '\0';
+
        src_ip.s = src_ip_c_str;
        src_ip.len = strlen(src_ip.s);
-
+       
        if (IS_SIP(msg))
        {
                if (parse_from_header(msg) < 0) return -1;
@@ -236,33 +265,46 @@ int match_hash_table(struct trusted_list** table, struct 
sip_msg* msg,
        }
 
        for (np = table[perm_hash(src_ip)]; np != NULL; np = np->next) {
-           if ((np->src_ip.len == src_ip.len) && 
-               (strncmp(np->src_ip.s, src_ip.s, src_ip.len) == 0) &&
-               ((np->proto == PROTO_NONE) || (proto == PROTO_NONE) ||
-                (np->proto == proto))) {
-               if (np->pattern && IS_SIP(msg)) {
-                   if (regcomp(&preg, np->pattern, REG_NOSUB)) {
-                       LM_ERR("invalid regular expression\n");
-                       continue;
-                   }
-                   if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
-                       regfree(&preg);
-                       continue;
-                   }
-                   regfree(&preg);
-               }
-               /* Found a match */
-               if (tag_avp.n && np->tag.s) {
-                   val.s = np->tag;
-                   if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) {
-                       LM_ERR("setting of tag_avp failed\n");
-                       return -1;
-                   }
+               if ((np->src_ip.len == src_ip.len) &&
+                       (strncmp(np->src_ip.s, src_ip.s, src_ip.len) == 0) &&
+                       ((np->proto == PROTO_NONE) || (proto == PROTO_NONE) ||
+                        (np->proto == proto))) {
+                       if (np->pattern && IS_SIP(msg)) {
+                               if (regcomp(&preg, np->pattern, REG_NOSUB)) {
+                                       LM_ERR("invalid regular expression\n");
+                                       if (!np->ruri_pattern) {
+                                               continue;
+                                       }
+                               }
+                               if (regexec(&preg, uri_string, 0, (regmatch_t 
*)0, 0)) {
+                                       regfree(&preg);
+                                       continue;
+                               }
+                               regfree(&preg);
+                               if (np->ruri_pattern) {
+                                       if (regcomp(&preg, np->ruri_pattern, 
REG_NOSUB)) {
+                                               LM_ERR("invalid regular 
expression\n");
+                                               continue;
+                                       }
+                                       if (regexec(&preg, ruri_str, 0, 
(regmatch_t *)0, 0)) {
+                                               regfree(&preg);
+                                               continue;
+                                       }
+                                       regfree(&preg);
+                               }
+                       }
+                       /* Found a match */
+                       if (tag_avp.n && np->tag.s) {
+                               val.s = np->tag;
+                               if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, 
val) != 0) {
+                                       LM_ERR("setting of tag_avp failed\n");
+                                       return -1;
+                               }
+                       }
+                       if (!peer_tag_mode)
+                               return 1;
+                       count++;
                }
-               if (!peer_tag_mode)
-                   return 1;
-               count++;
-           }
        }
        if (!count)
            return -1;
@@ -288,6 +330,7 @@ int hash_table_mi_print(struct trusted_list** table, struct 
mi_node* rpl)
                                                np->src_ip.len, 
ZSW(np->src_ip.s),
                                                np->proto,
                                                np->pattern?np->pattern:"NULL",
+                                               
np->ruri_pattern?np->ruri_pattern:"NULL",
                                                np->tag.len?np->tag.s:"NULL") 
== 0) {
                                return -1;
                        }
@@ -329,8 +372,9 @@ int hash_table_rpc_print(struct trusted_list** hash_table, 
rpc_t* rpc, void* c)
                                rpc->fault(c, 500, "Internal error creating rpc 
data (ip)");
                                return -1;
                        }
-                       if(rpc->struct_add(ih, "dss", "proto",  np->proto,
+                       if(rpc->struct_add(ih, "dsss", "proto",  np->proto,
                                                "pattern",  np->pattern ? 
np->pattern : "NULL",
+                                               "ruri_pattern",  
np->ruri_pattern ? np->ruri_pattern : "NULL",
                                                "tag",  np->tag.len ? np->tag.s 
: "NULL") < 0)
                        {
                                rpc->fault(c, 500, "Internal error creating rpc 
data");
@@ -356,6 +400,7 @@ void empty_hash_table(struct trusted_list **table)
                while (np) {
                        if (np->src_ip.s) shm_free(np->src_ip.s);
                        if (np->pattern) shm_free(np->pattern);
+                       if (np->ruri_pattern) shm_free(np->ruri_pattern);
                        if (np->tag.s) shm_free(np->tag.s);
                        next = np->next;
                        shm_free(np);
diff --git a/modules/permissions/hash.h b/modules/permissions/hash.h
index 1ae0072..81eebb0 100644
--- a/modules/permissions/hash.h
+++ b/modules/permissions/hash.h
@@ -41,6 +41,7 @@ struct trusted_list {
        str src_ip;                 /* Source IP of SIP message */
        int proto;                  /* Protocol -- UDP, TCP, TLS, or SCTP */
        char *pattern;              /* Pattern matching From header field */
+       char *ruri_pattern;             /* Pattern matching Request URI */
        str tag;                    /* Tag to be assigned to AVP */
        struct trusted_list *next;  /* Next element in the list */
 };
@@ -77,16 +78,16 @@ void destroy_hash_table(struct trusted_list** table);
 
 
 /* 
- * Add <src_ip, proto, pattern> into hash table, where proto is integer
+ * Add <src_ip, proto, pattern, ruri_pattern> into hash table, where proto is 
integer
  * representation of string argument proto.
  */
 int hash_table_insert(struct trusted_list** hash_table, char* src_ip,
-                     char* proto, char* pattern, char* tag);
+                     char* proto, char* pattern, char* ruri_pattern, char* 
tag);
 
 
 /* 
  * Check if an entry exists in hash table that has given src_ip and protocol
- * value and pattern that matches to From URI.
+ * value and pattern or ruri_pattern that matches to From URI.
  */
 int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
                     char *scr_ip, int proto);
diff --git a/modules/permissions/permissions.c 
b/modules/permissions/permissions.c
index 4170fef..9200406 100644
--- a/modules/permissions/permissions.c
+++ b/modules/permissions/permissions.c
@@ -68,6 +68,7 @@ str trusted_table = str_init("trusted");   /* Name of trusted 
table */
 str source_col = str_init("src_ip");       /* Name of source address column */
 str proto_col = str_init("proto");         /* Name of protocol column */
 str from_col = str_init("from_pattern");   /* Name of from pattern column */
+str ruri_col = str_init("ruri_pattern");   /* Name of RURI pattern column */
 str tag_col = str_init("tag");             /* Name of tag column */
 str tag_avp_param = {NULL, 0};             /* Peer tag AVP spec */
 int peer_tag_mode = 0;                     /* Add tags form all mathcing peers 
to avp */
@@ -166,6 +167,7 @@ static param_export_t params[] = {
        {"source_col",         PARAM_STR, &source_col      },
        {"proto_col",          PARAM_STR, &proto_col       },
        {"from_col",           PARAM_STR, &from_col        },
+       {"ruri_col",           PARAM_STR, &ruri_col        },
        {"tag_col",            PARAM_STR, &tag_col         },
        {"peer_tag_avp",       PARAM_STR, &tag_avp_param   },
        {"peer_tag_mode",      INT_PARAM, &peer_tag_mode     },
diff --git a/modules/permissions/permissions.h 
b/modules/permissions/permissions.h
index 0d2fa39..0c0c9ac 100644
--- a/modules/permissions/permissions.h
+++ b/modules/permissions/permissions.h
@@ -25,6 +25,7 @@
  * History:
  * --------
  *  2003-09-03  replaced /usr/local/et/ser/ with CFG_DIR (andrei)
+ *  2015-05-06  added regular expression matching R-URI 
(eschmidba...@voipxswitch.com)
  */
  
 #ifndef PERMISSIONS_H
@@ -55,6 +56,7 @@ extern str trusted_table; /* Name of trusted table */
 extern str source_col;    /* Name of source address column */
 extern str proto_col;     /* Name of protocol column */
 extern str from_col;      /* Name of from pattern column */
+extern str ruri_col;      /* Name of RURI pattern column */
 extern str tag_col;       /* Name of tag column */
 extern str address_table; /* Name of address table */
 extern str grp_col;       /* Name of address group column */
diff --git a/modules/permissions/trusted.c b/modules/permissions/trusted.c
index db20e8f..08a989d 100644
--- a/modules/permissions/trusted.c
+++ b/modules/permissions/trusted.c
@@ -41,7 +41,7 @@
 #include "../../parser/parse_from.h"
 #include "../../usr_avp.h"
 
-#define TABLE_VERSION 5
+#define TABLE_VERSION 6
 
 struct trusted_list ***hash_table;     /* Pointer to current hash table 
pointer */
 struct trusted_list **hash_table_1;   /* Pointer to hash table 1 */
@@ -58,7 +58,7 @@ static db_func_t perm_dbf;
  */
 int reload_trusted_table(void)
 {
-       db_key_t cols[4];
+       db_key_t cols[5];
        db1_res_t* res = NULL;
        db_row_t* row;
        db_val_t* val;
@@ -67,12 +67,13 @@ int reload_trusted_table(void)
        struct trusted_list **old_hash_table;
        int i;
 
-       char *pattern, *tag;
+       char *pattern, *ruri_pattern, *tag;
 
        cols[0] = &source_col;
        cols[1] = &proto_col;
        cols[2] = &from_col;
-       cols[3] = &tag_col;
+       cols[3] = &ruri_col;
+       cols[4] = &tag_col;
 
        if (db_handle == 0) {
            LM_ERR("no connection to database\n");
@@ -84,7 +85,7 @@ int reload_trusted_table(void)
                return -1;
        }
 
-       if (perm_dbf.query(db_handle, NULL, 0, NULL, cols, 0, 4, 0, &res) < 0) {
+       if (perm_dbf.query(db_handle, NULL, 0, NULL, cols, 0, 5, 0, &res) < 0) {
                LM_ERR("failed to query database\n");
                return -1;
        }
@@ -103,7 +104,7 @@ int reload_trusted_table(void)
                
        for (i = 0; i < RES_ROW_N(res); i++) {
            val = ROW_VALUES(row + i);
-           if ((ROW_N(row + i) == 4) &&
+           if ((ROW_N(row + i) == 5) &&
                ((VAL_TYPE(val) == DB1_STRING) || (VAL_TYPE(val) == DB1_STR) ) 
&& 
                !VAL_NULL(val) &&
                ((VAL_TYPE(val + 1) == DB1_STRING) || (VAL_TYPE(val + 1) == 
DB1_STR))
@@ -112,29 +113,36 @@ int reload_trusted_table(void)
                 (((VAL_TYPE(val + 2) == DB1_STRING) || (VAL_TYPE(val + 2) == 
DB1_STR)) &&
                !VAL_NULL(val + 2))) && (VAL_NULL(val + 3) ||
                 (((VAL_TYPE(val + 3) == DB1_STRING) || (VAL_TYPE(val + 3) == 
DB1_STR) )&& 
-               !VAL_NULL(val + 3)))) {
+               !VAL_NULL(val + 3))) && (VAL_NULL(val + 4) ||
+                (((VAL_TYPE(val + 4) == DB1_STRING) || (VAL_TYPE(val + 4) == 
DB1_STR) )&& 
+               !VAL_NULL(val + 4)))) {
                if (VAL_NULL(val + 2)) {
                    pattern = 0;
                } else {
                    pattern = (char *)VAL_STRING(val + 2);
                }
                if (VAL_NULL(val + 3)) {
+                   ruri_pattern = 0;
+               } else {
+                   ruri_pattern = (char *)VAL_STRING(val + 3);
+               }
+               if (VAL_NULL(val + 4)) {
                    tag = 0;
                } else {
-                   tag = (char *)VAL_STRING(val + 3);
+                   tag = (char *)VAL_STRING(val + 4);
                }
                if (hash_table_insert(new_hash_table,
                                      (char *)VAL_STRING(val),
                                      (char *)VAL_STRING(val + 1),
-                                     pattern, tag) == -1) {
+                                     pattern, ruri_pattern, tag) == -1) {
                    LM_ERR("hash table problem\n");
                    perm_dbf.free_result(db_handle, res);
                    empty_hash_table(new_hash_table);
                    return -1;
                }
-               LM_DBG("tuple <%s, %s, %s, %s> inserted into trusted hash "
+               LM_DBG("tuple <%s, %s, %s, %s, %s> inserted into trusted hash "
                    "table\n", VAL_STRING(val), VAL_STRING(val + 1),
-                   pattern, tag);
+                   pattern, ruri_pattern, tag);
            } else {
                LM_ERR("database problem\n");
                perm_dbf.free_result(db_handle, res);
@@ -369,6 +377,20 @@ static int match_res(struct sip_msg* msg, int proto, 
db1_res_t* _r)
        regex_t preg;
        int_str tag_avp, avp_val;
        int count = 0;
+       
+       int len;
+       static char ruri_str[EXPRESSION_LENGTH+1];
+       
+       len = msg->parsed_uri.user.len + msg->parsed_uri.host.len + 5;
+       if (len > EXPRESSION_LENGTH) {
+               LM_ERR("Request URI is too long: %d chars\n", len);
+               return -1;
+       }
+       strcpy(ruri_str, "sip:");
+       memcpy(ruri_str + 4, msg->parsed_uri.user.s, msg->parsed_uri.user.len);
+       ruri_str[msg->parsed_uri.user.len + 4] = '@';
+       memcpy(ruri_str + msg->parsed_uri.user.len + 5, msg->parsed_uri.host.s, 
msg->parsed_uri.host.len);
+       ruri_str[len] = '\0';
 
        if (IS_SIP(msg)) {
                if (parse_from_header(msg) < 0) return -1;
@@ -385,39 +407,56 @@ static int match_res(struct sip_msg* msg, int proto, 
db1_res_t* _r)
        row = RES_ROWS(_r);
 
        for(i = 0; i < RES_ROW_N(_r); i++) {
-               val = ROW_VALUES(row + i);
-               if ((ROW_N(row + i) == 3) &&
-                   (VAL_TYPE(val) == DB1_STRING) && !VAL_NULL(val) &&
-                   match_proto(VAL_STRING(val), proto) &&
-                   (VAL_NULL(val + 1) ||
-                     ((VAL_TYPE(val + 1) == DB1_STRING) && !VAL_NULL(val + 
1))) &&
-                   (VAL_NULL(val + 2) ||
-                     ((VAL_TYPE(val + 2) == DB1_STRING) && !VAL_NULL(val + 
2))))
-               {
-                       if (!VAL_NULL(val + 1) && IS_SIP(msg)) {
-                               if (regcomp(&preg, (char *)VAL_STRING(val + 1), 
REG_NOSUB)) {
-                                       LM_ERR("invalid regular expression\n");
-                                       continue;
-                               }
-                               if (regexec(&preg, uri_string, 0, (regmatch_t 
*)0, 0)) {
-                                       regfree(&preg);
-                                       continue;
+                       val = ROW_VALUES(row + i);
+                       if ((ROW_N(row + i) == 4) &&
+                               (VAL_TYPE(val) == DB1_STRING) && !VAL_NULL(val) 
&&
+                               match_proto(VAL_STRING(val), proto) &&
+                               (VAL_NULL(val + 1) ||
+                                 ((VAL_TYPE(val + 1) == DB1_STRING) && 
!VAL_NULL(val + 1))) &&
+                               (VAL_NULL(val + 2) ||
+                                 ((VAL_TYPE(val + 2) == DB1_STRING) && 
!VAL_NULL(val + 2))) &&
+                               (VAL_NULL(val + 3) ||
+                                 ((VAL_TYPE(val + 3) == DB1_STRING) && 
!VAL_NULL(val + 3))))
+                       {
+                               if (IS_SIP(msg)) {
+                                       if (!VAL_NULL(val + 1)) {
+                                               if (regcomp(&preg, (char 
*)VAL_STRING(val + 1), REG_NOSUB)) {
+                                                               LM_ERR("invalid 
regular expression\n");
+                                                               if 
(VAL_NULL(val + 2)) {
+                                                                       
continue;
+                                                               }
+                                               }
+                                               if (regexec(&preg, uri_string, 
0, (regmatch_t *)0, 0)) {
+                                                               regfree(&preg);
+                                                               continue;
+                                               }
+                                               regfree(&preg);
+                                               if (!VAL_NULL(val + 2)) {
+                                                       if (regcomp(&preg, 
(char *)VAL_STRING(val + 2), REG_NOSUB)) {
+                                                                       
LM_ERR("invalid regular expression\n");
+                                                                       
continue;
+                                                       }
+                                                       if (regexec(&preg, 
ruri_str, 0, (regmatch_t *)0, 0)) {
+                                                                       
regfree(&preg);
+                                                                       
continue;
+                                                       }
+                                                       regfree(&preg);
+                                               }
+                                       }
                                }
-                           regfree(&preg);
-                       }
-                       /* Found a match */
-                       if (tag_avp.n && !VAL_NULL(val + 2)) {
-                               avp_val.s.s = (char *)VAL_STRING(val + 2);
-                               avp_val.s.len = strlen(avp_val.s.s);
-                               if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, 
avp_val) != 0) {
-                                       LM_ERR("failed to set of tag_avp 
failed\n");
-                                       return -1;
+                               /* Found a match */
+                               if (tag_avp.n && !VAL_NULL(val + 3)) {
+                                               avp_val.s.s = (char 
*)VAL_STRING(val + 3);
+                                               avp_val.s.len = 
strlen(avp_val.s.s);
+                                               if 
(add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, avp_val) != 0) {
+                                                               LM_ERR("failed 
to set of tag_avp failed\n");
+                                                               return -1;
+                                               }
                                }
+                               if (!peer_tag_mode)
+                                               return 1;
+                               count++;
                        }
-                       if (!peer_tag_mode) 
-                               return 1;
-                       count++;
-               }
        }
        if (!count)
                return -1;
@@ -437,7 +476,7 @@ int allow_trusted(struct sip_msg* msg, char *src_ip, int 
proto)
        
        db_key_t keys[1];
        db_val_t vals[1];
-       db_key_t cols[3];
+       db_key_t cols[4];
 
        if (db_mode == DISABLE_CACHE) {
        
@@ -449,7 +488,8 @@ int allow_trusted(struct sip_msg* msg, char *src_ip, int 
proto)
                keys[0] = &source_col;
                cols[0] = &proto_col;
                cols[1] = &from_col;
-               cols[2] = &tag_col;
+               cols[2] = &ruri_col;
+               cols[3] = &tag_col;
 
                if (perm_dbf.use_table(db_handle, &trusted_table) < 0) {
                        LM_ERR("failed to use trusted table\n");
@@ -460,7 +500,7 @@ int allow_trusted(struct sip_msg* msg, char *src_ip, int 
proto)
                VAL_NULL(vals) = 0;
                VAL_STRING(vals) = src_ip;
 
-               if (perm_dbf.query(db_handle, keys, 0, vals, cols, 1, 3, 0,
+               if (perm_dbf.query(db_handle, keys, 0, vals, cols, 1, 4, 0,
                                   &res) < 0){
                        LM_ERR("failed to query database\n");
                        return -1;
diff --git a/utils/kamctl/postgres/permissions-create.sql 
b/utils/kamctl/postgres/permissions-create.sql
index 95f13de..e005243 100644
--- a/utils/kamctl/postgres/permissions-create.sql
+++ b/utils/kamctl/postgres/permissions-create.sql
@@ -1,9 +1,10 @@
-INSERT INTO version (table_name, table_version) values ('trusted','5');
+INSERT INTO version (table_name, table_version) values ('trusted','6');
 CREATE TABLE trusted (
     id SERIAL PRIMARY KEY NOT NULL,
     src_ip VARCHAR(50) NOT NULL,
     proto VARCHAR(4) NOT NULL,
     from_pattern VARCHAR(64) DEFAULT NULL,
+    ruri_pattern VARCHAR(64) DEFAULT NULL,
     tag VARCHAR(64)
 );
 
_______________________________________________
SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list
sr-users@lists.sip-router.org
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users

Reply via email to