Browse code

auth_db(k): new function is_subscriber(uri, dbtable, flags)

- check if URI corresponds to a subscriber record in dbtable and load
credentials for it

Daniel-Constantin Mierla authored on 16/10/2012 19:28:46
Showing 5 changed files
... ...
@@ -58,6 +58,7 @@ Jan Janak
58 58
               4.3. proxy_authenticate(realm, table)
59 59
               4.4. proxy_authorize(realm, table)
60 60
               4.5. auth_check(realm, table, flags)
61
+              4.6. is_subscriber(uri, dbtable, flags)
61 62
 
62 63
    List of Examples
63 64
 
... ...
@@ -73,6 +74,7 @@ Jan Janak
73 74
    1.10. www_authorize usage
74 75
    1.11. proxy_authorize usage
75 76
    1.12. auth_check usage
77
+   1.13. is_subscriber usage
76 78
 
77 79
 Chapter 1. Admin Guide
78 80
 
... ...
@@ -103,6 +105,7 @@ Chapter 1. Admin Guide
103 105
         4.3. proxy_authenticate(realm, table)
104 106
         4.4. proxy_authorize(realm, table)
105 107
         4.5. auth_check(realm, table, flags)
108
+        4.6. is_subscriber(uri, dbtable, flags)
106 109
 
107 110
 1. Overview
108 111
 
... ...
@@ -301,6 +304,7 @@ modparam("auth_db", "version_table", 0)
301 304
    4.3. proxy_authenticate(realm, table)
302 305
    4.4. proxy_authorize(realm, table)
303 306
    4.5. auth_check(realm, table, flags)
307
+   4.6. is_subscriber(uri, dbtable, flags)
304 308
 
305 309
 4.1. www_authenticate(realm, table)
306 310
 
... ...
@@ -420,3 +424,34 @@ if (!auth_check("$fd", "subscriber", "1")) {
420 424
     exit;
421 425
 }
422 426
 ...
427
+
428
+4.6. is_subscriber(uri, dbtable, flags)
429
+
430
+   The function checks if there is a subscriber corresponding to the AoR
431
+   in uri parameter. It uses same database connection as for
432
+   authentication functions.
433
+
434
+   In addition, if the subscriber record is found, then the
435
+   load_credentials attributes are loaded. An use case can be loading the
436
+   credential attributes for callee.
437
+
438
+   Meaning of the parameters is as follows:
439
+     * uri - a valid SIP URI value to identify the subscriber. The string
440
+       may contain pseudo variables.
441
+     * dbtable - Table to be used to lookup username and domain from URI
442
+       (usually subscriber table). The string may contain pseudo
443
+       variables.
444
+     * flags - set of flags to control the behaviour of the function. If
445
+       it is 1, then the function will use the domain part of the URI to
446
+       perform the database table search.
447
+       The parameter may be a pseudo variable.
448
+
449
+   This function can be used from ANY_ROUTE.
450
+
451
+   Example 1.13. is_subscriber usage
452
+...
453
+if (!is_subscriber("$ru", "subscriber", "1")) {
454
+    # callee is not a local subscriber
455
+    ...
456
+}
457
+...
... ...
@@ -43,6 +43,7 @@
43 43
 #include "../../mod_fix.h"
44 44
 #include "../../trim.h"
45 45
 #include "../../mem/mem.h"
46
+#include "../../parser/parse_uri.h"
46 47
 #include "../../modules/auth/api.h"
47 48
 #include "authorize.h"
48 49
 
... ...
@@ -68,6 +69,8 @@ static int child_init(int rank);
68 69
 static int mod_init(void);
69 70
 
70 71
 
72
+static int w_is_subscriber(sip_msg_t *msg, char *_uri, char* _table,
73
+		char *_flags);
71 74
 static int auth_fixup(void** param, int param_no);
72 75
 static int auth_check_fixup(void** param, int param_no);
73 76
 int parse_aaa_pvs(char *definition, pv_elem_t **pv_def, int *cnt);
... ...
@@ -122,6 +125,8 @@ static cmd_export_t cmds[] = {
122 125
 		REQUEST_ROUTE},
123 126
 	{"auth_check",         (cmd_function)auth_check,         3, auth_check_fixup, 0,
124 127
 		REQUEST_ROUTE},
128
+	{"is_subscriber",      (cmd_function)w_is_subscriber,    3, auth_check_fixup, 0,
129
+		ANY_ROUTE},
125 130
 	{"bind_auth_db",       (cmd_function)bind_auth_db,       0, 0, 0,
126 131
 		0},
127 132
 	{0, 0, 0, 0, 0, 0}
... ...
@@ -232,6 +237,64 @@ static void destroy(void)
232 237
 }
233 238
 
234 239
 
240
+/**
241
+ * check if the subscriber identified by _uri has a valid record in
242
+ * database table _table
243
+ */
244
+static int w_is_subscriber(sip_msg_t *msg, char *_uri, char* _table,
245
+		char *_flags)
246
+{
247
+	str suri;
248
+	str stable;
249
+	int iflags;
250
+	int ret;
251
+	sip_uri_t puri;
252
+
253
+	if(msg==NULL || _uri==NULL || _table==NULL || _flags==NULL) {
254
+		LM_ERR("invalid parameters\n");
255
+		return AUTH_ERROR;
256
+	}
257
+
258
+	if (get_str_fparam(&suri, msg, (fparam_t*)_uri) < 0) {
259
+		LM_ERR("failed to get uri value\n");
260
+		return -1;
261
+	}
262
+
263
+	if (suri.len==0) {
264
+		LM_ERR("invalid uri parameter - empty value\n");
265
+		return -1;
266
+	}
267
+	if(parse_uri(suri.s, suri.len, &puri)<0){
268
+		LM_ERR("invalid uri parameter format\n");
269
+		return -1;
270
+	}
271
+
272
+	if (get_str_fparam(&stable, msg, (fparam_t*)_table) < 0) {
273
+		LM_ERR("failed to get table value\n");
274
+		return -1;
275
+	}
276
+
277
+	if (stable.len==0) {
278
+		LM_ERR("invalid table parameter - empty value\n");
279
+		return -1;
280
+	}
281
+
282
+	if(fixup_get_ivalue(msg, (gparam_p)_flags, &iflags)!=0)
283
+	{
284
+		LM_ERR("invalid flags parameter\n");
285
+		return -1;
286
+	}
287
+
288
+	LM_DBG("uri [%.*s] table [%.*s] flags [%d]\n", suri.len, suri.s,
289
+			stable.len,  stable.s, iflags);
290
+	ret = fetch_credentials(msg, &puri.user, (iflags==1)?&puri.host:NULL,
291
+			&stable);
292
+
293
+	if(ret>=0)
294
+		return 1;
295
+	return ret;
296
+}
297
+
235 298
 /*
236 299
  * Convert the char* parameters
237 300
  */
... ...
@@ -52,6 +52,78 @@
52 52
 #include "authdb_mod.h"
53 53
 
54 54
 
55
+int fetch_credentials(sip_msg_t *msg, str *user, str* domain, str *table)
56
+{
57
+	pv_elem_t *cred;
58
+	db_key_t keys[2];
59
+	db_val_t vals[2];
60
+	db_key_t *col;
61
+	db1_res_t *res = NULL;
62
+
63
+	int n, nc;
64
+
65
+	col = pkg_malloc(sizeof(*col) * (credentials_n + 1));
66
+	if (col == NULL) {
67
+		LM_ERR("no more pkg memory\n");
68
+		return -1;
69
+	}
70
+
71
+	keys[0] = &user_column;
72
+	keys[1] = &domain_column;
73
+
74
+	for (n = 0, cred=credentials; cred ; n++, cred=cred->next) {
75
+		col[n] = &cred->text;
76
+	}
77
+
78
+	VAL_TYPE(vals) = VAL_TYPE(vals + 1) = DB1_STR;
79
+	VAL_NULL(vals) = VAL_NULL(vals + 1) = 0;
80
+
81
+	n = 1;
82
+	VAL_STR(vals) = *user;
83
+
84
+	if (domain && domain->len) {
85
+		VAL_STR(vals + 1) = *domain;
86
+		n = 2;
87
+	}
88
+
89
+	nc = credentials_n;
90
+	if (auth_dbf.use_table(auth_db_handle, table) < 0) {
91
+		LM_ERR("failed to use_table\n");
92
+		pkg_free(col);
93
+		return -1;
94
+	}
95
+
96
+	if (auth_dbf.query(auth_db_handle, keys, 0, vals, col, n, nc, 0, &res) < 0) {
97
+		LM_ERR("failed to query database\n");
98
+		pkg_free(col);
99
+		if(res)
100
+			auth_dbf.free_result(auth_db_handle, res);
101
+		return -1;
102
+	}
103
+	pkg_free(col);
104
+	if (RES_ROW_N(res) == 0) {
105
+		if(res)
106
+			auth_dbf.free_result(auth_db_handle, res);
107
+		LM_DBG("no result for user \'%.*s%s%.*s\' in [%.*s]\n",
108
+				user->len, user->s, (n==2)?"@":"",
109
+				(n==2)?domain->len:0, (n==2)?domain->s:"",
110
+				table->len, table->s);
111
+		return -2;
112
+	}
113
+	for (cred=credentials, n=0; cred; cred=cred->next, n++) {
114
+		if (db_val2pv_spec(msg, &RES_ROWS(res)[0].values[n], cred->spec) != 0) {
115
+			if(res)
116
+				auth_dbf.free_result(auth_db_handle, res);
117
+			LM_ERR("Failed to convert value for column %.*s\n",
118
+					RES_NAMES(res)[n]->len, RES_NAMES(res)[n]->s);
119
+			return -3;
120
+		}
121
+	}
122
+	if(res)
123
+		auth_dbf.free_result(auth_db_handle, res);
124
+	return 0;
125
+}
126
+
55 127
 static inline int get_ha1(struct username* _username, str* _domain,
56 128
 			  const str* _table, char* _ha1, db1_res_t** res)
57 129
 {
... ...
@@ -51,6 +51,11 @@ int www_authenticate(struct sip_msg* _msg, char* _realm, char* _table);
51 51
  */
52 52
 int auth_check(struct sip_msg* _m, char* _realm, char* _table, char *_flags);
53 53
 
54
+/*
55
+ * Fetch credentials for a specific user
56
+ */
57
+int fetch_credentials(sip_msg_t *msg, str *user, str* domain, str *table);
58
+
54 59
 /*
55 60
  * Bind to AUTH_DB API
56 61
  */
... ...
@@ -528,6 +528,58 @@ if (!auth_check("$fd", "subscriber", "1")) {
528 528
 	</section>
529 529
 
530 530
 
531
+	<section>
532
+		<title>
533
+			<function moreinfo="none">is_subscriber(uri, dbtable, flags)</function>
534
+		</title>
535
+		<para>The function checks if there is a subscriber corresponding to
536
+		the AoR in uri parameter. It uses same database connection as for
537
+		authentication functions.
538
+		</para>
539
+		<para>
540
+		In addition, if the subscriber record is found, then the load_credentials
541
+		attributes are loaded. An use case can be loading the credential attributes
542
+		for callee.
543
+		</para>
544
+		<para>Meaning of the parameters is as follows:</para>
545
+		<itemizedlist>
546
+		<listitem>
547
+			<para><emphasis>uri</emphasis> - a valid SIP URI value to identify
548
+			the subscriber. The string may contain pseudo variables.
549
+			</para>
550
+		</listitem>
551
+		<listitem>
552
+			<para><emphasis>dbtable</emphasis> - Table to be used to lookup
553
+			username and domain from URI (usually subscriber table). The string
554
+			may contain pseudo variables.
555
+			</para>
556
+		</listitem>
557
+		<listitem>
558
+			<para><emphasis>flags</emphasis> - set of flags to control the
559
+			behaviour of the function. If it is 1, then the function will
560
+			use the domain part of the URI to perform the database table search.
561
+			</para>
562
+			<para>
563
+			The parameter may be a pseudo variable.
564
+			</para>
565
+		</listitem>
566
+		</itemizedlist>
567
+		<para>
568
+		This function can be used from ANY_ROUTE.
569
+		</para>
570
+		<example>
571
+		<title>is_subscriber usage</title>
572
+		<programlisting format="linespecific">
573
+...
574
+if (!is_subscriber("$ru", "subscriber", "1")) {
575
+    # callee is not a local subscriber
576
+    ...
577
+}
578
+...
579
+</programlisting>
580
+		</example>
581
+	</section>
582
+
531 583
 	</section>
532 584
 </chapter>
533 585