Browse code

- regular expression based group matching added

git-svn-id: https://openser.svn.sourceforge.net/svnroot/openser/trunk@386 689a6050-402a-0410-94f2-e92a70836424

Bogdan-Andrei Iancu authored on 21/11/2005 18:12:35
Showing 8 changed files
... ...
@@ -16,6 +16,10 @@ Jan Janak
16 16
    1. User's Guide
17 17
 
18 18
         1.1. Overview
19
+
20
+              1.1.1. Strict membership checking
21
+              1.1.2. Regular Expression based checking
22
+
19 23
         1.2. Dependencies
20 24
 
21 25
               1.2.1. OpenSER Modules
... ...
@@ -29,10 +33,15 @@ Jan Janak
29 33
               1.3.4. domain_column (string)
30 34
               1.3.5. group_column (string)
31 35
               1.3.6. use_domain (integer)
36
+              1.3.7. re_table (string)
37
+              1.3.8. re_exp_column (string)
38
+              1.3.9. re_gid_column (string)
39
+              1.3.10. multiple_gid (integer)
32 40
 
33 41
         1.4. Exported Functions
34 42
 
35 43
               1.4.1. is_user_in(URI, group)
44
+              1.4.2. get_user_group(URI, AVP)
36 45
 
37 46
    2. Developer's Guide
38 47
    3. Frequently Asked Questions
... ...
@@ -44,17 +53,42 @@ Jan Janak
44 53
    1-4. Set domain_column parameter
45 54
    1-5. Set group_column parameter
46 55
    1-6. Set use_domain parameter
47
-   1-7. is_user_in usage
56
+   1-7. Set re_table parameter
57
+   1-8. Set reg_exp parameter
58
+   1-9. Set group_id parameter
59
+   1-10. Set multiple_gid parameter
60
+   1-11. is_user_in usage
61
+   1-12. get_user_group usage
48 62
      _________________________________________________________
49 63
 
50 64
 Chapter 1. User's Guide
51 65
 
52 66
 1.1. Overview
53 67
 
54
-   This module export functions necessary for group membership
55
-   checking. There is a database table that contains list of
56
-   users and groups they belong to. The table is used by
57
-   functions of this module.
68
+   This module provides functionalities for different methods of
69
+   group membership checking.
70
+     _________________________________________________________
71
+
72
+1.1.1. Strict membership checking
73
+
74
+   There is a database table that contains list of users and
75
+   groups they belong to. The module provides the possibility to
76
+   check if a specific user belongs to a specific group.
77
+
78
+   There is no DB caching support, each check involving a DB
79
+   query.
80
+     _________________________________________________________
81
+
82
+1.1.2. Regular Expression based checking
83
+
84
+   Another database table contains list of regular expressions
85
+   and group IDs. A matching occurs if the user URI match the
86
+   regular expression. This type of matching may be used to fetch
87
+   the group ID(s) the user belongs to (via RE matching) .
88
+
89
+   Due performance reasons (regular expression evaluation), DB
90
+   cache support is available: the table content is loaded into
91
+   memory at startup and all regular expressions are compiled.
58 92
      _________________________________________________________
59 93
 
60 94
 1.2. Dependencies
... ...
@@ -91,7 +125,8 @@ modparam("group", "db_url", "mysql://username:password@dbhost/openser")
91 125
 
92 126
 1.3.2. table (string)
93 127
 
94
-   Name of the table holding groups and their members.
128
+   Name of the table holding strict definitions of groups and
129
+   their members.
95 130
 
96 131
    Default value is "grp". 
97 132
 
... ...
@@ -103,7 +138,7 @@ modparam("group", "table", "grp_table")
103 138
 
104 139
 1.3.3. user_column (string)
105 140
 
106
-   Name of the column holding usernames.
141
+   Name of the "table" column holding usernames.
107 142
 
108 143
    Default value is "username". 
109 144
 
... ...
@@ -115,7 +150,7 @@ modparam("group", "user_column", "user")
115 150
 
116 151
 1.3.4. domain_column (string)
117 152
 
118
-   Name of the column holding domains.
153
+   Name of the "table" column holding domains.
119 154
 
120 155
    Default value is "domain". 
121 156
 
... ...
@@ -127,7 +162,7 @@ modparam("group", "domain_column", "realm")
127 162
 
128 163
 1.3.5. group_column (string)
129 164
 
130
-   Name of the column holding groups.
165
+   Name of the "table" column holding groups.
131 166
 
132 167
    Default value is "grp". 
133 168
 
... ...
@@ -139,8 +174,9 @@ modparam("group", "group_column", "grp")
139 174
 
140 175
 1.3.6. use_domain (integer)
141 176
 
142
-   If set to 1 then username@domain will be used for lookup, if
143
-   set to 0 then only username will be used.
177
+   If enabled (set to non zero value) then domain will be used
178
+   also used for strict group matching; otherwise only the
179
+   username part will be used.
144 180
 
145 181
    Default value is 0 (no). 
146 182
 
... ...
@@ -150,12 +186,65 @@ modparam("group", "use_domain", 1)
150 186
 ...
151 187
      _________________________________________________________
152 188
 
189
+1.3.7. re_table (string)
190
+
191
+   Name of the table holding definitions for regular-expression
192
+   based groups.
193
+
194
+   Default value is "re_grp". 
195
+
196
+   Example 1-7. Set re_table parameter
197
+...
198
+modparam("group", "re_table", "re_grp_table")
199
+...
200
+     _________________________________________________________
201
+
202
+1.3.8. re_exp_column (string)
203
+
204
+   Name of the "re_table" column holding the regular expression
205
+   used for user matching.
206
+
207
+   Default value is "reg_exp". 
208
+
209
+   Example 1-8. Set reg_exp parameter
210
+...
211
+modparam("group", "reg_exp", "re")
212
+...
213
+     _________________________________________________________
214
+
215
+1.3.9. re_gid_column (string)
216
+
217
+   Name of the "re_table" column holding the group IDs.
218
+
219
+   Default value is "group_id". 
220
+
221
+   Example 1-9. Set group_id parameter
222
+...
223
+modparam("group", "group_id", "grp_id")
224
+...
225
+     _________________________________________________________
226
+
227
+1.3.10. multiple_gid (integer)
228
+
229
+   If enabled (non zero value) the regular-expression matching
230
+   will return all group IDs that match the user; otherwise only
231
+   the first will be returned.
232
+
233
+   Default value is "1". 
234
+
235
+   Example 1-10. Set multiple_gid parameter
236
+...
237
+modparam("group", "multiple_gid", 0)
238
+...
239
+     _________________________________________________________
240
+
153 241
 1.4. Exported Functions
154 242
 
155 243
 1.4.1. is_user_in(URI, group)
156 244
 
157
-   The function returns true if username in the given URI is
158
-   member of the given group and false if not.
245
+   This function is to be used for script group membership. The
246
+   function returns true if username in the given URI is member
247
+   of the given group and false if not.
159 248
 
160 249
    Meaning of the parameters is as follows:
161 250
 
... ...
@@ -170,9 +259,10 @@ modparam("group", "use_domain", 1)
170 259
             specified by this pseudo-variable.
171 260
      * group - Name of the group to check.
172 261
 
173
-   This function can be used from REQUEST_ROUTE.
262
+   This function can be used from REQUEST_ROUTE and
263
+   FAILURE_ROUTE.
174 264
 
175
-   Example 1-7. is_user_in usage
265
+   Example 1-11. is_user_in usage
176 266
 ...
177 267
 if (is_user_in("Request-URI", "ld")) {
178 268
         ...
... ...
@@ -180,6 +270,39 @@ if (is_user_in("Request-URI", "ld")) {
180 270
 ...
181 271
      _________________________________________________________
182 272
 
273
+1.4.2. get_user_group(URI, AVP)
274
+
275
+   This function is to be used for regular expression based group
276
+   membership. The function returns true if username in the given
277
+   URI belongs to at least on group; the group ID(s) are returned
278
+   as AVPs.
279
+
280
+   Meaning of the parameters is as follows:
281
+
282
+     * URI - URI to be matched against the regular expressions:
283
+          + Request-URI - Use Request-URI
284
+          + To - Use To URI.
285
+          + From - Use From URI
286
+          + Credentials - Use digest credentials username and
287
+            realm.
288
+          + $avp[avp_name|avp_alias] - Use the URI from the AVP
289
+            specified by this pseudo-variable.
290
+     * AVP_ID - The matched group IDs are returned as AVPs named
291
+       "AVP". It accepts a full AVP specification: AVP, ID and
292
+       NAME. alias also
293
+
294
+   This function can be used from REQUEST_ROUTE and
295
+   FAILURE_ROUTE.
296
+
297
+   Example 1-12. get_user_group usage
298
+...
299
+if (get_user_group("Request-URI", "i:10")) {
300
+    xgdb("User $ru belongs to $avp(i:10[*]) group(s)\n");
301
+    ....
302
+};
303
+...
304
+     _________________________________________________________
305
+
183 306
 Chapter 2. Developer's Guide
184 307
 
185 308
    The module does not provide any API to use in other OpenSER
... ...
@@ -12,12 +12,36 @@
12 12
 	<title>User's Guide</title>
13 13
 	
14 14
 	<section>
15
-	<title>Overview</title>
16
-	<para>
17
-		This module export functions necessary for group membership checking. 
18
-		There is a database table that contains list of users and groups they
19
-		belong to. The table is used by functions of this module.
20
-	</para>
15
+		<title>Overview</title>
16
+		<para>
17
+		This module provides functionalities for different methods of group 
18
+		membership checking.
19
+		</para>
20
+		<section>
21
+			<title>Strict membership checking</title>
22
+			<para>
23
+			There is a database table that contains list of users and groups 
24
+			they belong to. The module provides the possibility to check if a
25
+			specific user belongs to a specific group.
26
+			</para>
27
+			<para>
28
+			There is no DB caching support, each check involving a DB query.
29
+			</para>
30
+		</section>
31
+		<section>
32
+			<title>Regular Expression based checking</title>
33
+			<para>
34
+			Another database table contains list of regular expressions and 
35
+			group IDs. A matching occurs if the user URI match the regular
36
+			expression. This type of matching may be used to fetch the 
37
+			group ID(s) the user belongs to (via RE matching) .
38
+			</para>
39
+			<para>
40
+			Due performance reasons (regular expression evaluation), DB cache
41
+			support is available: the table content is loaded into memory at 
42
+			startup and all regular expressions are compiled.
43
+			</para>
44
+		</section>
21 45
 	</section>
22 46
 
23 47
 	<section>
... ...
@@ -38,8 +62,8 @@
38 62
 	<section>
39 63
 		<title>External Libraries or Applications</title>
40 64
 		<para>
41
-		The following libraries or applications must be installed before running
42
-		&ser; with this module loaded:
65
+		The following libraries or applications must be installed before 
66
+		running &ser; with this module loaded:
43 67
 			<itemizedlist>
44 68
 			<listitem>
45 69
 			<para>
... ...
@@ -77,7 +101,8 @@ modparam("group", "db_url", "mysql://username:password@dbhost/openser")
77 101
 	<section>
78 102
 		<title><varname>table</varname> (string)</title>
79 103
 		<para>
80
-		Name of the table holding groups and their members.
104
+		Name of the table holding strict definitions of groups and 
105
+		their members.
81 106
 		</para>
82 107
 		<para>
83 108
 		<emphasis>
... ...
@@ -97,7 +122,7 @@ modparam("group", "table", "grp_table")
97 122
 	<section>
98 123
 		<title><varname>user_column</varname> (string)</title>
99 124
 		<para>
100
-		Name of the column holding usernames.
125
+		Name of the <quote>table</quote> column holding usernames.
101 126
 		</para>
102 127
 		<para>
103 128
 		<emphasis>
... ...
@@ -117,7 +142,7 @@ modparam("group", "user_column", "user")
117 142
 	<section>
118 143
 		<title><varname>domain_column</varname> (string)</title>
119 144
 		<para>
120
-		Name of the column holding domains.
145
+		Name of the <quote>table</quote> column holding domains.
121 146
 		</para>
122 147
 		<para>
123 148
 		<emphasis>
... ...
@@ -137,7 +162,7 @@ modparam("group", "domain_column", "realm")
137 162
 	<section>
138 163
 		<title><varname>group_column</varname> (string)</title>
139 164
 		<para>
140
-		Name of the column holding groups.
165
+		Name of the <quote>table</quote> column holding groups.
141 166
 		</para>
142 167
 		<para>
143 168
 		<emphasis>
... ...
@@ -157,8 +182,9 @@ modparam("group", "group_column", "grp")
157 182
 	<section>
158 183
 		<title><varname>use_domain</varname> (integer)</title>
159 184
 		<para>
160
-		If set to 1 then username@domain will be used for lookup, if set 
161
-		to 0 then only username will be used.
185
+		If enabled (set to non zero value) then domain will be used also used
186
+		for strict group matching; otherwise only the username part will be 
187
+		used.
162 188
 		</para>
163 189
 		<para>
164 190
 		<emphasis>
... ...
@@ -175,7 +201,91 @@ modparam("group", "use_domain", 1)
175 201
 		</example>
176 202
 	</section>
177 203
 
204
+	<section>
205
+		<title><varname>re_table</varname> (string)</title>
206
+		<para>
207
+		Name of the table holding definitions for regular-expression 
208
+		based groups.
209
+		</para>
210
+		<para>
211
+		<emphasis>
212
+			Default value is <quote>re_grp</quote>.
213
+		</emphasis>
214
+		</para>
215
+		<example>
216
+		<title>Set <varname>re_table</varname> parameter</title>
217
+		<programlisting format="linespecific">
218
+...
219
+modparam("group", "re_table", "re_grp_table")
220
+...
221
+</programlisting>
222
+		</example>
223
+	</section>
224
+
225
+	<section>
226
+		<title><varname>re_exp_column</varname> (string)</title>
227
+		<para>
228
+		Name of the <quote>re_table</quote> column holding the regular
229
+		expression used for user matching.
230
+		</para>
231
+		<para>
232
+		<emphasis>
233
+			Default value is <quote>reg_exp</quote>.
234
+		</emphasis>
235
+		</para>
236
+		<example>
237
+		<title>Set <varname>reg_exp</varname> parameter</title>
238
+		<programlisting format="linespecific">
239
+...
240
+modparam("group", "reg_exp", "re")
241
+...
242
+</programlisting>
243
+		</example>
244
+	</section>
245
+
246
+	<section>
247
+		<title><varname>re_gid_column</varname> (string)</title>
248
+		<para>
249
+		Name of the <quote>re_table</quote> column holding the group IDs.
250
+		</para>
251
+		<para>
252
+		<emphasis>
253
+			Default value is <quote>group_id</quote>.
254
+		</emphasis>
255
+		</para>
256
+		<example>
257
+		<title>Set <varname>group_id</varname> parameter</title>
258
+		<programlisting format="linespecific">
259
+...
260
+modparam("group", "group_id", "grp_id")
261
+...
262
+</programlisting>
263
+		</example>
264
+	</section>
265
+
266
+	<section>
267
+		<title><varname>multiple_gid</varname> (integer)</title>
268
+		<para>
269
+		If enabled (non zero value) the regular-expression matching will
270
+		return all group IDs that match the user; otherwise only the first
271
+		will be returned.
272
+		</para>
273
+		<para>
274
+		<emphasis>
275
+			Default value is <quote>1</quote>.
276
+		</emphasis>
277
+		</para>
278
+		<example>
279
+		<title>Set <varname>multiple_gid</varname> parameter</title>
280
+		<programlisting format="linespecific">
281
+...
282
+modparam("group", "multiple_gid", 0)
283
+...
284
+</programlisting>
285
+		</example>
286
+	</section>
178 287
 	</section>
288
+
179 289
 	<section>
180 290
 	<title>Exported Functions</title>
181 291
 	<section>
... ...
@@ -183,8 +293,9 @@ modparam("group", "use_domain", 1)
183 293
 		<function moreinfo="none">is_user_in(URI, group)</function>
184 294
 		</title>
185 295
 		<para>
186
-		The function returns true if username in the given &uri; is member of 
187
-		the given group and false if not.
296
+		This function is to be used for script group membership. The function 
297
+		returns true if username in the given &uri; is member of the given
298
+		group and false if not.
188 299
 		</para>
189 300
 		<para>Meaning of the parameters is as follows:</para>
190 301
 		<itemizedlist>
... ...
@@ -193,8 +304,8 @@ modparam("group", "use_domain", 1)
193 304
 			optionally domain to be used, this can be one of:
194 305
 			<itemizedlist>
195 306
 				<listitem>
196
-				<para>Request-URI - Use Request-URI username and (optionally) 
197
-				domain.</para>
307
+				<para>Request-URI - Use Request-URI username and 
308
+				(optionally) domain.</para>
198 309
 				</listitem>
199 310
 				<listitem>
200 311
 				<para>To - Use To username and (optionally) domain.</para>
... ...
@@ -218,7 +329,7 @@ modparam("group", "use_domain", 1)
218 329
 		</listitem>
219 330
 		</itemizedlist>
220 331
 		<para>
221
-		This function can be used from REQUEST_ROUTE.
332
+		This function can be used from REQUEST_ROUTE and FAILURE_ROUTE.
222 333
 		</para>
223 334
 		<example>
224 335
 		<title><function>is_user_in</function> usage</title>
... ...
@@ -231,7 +342,67 @@ if (is_user_in("Request-URI", "ld")) {
231 342
 </programlisting>
232 343
 		</example>
233 344
 	</section>
345
+
346
+	<section>
347
+		<title>
348
+		<function moreinfo="none">get_user_group(URI, AVP)</function>
349
+		</title>
350
+		<para>
351
+		This function is to be used for regular expression based group 
352
+		membership. The function returns true if username in the given &uri; 
353
+		belongs to at least on group; the group ID(s) are returned as AVPs.
354
+		</para>
355
+		<para>Meaning of the parameters is as follows:</para>
356
+		<itemizedlist>
357
+		<listitem>
358
+			<para><emphasis>&uri;</emphasis> - &uri; to be matched against
359
+			the regular expressions:
360
+			<itemizedlist>
361
+				<listitem>
362
+				<para>Request-URI - Use Request-URI</para>
363
+				</listitem>
364
+				<listitem>
365
+				<para>To - Use To URI.</para>
366
+				</listitem>
367
+				<listitem>
368
+				<para>From - Use From URI</para>
369
+				</listitem>
370
+				<listitem>
371
+				<para>Credentials - Use digest credentials username 
372
+				and realm.</para>
373
+				</listitem>
374
+				<listitem>
375
+				<para>$avp[avp_name|avp_alias] - Use the URI from the AVP
376
+				specified by this pseudo-variable.</para>
377
+				</listitem>
378
+			</itemizedlist>
379
+			</para>
380
+		</listitem>
381
+		<listitem>
382
+			<para><emphasis>AVP_ID</emphasis> - The matched group IDs are
383
+			returned as AVPs named <quote>AVP</quote>. It accepts a full AVP
384
+			specification: AVP, ID and NAME.
385
+			alias also</para>
386
+		</listitem>
387
+		</itemizedlist>
388
+		<para>
389
+		This function can be used from REQUEST_ROUTE and FAILURE_ROUTE.
390
+		</para>
391
+		<example>
392
+		<title><function>get_user_group</function> usage</title>
393
+		<programlisting format="linespecific">
394
+...
395
+if (get_user_group("Request-URI", "i:10")) {
396
+    xgdb("User $ru belongs to $avp(i:10[*]) group(s)\n");
397
+    ....
398
+};
399
+...
400
+</programlisting>
401
+		</example>
234 402
 	</section>
403
+	</section>
404
+
405
+
235 406
 </chapter>
236 407
 
237 408
 <!-- Keep this element at the end of the file
... ...
@@ -42,9 +42,6 @@
42 42
 #include "group_mod.h"                   /* Module parameters */
43 43
 
44 44
 
45
-static db_con_t* db_handle = 0;   /* Database connection handle */
46
-static db_func_t group_dbf;
47
-
48 45
 
49 46
 /*
50 47
  * Get Request-URI
... ...
@@ -97,119 +94,133 @@ static inline int get_from_uri(struct sip_msg* _m, str* _u)
97 94
 }
98 95
 
99 96
 
100
-/*
101
- * Check if username in specified header field is in a table
102
- */
103
-int is_user_in(struct sip_msg* _msg, char* _hf, char* _grp)
97
+int get_username_domain(struct sip_msg *msg, group_check_p gcp,
98
+											str *username, str *domain)
104 99
 {
105
-	db_key_t keys[3];
106
-	db_val_t vals[3];
107
-	db_key_t col[1];
108
-	db_res_t* res;
109
-	str uri;
110
-	long hf_type;
111 100
 	struct sip_uri puri;
112 101
 	struct hdr_field* h;
113 102
 	struct auth_body* c = 0; /* Makes gcc happy */
114
-	group_check_p gcp=NULL;
115 103
 	xl_value_t value;
116
-	
117
-	keys[0] = user_column.s;
118
-	keys[1] = group_column.s;
119
-	keys[2] = domain_column.s;
120
-	col[0] = group_column.s;
121
-	
122
-	gcp = (group_check_p)_hf;
123
-	hf_type = (long)gcp->id;
104
+	str uri;
124 105
 
125 106
 	uri.s = 0;
126 107
 	uri.len = 0;
127 108
 
128
-	switch(hf_type) {
129
-	case 1: /* Request-URI */
130
-		if (get_request_uri(_msg, &uri) < 0) {
131
-			LOG(L_ERR, "is_user_in(): Error while obtaining username from Request-URI\n");
132
-			return -1;
133
-		}
134
-		break;
109
+	switch(gcp->id) {
110
+		case 1: /* Request-URI */
111
+			if (get_request_uri( msg, &uri) < 0) {
112
+				LOG(L_ERR, "ERROR:group:get_username_domain: failed to get "
113
+					"Request-URI\n");
114
+				return -1;
115
+			}
116
+			break;
135 117
 
136
-	case 2: /* To */
137
-		if (get_to_uri(_msg, &uri) < 0) {
138
-			LOG(L_ERR, "is_user_in(): Error while extracting To username\n");
139
-			return -2;
140
-		}
141
-		break;
118
+		case 2: /* To */
119
+			if (get_to_uri( msg, &uri) < 0) {
120
+				LOG(L_ERR, "ERROR:group:get_username_domain: failed to get "
121
+					"To URI\n");
122
+				return -1;
123
+			}
124
+			break;
142 125
 
143
-	case 3: /* From */
144
-		if (get_from_uri(_msg, &uri) < 0) {
145
-			LOG(L_ERR, "is_user_in(): Error while extracting From username\n");
146
-			return -3;
147
-		}
148
-		break;
126
+		case 3: /* From */
127
+			if (get_from_uri( msg, &uri) < 0) {
128
+				LOG(L_ERR, "ERROR:group:get_username_domain: failed to get "
129
+					"From URI\n");
130
+				return -1;
131
+			}
132
+			break;
149 133
 
150
-	case 4: /* Credentials */
151
-		get_authorized_cred(_msg->authorization, &h);
152
-		if (!h) {
153
-			get_authorized_cred(_msg->proxy_auth, &h);
134
+		case 4: /* Credentials */
135
+			get_authorized_cred( msg->authorization, &h);
154 136
 			if (!h) {
155
-				LOG(L_ERR, "is_user_in(): No authorized credentials found (error in scripts)\n");
156
-				return -1;
137
+				get_authorized_cred( msg->proxy_auth, &h);
138
+				if (!h) {
139
+					LOG(L_ERR, "ERROR:group:get_username_domain: no "
140
+						"authorized credentials found (error in scripts)\n");
141
+					return -1;
142
+				}
157 143
 			}
158
-		}
159
-	
160
-		c = (auth_body_t*)(h->parsed);
161
-		break;
162
-	case 5: /* AVP spec */
163
-		if(xl_get_spec_value(_msg, &gcp->sp, &value)!=0 
144
+			c = (auth_body_t*)(h->parsed);
145
+			break;
146
+
147
+		case 5: /* AVP spec */
148
+			if(xl_get_spec_value( msg, &gcp->sp, &value)!=0 
164 149
 				|| value.flags&XL_VAL_NULL || value.rs.len<=0)
165
-		{
166
-			LOG(L_ERR,
167
-				"is_user_in(): no AVP found (error in scripts)\n");
168
-			return -1;
169
-		}
170
-		uri.s = value.rs.s;
171
-		uri.len = value.rs.len;
172
-		break;
150
+			{
151
+				LOG(L_ERR,"ERROR:group:get_username_domain: no AVP found"
152
+					" (error in scripts)\n");
153
+				return -1;
154
+			}
155
+			uri.s = value.rs.s;
156
+			uri.len = value.rs.len;
157
+			break;
173 158
 	}
174 159
 
175
-	if (hf_type != 4) {
160
+	if (gcp->id != 4) {
176 161
 		if (parse_uri(uri.s, uri.len, &puri) < 0) {
177
-			LOG(L_ERR, "is_user_in(): Error while parsing URI\n");
178
-			return -5;
162
+			LOG(L_ERR, "ERROR:group:get_username_domain: failed to parse "
163
+				"URI <%.*s>\n",uri.len,uri.s);
164
+			return -1;
179 165
 		}
180 166
 
181
-		VAL_STR(vals) = puri.user;
182
-		VAL_STR(vals + 2) = puri.host;
167
+		*username = puri.user;
168
+		*domain = puri.host;
183 169
 	} else {
184
-		VAL_STR(vals) = c->digest.username.user;
185
-		VAL_STR(vals + 2) = *(GET_REALM(&c->digest));
170
+		*username = c->digest.username.user;
171
+		*domain = *(GET_REALM(&c->digest));
186 172
 	}
187
-	
173
+	return 0;
174
+}
175
+
176
+
177
+
178
+/*
179
+ * Check if username in specified header field is in a table
180
+ */
181
+int is_user_in(struct sip_msg* _msg, char* _hf, char* _grp)
182
+{
183
+	db_key_t keys[3];
184
+	db_val_t vals[3];
185
+	db_key_t col[1];
186
+	db_res_t* res;
187
+
188
+	keys[0] = user_column.s;
189
+	keys[1] = group_column.s;
190
+	keys[2] = domain_column.s;
191
+	col[0] = group_column.s;
192
+
193
+	if ( get_username_domain( _msg, (group_check_p)_hf, &(VAL_STR(vals)),
194
+	&(VAL_STR(vals+2)))!=0) {
195
+		LOG(L_ERR, "is_user_in(): Error while getting username@domain\n");
196
+		return -1;
197
+	}
198
+
188 199
 	VAL_TYPE(vals) = VAL_TYPE(vals + 1) = VAL_TYPE(vals + 2) = DB_STR;
189 200
 	VAL_NULL(vals) = VAL_NULL(vals + 1) = VAL_NULL(vals + 2) = 0;
190 201
 
191 202
 	VAL_STR(vals + 1) = *((str*)_grp);
192
-	
193
-	if (group_dbf.use_table(db_handle, table.s) < 0) {
203
+
204
+	if (group_dbf.use_table(group_dbh, table.s) < 0) {
194 205
 		LOG(L_ERR, "is_user_in(): Error in use_table\n");
195 206
 		return -5;
196 207
 	}
197 208
 
198
-	if (group_dbf.query(db_handle, keys, 0, vals, col, (use_domain) ? (3): (2),
209
+	if (group_dbf.query(group_dbh, keys, 0, vals, col, (use_domain) ? (3): (2),
199 210
 				1, 0, &res) < 0) {
200 211
 		LOG(L_ERR, "is_user_in(): Error while querying database\n");
201 212
 		return -5;
202 213
 	}
203
-	
214
+
204 215
 	if (RES_ROW_N(res) == 0) {
205 216
 		DBG("is_user_in(): User is not in group '%.*s'\n", 
206 217
 		    ((str*)_grp)->len, ZSW(((str*)_grp)->s));
207
-		group_dbf.free_result(db_handle, res);
218
+		group_dbf.free_result(group_dbh, res);
208 219
 		return -6;
209 220
 	} else {
210 221
 		DBG("is_user_in(): User is in group '%.*s'\n", 
211 222
 		    ((str*)_grp)->len, ZSW(((str*)_grp)->s));
212
-		group_dbf.free_result(db_handle, res);
223
+		group_dbf.free_result(group_dbh, res);
213 224
 		return 1;
214 225
 	}
215 226
 }
... ...
@@ -221,8 +232,8 @@ int group_db_init(char* db_url)
221 232
 		LOG(L_CRIT, "BUG: group_db_bind: null dbf \n");
222 233
 		goto error;
223 234
 	}
224
-	db_handle=group_dbf.init(db_url);
225
-	if (db_handle==0){
235
+	group_dbh=group_dbf.init(db_url);
236
+	if (group_dbh==0){
226 237
 		LOG(L_ERR, "ERROR: group_db_bind: unable to connect to the "
227 238
 				"database\n");
228 239
 		goto error;
... ...
@@ -252,29 +263,14 @@ int group_db_bind(char* db_url)
252 263
 
253 264
 void group_db_close()
254 265
 {
255
-	if (db_handle && group_dbf.close){
256
-		group_dbf.close(db_handle);
257
-		db_handle=0;
266
+	if (group_dbh && group_dbf.close){
267
+		group_dbf.close(group_dbh);
268
+		group_dbh=0;
258 269
 	}
259 270
 }
260 271
 
261 272
 
262
-int group_db_ver(char* db_url, str* name)
273
+int group_db_ver(str* name)
263 274
 {
264
-	db_con_t* dbh;
265
-	int ver;
266
-
267
-	if (group_dbf.init==0){
268
-		LOG(L_CRIT, "BUG: group_db_ver: unbound database\n");
269
-		return -1;
270
-	}
271
-	dbh=group_dbf.init(db_url);
272
-	if (dbh==0){
273
-		LOG(L_ERR, "ERROR: group_db_ver: unable to open database "
274
-				"connection\n");
275
-		return -1;
276
-	}
277
-	ver=table_version(&group_dbf, dbh, name);
278
-	group_dbf.close(dbh);
279
-	return ver;
275
+	return table_version( &group_dbf, group_dbh, name);
280 276
 }
... ...
@@ -33,12 +33,23 @@
33 33
 
34 34
 #include "../../parser/msg_parser.h"
35 35
 #include "../../items.h"
36
+#include "../../usr_avp.h"
37
+
36 38
 
37 39
 typedef struct _group_check
38 40
 {
39 41
 	int id;
40 42
 	xl_spec_t sp;
41 43
 } group_check_t, *group_check_p;
44
+
45
+
46
+/*
47
+ * extracts username and domain from MSG
48
+ */
49
+int get_username_domain(struct sip_msg *msg, group_check_p gcp,
50
+	str *username, str *domain);
51
+
52
+
42 53
 /*
43 54
  * Check if username in specified header field is in a table
44 55
  */
... ...
@@ -48,6 +59,6 @@ int is_user_in(struct sip_msg* _msg, char* _hf, char* _grp);
48 59
 int group_db_init(char* db_url);
49 60
 int group_db_bind(char* db_url);
50 61
 void group_db_close();
51
-int group_db_ver(char* db_url, str* name);
62
+int group_db_ver(str* name);
52 63
 
53 64
 #endif /* GROUP_H */
... ...
@@ -1,4 +1,4 @@
1
-/* 
1
+/*
2 2
  * $Id$ 
3 3
  *
4 4
  * Group membership - module interface
... ...
@@ -29,6 +29,7 @@
29 29
  *  2003-03-19  all mallocs/frees replaced w/ pkg_malloc/pkg_free
30 30
  *  2003-04-05  default_uri #define used (jiri)
31 31
  *  2004-06-07  updated to the new DB api: calls to group_db_* (andrei)
32
+ *  2005-10-06 - added support for regexp-based groups (bogdan)
32 33
  */
33 34
 
34 35
 
... ...
@@ -40,12 +41,15 @@
40 41
 #include "../../ut.h"
41 42
 #include "../../error.h"
42 43
 #include "../../mem/mem.h"
44
+#include "../../usr_avp.h"
43 45
 #include "group_mod.h"
44 46
 #include "group.h"
47
+#include "re_group.h"
45 48
 
46 49
 MODULE_VERSION
47 50
 
48
-#define TABLE_VERSION 2
51
+#define TABLE_VERSION    2
52
+#define RE_TABLE_VERSION 1
49 53
 
50 54
 /*
51 55
  * Module destroy function prototype
... ...
@@ -69,6 +73,9 @@ static int mod_init(void);
69 73
 static int hf_fixup(void** param, int param_no);
70 74
 
71 75
 
76
+static int get_gid_fixup(void** param, int param_no);
77
+
78
+
72 79
 #define TABLE "grp"
73 80
 #define TABLE_LEN (sizeof(TABLE) - 1)
74 81
 
... ...
@@ -81,24 +88,45 @@ static int hf_fixup(void** param, int param_no);
81 88
 #define GROUP_COL "grp"
82 89
 #define GROUP_COL_LEN (sizeof(GROUP_COL) - 1)
83 90
 
91
+#define RE_TABLE "re_grp"
92
+#define RE_TABLE_LEN (sizeof(TABLE) - 1)
93
+
94
+#define RE_EXP_COL "reg_exp"
95
+#define RE_EXP_COL_LEN (sizeof(USER_COL) - 1)
96
+
97
+#define RE_GID_COL "group_id"
98
+#define RE_GID_COL_LEN (sizeof(DOMAIN_COL) - 1)
84 99
 
85 100
 /*
86 101
  * Module parameter variables
87 102
  */
88
-static str db_url        = {DEFAULT_RODB_URL, DEFAULT_RODB_URL_LEN};
89
-str table         = {TABLE, TABLE_LEN};         /* Table name where group definitions are stored */
103
+static str db_url = {DEFAULT_RODB_URL, DEFAULT_RODB_URL_LEN};
104
+/* Table name where group definitions are stored */
105
+str table         = {TABLE, TABLE_LEN}; 
90 106
 str user_column   = {USER_COL, USER_COL_LEN};
91 107
 str domain_column = {DOMAIN_COL, DOMAIN_COL_LEN};
92 108
 str group_column  = {GROUP_COL, GROUP_COL_LEN};
93 109
 int use_domain    = 0;
94 110
 
111
+/* tabel and columns used for re-based groups */
112
+str re_table      = {RE_TABLE, RE_TABLE_LEN};
113
+str re_exp_column = {RE_EXP_COL, RE_EXP_COL_LEN};
114
+str re_gid_column = {RE_GID_COL, RE_GID_COL_LEN};
115
+int multiple_gid  = 1;
116
+
117
+/* DB functions and handlers */
118
+db_func_t group_dbf;
119
+db_con_t* group_dbh = 0;
95 120
 
96 121
 
97 122
 /*
98 123
  * Exported functions
99 124
  */
100 125
 static cmd_export_t cmds[] = {
101
-	{"is_user_in", is_user_in, 2, hf_fixup, REQUEST_ROUTE},
126
+	{"is_user_in",      is_user_in,      2,  hf_fixup,
127
+			REQUEST_ROUTE|FAILURE_ROUTE},
128
+	{"get_user_group",  get_user_group,  2,  get_gid_fixup,
129
+			REQUEST_ROUTE|FAILURE_ROUTE},
102 130
 	{0, 0, 0, 0, 0}
103 131
 };
104 132
 
... ...
@@ -112,7 +140,11 @@ static param_export_t params[] = {
112 140
 	{"user_column",   STR_PARAM, &user_column.s  },
113 141
 	{"domain_column", STR_PARAM, &domain_column.s},
114 142
 	{"group_column",  STR_PARAM, &group_column.s },
115
-	{"use_domain",    INT_PARAM, &use_domain},
143
+	{"use_domain",    INT_PARAM, &use_domain     },
144
+	{"re_table",      STR_PARAM, &re_table.s     },
145
+	{"re_exp_column", STR_PARAM, &re_exp_column.s},
146
+	{"re_gid_column", STR_PARAM, &re_gid_column.s},
147
+	{"multiple_gid",  INT_PARAM, &multiple_gid   },
116 148
 	{0, 0, 0}
117 149
 };
118 150
 
... ...
@@ -144,27 +176,60 @@ static int mod_init(void)
144 176
 
145 177
 	DBG("group module - initializing\n");
146 178
 
147
-	     /* Calculate lengths */
179
+	/* Calculate lengths */
148 180
 	db_url.len = strlen(db_url.s);
149 181
 	table.len = strlen(table.s);
150 182
 	user_column.len = strlen(user_column.s);
151 183
 	domain_column.len = strlen(domain_column.s);
152 184
 	group_column.len = strlen(group_column.s);
153 185
 
154
-	     /* Find a database module */
186
+	re_table.len = strlen(re_table.s);
187
+	re_exp_column.len = strlen(re_exp_column.s);
188
+	re_gid_column.len = strlen(re_gid_column.s);
189
+
190
+	/* Find a database module */
155 191
 	if (group_db_bind(db_url.s)) {
156 192
 		return -1;
157 193
 	}
158
-	ver = group_db_ver(db_url.s, &table);
194
+
195
+	if (group_db_init(db_url.s) < 0 ){
196
+		LOG(L_ERR, "ERROR:group:mod_init: unable to open database "
197
+				"connection\n");
198
+		return -1;
199
+	}
200
+
201
+	/* check version for group table */
202
+	ver = group_db_ver( &table );
159 203
 	if (ver < 0) {
160
-		LOG(L_ERR, "group:mod_init(): Error while querying table version\n");
204
+		LOG(L_ERR, "ERROR:group:mod_init: failed to query table version\n");
161 205
 		return -1;
162 206
 	} else if (ver < TABLE_VERSION) {
163
-		LOG(L_ERR, "group:mod_init(): Invalid table version "
164
-				"(use ser_mysql.sh reinstall)\n");
207
+		LOG(L_ERR, "ERROR:group:mod_init: Invalid table version for %s "
208
+				"(use ser_mysql.sh reinstall)\n",table.s);
165 209
 		return -1;
166 210
 	}
167
-	
211
+
212
+	if (re_table.len) {
213
+		/* check version for re_group table */
214
+		ver = group_db_ver( &re_table );
215
+		if (ver < 0) {
216
+			LOG(L_ERR, "ERROR:group:mod_init: failed to query "
217
+				"table version\n");
218
+			return -1;
219
+		} else if (ver < RE_TABLE_VERSION) {
220
+			LOG(L_ERR, "ERROR:group:mod_init: Invalid table version for %s "
221
+					"(use ser_mysql.sh reinstall)\n",re_table.s);
222
+			return -1;
223
+		}
224
+
225
+		if (load_re( &re_table )!=0 ) {
226
+			LOG(L_ERR, "ERROR:group:mod_init: failed to load <%s> table\n",
227
+					re_table.s);
228
+			return -1;
229
+		}
230
+	}
231
+
232
+	group_db_close();
168 233
 	return 0;
169 234
 }
170 235
 
... ...
@@ -181,52 +246,61 @@ static void destroy(void)
181 246
  * Supported strings: 
182 247
  * "Request-URI", "To", "From", "Credentials"
183 248
  */
249
+static group_check_p get_hf( char *str)
250
+{
251
+	group_check_p gcp=NULL;
252
+
253
+	gcp = (group_check_p)pkg_malloc(sizeof(group_check_t));
254
+	if(gcp == NULL) {
255
+		LOG(L_ERR, "ERROR:group:get_hf: no more memory\n");
256
+		return 0;
257
+	}
258
+	memset(gcp, 0, sizeof(group_check_t));
259
+
260
+	if (!strcasecmp( str, "Request-URI")) {
261
+		gcp->id = 1;
262
+	} else if (!strcasecmp( str, "To")) {
263
+		gcp->id = 2;
264
+	} else if (!strcasecmp( str, "From")) {
265
+		gcp->id = 3;
266
+	} else if (!strcasecmp( str, "Credentials")) {
267
+		gcp->id = 4;
268
+	} else {
269
+		if(xl_parse_spec( str, &gcp->sp,
270
+				XL_THROW_ERROR|XL_DISABLE_MULTI|XL_DISABLE_COLORS)==NULL
271
+			|| gcp->sp.type!=XL_AVP)
272
+		{
273
+			LOG(L_ERR, "ERROR:group:get_hf: Unsupported User Field "
274
+				"identifier\n");
275
+			pkg_free( gcp );
276
+			return 0;
277
+		}
278
+		gcp->id = 5;
279
+	}
280
+
281
+	/* do not free all the time, needed by pseudo-variable spec */
282
+	if(gcp->id!=5)
283
+		pkg_free(str);
284
+
285
+	return gcp;
286
+}
287
+
288
+
184 289
 static int hf_fixup(void** param, int param_no)
185 290
 {
186 291
 	void* ptr;
187 292
 	str* s;
188
-	group_check_p gcp=NULL;
189
-	
293
+
190 294
 	if (param_no == 1) {
191
-		gcp = (group_check_p)pkg_malloc(sizeof(group_check_t));
192
-		if(gcp == NULL)
193
-		{
194
-			LOG(L_ERR, "group:hf_fixup: no more memory\n");
195
-			return E_UNSPEC;
196
-		}
197
-		memset(gcp, 0, sizeof(group_check_t));
198 295
 		ptr = *param;
199
-		
200
-		if (!strcasecmp((char*)*param, "Request-URI")) {
201
-			gcp->id = 1;
202
-		} else if (!strcasecmp((char*)*param, "To")) {
203
-			gcp->id = 2;
204
-		} else if (!strcasecmp((char*)*param, "From")) {
205
-			gcp->id = 3;
206
-		} else if (!strcasecmp((char*)*param, "Credentials")) {
207
-			gcp->id = 4;
208
-		} else {
209
-			if(xl_parse_spec((char*)*param, &gcp->sp,
210
-					XL_THROW_ERROR|XL_DISABLE_MULTI|XL_DISABLE_COLORS)==NULL
211
-				|| gcp->sp.type!=XL_AVP)
212
-			{
213
-				LOG(L_ERR,
214
-					"group:hf_fixup: Unsupported User Field identifier\n");
215
-				return E_UNSPEC;
216
-			}
217
-			gcp->id = 5;
218
-		}
219
-		*param = (void*)gcp;
220
-		/* do not free all the time, needed by pseudo-variable spec */
221
-		if(gcp->id != 5)
222
-			pkg_free(ptr);
296
+		if ( (*param = (void*)get_hf( ptr ))==0 )
297
+			return E_UNSPEC;
223 298
 	} else if (param_no == 2) {
224 299
 		s = (str*)pkg_malloc(sizeof(str));
225 300
 		if (!s) {
226
-			LOG(L_ERR, "hf_fixup(): No memory left\n");
301
+			LOG(L_ERR, "ERROR:group:hf_fixup: No pkg memory left\n");
227 302
 			return E_UNSPEC;
228 303
 		}
229
-
230 304
 		s->s = (char*)*param;
231 305
 		s->len = strlen(s->s);
232 306
 		*param = (void*)s;
... ...
@@ -235,3 +309,34 @@ static int hf_fixup(void** param, int param_no)
235 309
 	return 0;
236 310
 }
237 311
 
312
+
313
+static int get_gid_fixup(void** param, int param_no)
314
+{
315
+	struct gid_spec *gid;
316
+	void *ptr;
317
+	str  name;
318
+
319
+	if (param_no == 1) {
320
+		ptr = *param;
321
+		if ( (*param = (void*)get_hf( ptr ))==0 )
322
+			return E_UNSPEC;
323
+	} else if (param_no == 2) {
324
+		name.s = (char*)*param;
325
+		name.len = strlen(name.s);
326
+		gid = (struct gid_spec*)pkg_malloc(sizeof(struct gid_spec));
327
+		if (gid == NULL) {
328
+			LOG(L_ERR, "ERROR:group:get_gid_fixup: no more pkg memory\n");
329
+			return E_UNSPEC;
330
+		}
331
+		if ( parse_avp_spec( &name, &gid->avp_type, &gid->avp_name)!=0 ) {
332
+			LOG(L_ERR,"ERROR:group:get_gid_fixup: bad AVP spec <%s>\n",
333
+				name.s);
334
+			pkg_free( gid );
335
+			return E_UNSPEC;
336
+		}
337
+		*param = gid;
338
+	}
339
+
340
+	return 0;
341
+}
342
+
... ...
@@ -45,5 +45,14 @@ extern str domain_column;   /* 'domain' column name in group table */
45 45
 extern str group_column;    /* "group' column name in group table */
46 46
 extern int use_domain;      /* Use domain in is_user_in */
47 47
 
48
+extern str re_table;
49
+extern str re_exp_column;
50
+extern str re_gid_column;
51
+extern int multiple_gid;
52
+
53
+/* DB functions and handlers */
54
+extern db_func_t group_dbf;
55
+extern db_con_t* group_dbh;
56
+
48 57
 
49 58
 #endif /* GROUP_MOD_H */
50 59
new file mode 100644
... ...
@@ -0,0 +1,187 @@
1
+/*
2
+ * $Id$ 
3
+ *
4
+ * Copyright (C) 2005-2007 Voice Sistem SRL
5
+ *
6
+ * This file is part of openser, a free SIP server.
7
+ *
8
+ * openser is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version
12
+ *
13
+ * openser is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License 
19
+ * along with this program; if not, write to the Free Software 
20
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
+ *
22
+ * History:
23
+ * --------
24
+ *  2005-10-06 - created by bogdan
25
+ */
26
+
27
+#include <regex.h>
28
+
29
+#include "../../str.h"
30
+#include "../../mem/mem.h"
31
+#include "group_mod.h"
32
+#include "re_group.h"
33
+#include "group.h"
34
+
35
+
36
+struct re_grp {
37
+	regex_t       re;
38
+	int           gid;
39
+	struct re_grp *next;
40
+};
41
+
42
+
43
+static struct re_grp *re_list = 0;
44
+
45
+
46
+static int add_re(char *re, int gid)
47
+{
48
+	struct re_grp *rg;
49
+
50
+	DBG("DEBUG:group:add_re: adding <%s> with %d\n",re, gid);
51
+
52
+	rg = (struct re_grp*)pkg_malloc(sizeof(struct re_grp));
53
+	if (rg==0) {
54
+		LOG(L_ERR,"ERROR:group:add_re: no more pkg mem\n");
55
+		goto error;
56
+	}
57
+	memset( rg, 0, sizeof(struct re_grp));
58
+
59
+	if (regcomp(&rg->re, re, REG_EXTENDED|REG_ICASE|REG_NEWLINE) ) {
60
+		LOG(L_ERR, "ERROR:group:add_re: bad re %s\n", re);
61
+		pkg_free(rg);
62
+		goto error;
63
+	}
64
+
65
+	rg->gid = gid;
66
+
67
+	rg->next = re_list;
68
+	re_list = rg;
69
+
70
+	return 0;
71
+error:
72
+	return -1;
73
+}
74
+
75
+
76
+
77
+int load_re( str *table )
78
+{
79
+	db_key_t cols[2];
80
+	db_res_t* res;
81
+	db_row_t* row;
82
+	int n;
83
+
84
+	cols[0] = re_exp_column.s;
85
+	cols[1] = re_gid_column.s;
86
+
87
+	if (group_dbf.use_table(group_dbh, table->s) < 0) {
88
+		LOG(L_ERR, "ERROR:group:load_re: failed to set table <%s>\n",
89
+			table->s);
90
+		goto error;
91
+	}
92
+
93
+	if (group_dbf.query(group_dbh, 0, 0, 0, cols, 0, 2, 0, &res) < 0) {
94
+		LOG(L_ERR, "ERROR:group:load_re: Error while querying database\n");
95
+		goto error;
96
+	}
97
+
98
+	for( n=0 ; n<RES_ROW_N(res) ; n++) {
99
+		row = &res->rows[n];
100
+		/* validate row */
101
+		if (row->values[0].nul || row->values[0].type!=DB_STRING) {
102
+			LOG(L_ERR,"ERROR:group:load_re: empty or non-string "
103
+				"value for <%s>(re) column\n",re_exp_column.s);
104
+			goto error1;
105
+		}
106
+		if (row->values[1].nul || row->values[1].type!=DB_INT) {
107
+			LOG(L_ERR,"ERROR:group:load_re: empty or non-integer "
108
+				"value for <%s>(gid) column\n",re_gid_column.s);
109
+			goto error1;
110
+		}
111
+
112
+		if ( add_re( (char*)row->values[0].val.string_val,
113
+		row->values[1].val.int_val)!=0 ) {
114
+			LOG(L_ERR,"ERROR:group:load_re: failed to add row\n");
115
+			goto error1;
116
+		}
117
+	}
118
+	DBG("DEBUG:group:load_re: %d rules were loaded\n", n);
119
+
120
+	group_dbf.free_result(group_dbh, res);
121
+	return 0;
122
+error1:
123
+	group_dbf.free_result(group_dbh, res);
124
+error:
125
+	return -1;
126
+}
127
+
128
+
129
+
130
+int get_user_group(struct sip_msg *req, char *user, char *avp)
131
+{
132
+	static char uri_buf[MAX_URI_SIZE];
133
+	str  username;
134
+	str  domain;
135
+	struct gid_spec *gs;
136
+	struct re_grp *rg;
137
+	regmatch_t pmatch;
138
+	char *c;
139
+	int n;
140
+
141
+	if (get_username_domain( req, (group_check_p)user, &username, &domain)!=0){
142
+		LOG(L_ERR, "ERROR:group:get_user_group: failed to get "
143
+			"username@domain\n");
144
+		goto error;
145
+	}
146
+
147
+	if ( 4 + username.len + 1 + domain.len + 1 > MAX_URI_SIZE ) {
148
+		LOG(L_ERR, "ERROR:group:get_user_group: URI to large!!\n");
149
+		goto error;
150
+	}
151
+
152
+	*(int*)uri_buf = htonl(('s'<<24) + ('i'<<16) + ('p'<<8) + ':');
153
+	c = uri_buf + 4;
154
+	memcpy( c, username.s, username.len);
155
+	c += username.len;
156
+	*(c++) = '@';
157
+	memcpy( c, domain.s, domain.len);
158
+	c += domain.len;
159
+	*c = 0;
160
+
161
+	DBG("DEBUG:group:get_user_group: getting groups for <%s>\n",uri_buf);
162
+	gs = (struct gid_spec*)avp;
163
+
164
+	/* check against all re groups */
165
+	for( rg=re_list,n=0 ; rg ; rg=rg->next ) {
166
+		if (regexec( &rg->re, uri_buf, 1, &pmatch, 0)==0) {
167
+			DBG("DEBUG:group:get_user_group: user matched to group %d!\n",
168
+				rg->gid);
169
+			/* match -> add the gid as AVP */
170
+			if ( add_avp( (unsigned short)gs->avp_type, gs->avp_name,
171
+			(int_str)rg->gid )!= 0 ) {
172
+				LOG(L_ERR, "ERROR:group:get_user_group: failed to add avp\n");
173
+				goto error;
174
+			}
175
+			n++;
176
+			/* continue? */
177
+			if (multiple_gid==0)
178
+				break;
179
+		}
180
+	}
181
+
182
+	return n?n:-1;
183
+error:
184
+	return -1;
185
+}
186
+
187
+
0 188
new file mode 100644
... ...
@@ -0,0 +1,44 @@
1
+/*
2
+ * $Id$ 
3
+ *
4
+ * Copyright (C) 2005-2007 Voice Sistem SRL
5
+ *
6
+ * This file is part of openser, a free SIP server.
7
+ *
8
+ * openser is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version
12
+ *
13
+ * openser is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License 
19
+ * along with this program; if not, write to the Free Software 
20
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
+ *
22
+ * History:
23
+ * --------
24
+ *  2005-10-06 - created by bogdan
25
+ */
26
+
27
+#ifndef RE_GROUP_H
28
+#define RE_GROUP_H
29
+
30
+#include "../../str.h"
31
+#include "../../usr_avp.h"
32
+#include "../../parser/msg_parser.h"
33
+
34
+typedef struct gid_spec {
35
+	int     avp_type;
36
+	int_str avp_name;
37
+} gid_spec_t;
38
+
39
+
40
+int load_re(str *table);
41
+
42
+int get_user_group(struct sip_msg *req, char *user, char *avp);
43
+
44
+#endif