[SR-Dev] git:janakj/ldap: simple user authentication mechanism added

Jan Janak jan at iptel.org
Fri Feb 13 00:57:04 CET 2009


Module: sip-router
Branch: janakj/ldap
Commit: 6bbe8456d8ddf3e999d16d694d58719fe41b5121
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=6bbe8456d8ddf3e999d16d694d58719fe41b5121

Author: Gergely Kovacs <gergo at iptel.org>
Committer: Gergely Kovacs <gergo at iptel.org>
Date:   Wed Jun  4 21:43:27 2008 +0000

simple user authentication mechanism added

---

 modules/db_ldap/ld_con.c |   25 +++---
 modules/db_ldap/ld_uri.c |  194 ++++++++++++++++++++++++++++++++++++++++------
 modules/db_ldap/ld_uri.h |    8 +-
 3 files changed, 187 insertions(+), 40 deletions(-)

diff --git a/modules/db_ldap/ld_con.c b/modules/db_ldap/ld_con.c
index 32a0db9..21df896 100644
--- a/modules/db_ldap/ld_con.c
+++ b/modules/db_ldap/ld_con.c
@@ -23,10 +23,10 @@
  */
 
 /** \addtogroup ldap
- * @{ 
+ * @{
  */
 
-/** \file 
+/** \file
  * Functions related to connections to LDAP servers.
  */
 
@@ -62,12 +62,12 @@ static void ld_con_free(db_con_t* con, struct ld_con* payload)
 	 * to it in the connection pool
 	 */
 	if (db_pool_remove((db_pool_entry_t*)payload) == 0) return;
-	
+
 	db_pool_entry_free(&payload->gen);
 	if (payload->con) {
 		ret = ldap_unbind_ext_s(payload->con, NULL, NULL);
 		if (ret != LDAP_SUCCESS) {
-			ERR("ldap: Error while unbinding from %s: %s\n", 
+			ERR("ldap: Error while unbinding from %s: %s\n",
 				luri->uri, ldap_err2string(ret));
 		}
 	}
@@ -129,10 +129,10 @@ int ld_con_connect(db_con_t* con)
 	struct ld_con* lcon;
 	struct ld_uri* luri;
 	int ret, version = 3;
-	
+
 	lcon = DB_GET_PAYLOAD(con);
 	luri = DB_GET_PAYLOAD(con->uri);
-	
+
 	/* Do not reconnect already connected connections */
 	if (lcon->flags & LD_CONNECTED) return 0;
 
@@ -141,7 +141,7 @@ int ld_con_connect(db_con_t* con)
 	if (lcon->con) {
 		ret = ldap_unbind_ext_s(lcon->con, NULL, NULL);
 		if (ret != LDAP_SUCCESS) {
-			ERR("ldap: Error while unbinding from %s: %s\n", 
+			ERR("ldap: Error while unbinding from %s: %s\n",
 				luri->uri, ldap_err2string(ret));
 		}
 	}
@@ -155,15 +155,14 @@ int ld_con_connect(db_con_t* con)
 
 	ret = ldap_set_option(lcon->con, LDAP_OPT_PROTOCOL_VERSION, &version);
 	if (ret != LDAP_OPT_SUCCESS) {
-		ERR("ldap: Error while setting protocol version 3: %s\n", 
+		ERR("ldap: Error while setting protocol version 3: %s\n",
 			ldap_err2string(ret));
 		goto error;
 	}
 
-	/* FIXME: Currently only anonymous binds are supported */
-	ret = ldap_simple_bind_s(lcon->con, NULL, NULL);
+	ret = ldap_simple_bind_s(lcon->con, luri->username, luri->password);
 	if (ret != LDAP_SUCCESS) {
-		ERR("ldap: Bind to %s failed: %s\n", 
+		ERR("ldap: Bind to %s failed: %s\n",
 			luri->uri, ldap_err2string(ret));
 		goto error;
 	}
@@ -176,7 +175,7 @@ int ld_con_connect(db_con_t* con)
 	if (lcon->con) {
 		ret = ldap_unbind_ext_s(lcon->con, NULL, NULL);
 		if (ret) {
-			ERR("ldap: Error while unbinding from %s: %s\n", 
+			ERR("ldap: Error while unbinding from %s: %s\n",
 				luri->uri, ldap_err2string(ret));
 		}
 	}
@@ -201,7 +200,7 @@ void ld_con_disconnect(db_con_t* con)
 	if (lcon->con) {
 		ret = ldap_unbind_ext_s(lcon->con, NULL, NULL);
 		if (ret) {
-			ERR("ldap: Error while unbinding from %s: %s\n", 
+			ERR("ldap: Error while unbinding from %s: %s\n",
 				luri->uri, ldap_err2string(ret));
 		}
 	}
diff --git a/modules/db_ldap/ld_uri.c b/modules/db_ldap/ld_uri.c
index 2911b28..ee36918 100644
--- a/modules/db_ldap/ld_uri.c
+++ b/modules/db_ldap/ld_uri.c
@@ -1,5 +1,5 @@
-/* 
- * $Id$ 
+/*
+ * $Id$
  *
  * LDAP Database Driver for SER
  *
@@ -18,15 +18,15 @@
  * 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., 
+ * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
 /** \addtogroup ldap
- * @{ 
+ * @{
  */
 
-/** \file 
+/** \file
  * The implementation of parser parsing ldap:.. URIs.
  */
 
@@ -39,7 +39,7 @@
 
 /** compare s1 & s2  with a function f (which should return 0 if ==);
  * s1 & s2 can be null
- * return 0 if match, 1 if not 
+ * return 0 if match, 1 if not
  */
 #define cmpstr(s1, s2, f) \
 	((s1)!=(s2)) && ((s1)==0 || (s2)==0 || (f)((s1), (s2))!=0)
@@ -63,18 +63,178 @@ static unsigned char ld_uri_cmp(db_uri_t* uri1, db_uri_t* uri2)
 	luri2 = DB_GET_PAYLOAD(uri2);
 
 	if (luri1->ldap_url->lud_port != luri2->ldap_url->lud_port) return 0;
-	if (cmpstr(luri1->ldap_url->lud_host, 
-			   luri2->ldap_url->lud_host, strcasecmp)) 
+	if (cmpstr(luri1->ldap_url->lud_host,
+			   luri2->ldap_url->lud_host, strcasecmp))
 		return 0;
 	return 1;
 }
 
+/** Duplicate a string
+ */
+static int dupl_string(char** dst, const char* begin, const char* end)
+{
+	if (*dst) pkg_free(*dst);
+
+	*dst = pkg_malloc(end - begin + 1);
+	if ((*dst) == NULL) {
+		return -1;
+	}
+
+	memcpy(*dst, begin, end - begin);
+	(*dst)[end - begin] = '\0';
+	return 0;
+}
+
+/*
+ * Parse ldap URI of form
+ * //[username[:password]@]hostname[:port]
+ *
+ * Returns 0 if parsing was successful and -1 otherwise
+ */
+int parse_ldap_uri(struct ld_uri* res, str* scheme, str* uri)
+{
+#define SHORTEST_DB_URL "a"
+#define SHORTEST_DB_URL_LEN (sizeof(SHORTEST_DB_URL) - 1)
+
+	enum state {
+		ST_BEGIN,      /* First state */
+		ST_SECTTITLE,  /* Config section title */
+		ST_SLASH2,     /* Second slash */
+		ST_USER_HOST,  /* Username or hostname */
+		ST_PASS_PORT,  /* Password or port part */
+		ST_HOST_PORT   /* Hostname and port part */
+	};
+	enum state st;
+	int  i, ldapurllen;
+	const char* begin;
+	const char* ldapbegin;
+	char* prev_token;
+
+	prev_token = 0;
+
+	if (!res || !scheme || !uri) {
+		goto err;
+	}
+
+	if (uri->len < SHORTEST_DB_URL_LEN) {
+		goto err;
+	}
+
+	st = ST_BEGIN;
+	ldapbegin = begin = uri->s;
+
+	for(i = 0; i < uri->len; i++) {
+		switch(st) {
+		case ST_BEGIN:
+			switch(uri->s[i]) {
+			case '/':
+				st = ST_SLASH2;
+				break;
+
+			default:
+				st = ST_SECTTITLE;
+			}
+			break;
+
+		case ST_SECTTITLE:
+			break;
+
+		case ST_SLASH2:
+			switch(uri->s[i]) {
+			case '/':
+				st = ST_USER_HOST;
+				ldapbegin = begin = uri->s + i + 1;
+				break;
+
+			default:
+				goto err;
+			}
+			break;
+
+		case ST_USER_HOST:
+			switch(uri->s[i]) {
+			case '@':
+				st = ST_HOST_PORT;
+				if (dupl_string(&res->username, begin, uri->s + i) < 0) goto err;
+				ldapbegin = begin = uri->s + i + 1;
+				break;
+
+			case ':':
+				st = ST_PASS_PORT;
+				if (dupl_string(&prev_token, begin, uri->s + i) < 0) goto err;
+				begin = uri->s + i + 1;
+				break;
+			}
+			break;
+
+		case ST_PASS_PORT:
+			switch(uri->s[i]) {
+			case '@':
+				st = ST_HOST_PORT;
+				res->username = prev_token;
+				if (dupl_string(&res->password, begin, uri->s + i) < 0) goto err;
+				ldapbegin = begin = uri->s + i + 1;
+				break;
+			}
+			break;
+
+		case ST_HOST_PORT:
+			break;
+		}
+	}
+
+	switch(st) {
+	case ST_PASS_PORT:
+	case ST_USER_HOST:
+	case ST_HOST_PORT:
+		ldapurllen = uri->len - (int)(ldapbegin - uri->s);
+		// +3 for the '://' ldap url snippet
+		res->uri = pkg_malloc(scheme->len + 3 + ldapurllen + 1);
+		if (res->uri== NULL) {
+			ERR("ldap: No memory left\n");
+			goto err;
+		}
+		memcpy(res->uri, scheme->s, scheme->len);
+		res->uri[scheme->len] = ':';
+		res->uri[scheme->len + 1] = '/';
+		res->uri[scheme->len + 2] = '/';
+		memcpy(res->uri + scheme->len + 3, ldapbegin, ldapurllen);
+		res->uri[scheme->len + 3 + ldapurllen] = '\0';
+
+		if (ldap_url_parse(res->uri, &res->ldap_url) != 0) {
+			ERR("ldap: Error while parsing URL '%s'\n", res->uri);
+			goto err;
+		}
+		break;
+	case ST_SECTTITLE:
+		/* haven't supported yet */
+	default:
+		goto err;
+	}
+
+	return 0;
+
+ err:
+	if (prev_token) pkg_free(prev_token);
+	if (res == NULL) return -1;
+	if (res->username) {
+		pkg_free(res->username);
+		res->username = NULL;
+	}
+	if (res->password) {
+		pkg_free(res->password);
+		res->password = NULL;
+	}
+	return -1;
+}
 
 static void ld_uri_free(db_uri_t* uri, struct ld_uri* payload)
 {
 	if (payload == NULL) return;
 	if (payload->ldap_url) ldap_free_urldesc(payload->ldap_url);
 	if (payload->uri) pkg_free(payload->uri);
+    if (payload->username) pkg_free(payload->username);
+    if (payload->password) pkg_free(payload->password);
 	db_drv_free(&payload->drv);
 	pkg_free(payload);
 }
@@ -91,21 +251,7 @@ int ld_uri(db_uri_t* uri)
 	}
 	memset(luri, '\0', sizeof(struct ld_uri));
 	if (db_drv_init(&luri->drv, ld_uri_free) < 0) goto error;
-
-	luri->uri = pkg_malloc(uri->scheme.len + 1 + uri->body.len + 1);
-	if (luri->uri== NULL) {
-		ERR("ldap: No memory left\n");
-		goto error;
-	}
-	memcpy(luri->uri, uri->scheme.s, uri->scheme.len);
-	luri->uri[uri->scheme.len] = ':';
-	memcpy(luri->uri + uri->scheme.len + 1, uri->body.s, uri->body.len);
-	luri->uri[uri->scheme.len + 1 + uri->body.len] = '\0';
-
-	if (ldap_url_parse(luri->uri, &luri->ldap_url) != 0) {
-		ERR("ldap: Error while parsing URL '%s'\n", luri->uri);
-		goto error;
-	}
+    if (parse_ldap_uri(luri,  &uri->scheme, &uri->body) < 0) goto error;
 
 	DB_SET_PAYLOAD(uri, luri);
 	uri->cmp = ld_uri_cmp;
@@ -118,7 +264,7 @@ int ld_uri(db_uri_t* uri)
 		db_drv_free(&luri->drv);
 		pkg_free(luri);
 	}
-	return -1;	
+	return -1;
 }
 
 
diff --git a/modules/db_ldap/ld_uri.h b/modules/db_ldap/ld_uri.h
index d6886c0..f125767 100644
--- a/modules/db_ldap/ld_uri.h
+++ b/modules/db_ldap/ld_uri.h
@@ -26,10 +26,10 @@
 #define _LD_URI_H
 
 /** \addtogroup ldap
- * @{ 
+ * @{
  */
 
-/** \file 
+/** \file
  * The functions parsing and interpreting ldap: URIs.
  */
 
@@ -41,11 +41,13 @@
 
 /** LDAP driver specific payload to attach to db_uri structures.
  * This is the LDAP specific structure that will be attached
- * to generic db_uri structures in the database API in SER. The 
+ * to generic db_uri structures in the database API in SER. The
  * structure contains parsed elements of the ldap: URI.
  */
 struct ld_uri {
 	db_drv_t drv;
+	char* username;
+	char* password;
 	char* uri;             /**< The whole URI, including scheme */
 	LDAPURLDesc* ldap_url; /**< URI parsed by the ldap client library */
 };




More information about the sr-dev mailing list