pg84-ldap.patch
text/x-patch
Filename: pg84-ldap.patch
Type: text/x-patch
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/libpq/auth.c | 104 | 4 |
| src/backend/libpq/hba.c | 20 | 0 |
| src/include/libpq/hba.h | 4 | 0 |
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-17 18:12:57.000000000 -0700
@@ -2150,10 +2150,110 @@
}
}
- 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;
+
+ /* bind for searching */
+ r = ldap_simple_bind_s(ldap,
+ port->hba->ldapbinddn ? port->hba->ldapbinddn : "",
+ port->hba->ldapbindpasswd ? port->hba->ldapbindpasswd : "");
+ if (r != LDAP_SUCCESS)
+ {
+ ereport(LOG,
+ (errmsg("LDAP initial bind failed for ldapbinddn \"%s\" on server \"%s\": error code %d",
+ port->hba->ldapbinddn, port->hba->ldapserver, r)));
+ return STATUS_ERROR;
+ }
+
+ /* fetch just one attribute, else /all/ attributes are returned */
+ attributes[0] = "uid";
+ attributes[1] = NULL;
+
+ snprintf(filter, sizeof(filter), "(%s=%s)",
+ port->hba->ldapsearchattribute ? port->hba->ldapsearchattribute : "uid",
+ port->user_name); /* FIXME: sanitize 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 filter \"%s\" on server \"%s\": error code %d",
+ filter, 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 filter \"%s\" on server \"%s\": no such user",
+ filter, port->hba->ldapserver)));
+ else
+ ereport(LOG,
+ (errmsg("LDAP search failed for filter \"%s\" on server \"%s\": user is not unique (%d matches)",
+ filter, 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;
+ (void)ldap_get_option(ldap, LDAP_OPT_RESULT_CODE, &error);
+ ereport(LOG,
+ (errmsg("LDAP get_dn() for the first entry matching \"%s\" on server \"%s\": %s",
+ filter, 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);
+
+ /* unbind */
+ r = ldap_unbind_s(ldap);
+ if (r != LDAP_SUCCESS)
+ {
+ int error;
+ (void)ldap_get_option(ldap, LDAP_OPT_RESULT_CODE, &error);
+ ereport(LOG,
+ (errmsg("LDAP unbind failed for user \"%s\" on server \"%s\": %s",
+ fulluser, port->hba->ldapserver, ldap_err2string(error))));
+ return STATUS_ERROR;
+ }
+
+ /* re-init */
+ ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
+ if (!ldap)
+ {
+ printf("could not initialize LDAP: error code %d",
+ errno);
+ return STATUS_ERROR;
+ }
+ }
+ 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-17 17:46:21.000000000 -0700
@@ -1032,6 +1032,26 @@
return false;
}
}
+ else if (strcmp(token, "ldapbinddn") == 0)
+ {
+ REQUIRE_AUTH_OPTION(uaLDAP, "ldapbinddn", "ldap");
+ parsedline->ldapbinddn = pstrdup(c);
+ }
+ else if (strcmp(token, "ldapbindpasswd") == 0)
+ {
+ REQUIRE_AUTH_OPTION(uaLDAP, "ldapbindpasswd", "ldap");
+ parsedline->ldapbindpasswd = pstrdup(c);
+ }
+ else if (strcmp(token, "ldapsearchattribute") == 0)
+ {
+ REQUIRE_AUTH_OPTION(uaLDAP, "ldapsearchattribute", "ldap");
+ parsedline->ldapsearchattribute = pstrdup(c);
+ }
+ 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-17 17:46:00.000000000 -0700
@@ -53,6 +53,10 @@
bool ldaptls;
char *ldapserver;
int ldapport;
+ char *ldapbinddn;
+ char *ldapbindpasswd;
+ char *ldapsearchattribute;
+ char *ldapbasedn;
char *ldapprefix;
char *ldapsuffix;
bool clientcert;