Browse code

permissions: match trusted rules considering priority and regexp over r-uri

- two new columns to set priority of the rule as well as regular
expression matching over r-uri

Emmanuel Schmidbauer authored on 17/06/2015 14:18:18
Showing 5 changed files
... ...
@@ -22,6 +22,7 @@
22 22
 
23 23
 #include <sys/types.h>
24 24
 #include <regex.h>
25
+#include "parse_config.h"
25 26
 #include "../../mem/shm_mem.h"
26 27
 #include "../../parser/parse_from.h"
27 28
 #include "../../ut.h"
... ...
@@ -116,13 +117,15 @@ void free_hash_table(struct trusted_list** table)
116 116
 
117 117
 
118 118
 /* 
119
- * Add <src_ip, proto, pattern, tag> into hash table, where proto is integer
119
+ * Add <src_ip, proto, pattern, ruri_pattern, tag, priority> into hash table, where proto is integer
120 120
  * representation of string argument proto.
121 121
  */
122 122
 int hash_table_insert(struct trusted_list** table, char* src_ip, 
123
-		char* proto, char* pattern, char* tag)
123
+		char* proto, char* pattern, char* ruri_pattern, char* tag, int priority)
124 124
 {
125 125
 	struct trusted_list *np;
126
+	struct trusted_list *np0 = NULL;
127
+	struct trusted_list *np1 = NULL;
126 128
 	unsigned int hash_val;
127 129
 
128 130
 	np = (struct trusted_list *) shm_malloc(sizeof(*np));
... ...
@@ -179,13 +182,27 @@ int hash_table_insert(struct trusted_list** table, char* src_ip,
179 179
 		np->pattern = 0;
180 180
 	}
181 181
 
182
+	if (ruri_pattern) {
183
+		np->ruri_pattern = (char *) shm_malloc(strlen(ruri_pattern)+1);
184
+		if (np->ruri_pattern == NULL) {
185
+			LM_CRIT("cannot allocate shm memory for ruri_pattern string\n");
186
+			shm_free(np->src_ip.s);
187
+			shm_free(np);
188
+			return -1;
189
+		}
190
+		(void) strcpy(np->ruri_pattern, ruri_pattern);
191
+	} else {
192
+		np->ruri_pattern = 0;
193
+	}
194
+
182 195
 	if (tag) {
183 196
 		np->tag.len = strlen(tag);
184 197
 		np->tag.s = (char *) shm_malloc((np->tag.len) + 1);
185 198
 		if (np->tag.s == NULL) {
186
-			LM_CRIT("cannot allocate shm memory for pattern string\n");
199
+			LM_CRIT("cannot allocate shm memory for pattern or ruri_pattern string\n");
187 200
 			shm_free(np->src_ip.s);
188 201
 			shm_free(np->pattern);
202
+			shm_free(np->ruri_pattern);
189 203
 			shm_free(np);
190 204
 			return -1;
191 205
 		}
... ...
@@ -195,9 +212,29 @@ int hash_table_insert(struct trusted_list** table, char* src_ip,
195 195
 		np->tag.s = 0;
196 196
 	}
197 197
 
198
+	np->priority = priority;
199
+
198 200
 	hash_val = perm_hash(np->src_ip);
199
-	np->next = table[hash_val];
200
-	table[hash_val] = np;
201
+	if(table[hash_val]==NULL) {
202
+		np->next = NULL;
203
+		table[hash_val] = np;
204
+	} else {
205
+		np1 = NULL;
206
+		np0 = table[hash_val];
207
+		while(np0) {
208
+			if(np0->priority < np->priority)
209
+				break;
210
+			np1 = np0;
211
+			np0 = np0->next;
212
+		}
213
+		if(np1==NULL) {
214
+			np->next = table[hash_val];
215
+			table[hash_val] = np;
216
+		} else {
217
+			np->next = np1->next;
218
+			np1->next = np;
219
+		}
220
+	}
201 221
 
202 222
 	return 1;
203 223
 }
... ...
@@ -212,8 +249,9 @@ int hash_table_insert(struct trusted_list** table, char* src_ip,
212 212
 int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
213 213
 		char *src_ip_c_str, int proto)
214 214
 {
215
-	str uri;
215
+	str uri, ruri;
216 216
 	char uri_string[MAX_URI_SIZE + 1];
217
+	char ruri_string[MAX_URI_SIZE + 1];
217 218
 	regex_t preg;
218 219
 	struct trusted_list *np;
219 220
 	str src_ip;
... ...
@@ -233,6 +271,13 @@ int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
233 233
 		}
234 234
 		memcpy(uri_string, uri.s, uri.len);
235 235
 		uri_string[uri.len] = (char)0;
236
+		ruri = msg->first_line.u.request.uri;
237
+		if (ruri.len > MAX_URI_SIZE) {
238
+			LM_ERR("message has Request URI too large\n");
239
+			return -1;
240
+		}
241
+		memcpy(ruri_string, ruri.s, ruri.len);
242
+		ruri_string[ruri.len] = (char)0;
236 243
 	}
237 244
 
238 245
 	for (np = table[perm_hash(src_ip)]; np != NULL; np = np->next) {
... ...
@@ -240,16 +285,31 @@ int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
240 240
 		(strncmp(np->src_ip.s, src_ip.s, src_ip.len) == 0) &&
241 241
 		((np->proto == PROTO_NONE) || (proto == PROTO_NONE) ||
242 242
 		 (np->proto == proto))) {
243
-		if (np->pattern && IS_SIP(msg)) {
244
-		    if (regcomp(&preg, np->pattern, REG_NOSUB)) {
245
-			LM_ERR("invalid regular expression\n");
246
-			continue;
243
+		if (IS_SIP(msg)) {
244
+		    if (np->pattern) {
245
+		        if (regcomp(&preg, np->pattern, REG_NOSUB)) {
246
+			    LM_ERR("invalid regular expression\n");
247
+			    if (!np->ruri_pattern) {
248
+				continue;
249
+			    }
250
+		        }
251
+		        if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
252
+			    regfree(&preg);
253
+			    continue;
254
+		        }
255
+		        regfree(&preg);
247 256
 		    }
248
-		    if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
257
+		    if (np->ruri_pattern) {
258
+			if (regcomp(&preg, np->ruri_pattern, REG_NOSUB)) {
259
+			    LM_ERR("invalid regular expression\n");
260
+			    continue;
261
+			}
262
+			if (regexec(&preg, ruri_string, 0, (regmatch_t *)0, 0)) {
263
+			    regfree(&preg);
264
+			    continue;
265
+			}
249 266
 			regfree(&preg);
250
-			continue;
251 267
 		    }
252
-		    regfree(&preg);
253 268
 		}
254 269
 		/* Found a match */
255 270
 		if (tag_avp.n && np->tag.s) {
... ...
@@ -283,12 +343,14 @@ int hash_table_mi_print(struct trusted_list** table, struct mi_node* rpl)
283 283
 		np = table[i];
284 284
 		while (np) {
285 285
 			if (addf_mi_node_child(rpl, 0, 0, 0,
286
-						"%4d <%.*s, %d, %s, %s>",
286
+						"%4d <%.*s, %d, %s, %s, %s, %d>",
287 287
 						i,
288 288
 						np->src_ip.len, ZSW(np->src_ip.s),
289 289
 						np->proto,
290 290
 						np->pattern?np->pattern:"NULL",
291
-						np->tag.len?np->tag.s:"NULL") == 0) {
291
+						np->ruri_pattern?np->ruri_pattern:"NULL",
292
+						np->tag.len?np->tag.s:"NULL",
293
+						np->priority) == 0) {
292 294
 				return -1;
293 295
 			}
294 296
 			np = np->next;
... ...
@@ -329,9 +391,11 @@ int hash_table_rpc_print(struct trusted_list** hash_table, rpc_t* rpc, void* c)
329 329
 				rpc->fault(c, 500, "Internal error creating rpc data (ip)");
330 330
 				return -1;
331 331
 			}
332
-			if(rpc->struct_add(ih, "dss", "proto",  np->proto,
332
+			if(rpc->struct_add(ih, "dsssd", "proto",  np->proto,
333 333
 						"pattern",  np->pattern ? np->pattern : "NULL",
334
-						"tag",  np->tag.len ? np->tag.s : "NULL") < 0)
334
+						"ruri_pattern",  np->ruri_pattern ? np->ruri_pattern : "NULL",
335
+						"tag",  np->tag.len ? np->tag.s : "NULL",
336
+						"priority", np->priority) < 0)
335 337
 			{
336 338
 				rpc->fault(c, 500, "Internal error creating rpc data");
337 339
 				return -1;
... ...
@@ -41,7 +41,9 @@ struct trusted_list {
41 41
 	str src_ip;                 /* Source IP of SIP message */
42 42
 	int proto;                  /* Protocol -- UDP, TCP, TLS, or SCTP */
43 43
 	char *pattern;              /* Pattern matching From header field */
44
+	char *ruri_pattern;         /* Pattern matching Request URI */
44 45
 	str tag;                    /* Tag to be assigned to AVP */
46
+	int priority;               /* priority */
45 47
 	struct trusted_list *next;  /* Next element in the list */
46 48
 };
47 49
 
... ...
@@ -77,16 +79,16 @@ void destroy_hash_table(struct trusted_list** table);
77 77
 
78 78
 
79 79
 /* 
80
- * Add <src_ip, proto, pattern> into hash table, where proto is integer
80
+ * Add <src_ip, proto, pattern, ruri_pattern, priority> into hash table, where proto is integer
81 81
  * representation of string argument proto.
82 82
  */
83 83
 int hash_table_insert(struct trusted_list** hash_table, char* src_ip,
84
-		      char* proto, char* pattern, char* tag);
84
+		      char* proto, char* pattern, char* ruri_pattern, char* tag, int priority);
85 85
 
86 86
 
87 87
 /* 
88 88
  * Check if an entry exists in hash table that has given src_ip and protocol
89
- * value and pattern that matches to From URI.
89
+ * value and pattern or ruri_pattern that matches to From URI.
90 90
  */
91 91
 int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
92 92
 		     char *scr_ip, int proto);
... ...
@@ -68,7 +68,9 @@ str trusted_table = str_init("trusted");   /* Name of trusted table */
68 68
 str source_col = str_init("src_ip");       /* Name of source address column */
69 69
 str proto_col = str_init("proto");         /* Name of protocol column */
70 70
 str from_col = str_init("from_pattern");   /* Name of from pattern column */
71
+str ruri_col = str_init("ruri_pattern");   /* Name of RURI pattern column */
71 72
 str tag_col = str_init("tag");             /* Name of tag column */
73
+str priority_col = str_init("priority");   /* Name of priority column */
72 74
 str tag_avp_param = {NULL, 0};             /* Peer tag AVP spec */
73 75
 int peer_tag_mode = 0;                     /* Add tags form all mathcing peers to avp */
74 76
 
... ...
@@ -166,7 +168,9 @@ static param_export_t params[] = {
166 166
 	{"source_col",         PARAM_STR, &source_col      },
167 167
 	{"proto_col",          PARAM_STR, &proto_col       },
168 168
 	{"from_col",           PARAM_STR, &from_col        },
169
+	{"ruri_col",           PARAM_STR, &ruri_col        },
169 170
 	{"tag_col",            PARAM_STR, &tag_col         },
171
+	{"priority_col",       PARAM_STR, &priority_col    },
170 172
 	{"peer_tag_avp",       PARAM_STR, &tag_avp_param   },
171 173
 	{"peer_tag_mode",      INT_PARAM, &peer_tag_mode     },
172 174
 	{"address_table",      PARAM_STR, &address_table   },
... ...
@@ -55,7 +55,9 @@ extern str trusted_table; /* Name of trusted table */
55 55
 extern str source_col;    /* Name of source address column */
56 56
 extern str proto_col;     /* Name of protocol column */
57 57
 extern str from_col;      /* Name of from pattern column */
58
+extern str ruri_col;      /* Name of RURI pattern column */
58 59
 extern str tag_col;       /* Name of tag column */
60
+extern str priority_col;  /* Name of priority column */
59 61
 extern str address_table; /* Name of address table */
60 62
 extern str grp_col;       /* Name of address group column */
61 63
 extern str ip_addr_col;   /* Name of ip address column */
... ...
@@ -41,7 +41,7 @@
41 41
 #include "../../parser/parse_from.h"
42 42
 #include "../../usr_avp.h"
43 43
 
44
-#define TABLE_VERSION 5
44
+#define TABLE_VERSION 6
45 45
 
46 46
 struct trusted_list ***hash_table;     /* Pointer to current hash table pointer */
47 47
 struct trusted_list **hash_table_1;   /* Pointer to hash table 1 */
... ...
@@ -58,7 +58,7 @@ static db_func_t perm_dbf;
58 58
  */
59 59
 int reload_trusted_table(void)
60 60
 {
61
-	db_key_t cols[4];
61
+	db_key_t cols[6];
62 62
 	db1_res_t* res = NULL;
63 63
 	db_row_t* row;
64 64
 	db_val_t* val;
... ...
@@ -66,13 +66,16 @@ int reload_trusted_table(void)
66 66
 	struct trusted_list **new_hash_table;
67 67
 	struct trusted_list **old_hash_table;
68 68
 	int i;
69
+	int priority;
69 70
 
70
-	char *pattern, *tag;
71
+	char *pattern, *ruri_pattern, *tag;
71 72
 
72 73
 	cols[0] = &source_col;
73 74
 	cols[1] = &proto_col;
74 75
 	cols[2] = &from_col;
75
-	cols[3] = &tag_col;
76
+	cols[3] = &ruri_col;
77
+	cols[4] = &tag_col;
78
+	cols[5] = &priority_col;
76 79
 
77 80
 	if (db_handle == 0) {
78 81
 	    LM_ERR("no connection to database\n");
... ...
@@ -84,7 +87,7 @@ int reload_trusted_table(void)
84 84
 		return -1;
85 85
 	}
86 86
 
87
-	if (perm_dbf.query(db_handle, NULL, 0, NULL, cols, 0, 4, 0, &res) < 0) {
87
+	if (perm_dbf.query(db_handle, NULL, 0, NULL, cols, 0, 6, 0, &res) < 0) {
88 88
 		LM_ERR("failed to query database\n");
89 89
 		return -1;
90 90
 	}
... ...
@@ -103,7 +106,7 @@ int reload_trusted_table(void)
103 103
 		
104 104
 	for (i = 0; i < RES_ROW_N(res); i++) {
105 105
 	    val = ROW_VALUES(row + i);
106
-	    if ((ROW_N(row + i) == 4) &&
106
+	    if ((ROW_N(row + i) == 6) &&
107 107
 		((VAL_TYPE(val) == DB1_STRING) || (VAL_TYPE(val) == DB1_STR) ) && 
108 108
 		!VAL_NULL(val) &&
109 109
 		((VAL_TYPE(val + 1) == DB1_STRING) || (VAL_TYPE(val + 1) == DB1_STR))
... ...
@@ -111,30 +114,42 @@ int reload_trusted_table(void)
111 111
 		(VAL_NULL(val + 2) ||
112 112
 		 (((VAL_TYPE(val + 2) == DB1_STRING) || (VAL_TYPE(val + 2) == DB1_STR)) &&
113 113
 		!VAL_NULL(val + 2))) && (VAL_NULL(val + 3) ||
114
-		 (((VAL_TYPE(val + 3) == DB1_STRING) || (VAL_TYPE(val + 3) == DB1_STR) )&& 
115
-		!VAL_NULL(val + 3)))) {
114
+		 (((VAL_TYPE(val + 3) == DB1_STRING) || (VAL_TYPE(val + 3) == DB1_STR) )&&
115
+		!VAL_NULL(val + 3))) && (VAL_NULL(val + 4) ||
116
+		 (((VAL_TYPE(val + 4) == DB1_STRING) || (VAL_TYPE(val + 4) == DB1_STR) )&&
117
+		!VAL_NULL(val + 4)))) {
116 118
 		if (VAL_NULL(val + 2)) {
117 119
 		    pattern = 0;
118 120
 		} else {
119 121
 		    pattern = (char *)VAL_STRING(val + 2);
120 122
 		}
121 123
 		if (VAL_NULL(val + 3)) {
124
+		    ruri_pattern = 0;
125
+		} else {
126
+		    ruri_pattern = (char *)VAL_STRING(val + 3);
127
+		}
128
+		if (VAL_NULL(val + 4)) {
122 129
 		    tag = 0;
123 130
 		} else {
124
-		    tag = (char *)VAL_STRING(val + 3);
131
+		    tag = (char *)VAL_STRING(val + 4);
132
+		}
133
+		if (VAL_NULL(val + 5)) {
134
+		    priority = 0;
135
+		} else {
136
+		    priority = (int)VAL_INT(val + 5);
125 137
 		}
126 138
 		if (hash_table_insert(new_hash_table,
127 139
 				      (char *)VAL_STRING(val),
128 140
 				      (char *)VAL_STRING(val + 1),
129
-				      pattern, tag) == -1) {
141
+				      pattern, ruri_pattern, tag, priority) == -1) {
130 142
 		    LM_ERR("hash table problem\n");
131 143
 		    perm_dbf.free_result(db_handle, res);
132 144
 		    empty_hash_table(new_hash_table);
133 145
 		    return -1;
134 146
 		}
135
-		LM_DBG("tuple <%s, %s, %s, %s> inserted into trusted hash "
147
+		LM_DBG("tuple <%s, %s, %s, %s, %s> inserted into trusted hash "
136 148
 		    "table\n", VAL_STRING(val), VAL_STRING(val + 1),
137
-		    pattern, tag);
149
+		    pattern, ruri_pattern, tag);
138 150
 	    } else {
139 151
 		LM_ERR("database problem\n");
140 152
 		perm_dbf.free_result(db_handle, res);
... ...
@@ -362,8 +377,9 @@ static inline int match_proto(const char *proto_string, int proto_int)
362 362
 static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
363 363
 {
364 364
 	int i, tag_avp_type;
365
-	str uri;
365
+	str uri, ruri;
366 366
 	char uri_string[MAX_URI_SIZE+1];
367
+	char ruri_string[MAX_URI_SIZE+1];
367 368
 	db_row_t* row;
368 369
 	db_val_t* val;
369 370
 	regex_t preg;
... ...
@@ -379,6 +395,13 @@ static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
379 379
 		}
380 380
 		memcpy(uri_string, uri.s, uri.len);
381 381
 		uri_string[uri.len] = (char)0;
382
+		ruri = msg->first_line.u.request.uri;
383
+		if (ruri.len > MAX_URI_SIZE) {
384
+			LM_ERR("message has Request URI too large\n");
385
+			return -1;
386
+		}
387
+		memcpy(ruri_string, ruri.s, ruri.len);
388
+		ruri_string[ruri.len] = (char)0;
382 389
 	}
383 390
 	get_tag_avp(&tag_avp, &tag_avp_type);
384 391
 
... ...
@@ -386,28 +409,45 @@ static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
386 386
 
387 387
 	for(i = 0; i < RES_ROW_N(_r); i++) {
388 388
 		val = ROW_VALUES(row + i);
389
-		if ((ROW_N(row + i) == 3) &&
389
+		if ((ROW_N(row + i) == 4) &&
390 390
 		    (VAL_TYPE(val) == DB1_STRING) && !VAL_NULL(val) &&
391 391
 		    match_proto(VAL_STRING(val), proto) &&
392 392
 		    (VAL_NULL(val + 1) ||
393 393
 		      ((VAL_TYPE(val + 1) == DB1_STRING) && !VAL_NULL(val + 1))) &&
394 394
 		    (VAL_NULL(val + 2) ||
395
-		      ((VAL_TYPE(val + 2) == DB1_STRING) && !VAL_NULL(val + 2))))
395
+		      ((VAL_TYPE(val + 2) == DB1_STRING) && !VAL_NULL(val + 2))) &&
396
+		    (VAL_NULL(val + 3) ||
397
+		      ((VAL_TYPE(val + 3) == DB1_STRING) && !VAL_NULL(val + 3))))
396 398
 		{
397
-			if (!VAL_NULL(val + 1) && IS_SIP(msg)) {
399
+			if (IS_SIP(msg)) {
400
+			    if (!VAL_NULL(val + 1)) {
398 401
 				if (regcomp(&preg, (char *)VAL_STRING(val + 1), REG_NOSUB)) {
399 402
 					LM_ERR("invalid regular expression\n");
400
-					continue;
403
+					if (VAL_NULL(val + 2)) {
404
+						continue;
405
+					}
401 406
 				}
402 407
 				if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
403 408
 					regfree(&preg);
404 409
 					continue;
405 410
 				}
406
-			    regfree(&preg);
411
+				regfree(&preg);
412
+			    }
413
+			    if (!VAL_NULL(val + 2)) {
414
+				if (regcomp(&preg, (char *)VAL_STRING(val + 2), REG_NOSUB)) {
415
+					LM_ERR("invalid regular expression\n");
416
+					continue;
417
+				}
418
+				if (regexec(&preg, ruri_string, 0, (regmatch_t *)0, 0)) {
419
+					regfree(&preg);
420
+					continue;
421
+				}
422
+				regfree(&preg);
423
+			    }
407 424
 			}
408 425
 			/* Found a match */
409
-			if (tag_avp.n && !VAL_NULL(val + 2)) {
410
-				avp_val.s.s = (char *)VAL_STRING(val + 2);
426
+			if (tag_avp.n && !VAL_NULL(val + 3)) {
427
+				avp_val.s.s = (char *)VAL_STRING(val + 3);
411 428
 				avp_val.s.len = strlen(avp_val.s.s);
412 429
 				if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, avp_val) != 0) {
413 430
 					LM_ERR("failed to set of tag_avp failed\n");
... ...
@@ -437,9 +477,10 @@ int allow_trusted(struct sip_msg* msg, char *src_ip, int proto)
437 437
 	
438 438
 	db_key_t keys[1];
439 439
 	db_val_t vals[1];
440
-	db_key_t cols[3];
440
+	db_key_t cols[4];
441 441
 
442 442
 	if (db_mode == DISABLE_CACHE) {
443
+		db_key_t order = &priority_col;
443 444
 	
444 445
 	        if (db_handle == 0) {
445 446
 		    LM_ERR("no connection to database\n");
... ...
@@ -449,7 +490,8 @@ int allow_trusted(struct sip_msg* msg, char *src_ip, int proto)
449 449
 		keys[0] = &source_col;
450 450
 		cols[0] = &proto_col;
451 451
 		cols[1] = &from_col;
452
-		cols[2] = &tag_col;
452
+		cols[2] = &ruri_col;
453
+		cols[3] = &tag_col;
453 454
 
454 455
 		if (perm_dbf.use_table(db_handle, &trusted_table) < 0) {
455 456
 			LM_ERR("failed to use trusted table\n");
... ...
@@ -460,7 +502,7 @@ int allow_trusted(struct sip_msg* msg, char *src_ip, int proto)
460 460
 		VAL_NULL(vals) = 0;
461 461
 		VAL_STRING(vals) = src_ip;
462 462
 
463
-		if (perm_dbf.query(db_handle, keys, 0, vals, cols, 1, 3, 0,
463
+		if (perm_dbf.query(db_handle, keys, 0, vals, cols, 1, 4, order,
464 464
 				   &res) < 0){
465 465
 			LM_ERR("failed to query database\n");
466 466
 			return -1;