Following a discussion on the pgsql-admin list <
http://archives.postgresql.org/pgsql-admin/2009-09/msg00075.php>, I have
created a patch to (optionally) allow PostgreSQL to do a LDAP search to
determine the user's DN (as is done in Apache, MediaWiki, Bugzilla, et al.)
instead of building the DN from a prefix and suffix.
This is necessary for schemas where the login attribute is not in the DN,
such as is described here <
http://www.ldapman.org/articles/intro_to_ldap.html#individual> (look for
"name-based").  This patch is against PostgreSQL 8.4.0 from Debian
Lenny-backports.  If this would be a welcome addition, I can port it forward
to the latest from postgresql.org.
Thanks in advance for your feedback.
Robert
diff -ru postgresql-8.4-8.4.0-original/src/backend/libpq/auth.c postgresql-8.4-8.4.0/src/backend/libpq/auth.c
--- postgresql-8.4-8.4.0-original/src/backend/libpq/auth.c	2009-06-25 04:30:08.000000000 -0700
+++ postgresql-8.4-8.4.0/src/backend/libpq/auth.c	2009-09-16 22:33:46.000000000 -0700
@@ -2150,10 +2150,75 @@
 		}
 	}
 
-	snprintf(fulluser, sizeof(fulluser), "%s%s%s",
-			 port->hba->ldapprefix ? port->hba->ldapprefix : "",
-			 port->user_name,
-			 port->hba->ldapsuffix ? port->hba->ldapsuffix : "");
+	if (port->hba->ldapbasedn)
+	  {
+	    char filter[NAMEDATALEN + 10]; // FIXME: maybe there's a preferred way to pick this size?
+	    LDAPMessage* search_message;
+	    char* attributes[2];
+	    LDAPMessage* entry;
+	    char* dn;
+
+	    /* it seems that you need to search for at least one attribute, else /all/ attributes are returned */
+	    attributes[0] = "uid";
+	    attributes[1] = NULL;
+
+	    snprintf(filter, sizeof(filter), "(uid=%s)", port->user_name);
+	    filter[sizeof(filter) - 1] = '\0';
+
+	    r = ldap_search_s(ldap,
+			      port->hba->ldapbasedn,
+			      LDAP_SCOPE_SUBTREE,
+			      filter,
+			      attributes,
+			      0,
+			      &search_message);
+
+	    if (r != LDAP_SUCCESS)
+	      {
+		ereport(LOG,
+			(errmsg("LDAP search failed for user \"%s\" on server \"%s\": error code %d",
+				fulluser, port->hba->ldapserver, r)));
+		return STATUS_ERROR;
+	      }
+
+	    if (ldap_count_entries(ldap, search_message) != 1)
+	      {
+		if (ldap_count_entries(ldap, search_message) == 0)
+		  ereport(LOG,
+			  (errmsg("LDAP search failed for user \"%s\" on server \"%s\": no such user",
+				  fulluser, port->hba->ldapserver)));
+		else
+		  ereport(LOG,
+			  (errmsg("LDAP search failed for user \"%s\" on server \"%s\": user is not unique (%d matches)",
+				  fulluser, port->hba->ldapserver, ldap_count_entries(ldap, search_message))));
+
+		ldap_msgfree(search_message);
+		return STATUS_ERROR;
+	      }
+
+	    entry = ldap_first_entry(ldap, search_message);
+	    dn = ldap_get_dn(ldap, entry);
+	    if (dn == NULL)
+	      {
+		int error;
+		r = ldap_get_option(ldap, LDAP_OPT_RESULT_CODE, &error);
+		ereport(LOG,
+			(errmsg("LDAP search failed for user \"%s\" on server \"%s\": %s",
+				fulluser, port->hba->ldapserver, ldap_err2string(error))));
+		ldap_msgfree(search_message);
+		return STATUS_ERROR;
+	      }
+	    strncpy(fulluser, dn, sizeof(fulluser));
+
+	    ldap_memfree(dn);
+	    ldap_msgfree(search_message);
+	  }
+	else
+	  snprintf(fulluser, sizeof(fulluser), "%s%s%s",
+		   port->hba->ldapprefix ? port->hba->ldapprefix : "",
+		   port->user_name,
+		   port->hba->ldapsuffix ? port->hba->ldapsuffix : "");
+
 	fulluser[sizeof(fulluser) - 1] = '\0';
 
 	r = ldap_simple_bind_s(ldap, fulluser, passwd);
diff -ru postgresql-8.4-8.4.0-original/src/backend/libpq/hba.c postgresql-8.4-8.4.0/src/backend/libpq/hba.c
--- postgresql-8.4-8.4.0-original/src/backend/libpq/hba.c	2009-06-24 06:39:42.000000000 -0700
+++ postgresql-8.4-8.4.0/src/backend/libpq/hba.c	2009-09-16 22:19:59.000000000 -0700
@@ -1032,6 +1032,11 @@
 					return false;
 				}
 			}
+			else if (strcmp(token, "ldapbasedn") == 0)
+			{
+				REQUIRE_AUTH_OPTION(uaLDAP, "ldapbasedn", "ldap");
+				parsedline->ldapbasedn = pstrdup(c);
+			}
 			else if (strcmp(token, "ldapprefix") == 0)
 			{
 				REQUIRE_AUTH_OPTION(uaLDAP, "ldapprefix", "ldap");
diff -ru postgresql-8.4-8.4.0-original/src/include/libpq/hba.h postgresql-8.4-8.4.0/src/include/libpq/hba.h
--- postgresql-8.4-8.4.0-original/src/include/libpq/hba.h	2009-06-11 07:49:11.000000000 -0700
+++ postgresql-8.4-8.4.0/src/include/libpq/hba.h	2009-09-16 22:20:07.000000000 -0700
@@ -53,6 +53,7 @@
 	bool		ldaptls;
 	char	   *ldapserver;
 	int			ldapport;
+	char	   *ldapbasedn;
 	char	   *ldapprefix;
 	char	   *ldapsuffix;
 	bool		clientcert;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to