From 91b98c5f803b367b5e4e6a2c15391c24162a61c8 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Fri, 15 Sep 2017 21:40:59 +1200 Subject: [PATCH 2/2] Log diagnostic messages if errors occur during LDAP auth. Diagnostic messages seem likely to help users diagnose root causes more easily, so let's report them as errdetail. Author: Thomas Munro Reviewed-By: Ashutosh Bapat, Christoph Berg, Alvaro Herrera Discussion: https://postgr.es/m/CAEepm=2_dA-SYpFdmNVwvKsEBXOUj=K4ooKovHmvj6jnMdt8dw@mail.gmail.com --- src/backend/libpq/auth.c | 76 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 847ded30c0..1a94fee34e 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -2305,6 +2305,8 @@ CheckBSDAuth(Port *port, char *user) */ #ifdef USE_LDAP +static char *GetLDAPDiagnosticMessage(LDAP *ldap); + /* * Initialize a connection to the LDAP server, including setting up * TLS if requested. @@ -2331,9 +2333,15 @@ InitializeLDAPConnection(Port *port, LDAP **ldap) if ((r = ldap_set_option(*ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS) { + char *message = GetLDAPDiagnosticMessage(*ldap); + ldap_unbind(*ldap); ereport(LOG, - (errmsg("could not set LDAP protocol version: %s", ldap_err2string(r)))); + (errmsg("could not set LDAP protocol version: %s", + ldap_err2string(r)), + message ? errdetail("LDAP diagnostics: %s", message) : 0)); + if (message) + pfree(message); return STATUS_ERROR; } @@ -2384,9 +2392,16 @@ InitializeLDAPConnection(Port *port, LDAP **ldap) if ((r = _ldap_start_tls_sA(*ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS) #endif { + char *message = GetLDAPDiagnosticMessage(*ldap); + ldap_unbind(*ldap); ereport(LOG, - (errmsg("could not start LDAP TLS session: %s", ldap_err2string(r)))); + (errmsg("could not start LDAP TLS session: %s", + ldap_err2string(r)), + message ? errdetail("LDAP diagnostics: %s", + message) : 0)); + if (message) + pfree(message); return STATUS_ERROR; } } @@ -2506,10 +2521,17 @@ CheckLDAPAuth(Port *port) port->hba->ldapbindpasswd ? port->hba->ldapbindpasswd : ""); if (r != LDAP_SUCCESS) { + char *message = GetLDAPDiagnosticMessage(ldap); + ldap_unbind(ldap); ereport(LOG, (errmsg("could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": %s", - port->hba->ldapbinddn, port->hba->ldapserver, ldap_err2string(r)))); + port->hba->ldapbinddn, port->hba->ldapserver, + ldap_err2string(r)), + message ? errdetail("LDAP diagnostics: %s", + message) : 0)); + if (message) + pfree(message); pfree(passwd); return STATUS_ERROR; } @@ -2532,10 +2554,16 @@ CheckLDAPAuth(Port *port) if (r != LDAP_SUCCESS) { + char *message = GetLDAPDiagnosticMessage(ldap); + ldap_unbind(ldap); ereport(LOG, (errmsg("could not search LDAP for filter \"%s\" on server \"%s\": %s", - filter, port->hba->ldapserver, ldap_err2string(r)))); + filter, port->hba->ldapserver, ldap_err2string(r)), + message ? errdetail("LDAP diagnostics: %s", + message) : 0)); + if (message) + pfree(message); pfree(passwd); pfree(filter); return STATUS_ERROR; @@ -2568,13 +2596,19 @@ CheckLDAPAuth(Port *port) dn = ldap_get_dn(ldap, entry); if (dn == NULL) { + char *message = GetLDAPDiagnosticMessage(ldap); int error; (void) ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &error); ldap_unbind(ldap); ereport(LOG, (errmsg("could not get dn for the first entry matching \"%s\" on server \"%s\": %s", - filter, port->hba->ldapserver, ldap_err2string(error)))); + filter, port->hba->ldapserver, + ldap_err2string(error)), + message ? errdetail("LDAP diagnostics: %s", + message) : 0)); + if (message) + pfree(message); pfree(passwd); pfree(filter); ldap_msgfree(search_message); @@ -2618,23 +2652,51 @@ CheckLDAPAuth(Port *port) port->hba->ldapsuffix ? port->hba->ldapsuffix : ""); r = ldap_simple_bind_s(ldap, fulluser, passwd); - ldap_unbind(ldap); if (r != LDAP_SUCCESS) { + char *message = GetLDAPDiagnosticMessage(ldap); + + ldap_unbind(ldap); ereport(LOG, (errmsg("LDAP login failed for user \"%s\" on server \"%s\": %s", - fulluser, port->hba->ldapserver, ldap_err2string(r)))); + fulluser, port->hba->ldapserver, ldap_err2string(r)), + message ? errdetail("LDAP diagnostics: %s", message) : 0)); + if (message) + pfree(message); pfree(passwd); pfree(fulluser); return STATUS_ERROR; } + ldap_unbind(ldap); pfree(passwd); pfree(fulluser); return STATUS_OK; } + +/* + * Return a palloc'd copy of the current LDAP diagnostic message, or NULL if + * there is none. + */ +static char * +GetLDAPDiagnosticMessage(LDAP *ldap) +{ + char *result = NULL; + char *message; + int rc; + + rc = ldap_get_option(ldap, LDAP_OPT_DIAGNOSTIC_MESSAGE, &message); + if (rc == LDAP_SUCCESS && message != NULL) + { + result = pstrdup(message); + ldap_memfree(message); + } + + return result; +} + #endif /* USE_LDAP */ -- 2.13.5