[Devel] Proposed enhancement to auth_db module.

Kobi Eshun kobi at sightspeed.com
Wed Sep 13 01:23:08 CEST 2006


Hi,

I needed to support a customized mechanism (basically, a stored  
procedure call) for retrieving user passwords while executing the  
'www_authorize()' procedure. I came up with the following scheme  
(patch appended below) which I'd love to see adopted as an  
enhancement. I'd also be interested in hearing about other ways to  
accomplish the same.

-- First, define a new module parameter, 'pass_avp' in authdb_mod.[ch]

-- Second, modify 'get_ha1()' in authorize.c to test for validity and  
contents of said avp before hitting database

To use new functionality,
-- bind that avp as appropriate in the configuration file, e.g.:  
modparam ("auth_db","pass_avp","i:100")

-- prior to invoking www_authorize(), optionally populate the  
specified avp with custom DB calls/avp_write()/avp_subst() etc.

-- invoke www_authorize() as usual.

Please let me know if this patch (or similar functionality) is likely  
to be adopted in the future. Best regards,
--
kobi


The following  patch is known to compile and work against 1.1 stable.
Index: modules/auth_db/authdb_mod.c
===================================================================
RCS file: /cvsroot/openser/sip-server/modules/auth_db/authdb_mod.c,v
retrieving revision 1.5
diff -u -r1.5 authdb_mod.c
--- modules/auth_db/authdb_mod.c	1 Mar 2006 18:07:32 -0000	1.5
+++ modules/auth_db/authdb_mod.c	25 Aug 2006 04:20:59 -0000
@@ -45,6 +45,7 @@
#include "../auth/aaa_avps.h"
#include "../auth/api.h"
#include "authorize.h"
+#include "authdb_mod.h"
MODULE_VERSION
@@ -113,6 +114,12 @@
int credentials_n           = 0; /* Number of credentials in the list */
/*
+ * XXX: KE hack to support loading of pass/ha1 via AVPs.
+ * retrieval instead of default SQL select method.
+ */
+auth_avp_t pass_avp_info =  { {"",0}, 0, (int_str)0};
+
+/*
   * Exported functions
   */
static cmd_export_t cmds[] = {
@@ -134,6 +141,7 @@
	{"calculate_ha1",     INT_PARAM, &calc_ha1           },
	{"use_domain",        INT_PARAM, &use_domain         },
	{"load_credentials",  STR_PARAM, &credentials_list   },
+	{"pass_avp",		  STR_PARAM, &pass_avp_info.spec.s},
	{0, 0, 0}
};
@@ -176,6 +184,14 @@
	pass_column.len = strlen(pass_column.s);
	pass_column_2.len = strlen(pass_column.s);
+	pass_avp_info.spec.len = strlen (pass_avp_info.spec.s);
+	if (parse_avp_spec
+		(&pass_avp_info.spec, &pass_avp_info.type,  
&pass_avp_info.avp_name)) {
+		LOG (L_CRIT,"ERROR:auth_db:init:pass_avp: invalid AVP spec: %s\n",
+			 pass_avp_info.spec.s);
+		return -1;
+	}
+
	/* Find a database module */
	if (bind_dbmod(db_url, &auth_dbf) < 0){
		LOG(L_ERR,"ERROR:auth_db:child_init: Unable to bind to "
Index: modules/auth_db/authdb_mod.h
===================================================================
RCS file: /cvsroot/openser/sip-server/modules/auth_db/authdb_mod.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 authdb_mod.h
--- modules/auth_db/authdb_mod.h	13 Jun 2005 16:47:33 -0000	1.1.1.1
+++ modules/auth_db/authdb_mod.h	25 Aug 2006 04:20:59 -0000
@@ -55,6 +55,16 @@
extern int credentials_n;
/*
+ * XXX: KE hack to support loading pass/ha1 via AVPs.
+ */
+typedef struct auth_avp_struct {
+	str spec;
+	int type;
+	int_str avp_name;
+} auth_avp_t;
+extern auth_avp_t pass_avp_info;
+
+/*
   * Pointer to reply function in stateless module
   */
extern int (*sl_reply)(struct sip_msg* _msg, char* _str1, char* _str2);
Index: modules/auth_db/authorize.c
===================================================================
RCS file: /cvsroot/openser/sip-server/modules/auth_db/authorize.c,v
retrieving revision 1.9
diff -u -r1.9 authorize.c
--- modules/auth_db/authorize.c	25 May 2006 18:10:19 -0000	1.9
+++ modules/auth_db/authorize.c	25 Aug 2006 04:20:59 -0000
@@ -61,59 +61,70 @@
	db_key_t *col;
	str result;
	int n, nc;
+	int_str the_password=(int_str)0;
-	col = pkg_malloc(sizeof(*col) * (credentials_n + 1));
-	if (col == NULL) {
-		LOG(L_ERR, "get_ha1(): Error while allocating memory\n");
-		return -1;
-	}
+	if (pass_avp_info.spec.len &&
+		search_first_avp (
+			pass_avp_info.type, pass_avp_info.avp_name, &the_password, NULL)) {
+		/*
+		 * XXX: KE hack to bypass DB hit. Try pass_avp before defaulting
+		 * to "usual" scheme.
+		 */
+		result.s=the_password.s.len?the_password.s.s:"";
+		result.len=strlen (result.s);
+	} else {
+		col = pkg_malloc(sizeof(*col) * (credentials_n + 1));
+		if (col == NULL) {
+			LOG(L_ERR, "get_ha1(): Error while allocating memory\n");
+			return -1;
+		}
-	keys[0] = user_column.s;
-	keys[1] = domain_column.s;
-	col[0] = (_username->domain.len && !calc_ha1) ?
-		(pass_column_2.s) : (pass_column.s);
+		keys[0] = user_column.s;
+		keys[1] = domain_column.s;
+		col[0] = (_username->domain.len && !calc_ha1) ?
+			(pass_column_2.s) : (pass_column.s);
-	for (n = 0, cred=credentials; cred ; n++, cred=cred->next) {
-		col[1 + n] = cred->attr_name.s;
-	}
+		for (n = 0, cred=credentials; cred ; n++, cred=cred->next) {
+			col[1 + n] = cred->attr_name.s;
+		}
-	VAL_TYPE(vals) = VAL_TYPE(vals + 1) = DB_STR;
-	VAL_NULL(vals) = VAL_NULL(vals + 1) = 0;
+		VAL_TYPE(vals) = VAL_TYPE(vals + 1) = DB_STR;
+		VAL_NULL(vals) = VAL_NULL(vals + 1) = 0;
-	VAL_STR(vals).s = _username->user.s;
-	VAL_STR(vals).len = _username->user.len;
+		VAL_STR(vals).s = _username->user.s;
+		VAL_STR(vals).len = _username->user.len;
-	if (_username->domain.len) {
-		VAL_STR(vals + 1) = _username->domain;
-	} else {
-		VAL_STR(vals + 1) = *_domain;
-	}
+		if (_username->domain.len) {
+			VAL_STR(vals + 1) = _username->domain;
+		} else {
+			VAL_STR(vals + 1) = *_domain;
+		}
-	n = (use_domain ? 2 : 1);
-	nc = 1 + credentials_n;
-	if (auth_dbf.use_table(auth_db_handle, _table) < 0) {
-		LOG(L_ERR, "get_ha1(): Error in use_table\n");
-		pkg_free(col);
-		return -1;
-	}
+		n = (use_domain ? 2 : 1);
+		nc = 1 + credentials_n;
+		if (auth_dbf.use_table(auth_db_handle, _table) < 0) {
+			LOG(L_ERR, "get_ha1(): Error in use_table\n");
+			pkg_free(col);
+			return -1;
+		}
-	if (auth_dbf.query(auth_db_handle, keys, 0, vals, col, n, nc, 0,  
res) < 0) {
-		LOG(L_ERR, "get_ha1(): Error while querying database\n");
+		if (auth_dbf.query(auth_db_handle, keys, 0, vals, col, n, nc, 0,  
res) < 0) {
+			LOG(L_ERR, "get_ha1(): Error while querying database\n");
+			pkg_free(col);
+			return -1;
+		}
		pkg_free(col);
-		return -1;
-	}
-	pkg_free(col);
-
-	if (RES_ROW_N(*res) == 0) {
-		DBG("get_ha1(): no result for user \'%.*s@%.*s\'\n",
-			_username->user.len, ZSW(_username->user.s),
-			(use_domain ? (_domain->len) : 0), ZSW(_domain->s));
-		return 1;
-	}
-	result.s = (char*)ROW_VALUES(RES_ROWS(*res))[0].val.string_val;
-	result.len = strlen(result.s);
+		if (RES_ROW_N(*res) == 0) {
+			DBG("get_ha1(): no result for user \'%.*s@%.*s\'\n",
+				_username->user.len, ZSW(_username->user.s),
+				(use_domain ? (_domain->len) : 0), ZSW(_domain->s));
+			return 1;
+		}
+		result.s = (char*)ROW_VALUES(RES_ROWS(*res))[0].val.string_val;
+		result.len = strlen(result.s);
+	}
	if (calc_ha1) {
		/* Only plaintext passwords are stored in database,
		 * we have to calculate HA1 */
@@ -255,7 +266,7 @@
	auth_body_t* cred;
	auth_result_t ret;
	str domain;
-	db_res_t* result;
+	db_res_t* result=NULL;
	if (_realm) {
		if (xl_printf_s(_m, _realm, &domain)!=0) {
@@ -288,7 +299,8 @@
	}
	if (res > 0) {
		/* Username not found in the database */
-		auth_dbf.free_result(auth_db_handle, result);
+		if (result)
+			auth_dbf.free_result(auth_db_handle, result);
		return -1;
	}
@@ -297,25 +309,30 @@
		ret = auth_api.post_auth(_m, h);
		switch(ret) {
		case ERROR:
-			auth_dbf.free_result(auth_db_handle, result);
+			if (result)
+				auth_dbf.free_result(auth_db_handle, result);
			return 1;
		case NOT_AUTHORIZED:
-			auth_dbf.free_result(auth_db_handle, result);
+			if (result)
+				auth_dbf.free_result(auth_db_handle, result);
			return -1;
		case AUTHORIZED:
-			generate_avps(result);
-			auth_dbf.free_result(auth_db_handle, result);
+			if (result) {
+				generate_avps(result);
+				auth_dbf.free_result(auth_db_handle, result);
+			}
			return 1;
		default:
-			auth_dbf.free_result(auth_db_handle, result);
+			if (result)
+				auth_dbf.free_result(auth_db_handle, result);
			return -1;
		}
	}
-
-	auth_dbf.free_result(auth_db_handle, result);
+	if (result)
+		auth_dbf.free_result(auth_db_handle, result);
	return -1;
}

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://openser.org/pipermail/devel/attachments/20060912/12eface7/attachment.htm


More information about the Devel mailing list