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