Browse code

permissions: Improve From pattern matching in kamailio permissions module

- allow_trusted() now can take optional parameter of value to match.
- provided parameter will be used instead of From header in match_res() and match_hash_table()
- documentation extended with 3-arguments allow_trusted() function description

Roman Romanchenko authored on 09/07/2018 10:58:00
Showing 6 changed files
... ...
@@ -254,7 +254,7 @@
254 254
 		<listitem>
255 255
 			<para>
256 256
 			regular expression is either empty (NULL in
257
-			database) or matches the From URI of request.
257
+			database) or matches the request's From (or optionally provided) URI.
258 258
 			</para>
259 259
 		</listitem>
260 260
 		</itemizedlist>
... ...
@@ -1185,12 +1185,12 @@ if ($var(group) != -1) {
1185 1185
 	</section>
1186 1186
 	<section id ="permissions.f.allow_trusted">
1187 1187
 		<title>
1188
-		<function moreinfo="none">allow_trusted([src_ip_pvar, proto_pvar])</function>
1188
+		<function moreinfo="none">allow_trusted([src_ip_pvar, proto_pvar, uri_pvar])</function>
1189 1189
 		</title>
1190 1190
 		<para>
1191 1191
 		Checks based either on request's source address and transport
1192 1192
 		protocol or source address and transport protocol given
1193
-		in pvar arguments, and From URI of request
1193
+		in pvar arguments, and From URI of request (or uri_pvar if provided)
1194 1194
 		if request can be trusted without
1195 1195
 		authentication.  Returns <quote>1</quote> if a match is found
1196 1196
 		as described in <xref linkend="sec-trusted-requests"/>
... ...
@@ -1200,7 +1200,7 @@ if ($var(group) != -1) {
1200 1200
 		matching peer to AVP peer_tag_avp.
1201 1201
 		</para>
1202 1202
 		<para>
1203
-		Source address and transport protocol given in pvar
1203
+		Source address, transport protocol and uri given in pvar
1204 1204
 		arguments must be in string format.  Valid transport
1205 1205
 		protocol values are (ignoring case) "any", "udp, "tcp", "tls",
1206 1206
 		"ws", "wss" and "sctp".
... ...
@@ -250,10 +250,10 @@ int hash_table_insert(struct trusted_list** table, char* src_ip,
250 250
  * Returns number of matches or -1 if none matched.
251 251
  */
252 252
 int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
253
-		char *src_ip_c_str, int proto)
253
+		char *src_ip_c_str, int proto, char *uri)
254 254
 {
255
-	str uri, ruri;
256
-	char uri_string[MAX_URI_SIZE + 1];
255
+	LM_DBG("match_hash_table src_ip: %s, proto: %d, uri: %s\n", src_ip_c_str, proto, uri);
256
+	str ruri;
257 257
 	char ruri_string[MAX_URI_SIZE + 1];
258 258
 	regex_t preg;
259 259
 	struct trusted_list *np;
... ...
@@ -266,14 +266,6 @@ int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
266 266
 
267 267
 	if (IS_SIP(msg))
268 268
 	{
269
-		if (parse_from_header(msg) < 0) return -1;
270
-		uri = get_from(msg)->uri;
271
-		if (uri.len > MAX_URI_SIZE) {
272
-			LM_ERR("from URI too large\n");
273
-			return -1;
274
-		}
275
-		memcpy(uri_string, uri.s, uri.len);
276
-		uri_string[uri.len] = (char)0;
277 269
 		ruri = msg->first_line.u.request.uri;
278 270
 		if (ruri.len > MAX_URI_SIZE) {
279 271
 			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,
288 280
 				(strncmp(np->src_ip.s, src_ip.s, src_ip.len) == 0) &&
289 281
 				((np->proto == PROTO_NONE) || (proto == PROTO_NONE) ||
290 282
 				(np->proto == proto))) {
283
+
284
+			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"));
285
+
291 286
 			if (IS_SIP(msg)) {
292 287
 				if (np->pattern) {
293 288
 					if (regcomp(&preg, np->pattern, REG_NOSUB)) {
294 289
 						LM_ERR("invalid regular expression\n");
295
-						if (!np->ruri_pattern) {
290
+						if (!np->pattern) {
296 291
 							continue;
297 292
 						}
298 293
 					}
299
-					if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
294
+					if (regexec(&preg, uri, 0, (regmatch_t *)0, 0)) {
300 295
 						regfree(&preg);
301 296
 						continue;
302 297
 					}
... ...
@@ -327,6 +322,7 @@ int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
327 322
 			count++;
328 323
 		}
329 324
 	}
325
+
330 326
 	if (!count)
331 327
 		return -1;
332 328
 	else
... ...
@@ -85,10 +85,10 @@ int hash_table_insert(struct trusted_list** hash_table, char* src_ip,
85 85
 
86 86
 /*
87 87
  * Check if an entry exists in hash table that has given src_ip and protocol
88
- * value and pattern or ruri_pattern that matches to From URI.
88
+ * value and pattern or ruri_pattern that matches to provided URI.
89 89
  */
90 90
 int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
91
-		char *scr_ip, int proto);
91
+		char *scr_ip, int proto, char *uri);
92 92
 
93 93
 
94 94
 /*
... ...
@@ -141,6 +141,8 @@ static cmd_export_t cmds[] = {
141 141
 		ANY_ROUTE},
142 142
 	{"allow_trusted",  (cmd_function)allow_trusted_2,  2, fixup_spve_spve,
143 143
 		fixup_free_spve_spve, ANY_ROUTE},
144
+	{"allow_trusted",  (cmd_function)allow_trusted_3,  3, fixup_spve_all,
145
+		fixup_free_spve_all, ANY_ROUTE},
144 146
 	{"allow_uri",      (cmd_function)allow_uri, 2, double_fixup, 0,
145 147
 		REQUEST_ROUTE | FAILURE_ROUTE},
146 148
 	{"allow_address",  (cmd_function)w_allow_address, 3, fixup_allow_address,
... ...
@@ -354,16 +354,15 @@ static inline int match_proto(const char *proto_string, int proto_int)
354 354
 
355 355
 	return 0;
356 356
 }
357
-
358 357
 /*
359 358
  * Matches from uri against patterns returned from database.  Returns number
360 359
  * of matches or -1 if none of the patterns match.
361 360
  */
362
-static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
361
+static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r, char* uri)
363 362
 {
364 363
 	int i, tag_avp_type;
365
-	str uri, ruri;
366
-	char uri_string[MAX_URI_SIZE+1];
364
+	str ruri;
365
+
367 366
 	char ruri_string[MAX_URI_SIZE+1];
368 367
 	db_row_t* row;
369 368
 	db_val_t* val;
... ...
@@ -372,14 +371,6 @@ static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
372 371
 	int count = 0;
373 372
 
374 373
 	if (IS_SIP(msg)) {
375
-		if (parse_from_header(msg) < 0) return -1;
376
-		uri = get_from(msg)->uri;
377
-		if (uri.len > MAX_URI_SIZE) {
378
-			LM_ERR("message has From URI too large\n");
379
-			return -1;
380
-		}
381
-		memcpy(uri_string, uri.s, uri.len);
382
-		uri_string[uri.len] = (char)0;
383 374
 		ruri = msg->first_line.u.request.uri;
384 375
 		if (ruri.len > MAX_URI_SIZE) {
385 376
 			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)
392 383
 
393 384
 	row = RES_ROWS(_r);
394 385
 
386
+	LM_DBG("match_res: row numbers %d\n",  RES_ROW_N(_r));
387
+
395 388
 	for(i = 0; i < RES_ROW_N(_r); i++) {
396 389
 		val = ROW_VALUES(row + i);
397 390
 		if ((ROW_N(row + i) == 4) &&
... ...
@@ -404,6 +397,8 @@ static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
404 397
 				(VAL_NULL(val + 3) ||
405 398
 				((VAL_TYPE(val + 3) == DB1_STRING) && !VAL_NULL(val + 3))))
406 399
 		{
400
+			LM_DBG("match_res: %s, %s, %s, %s\n", VAL_STRING(val), VAL_STRING(val + 1), VAL_STRING(val + 2), VAL_STRING(val + 3));
401
+
407 402
 			if (IS_SIP(msg)) {
408 403
 				if (!VAL_NULL(val + 1)) {
409 404
 					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)
412 407
 							continue;
413 408
 						}
414 409
 					}
415
-					if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
410
+					if (regexec(&preg, uri, 0, (regmatch_t *)0, 0)) {
416 411
 						regfree(&preg);
417 412
 						continue;
418 413
 					}
... ...
@@ -444,19 +439,17 @@ static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
444 439
 			count++;
445 440
 		}
446 441
 	}
447
-	if (!count)
448
-		return -1;
449
-	else
450
-		return count;
451
-}
452 442
 
443
+	return (count == 0 ? -1 : count);
444
+}
453 445
 
454 446
 /*
455 447
  * Checks based on given source IP address and protocol, and From URI
456 448
  * of request if request can be trusted without authentication.
457 449
  */
458
-int allow_trusted(struct sip_msg* msg, char *src_ip, int proto)
450
+int allow_trusted(struct sip_msg* msg, char *src_ip, int proto, char *uri)
459 451
 {
452
+	LM_DBG("allow_trusted src_ip: %s, proto: %d, uri: %s\n", src_ip, proto, uri);
460 453
 	int result;
461 454
 	db1_res_t* res = NULL;
462 455
 
... ...
@@ -498,11 +491,11 @@ int allow_trusted(struct sip_msg* msg, char *src_ip, int proto)
498 491
 			return -1;
499 492
 		}
500 493
 
501
-		result = match_res(msg, proto, res);
494
+		result = match_res(msg, proto, res, uri);
502 495
 		perm_dbf.free_result(db_handle, res);
503 496
 		return result;
504 497
 	} else {
505
-		return match_hash_table(*hash_table, msg, src_ip, proto);
498
+		return match_hash_table(*hash_table, msg, src_ip, proto, uri);
506 499
 	}
507 500
 }
508 501
 
... ...
@@ -513,16 +506,29 @@ int allow_trusted(struct sip_msg* msg, char *src_ip, int proto)
513 506
  */
514 507
 int allow_trusted_0(struct sip_msg* _msg, char* str1, char* str2)
515 508
 {
516
-	return allow_trusted(_msg, ip_addr2a(&(_msg->rcv.src_ip)),
517
-			_msg->rcv.proto);
518
-}
509
+	str uri;
510
+	char uri_string[MAX_URI_SIZE+1];
511
+
512
+	if (IS_SIP(_msg)) {
513
+		if (parse_from_header(_msg) < 0) return -1;
514
+		uri = get_from(_msg)->uri;
515
+		if (uri.len > MAX_URI_SIZE) {
516
+			LM_ERR("message has From URI too large\n");
517
+			return -1;
518
+		}
519 519
 
520
+		memcpy(uri_string, uri.s, uri.len);
521
+		uri_string[uri.len] = (char)0;
522
+	}
523
+
524
+	return allow_trusted(_msg, ip_addr2a(&(_msg->rcv.src_ip)), _msg->rcv.proto, uri_string);
525
+}
520 526
 
521 527
 /*
522 528
  * Checks based on source address and protocol given in pvar arguments and
523
- * and requests's From URI, if request can be trusted without authentication.
529
+ * provided uri, if request can be trusted without authentication.
524 530
  */
525
-int allow_trusted_2(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp)
531
+int allow_trusted_1(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp, char *uri_string)
526 532
 {
527 533
 	str src_ip, proto;
528 534
 	int proto_int;
... ...
@@ -576,12 +582,50 @@ int allow_trusted_2(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp)
576 582
 			goto error;
577 583
 	}
578 584
 
579
-	return allow_trusted(_msg, src_ip.s, proto_int);
585
+	return allow_trusted(_msg, src_ip.s, proto_int, uri_string);
580 586
 error:
581 587
 	LM_ERR("unknown protocol %.*s\n", proto.len, proto.s);
582 588
 	return -1;
583 589
 }
584 590
 
591
+/*
592
+ * Checks based on source address and protocol given in pvar arguments and
593
+ * and requests's From URI, if request can be trusted without authentication.
594
+ */
595
+int allow_trusted_2(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp)
596
+{
597
+	str uri;
598
+	char uri_string[MAX_URI_SIZE+1];
599
+
600
+	if (IS_SIP(_msg)) {
601
+		if (parse_from_header(_msg) < 0) return -1;
602
+		uri = get_from(_msg)->uri;
603
+		if (uri.len > MAX_URI_SIZE) {
604
+			LM_ERR("message has From URI too large\n");
605
+			return -1;
606
+		}
607
+
608
+		memcpy(uri_string, uri.s, uri.len);
609
+		uri_string[uri.len] = (char)0;
610
+	}
611
+
612
+	return allow_trusted_1(_msg, _src_ip_sp, _proto_sp, uri_string);
613
+}
614
+
615
+/*
616
+ * Checks based on source address and protocol given in pvar arguments and
617
+ * and requests's From URI, if request can be trusted without authentication.
618
+ */
619
+int allow_trusted_3(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp, char *_uri)
620
+{
621
+	str uri;
622
+	if (_uri==NULL || (fixup_get_svalue(_msg, (gparam_p)_uri, &uri) != 0)) {
623
+		LM_ERR("uri param does not exist or has no value\n");
624
+		return -1;
625
+	}
626
+
627
+	return allow_trusted_1(_msg, _src_ip_sp, _proto_sp, uri.s);
628
+}
585 629
 
586 630
 int reload_trusted_table_cmd(void)
587 631
 {
... ...
@@ -75,6 +75,11 @@ int allow_trusted_0(struct sip_msg* _msg, char* str1, char* str2);
75 75
  */
76 76
 int allow_trusted_2(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp);
77 77
 
78
+/*
79
+ * Checks based on source address and protocol given in pvar arguments and
80
+ * provided URI, if request can be trusted without authentication.
81
+ */
82
+int allow_trusted_3(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp, char* uri);
78 83
 
79 84
 int reload_trusted_table_cmd(void);
80 85