Browse code

- AVP support clean up (only one list which defaults to 'rpid') - RPID handling is no more an exception -- it is now stored in AVPs as well

Jan Janak authored on 31/01/2005 17:54:02
Showing 4 changed files
... ...
@@ -44,8 +44,8 @@
44 44
 #include "../../error.h"
45 45
 #include "../../mem/mem.h"
46 46
 #include "authorize.h"
47
+#include "../auth/aaa_avps.h"
47 48
 #include "../auth/api.h"
48
-#include "aaa_avps.h"
49 49
 
50 50
 MODULE_VERSION
51 51
 
... ...
@@ -72,9 +72,6 @@ static int mod_init(void);
72 72
 static int str_fixup(void** param, int param_no);
73 73
 
74 74
 
75
-pre_auth_f pre_auth_func = 0;
76
-post_auth_f post_auth_func = 0;
77
-
78 75
 /*
79 76
  * Pointer to reply function in stateless module
80 77
  */
... ...
@@ -93,31 +90,28 @@ int (*sl_reply)(struct sip_msg* _msg, char* _str1, char* _str2);
93 90
 #define PASS_COL_2 "ha1b"
94 91
 #define PASS_COL_2_LEN (sizeof(PASS_COL_2) - 1)
95 92
 
96
-#define AVPS_COL_INT "domn"
97
-#define AVPS_COL_INT_LEN (sizeof(AVPS_COL_INT) - 1)
98
-
99
-#define AVPS_COL_STR "uuid|rpid"
100
-#define AVPS_COL_STR_LEN (sizeof(AVPS_COL_STR) - 1)
101
-
93
+#define DEFAULT_CRED_LIST "rpid"
102 94
 
103 95
 /*
104 96
  * Module parameter variables
105 97
  */
106
-static str db_url           = {DEFAULT_RODB_URL, DEFAULT_RODB_URL_LEN};
107
-str user_column      = {USER_COL, USER_COL_LEN};
108
-str domain_column    = {DOMAIN_COL, DOMAIN_COL_LEN};
109
-str pass_column      = {PASS_COL, PASS_COL_LEN};
110
-str pass_column_2    = {PASS_COL_2, PASS_COL_2_LEN};
111
-static str avps_column_int  = {AVPS_COL_INT, AVPS_COL_INT_LEN};
112
-static str avps_column_str  = {AVPS_COL_STR, AVPS_COL_STR_LEN};
113
-str *avps_int        = NULL;
114
-str *avps_str        = NULL;
115
-int avps_int_n       = 0;
116
-int avps_str_n       = 0;
117
-int calc_ha1         = 0;
118
-int use_domain       = 0;    /* Use also domain when looking up a table row */
98
+static char* db_url         = DEFAULT_RODB_URL;
99
+str user_column             = {USER_COL, USER_COL_LEN};
100
+str domain_column           = {DOMAIN_COL, DOMAIN_COL_LEN};
101
+str pass_column             = {PASS_COL, PASS_COL_LEN};
102
+str pass_column_2           = {PASS_COL_2, PASS_COL_2_LEN};
103
+
104
+
105
+int calc_ha1                = 0;
106
+int use_domain              = 0;   /* Use also domain when looking up a table row */
119 107
 
108
+db_con_t* auth_db_handle = 0;      /* database connection handle */
109
+db_func_t auth_dbf;
110
+auth_api_t auth_api;
120 111
 
112
+str credentials_list        = {DEFAULT_CRED_LIST, sizeof(DEFAULT_CRED_LIST)};
113
+str* credentials;          /* Parsed list of credentials to load */
114
+int credentials_n;         /* Number of credentials in the list */
121 115
 
122 116
 /*
123 117
  * Exported functions
... ...
@@ -133,15 +127,14 @@ static cmd_export_t cmds[] = {
133 127
  * Exported parameters
134 128
  */
135 129
 static param_export_t params[] = {
136
-	{"db_url",            STR_PARAM, &db_url.s         },
137
-	{"user_column",       STR_PARAM, &user_column.s    },
138
-	{"domain_column",     STR_PARAM, &domain_column.s  },
139
-	{"password_column",   STR_PARAM, &pass_column.s    },
140
-	{"password_column_2", STR_PARAM, &pass_column_2.s  },
141
-	{"avps_column_int",   STR_PARAM, &avps_column_int.s},
142
-	{"avps_column_str",   STR_PARAM, &avps_column_str.s},
143
-	{"calculate_ha1",     INT_PARAM, &calc_ha1         },
144
-	{"use_domain",        INT_PARAM, &use_domain       },
130
+	{"db_url",            STR_PARAM, &db_url             },
131
+	{"user_column",       STR_PARAM, &user_column.s      },
132
+	{"domain_column",     STR_PARAM, &domain_column.s    },
133
+	{"password_column",   STR_PARAM, &pass_column.s      },
134
+	{"password_column_2", STR_PARAM, &pass_column_2.s    },
135
+	{"calculate_ha1",     INT_PARAM, &calc_ha1           },
136
+	{"use_domain",        INT_PARAM, &use_domain         },
137
+	{"load_credentials",  STR_PARAM, &credentials_list.s },
145 138
 	{0, 0, 0}
146 139
 };
147 140
 
... ...
@@ -163,35 +156,44 @@ struct module_exports exports = {
163 156
 
164 157
 static int child_init(int rank)
165 158
 {
166
-	     /* Close connection opened in mod_init */
167
-	return auth_db_init(db_url.s);
159
+	auth_db_handle = auth_dbf.init(db_url);
160
+	if (auth_db_handle == 0){
161
+		LOG(L_ERR, "auth_db:child_init: unable to connect to the database\n");
162
+		return -1;
163
+	}
164
+
165
+	return 0;
168 166
 }
169 167
 
170 168
 
171 169
 static int mod_init(void)
172 170
 {
171
+	bind_auth_t bind_auth;
173 172
 
174 173
 	DBG("auth_db module - initializing\n");
175 174
 
176
-	db_url.len = strlen(db_url.s);
177 175
 	user_column.len = strlen(user_column.s);
178 176
 	domain_column.len = strlen(domain_column.s);
179 177
 	pass_column.len = strlen(pass_column.s);
180 178
 	pass_column_2.len = strlen(pass_column.s);
181 179
 
182
-	if (aaa_avps_init(&avps_column_int, &avps_column_str, &avps_int,
183
-	    &avps_str, &avps_int_n, &avps_str_n) == -1)
184
-		return -1;
180
+	credentials_list.len = strlen(credentials_list.s);
185 181
 
186 182
 	     /* Find a database module */
187
-	if (auth_db_bind(db_url.s)<0)
183
+
184
+	if (bind_dbmod(db_url, &auth_dbf) < 0){
185
+		LOG(L_ERR, "auth_db:child_init: Unable to bind a database driver\n");
188 186
 		return -2;
187
+	}
189 188
 
190
-	pre_auth_func = (pre_auth_f)find_export("pre_auth", 0, 0);
191
-	post_auth_func = (post_auth_f)find_export("post_auth", 0, 0);
189
+        bind_auth = (bind_auth_t)find_export("bind_auth", 0, 0);
190
+        if (!bind_auth) {
191
+		LOG(L_ERR, "auth_db:mod_init: Unable to find bind_auth function\n");
192
+	        return -1;
193
+	}
192 194
 
193
-	if (!(pre_auth_func && post_auth_func)) {
194
-		LOG(L_ERR, "auth_db:mod_init(): This module requires auth module\n");
195
+	if (bind_auth(&auth_api) < 0) {
196
+		LOG(L_ERR, "auth_db:child_init: Unable to bind auth module\n");
195 197
 		return -3;
196 198
 	}
197 199
 
... ...
@@ -201,14 +203,19 @@ static int mod_init(void)
201 203
 		return -4;
202 204
 	}
203 205
 
206
+	if (aaa_avps_init(&credentials_list, &credentials, &credentials_n)) {
207
+		return -1;
208
+	}
209
+
204 210
 	return 0;
205 211
 }
206 212
 
207 213
 
208
-
209 214
 static void destroy(void)
210 215
 {
211
-	auth_db_close();
216
+	if (auth_db_handle) {
217
+		auth_dbf.close(auth_db_handle);
218
+	}
212 219
 }
213 220
 
214 221
 
... ...
@@ -217,6 +224,7 @@ static void destroy(void)
217 224
  */
218 225
 static int str_fixup(void** param, int param_no)
219 226
 {
227
+	db_con_t* dbh;
220 228
 	str* s;
221 229
 	int ver;
222 230
 	str name;
... ...
@@ -235,12 +243,18 @@ static int str_fixup(void** param, int param_no)
235 243
 		name.s = (char*)*param;
236 244
 		name.len = strlen(name.s);
237 245
 
238
-		ver=auth_db_ver(db_url.s, &name);
246
+		dbh = auth_dbf.init(db_url);
247
+		if (!dbh) {
248
+			LOG(L_ERR, "auth_db:str_fixup: Unable to open database connection\n");
249
+			return -1;
250
+		}
251
+		ver = table_version(&auth_dbf, dbh, &name);
252
+		auth_dbf.close(dbh);
239 253
 		if (ver < 0) {
240
-			LOG(L_ERR, "auth_db:str_fixup(): Error while querying table version\n");
254
+			LOG(L_ERR, "auth_db:str_fixup: Error while querying table version\n");
241 255
 			return -1;
242 256
 		} else if (ver < TABLE_VERSION) {
243
-			LOG(L_ERR, "auth_db:str_fixup(): Invalid table version (use ser_mysql.sh reinstall)\n");
257
+			LOG(L_ERR, "auth_db:str_fixup: Invalid table version (use ser_mysql.sh reinstall)\n");
244 258
 			return -1;
245 259
 		}
246 260
 	}
... ...
@@ -47,16 +47,17 @@ extern str pass_column;     /* 'password' column name */
47 47
 extern str pass_column_2;   /* Column containing HA1 string constructed
48 48
 			     * of user@domain username
49 49
 			     */
50
-extern str *avps_int;       /* Columns containing int AVPs to be set after successful auth */
51
-extern str *avps_str;       /* Columns containing str AVPs to be set after successful auth */
52
-extern int avps_int_n;
53
-extern int avps_str_n;
54 50
 
55 51
 extern int calc_ha1;          /* if set to 1, ha1 is calculated by the server */
56 52
 extern int use_domain;        /* If set to 1 then the domain will be used when selecting a row */
57 53
 
58
-extern pre_auth_f pre_auth_func;
59
-extern post_auth_f post_auth_func;
54
+extern db_con_t* auth_db_handle; /* database connection handle */
55
+extern db_func_t auth_dbf;
56
+
57
+extern auth_api_t auth_api;
58
+
59
+extern str* credentials;
60
+extern int credentials_n;
60 61
 
61 62
 /*
62 63
  * Pointer to reply function in stateless module
... ...
@@ -51,11 +51,9 @@
51 51
 
52 52
 #define MESSAGE_500 "Server Internal Error"
53 53
 
54
-static db_con_t* db_handle=0; /* database connection handle */
55
-static db_func_t  auth_dbf;
56 54
 
57 55
 static inline int get_ha1(struct username* _username, str* _domain,
58
-    char* _table, char* _ha1, db_res_t** res)
56
+			  char* _table, char* _ha1, db_res_t** res)
59 57
 {
60 58
 	db_key_t keys[2];
61 59
 	db_val_t vals[2];
... ...
@@ -63,7 +61,7 @@ static inline int get_ha1(struct username* _username, str* _domain,
63 61
 	str result;
64 62
 	int n, nc;
65 63
 
66
-	col = pkg_malloc(sizeof(*col) * (avps_int_n + avps_str_n + 1));
64
+	col = pkg_malloc(sizeof(*col) * (credentials_n + 1));
67 65
 	if (col == NULL) {
68 66
 		LOG(L_ERR, "get_ha1(): Error while allocating memory\n");
69 67
 		return -1;
... ...
@@ -72,10 +70,10 @@ static inline int get_ha1(struct username* _username, str* _domain,
72 70
 	keys[0] = user_column.s;
73 71
 	keys[1] = domain_column.s;
74 72
 	col[0] = (_username->domain.len && !calc_ha1) ? (pass_column_2.s) : (pass_column.s);
75
-	for (n = 0; n < avps_int_n; n++)
76
-		col[1 + n] = avps_int[n].s;
77
-	for (n = 0; n < avps_str_n; n++)
78
-		col[1 + avps_int_n + n] = avps_str[n].s;
73
+
74
+	for (n = 0; n < credentials_n; n++) {
75
+		col[1 + n] = credentials[n].s;
76
+	}
79 77
 
80 78
 	VAL_TYPE(vals) = VAL_TYPE(vals + 1) = DB_STR;
81 79
 	VAL_NULL(vals) = VAL_NULL(vals + 1) = 0;
... ...
@@ -87,14 +85,14 @@ static inline int get_ha1(struct username* _username, str* _domain,
87 85
 	VAL_STR(vals + 1).len = _domain->len;
88 86
 
89 87
 	n = (use_domain ? 2 : 1);
90
-	nc = 1 + avps_int_n + avps_str_n;
91
-	if (auth_dbf.use_table(db_handle, _table) < 0) {
88
+	nc = 1 + credentials_n;
89
+	if (auth_dbf.use_table(auth_db_handle, _table) < 0) {
92 90
 		LOG(L_ERR, "get_ha1(): Error in use_table\n");
93 91
 		pkg_free(col);
94 92
 		return -1;
95 93
 	}
96 94
 
97
-	if (auth_dbf.query(db_handle, keys, 0, vals, col, n, nc, 0, res) < 0) {
95
+	if (auth_dbf.query(auth_db_handle, keys, 0, vals, col, n, nc, 0, res) < 0) {
98 96
 		LOG(L_ERR, "get_ha1(): Error while querying database\n");
99 97
 		pkg_free(col);
100 98
 		return -1;
... ...
@@ -165,24 +163,56 @@ static inline int check_response(dig_cred_t* _cred, str* _method, char* _ha1)
165 163
 }
166 164
 
167 165
 
166
+/*
167
+ * Generate AVPs from the database result
168
+ */
169
+static int generate_avps(db_res_t* result)
170
+{
171
+	int i;
172
+	int_str iname, ivalue;
173
+	str value;
174
+
175
+	for (i = 1; i <= credentials_n; i++) {
176
+		value.s = (char*)VAL_STRING(&(result->rows[0].values[i]));
177
+
178
+		if (VAL_NULL(&(result->rows[0].values[i]))
179
+		    || value.s == NULL) {
180
+			continue;
181
+		}
182
+		
183
+		iname.s = &credentials[i];
184
+		value.len = strlen(value.s);
185
+		ivalue.s = &value;
186
+
187
+		if (add_avp(AVP_NAME_STR | AVP_VAL_STR, iname, ivalue) < 0) {
188
+			LOG(L_ERR, "generate_avps: Error while creating AVPs\n");
189
+			return -1;
190
+		}
191
+
192
+		DBG("generate_avps: set string AVP \'%.*s = %.*s\'\n",
193
+		    iname.s->len, ZSW(iname.s->s), value.len, ZSW(value.s));
194
+	}
195
+
196
+	return 0;
197
+}
198
+
199
+
168 200
 /*
169 201
  * Authorize digest credentials
170 202
  */
171 203
 static inline int authorize(struct sip_msg* _m, str* _realm, char* _table, int _hftype)
172 204
 {
173 205
 	char ha1[256];
174
-	int res, i;
206
+	int res;
175 207
 	struct hdr_field* h;
176 208
 	auth_body_t* cred;
177 209
 	auth_result_t ret;
178
-	str domain, value;
179
-	int_str iname, ivalue;
210
+	str domain;
180 211
 	db_res_t* result;
181
-	str rpid;
182 212
 
183 213
 	domain = *_realm;
184 214
 
185
-	ret = pre_auth_func(_m, &domain, _hftype, &h);
215
+	ret = auth_api.pre_auth(_m, &domain, _hftype, &h);
186 216
 
187 217
 	switch(ret) {
188 218
 	case ERROR:            return 0;
... ...
@@ -203,62 +233,33 @@ static inline int authorize(struct sip_msg* _m, str* _realm, char* _table, int _
203 233
 	}
204 234
 	if (res > 0) {
205 235
 		     /* Username not found in the database */
206
-		auth_dbf.free_result(db_handle, result);
236
+		auth_dbf.free_result(auth_db_handle, result);
207 237
 		return -1;
208 238
 	}
209 239
 
210 240
 	     /* Recalculate response, it must be same to authorize successfully */
211 241
         if (!check_response(&(cred->digest), &_m->first_line.u.request.method, ha1)) {
212
-		rpid.s = NULL;
213
-		rpid.len = 0;
214
-		for (i = 0; i < avps_str_n; i++) {
215
-			if (avps_str[i].len != 4
216
-					|| VAL_NULL(&(result->rows[0].values[1 + avps_int_n + i]))
217
-					|| memcmp(avps_str[i].s, "rpid", 4) != 0)
218
-				continue;
219
-			rpid.s = (char*)VAL_STRING(&(result->rows[0].values[1 + avps_int_n + i]));
220
-			if(rpid.s!=NULL)
221
-				rpid.len = strlen(rpid.s);
222
-		}
223
-		ret = post_auth_func(_m, h, &rpid);
242
+		ret = auth_api.post_auth(_m, h);
224 243
 		switch(ret) {
225 244
 		case ERROR:
226
-			auth_dbf.free_result(db_handle, result);
227
-			return 0;
245
+			auth_dbf.free_result(auth_db_handle, result);
246
+			return 1;
247
+
228 248
 		case NOT_AUTHORIZED:
229
-			auth_dbf.free_result(db_handle, result);
249
+			auth_dbf.free_result(auth_db_handle, result);
230 250
 			return -1;
251
+
231 252
 		case AUTHORIZED:
232
-			for (i = 0; i < avps_int_n; i++) {
233
-				if(VAL_NULL(&(result->rows[0].values[1 + i])))
234
-					continue;
235
-				iname.s = &(avps_int[i]);
236
-				ivalue.n = VAL_INT(&(result->rows[0].values[1 + i]));
237
-				add_avp(AVP_NAME_STR, iname, ivalue);
238
-				DBG("authorize(): set integer AVP \'%.*s = %d\'\n",
239
-				    iname.s->len, ZSW(iname.s->s), ivalue.n);
240
-			}
241
-			for (i = 0; i < avps_str_n; i++) {
242
-				value.s = (char*)VAL_STRING(&(result->rows[0].values[1 + avps_int_n + i]));
243
-				if(VAL_NULL(&(result->rows[0].values[1 + avps_int_n + i]))
244
-						|| value.s==NULL)
245
-					continue;
246
-				iname.s = &(avps_str[i]);
247
-				value.len = strlen(value.s);
248
-				ivalue.s = &value;
249
-				add_avp(AVP_NAME_STR | AVP_VAL_STR, iname, ivalue);
250
-				DBG("authorize(): set string AVP \'%.*s = %.*s\'\n",
251
-				    iname.s->len, ZSW(iname.s->s), value.len, ZSW(value.s));
252
-			}
253
-			auth_dbf.free_result(db_handle, result);
253
+			generate_avps(result);
254
+			auth_dbf.free_result(auth_db_handle, result);
254 255
 			return 1;
255 256
 		default:
256
-			auth_dbf.free_result(db_handle, result);
257
+			auth_dbf.free_result(auth_db_handle, result);
257 258
 			return -1;
258 259
 		}
259 260
 	}
260 261
 
261
-	auth_dbf.free_result(db_handle, result);
262
+	auth_dbf.free_result(auth_db_handle, result);
262 263
 	return -1;
263 264
 }
264 265
 
... ...
@@ -280,61 +281,3 @@ int www_authorize(struct sip_msg* _m, char* _realm, char* _table)
280 281
 {
281 282
 	return authorize(_m, (str*)_realm, _table, HDR_AUTHORIZATION);
282 283
 }
283
-
284
-
285
-
286
-int auth_db_init(char* db_url)
287
-{
288
-	if (auth_dbf.init==0){
289
-		LOG(L_CRIT, "BUG: auth_db_bind: null dbf\n");
290
-		goto error;
291
-	}
292
-	db_handle=auth_dbf.init(db_url);
293
-	if (db_handle==0){
294
-		LOG(L_ERR, "ERROR: auth_db_bind: unable to connect to the database\n");
295
-		goto error;
296
-	}
297
-	return 0;
298
-error:
299
-	return -1;
300
-}
301
-
302
-
303
-int auth_db_bind(char* db_url)
304
-{
305
-	if (bind_dbmod(db_url, &auth_dbf)<0){
306
-		LOG(L_ERR, "ERROR: auth_db_bind: unable to bind to the database"
307
-				" module\n");
308
-		return -1;
309
-	}
310
-	return 0;
311
-}
312
-
313
-
314
-void auth_db_close()
315
-{
316
-	if (db_handle && auth_dbf.close){
317
-		auth_dbf.close(db_handle);
318
-		db_handle=0;
319
-	}
320
-}
321
-
322
-
323
-int auth_db_ver(char* db_url, str* name)
324
-{
325
-	db_con_t* dbh;
326
-	int ver;
327
-
328
-	if (auth_dbf.init==0){
329
-		LOG(L_CRIT, "BUG: auth_db_ver: unbound database\n");
330
-		return -1;
331
-	}
332
-	dbh=auth_dbf.init(db_url);
333
-	if (dbh==0){
334
-		LOG(L_ERR, "ERROR: auth_db_ver: unable to open database connection\n");
335
-		return -1;
336
-	}
337
-	ver=table_version(&auth_dbf, dbh, name);
338
-	auth_dbf.close(dbh);
339
-	return ver;
340
-}
... ...
@@ -37,7 +37,6 @@
37 37
 int auth_db_init(char* db_url);
38 38
 int auth_db_bind(char* db_url);
39 39
 void auth_db_close();
40
-int auth_db_ver(char* db_url, str* name);
41 40
 
42 41
 /*
43 42
  * Authorize using Proxy-Authorization header field