Browse Source

modules_k/auth_db: allow arbitrary PV's in load_credentials

Instead of just avp's, now every writable PV can be used.
Alex Hermann 14 years ago
parent
commit
560bf0f68e

+ 0 - 188
modules_k/auth_db/aaa_avps.h

@@ -1,188 +0,0 @@
-/*
- * $Id$
- *
- * Copyright (C) 2005 Voice Sistem SRL
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * Kamailio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * Kamailio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * History:
- * --------
- *  2005-05-31 created by bogdan
- */
-
-#ifndef _OPENSER_AAA_AVPS_H_
-#define _OPENSER_AAA_AVPS_H_
-
-#include "../../mem/mem.h"
-#include "../../dprint.h"
-#include "../../trim.h"
-#include "../../pvar.h"
-
-#include <string.h>
-
-
-struct aaa_avp {
-	int_str avp_name;
-	unsigned short avp_type;
-	str attr_name;
-	struct aaa_avp *next;
-};
-
-
-
-static inline void free_aaa_avp(struct aaa_avp *avp)
-{
-	if (avp) {
-		if (avp->avp_type&AVP_NAME_STR && avp->avp_name.s.s!=avp->attr_name.s)
-			pkg_free(avp->avp_name.s.s);
-		if (avp->attr_name.s)
-			pkg_free(avp->attr_name.s);
-		pkg_free(avp);
-	}
-}
-
-
-
-static inline void free_aaa_avp_list(struct aaa_avp *avp)
-{
-	struct aaa_avp *tmp;
-
-	while (avp) {
-		tmp = avp;
-		avp = avp->next;
-		free_aaa_avp( tmp );
-	}
-}
-
-
-
-static inline int parse_aaa_avps(char *definition,
-										struct aaa_avp **avp_def, int *cnt)
-{
-	struct aaa_avp *avp;
-	int_str avp_name;
-	pv_spec_t avp_spec;
-	str  foo;
-	char *p;
-	char *e;
-	char *s;
-	char t;
-
-	p = definition;
-	*avp_def = 0;
-	*cnt = 0;
-
-	if (p==0 || *p==0)
-		return 0;
-
-	/* get element by element */
-	while ( (e=strchr(p,';'))!=0 || (e=p+strlen(p))!=p ) {
-		/* new aaa_avp struct */
-		if ( (avp=(struct aaa_avp*)pkg_malloc(sizeof(struct aaa_avp)))==0 ) {
-			LM_ERR("no more pkg mem\n");
-			goto error;
-		}
-		memset( avp, 0, sizeof(struct aaa_avp));
-		/* definition is between p and e */
-		if ( (s=strchr(p,'='))!=0 && s<e ) {
-			/* avp = attr */
-			foo.s = p;
-			foo.len = s-p;
-			trim( &foo );
-			if (foo.len==0)
-				goto parse_error;
-			t = foo.s[foo.len];
-			foo.s[foo.len] = '\0';
-			
-			if (pv_parse_spec(&foo, &avp_spec)==0
-					|| avp_spec.type!=PVT_AVP) {
-				LM_ERR("malformed or non AVP %s AVP definition\n", foo.s);
-				goto parse_error;;
-			}
-
-			if(pv_get_avp_name(0, &(avp_spec.pvp), &avp_name,
-						&avp->avp_type)!=0)
-			{
-				LM_ERR("[%s]- invalid AVP definition\n", foo.s);
-				goto parse_error;
-			}
-			foo.s[foo.len] = t;
-
-			/* copy the avp name into the avp structure */
-			if (avp->avp_type&AVP_NAME_STR) {
-				avp->avp_name.s.s =
-					(char*)pkg_malloc(avp_name.s.len+1);
-				if (avp->avp_name.s.s==0) {
-					LM_ERR("no more pkg mem\n");
-					goto error;
-				}
-				avp->avp_name.s.len = avp_name.s.len;
-				memcpy(avp->avp_name.s.s, avp_name.s.s, avp_name.s.len);
-				avp->avp_name.s.s[avp->avp_name.s.len] = 0;
-			} else {
-				avp->avp_name.n = avp_name.n;
-			}
-			/* go to after the equal sign */
-			p = s+1;
-		}
-		/* attr - is between p and e*/
-		foo.s = p;
-		foo.len = e-p;
-		trim( &foo );
-		if (foo.len==0)
-			goto parse_error;
-		/* copy the attr into the avp structure */
-		avp->attr_name.s = (char*)pkg_malloc( foo.len+1 );
-		if (avp->attr_name.s==0) {
-			LM_ERR("no more pkg mem\n");
-			goto error;
-		}
-		avp->attr_name.len = foo.len;
-		memcpy( avp->attr_name.s, foo.s, foo.len );
-		avp->attr_name.s[foo.len] = 0;
-		/* was an avp name specified? */
-		if (avp->avp_name.s.s==0) {
-			/* use as avp_name the attr name */
-			avp->avp_type = AVP_NAME_STR;
-			avp->avp_name.s = avp->attr_name;
-		}
-		/* link the element */
-		avp->next = *avp_def;
-		*avp_def = avp;
-		(*cnt)++;
-		avp = 0;
-		/* go to the end */
-		p = e;
-		if (*p==';')
-			p++;
-		if (*p==0)
-			break;
-	}
-
-	return 0;
-parse_error:
-	LM_ERR("parse failed in \"%s\" at pos %d(%s)\n",
-		definition, (int)(long)(p-definition),p);
-error:
-	free_aaa_avp( avp );
-	free_aaa_avp_list( *avp_def );
-	*avp_def = 0;
-	*cnt = 0;
-	return -1;
-}
-
-#endif

+ 102 - 4
modules_k/auth_db/authdb_mod.c

@@ -41,9 +41,9 @@
 #include "../../dprint.h"
 #include "../../error.h"
 #include "../../mod_fix.h"
+#include "../../trim.h"
 #include "../../mem/mem.h"
 #include "../../modules/auth/api.h"
-#include "aaa_avps.h"
 #include "authorize.h"
 
 MODULE_VERSION
@@ -69,6 +69,7 @@ static int mod_init(void);
 
 
 static int auth_fixup(void** param, int param_no);
+int parse_aaa_pvs(char *definition, pv_elem_t **pv_def, int *cnt);
 
 #define USER_COL "username"
 #define USER_COL_LEN (sizeof(USER_COL) - 1)
@@ -103,7 +104,7 @@ db_func_t auth_dbf;
 auth_api_s_t auth_api;
 
 char *credentials_list      = DEFAULT_CRED_LIST;
-struct aaa_avp *credentials = 0; /* Parsed list of credentials to load */
+pv_elem_t *credentials      = 0; /* Parsed list of credentials to load */
 int credentials_n           = 0; /* Number of credentials in the list */
 
 /*
@@ -205,7 +206,7 @@ static int mod_init(void)
 	}
 
 	/* process additional list of credentials */
-	if (parse_aaa_avps( credentials_list, &credentials, &credentials_n)!=0) {
+	if (parse_aaa_pvs(credentials_list, &credentials, &credentials_n) != 0) {
 		LM_ERR("failed to parse credentials\n");
 		return -5;
 	}
@@ -221,7 +222,7 @@ static void destroy(void)
 		auth_db_handle = 0;
 	}
 	if (credentials) {
-		free_aaa_avp_list(credentials);
+		pv_elem_free_all(credentials);
 		credentials = 0;
 		credentials_n = 0;
 	}
@@ -263,3 +264,100 @@ static int auth_fixup(void** param, int param_no)
 	}
 	return 0;
 }
+
+/*
+ * Parse extra credentials list
+ */
+int parse_aaa_pvs(char *definition, pv_elem_t **pv_def, int *cnt)
+{
+	pv_elem_t *pve;
+	str pv;
+	char *p;
+	char *end;
+	char *sep;
+
+	p = definition;
+	*pv_def = 0;
+	*cnt = 0;
+
+	if (p==0 || *p==0)
+		return 0;
+
+	/* get element by element */
+	while ( (end=strchr(p,';'))!=0 || (end=p+strlen(p))!=p ) {
+		/* new pv_elem_t */
+		if ( (pve=(pv_elem_t*)pkg_malloc(sizeof(pv_elem_t)))==0 ) {
+			LM_ERR("no more pkg mem\n");
+			goto error;
+		}
+		memset( pve, 0, sizeof(pv_elem_t));
+
+		/* definition is between p and e */
+		/* search backwards because PV definition may contain '=' characters */
+		for (sep = end; sep >= p && *sep != '='; sep--); 
+		if (sep > p) {
+			/* pv=column style */
+			/* set column name */
+			pve->text.s = sep + 1;
+			pve->text.len = end - pve->text.s;
+			trim(&pve->text);
+			if (pve->text.len == 0)
+				goto parse_error;
+			/* set pv spec */
+			pv.s = p;
+			pv.len = sep - p;
+			trim(&pv);
+			if (pv.len == 0)
+				goto parse_error;
+		} else {
+			/* no pv, only column name */
+			pve->text.s = p;
+			pve->text.len = end - pve->text.s;
+			trim(&pve->text);
+			if (pve->text.len == 0)
+				goto parse_error;
+			/* create an avp definition for the spec parser */
+			pv.s = (char*)pkg_malloc(pve->text.len + 7);
+			if (pv.s == NULL) {
+				LM_ERR("no more pkg mem\n");
+				goto parse_error;
+			}
+			pv.len = snprintf(pv.s, pve->text.len + 7, "$avp(%.*s)",
+			                  pve->text.len, pve->text.s);
+		}
+
+		/* create a pv spec */
+		LM_DBG("column: %.*s  pv: %.*s\n", pve->text.len, pve->text.s, pv.len, pv.s);
+		if (pv_parse_spec(&pv, &pve->spec) == 0) {
+			LM_ERR("malformed PV definition: %.*s\n", pv.len, pv.s);
+			goto parse_error;;
+		}
+		if(pve->spec.setf == NULL) {
+			LM_ERR("PV is not writeable: %.*s\n", pv.len, pv.s);
+			goto parse_error;
+		}
+
+		/* link the element */
+		pve->next = *pv_def;
+		*pv_def = pve;
+		(*cnt)++;
+		pve = 0;
+		/* go to the end */
+		p = end;
+		if (*p==';')
+			p++;
+		if (*p==0)
+			break;
+	}
+
+	return 0;
+parse_error:
+	LM_ERR("parse failed in \"%s\" at pos %d(%s)\n",
+		definition, (int)(long)(p-definition),p);
+error:
+	pkg_free( pve );
+	pv_elem_free_all( *pv_def );
+	*pv_def = 0;
+	*cnt = 0;
+	return -1;
+}

+ 1 - 1
modules_k/auth_db/authdb_mod.h

@@ -51,7 +51,7 @@ extern db_func_t auth_dbf;
 
 extern auth_api_s_t auth_api;
 
-extern struct aaa_avp* credentials;
+extern pv_elem_t *credentials;
 extern int credentials_n;
 
 #endif /* AUTHDB_MOD_H */

+ 10 - 65
modules_k/auth_db/authorize.c

@@ -37,6 +37,7 @@
 #include "../../ut.h"
 #include "../../str.h"
 #include "../../lib/srdb1/db.h"
+#include "../../lib/srdb1/db_ut.h"
 #include "../../dprint.h"
 #include "../../parser/digest/digest.h"
 #include "../../parser/hf.h"
@@ -44,7 +45,6 @@
 #include "../../usr_avp.h"
 #include "../../mod_fix.h"
 #include "../../mem/mem.h"
-#include "aaa_avps.h"
 #include "api.h"
 #include "authdb_mod.h"
 
@@ -52,7 +52,7 @@
 static inline int get_ha1(struct username* _username, str* _domain,
 			  const str* _table, char* _ha1, db1_res_t** res)
 {
-	struct aaa_avp *cred;
+	pv_elem_t *cred;
 	db_key_t keys[2];
 	db_val_t vals[2];
 	db_key_t *col;
@@ -73,7 +73,7 @@ static inline int get_ha1(struct username* _username, str* _domain,
 		(&pass_column_2) : (&pass_column);
 
 	for (n = 0, cred=credentials; cred ; n++, cred=cred->next) {
-		col[1 + n] = &cred->attr_name;
+		col[1 + n] = &cred->text;
 	}
 
 	VAL_TYPE(vals) = VAL_TYPE(vals + 1) = DB1_STR;
@@ -131,73 +131,18 @@ static inline int get_ha1(struct username* _username, str* _domain,
 /*
  * Generate AVPs from the database result
  */
-static int generate_avps(db1_res_t* result)
+static int generate_avps(struct sip_msg* msg, db1_res_t* db_res)
 {
-	struct aaa_avp *cred;
-	int_str ivalue;
+	pv_elem_t *cred;
 	int i;
 
 	for (cred=credentials, i=1; cred; cred=cred->next, i++) {
-		switch (result->col.types[i]) {
-		case DB1_STR:
-			ivalue.s = VAL_STR(&(result->rows[0].values[i]));
-
-			if (VAL_NULL(&(result->rows[0].values[i])) ||
-			ivalue.s.s == NULL || ivalue.s.len==0)
-				continue;
-
-			if (add_avp(cred->avp_type|AVP_VAL_STR,cred->avp_name,ivalue)!=0){
-				LM_ERR("failed to add AVP\n");
-				return -1;
-			}
-
-			LM_DBG("set string AVP \"%s\"/%d = \"%.*s\"\n",
-				(cred->avp_type&AVP_NAME_STR)?cred->avp_name.s.s:"",
-				(cred->avp_type&AVP_NAME_STR)?0:cred->avp_name.n,
-				ivalue.s.len, ZSW(ivalue.s.s));
-			break;
-		case DB1_STRING:
-			ivalue.s.s = (char*)VAL_STRING(&(result->rows[0].values[i]));
-
-			if (VAL_NULL(&(result->rows[0].values[i])) ||
-			ivalue.s.s == NULL || (ivalue.s.len=strlen(ivalue.s.s))==0 )
-				continue;
-
-			if (add_avp(cred->avp_type|AVP_VAL_STR,cred->avp_name,ivalue)!=0){
-				LM_ERR("failed to add AVP\n");
-				return -1;
-			}
-
-			LM_DBG("set string AVP \"%s\"/%d = \"%.*s\"\n",
-				(cred->avp_type&AVP_NAME_STR)?cred->avp_name.s.s:"",
-				(cred->avp_type&AVP_NAME_STR)?0:cred->avp_name.n,
-				ivalue.s.len, ZSW(ivalue.s.s));
-			break;
-		case DB1_INT:
-			if (VAL_NULL(&(result->rows[0].values[i])))
-				continue;
-
-			ivalue.n = (int)VAL_INT(&(result->rows[0].values[i]));
-
-			if (add_avp(cred->avp_type, cred->avp_name, ivalue)!=0) {
-				LM_ERR("failed to add AVP\n");
-				return -1;
-			}
-
-			LM_DBG("set int AVP \"%s\"/%d = %d\n",
-				(cred->avp_type&AVP_NAME_STR)?cred->avp_name.s.s:"",
-				(cred->avp_type&AVP_NAME_STR)?0:cred->avp_name.n,
-				ivalue.n);
-			break;
-		default:
-			LM_ERR("subscriber table column `%.*s' has unsuported type. "
-				"Only string/str or int columns are supported by"
-				"load_credentials.\n", result->col.names[i]->len,
-				result->col.names[i]->s);
-			break;
+		if (db_val2pv_spec(msg, &RES_ROWS(db_res)[0].values[i], &cred->spec) != 0) {
+			LM_ERR("Failed to convert value for column %.*s\n",
+					RES_NAMES(db_res)[i]->len, RES_NAMES(db_res)[i]->s);
+			return -1;
 		}
 	}
-
 	return 0;
 }
 
@@ -277,7 +222,7 @@ static int digest_authenticate(struct sip_msg* msg, str *realm,
 		ret = AUTH_OK;
 		switch(auth_api.post_auth(msg, h)) {
 			case AUTHENTICATED:
-				generate_avps(result);
+				generate_avps(msg, result);
 				break;
 			default:
 				ret = AUTH_ERROR;