]> granicus.if.org Git - postgresql/commitdiff
Fix timeout in LDAP lookup of libpq connection parameters
authorMagnus Hagander <magnus@hagander.net>
Wed, 16 Apr 2014 15:18:02 +0000 (17:18 +0200)
committerMagnus Hagander <magnus@hagander.net>
Wed, 16 Apr 2014 16:58:55 +0000 (18:58 +0200)
Bind attempts to an LDAP server should time out after two seconds,
allowing additional lines in the service control file to be parsed
(which provide a fall back to a secondary LDAP server or default options).
The existing code failed to enforce that timeout during TCP connect,
resulting in a hang far longer than two seconds if the LDAP server
does not respond.

Laurenz Albe

src/interfaces/libpq/fe-connect.c

index 5f1bfb801ebb9ac2c5a1854129958fdffd8356ad..a688d0696e6ca035006bc81c99b549732cd985d1 100644 (file)
@@ -3526,12 +3526,37 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
        }
 
        /*
-        * Initialize connection to the server.  We do an explicit bind because we
-        * want to return 2 if the bind fails.
+        * Perform an explicit anonymous bind.
+        * LDAP does not require that an anonymous bind is preformed explicitly,
+        * but we want to distinguish between the case where LDAP bind does not
+        * succeed within PGLDAP_TIMEOUT seconds (return 2 to continue parsing
+        * the service control file) and the case where querying the LDAP server
+        * fails (return 1 to end parsing).
+        * Unfortunately there is no way of setting a timeout that works for
+        * both Windows and OpenLDAP.
         */
+#ifdef WIN32
+       /* the nonstandard ldap_connect function performs an anonymous bind */
+       if (ldap_connect(ld, &time) != LDAP_SUCCESS)
+       {
+               /* error or timeout in ldap_connect */
+               free(url);
+               ldap_unbind(ld);
+               return 2;
+       }
+#else /* WIN32 */
+       /* in OpenLDAP, use the LDAP_OPT_NETWORK_TIMEOUT option */
+       if (ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &time) != LDAP_SUCCESS)
+       {
+               free(url);
+               ldap_unbind(ld);
+               return 3;
+       }
+
+       /* anonymous bind */
        if ((msgid = ldap_simple_bind(ld, NULL, NULL)) == -1)
        {
-               /* error in ldap_simple_bind() */
+               /* error or network timeout */
                free(url);
                ldap_unbind(ld);
                return 2;
@@ -3542,18 +3567,25 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
        if ((rc = ldap_result(ld, msgid, LDAP_MSG_ALL, &time, &res)) == -1 ||
                res == NULL)
        {
+               /* error or timeout */
                if (res != NULL)
-               {
-                       /* timeout */
                        ldap_msgfree(res);
-               }
-               /* error in ldap_result() */
                free(url);
                ldap_unbind(ld);
                return 2;
        }
        ldap_msgfree(res);
 
+       /* reset timeout */
+       time.tv_sec = -1;
+       if (ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &time) != LDAP_SUCCESS)
+       {
+               free(url);
+               ldap_unbind(ld);
+               return 3;
+       }
+#endif /* WIN32 */
+
        /* search */
        res = NULL;
        if ((rc = ldap_search_st(ld, dn, scope, filter, attrs, 0, &time, &res))