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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers