ldap_search.patch
application/octet-stream
Filename: ldap_search.patch
Type: application/octet-stream
Part: 0
Patch
Format: context
| File | + | − |
|---|---|---|
| src/backend/libpq/auth.c | 182 | 0 |
| src/backend/libpq/hba.c | 20 | 0 |
| src/include/libpq/hba.h | 4 | 0 |
*** a/src/backend/libpq/auth.c
--- b/src/backend/libpq/auth.c
***************
*** 2096,2135 **** CheckPAMAuth(Port *port, char *user, char *password)
*/
#ifdef USE_LDAP
static int
! CheckLDAPAuth(Port *port)
{
- char *passwd;
- LDAP *ldap;
- int r;
int ldapversion = LDAP_VERSION3;
! char fulluser[NAMEDATALEN + 256 + 1];
!
! if (!port->hba->ldapserver || port->hba->ldapserver[0] == '\0')
! {
! ereport(LOG,
! (errmsg("LDAP server not specified")));
! return STATUS_ERROR;
! }
!
! if (port->hba->ldapport == 0)
! port->hba->ldapport = LDAP_PORT;
!
! sendAuthRequest(port, AUTH_REQ_PASSWORD);
!
! passwd = recv_password_packet(port);
! if (passwd == NULL)
! return STATUS_EOF; /* client wouldn't send password */
!
! if (strlen(passwd) == 0)
! {
! ereport(LOG,
! (errmsg("empty password returned by client")));
! return STATUS_ERROR;
! }
! ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
! if (!ldap)
{
#ifndef WIN32
ereport(LOG,
--- 2096,2113 ----
*/
#ifdef USE_LDAP
+ /*
+ * Initialize a connection to the LDAP server, including setting up
+ * TLS if requested.
+ */
static int
! InitializeLDAPConnection(Port *port, LDAP **ldap)
{
int ldapversion = LDAP_VERSION3;
! int r;
! *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
! if (!*ldap)
{
#ifndef WIN32
ereport(LOG,
***************
*** 2143,2151 **** CheckLDAPAuth(Port *port)
return STATUS_ERROR;
}
! if ((r = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
{
! ldap_unbind(ldap);
ereport(LOG,
(errmsg("could not set LDAP protocol version: error code %d", r)));
return STATUS_ERROR;
--- 2121,2129 ----
return STATUS_ERROR;
}
! if ((r = ldap_set_option(*ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
{
! ldap_unbind(*ldap);
ereport(LOG,
(errmsg("could not set LDAP protocol version: error code %d", r)));
return STATUS_ERROR;
***************
*** 2154,2160 **** CheckLDAPAuth(Port *port)
if (port->hba->ldaptls)
{
#ifndef WIN32
! if ((r = ldap_start_tls_s(ldap, NULL, NULL)) != LDAP_SUCCESS)
#else
static __ldap_start_tls_sA _ldap_start_tls_sA = NULL;
--- 2132,2138 ----
if (port->hba->ldaptls)
{
#ifndef WIN32
! if ((r = ldap_start_tls_s(*ldap, NULL, NULL)) != LDAP_SUCCESS)
#else
static __ldap_start_tls_sA _ldap_start_tls_sA = NULL;
***************
*** 2195,2215 **** CheckLDAPAuth(Port *port)
* per process and is automatically cleaned up on process exit.
*/
}
! if ((r = _ldap_start_tls_sA(ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS)
#endif
{
! ldap_unbind(ldap);
ereport(LOG,
(errmsg("could not start LDAP TLS session: error code %d", r)));
return STATUS_ERROR;
}
}
! 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);
ldap_unbind(ldap);
--- 2173,2354 ----
* per process and is automatically cleaned up on process exit.
*/
}
! if ((r = _ldap_start_tls_sA(*ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS)
#endif
{
! ldap_unbind(*ldap);
ereport(LOG,
(errmsg("could not start LDAP TLS session: error code %d", r)));
return STATUS_ERROR;
}
}
! return STATUS_OK;
! }
!
! /*
! * Perform LDAP authentication
! */
! static int
! CheckLDAPAuth(Port *port)
! {
! char *passwd;
! LDAP *ldap;
! int r;
! char *fulluser;
!
! if (!port->hba->ldapserver || port->hba->ldapserver[0] == '\0')
! {
! ereport(LOG,
! (errmsg("LDAP server not specified")));
! return STATUS_ERROR;
! }
!
! if (port->hba->ldapport == 0)
! port->hba->ldapport = LDAP_PORT;
!
! sendAuthRequest(port, AUTH_REQ_PASSWORD);
!
! passwd = recv_password_packet(port);
! if (passwd == NULL)
! return STATUS_EOF; /* client wouldn't send password */
!
! if (strlen(passwd) == 0)
! {
! ereport(LOG,
! (errmsg("empty password returned by client")));
! return STATUS_ERROR;
! }
!
! if (InitializeLDAPConnection(port, &ldap) == STATUS_ERROR)
! /* Error message already sent */
! return STATUS_ERROR;
!
! if (port->hba->ldapbasedn)
! {
! /*
! * First perform an LDAP search to find the DN for the user we are trying to log
! * in as.
! */
! char *filter;
! LDAPMessage *search_message;
! LDAPMessage *entry;
! char *attributes[2];
! char *dn;
!
! /*
! * Bind with a pre-defined username/password (if available) for searching. If
! * none is specified, this turns into an anonymous bind.
! */
! 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("could not perform initial LDAP bind 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] = port->hba->ldapsearchattribute ? port->hba->ldapsearchattribute : "uid";
! attributes[1] = NULL;
!
! filter = palloc(strlen(attributes[0])+strlen(port->user_name)+4);
! sprintf(filter, "(%s=%s)",
! attributes[0],
! port->user_name); /* FIXME: sanitize user_name? */
!
! r = ldap_search_s(ldap,
! port->hba->ldapbasedn,
! LDAP_SCOPE_SUBTREE,
! filter,
! attributes,
! 0,
! &search_message);
!
! if (r != LDAP_SUCCESS)
! {
! ereport(LOG,
! (errmsg("could not search LDAP for filter \"%s\" on server \"%s\": error code %d",
! filter, port->hba->ldapserver, r)));
! pfree(filter);
! 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))));
!
! pfree(filter);
! 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_ERROR_NUMBER, &error);
! ereport(LOG,
! (errmsg("could not get dn for the first entry matching \"%s\" on server \"%s\": %s",
! filter, port->hba->ldapserver, ldap_err2string(error))));
! pfree(filter);
! ldap_msgfree(search_message);
! return STATUS_ERROR;
! }
! fulluser = pstrdup(dn);
!
! pfree(filter);
! ldap_memfree(dn);
! ldap_msgfree(search_message);
!
! /* Unbind and disconnect from the LDAP server */
! r = ldap_unbind_s(ldap);
! if (r != LDAP_SUCCESS)
! {
! int error;
! (void)ldap_get_option(ldap, LDAP_OPT_RESULT_CODE, &error);
! ereport(LOG,
! (errmsg("could not unbind after searching for user \"%s\" on server \"%s\": %s",
! fulluser, port->hba->ldapserver, ldap_err2string(error))));
! pfree(fulluser);
! return STATUS_ERROR;
! }
!
! /*
! * Need to re-initialize the LDAP connection, so that we can bind
! * to it with a different username.
! */
! if (InitializeLDAPConnection(port, &ldap) == STATUS_ERROR)
! {
! pfree(fulluser);
!
! /* Error message already sent */
! return STATUS_ERROR;
! }
! }
! else
! {
! fulluser = palloc(port->hba->ldapprefix ? strlen(port->hba->ldapprefix) : 0 +
! strlen(port->user_name) +
! port->hba->ldapsuffix ? strlen(port->hba->ldapsuffix) : 0 +
! 1);
!
! sprintf(fulluser, "%s%s%s",
! port->hba->ldapprefix ? port->hba->ldapprefix : "",
! port->user_name,
! port->hba->ldapsuffix ? port->hba->ldapsuffix : "");
! }
r = ldap_simple_bind_s(ldap, fulluser, passwd);
ldap_unbind(ldap);
***************
*** 2219,2227 **** CheckLDAPAuth(Port *port)
--- 2358,2369 ----
ereport(LOG,
(errmsg("LDAP login failed for user \"%s\" on server \"%s\": error code %d",
fulluser, port->hba->ldapserver, r)));
+ pfree(fulluser);
return STATUS_ERROR;
}
+ pfree(fulluser);
+
return STATUS_OK;
}
#endif /* USE_LDAP */
*** a/src/backend/libpq/hba.c
--- b/src/backend/libpq/hba.c
***************
*** 1103,1108 **** parse_hba_line(List *line, int line_num, HbaLine *parsedline)
--- 1103,1128 ----
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");
*** a/src/include/libpq/hba.h
--- b/src/include/libpq/hba.h
***************
*** 61,66 **** typedef struct
--- 61,70 ----
bool ldaptls;
char *ldapserver;
int ldapport;
+ char *ldapbinddn;
+ char *ldapbindpasswd;
+ char *ldapsearchattribute;
+ char *ldapbasedn;
char *ldapprefix;
char *ldapsuffix;
bool clientcert;