Re: bug: Partial results from DB lookup causing parsing problems

Simon Horman <[email protected]>
Newsgroups gmane.mail.perdition.user
Message-ID <[email protected]>
On Mon, Oct 27, 2008 at 11:25:40AM +0000, Simon Fraser wrote:
> 
> I initially hit 'reply' rather than 'reply to all', so I'll re-send this
> to the list.
> 
> > I don't have an LDAP db handy to test against, so could
> > you please test the following change for me to see if
> > it helps your problem. If not, I'll dig deeper into the problem.
> 
> Many thanks for getting back to me so quickly.  I've patched a clean
> version of 1.17.1, and tested. 
> 
> > +     if (returns[0])
> > +             user_str = &returns[0];
> > +     if (returns[1])
> > +             server_str = &returns[1];
> > +     if (returns[2])
> > +             port_str = &returns[2];
> 
> The lookup was failing, and I've traced it to the lines above.  These
> pointers are directed to &returns, but a few lines later, all the values
> of returns are passed to free():
> 
>         for (count = 0; count < attrcount; count++)
>                 if (returns[count] != NULL)
>                         free(returns[count]);
>         free(returns);
> 
> I've replaced the lines quoted above with ones like:
> 
> if (returns[1])
>         *server_str = strdup(returns[1]);
> 
> This works fine, but my C is rusty enough that I don't know if this will
> create memory problems over time. 

Sorry about that. I think that your fix is ok, though
I think I will go with the change below that just makes
sure the strings aren't freed if we make it to the bottom
cleanly.

The key is the following snippet

       leave:
-       if (returns) {
+       if (returns && status) {
                for (count = 0; count < attrcount; count++)

I actually think that the code could be restructured to get rid of
returns[]. Which may simplify things, but on the other hand
it may make error handling trickier.

> With strdup() in place, outgoing_server is used if the LDAP directory is
> missing either username or server, but port is filled in appropriately
> if it is missing. Since a missing username means no entry in LDAP for
> that user, and the lookup falls through correctly for a missing server
> entry, this is now working as I'd hoped for.

Great.

> Incidentally, I've ventured into nasty kludge territory to work around a
> bug that appears not to be in your code, but either in libldap or
> libldap's interaction with Active Directory.  ldap_init, ldap_set_option
> and ldap_bind_s are all successful, but ldap_search_s does not return
> LDAP_SUCCESS.  Instead, it returns LDAP_SERVER_DOWN, _even if_ the
> search was successful. It seems insane, but if I comment out the check
> for (err != LDAP_SUCCESS) and just check for returned attributes, all
> the data is there.  I can replicate this in my own test program using
> libldap both from debian-etch (2.1.30) and the openldap-2.4.11 source
> package, so I'm confident the problem isn't in your code, but it's
> probably worth knowing about.

That does sound bizarre - but believable.

Could you send a patch just to confirm the change / workaround that you are
suggesting?

-- 
Simon Horman
  VA Linux Systems Japan K.K., Sydney, Australia Satellite Office
  H: www.vergenet.net/~horms/             W: www.valinux.co.jp/en

Allow the ldap db to return any one or more of: username, server and port.

This is done by switching the ldap module over to use db_getsever2() instead
of db_getserver(), which allows these elements to be returned individually,
rather than as a string that then has to be broken down into its parts -
which assumes that server is always present.

Signed-off-by: Simon Horman <[email protected]>
Index: perdition-1.17.1/perdition/db/ldap/perditiondb_ldap.c
===================================================================
--- perdition-1.17.1.orig/perdition/db/ldap/perditiondb_ldap.c	2007-10-31 13:43:25.000000000 +1100
+++ perdition-1.17.1/perdition/db/ldap/perditiondb_ldap.c	2008-10-28 11:41:52.000000000 +1100
@@ -285,25 +285,26 @@ static int pldap_scan_exts(char **exts, 
 
 
 /**********************************************************************
- * dbserver_get
+ * dbserver_get2
  * Read the server (value) from an LDAP directory given the user (key)
  * pre: key_str: Key as a null terminated string
- *      options_str: Options string. 
+ *      options_str: Options string.
  *                   Ignored if NULL
  *                   Used as the map to open otherwise
- *      str_return: value is returned here
- *      len_return: length of value is returned here
- * post: The str_key is looked up in the gdbm map and the
- *       corresponding value is returned in str_return and len_return.
+ *      user_str: string for user is returned here
+ *      server_str: string for server is returned here
+ *      port_str: string for port is returned here
+ * post: The str_key is looked up in the ldap database and the
+ *       corresponding values are returned in user_str, server_str and
+ *       port_str.
  * return:  0 on success
  *         -1 on LDAP access error
  *         -2 if key cannot be found in map
  *         -3 on other error
  **********************************************************************/
 
-int dbserver_get(const char *key_str,
-		 const char *options_str,
-		 char **str_return, int *len_return)
+int dbserver_get2(const char *key_str, const char *options_str,
+		 char **user_str, char **server_str, char **port_str)
 {
 	LDAPURLDesc *lud = NULL;
 	LDAP *connection = NULL;
@@ -322,9 +323,6 @@ int dbserver_get(const char *key_str,
 
 	extern options_t opt;
 
-	*len_return = 0;
-
-
 	/* get filter string */
 	if (pldap_get_filter(key_str, pldap_filter, &lud) < 0) {
 		VANESSA_LOGGER_DEBUG("pldap_get_filter");
@@ -432,7 +430,6 @@ int dbserver_get(const char *key_str,
 		goto leave;
 	}
 
-	*len_return = 0;
 	for (pstr = ldap_first_attribute(connection, mptr, &ber);
 	     pstr != NULL;
 	     pstr = ldap_next_attribute(connection, mptr, ber)) {
@@ -442,7 +439,6 @@ int dbserver_get(const char *key_str,
 			if (strcasecmp(lud->lud_attrs[count], pstr) != 0) {
 				continue;
 			}
-			*len_return += strlen(*bv_val);
 			if (returns[count] != NULL) {
 				free(returns[count]);
 			}
@@ -465,41 +461,18 @@ int dbserver_get(const char *key_str,
 	ber_free(ber, 0);
 	ber = NULL;
 
-	/* Add in some extra for the separators and terminating NULL */
-	*len_return += 2 + strlen(opt.domain_delimiter);
-
-	if ((*str_return = (char *) calloc(1, *len_return)) == NULL) {
-		VANESSA_LOGGER_DEBUG_ERRNO("str_return calloc");
-		status = -3;
-		goto leave;
-	}
-
 	/* Build the return string */
-	if (attrcount > 0 && returns[0]) {
-		strcat(*str_return, returns[0]);
-	}
-	if (attrcount > 1 && returns[1]) {
-		if (returns[0]) {
-			strcat(*str_return, opt.domain_delimiter);
-		}
-		strcat(*str_return, returns[1]);
-	}
-	if (attrcount > 2 && returns[2] && returns[1]) {
-		strcat(*str_return, ":");
-		strcat(*str_return, returns[2]);
-	}
-	for (count = 0; count < attrcount; count++) {
-		if (!returns[count]) {
-			continue;
-		}
-		free(returns[count]);
-		returns[count] = NULL;
-	}
+	if (returns[0])
+		user_str = &returns[0];
+	if (returns[1])
+		server_str = &returns[1];
+	if (returns[2])
+		port_str = &returns[2];
 
 	status = 0;
 
       leave:
-	if (returns) {
+	if (returns && status) {
 		for (count = 0; count < attrcount; count++)
 			if (returns[count] != NULL)
 				free(returns[count]);
Index: perdition-1.17.1/perdition/getserver.c
===================================================================
--- perdition-1.17.1.orig/perdition/getserver.c	2005-06-22 15:50:05.000000000 +1000
+++ perdition-1.17.1/perdition/getserver.c	2008-10-28 11:39:33.000000000 +1100
@@ -291,9 +291,21 @@ do_getserver(
 	}
 
 	/* Check for an empty result */
-	if(!server_str || *server_str=='\0') {
-		VANESSA_LOGGER_DEBUG("dbserver_get returned empty string");
-		goto fail;
+	if(dbserver_get) {
+		if(!server_str || *server_str=='\0') {
+			VANESSA_LOGGER_DEBUG("dbserver_get returned empty "
+					     "string");
+			goto fail;
+		}
+	}
+	else {
+		if((!user_str || *user_str=='\0') &&
+		   (!server_str || *server_str=='\0') &&
+		   (!port_str || *port_str=='\0')) {
+			VANESSA_LOGGER_DEBUG("dbserver_get returned empty "
+					     "string");
+			goto fail;
+		}
 	}
 
 	if(dbserver_get) {
______________________________________________
Perdition-users mailing list
[email protected]
http://lists.vergenet.net/listinfo/perdition-users
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.