Fix encrypted-LDAP support so that it doesn't cause the server to fail
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 21 Aug 2006 19:21:38 +0000 (19:21 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 21 Aug 2006 19:21:38 +0000 (19:21 +0000)
entirely on older Windows platforms without the needed library function.
Magnus Hagander

doc/src/sgml/client-auth.sgml
src/backend/libpq/auth.c

index 6344c666a4b3a1a809507dbafd28f3480793a945..276094170a49d29620ce71a56209ac73df236070 100644 (file)
@@ -938,7 +938,8 @@ ldap://ldap.example.net/dc=example,dc=net;EXAMPLE\
     and the LDAP server. The connection between the client and the
     PostgreSQL server is not affected by this setting. To make use of
     TLS encryption, you may need to configure the LDAP library prior
-    to configuring PostgreSQL.
+    to configuring PostgreSQL. Note that encrypted LDAP is available only
+    if the platform's LDAP library supports it.
    </para>
    <para>
     If no port is specified, the default port as configured in the
index bab55229ffad9f1160ca9f10f44217c295d5a280..588abe4b9ddedd54c4f775053d9da44efd0c2359 100644 (file)
@@ -73,13 +73,10 @@ static Port *pam_port_cludge;       /* Workaround for passing "Port *port" into
 #define LDAP_DEPRECATED 1
 #include <ldap.h>
 #else
-/* Header broken in MingW */
-#define ldap_start_tls_sA __BROKEN_LDAP_HEADER
 #include <winldap.h>
-#undef ldap_start_tls_sA
 
 /* Correct header from the Platform SDK */
-WINLDAPAPI ULONG ldap_start_tls_sA (
+typedef ULONG (WINLDAPAPI *__ldap_start_tls_sA)(
     IN   PLDAP          ExternalHandle,
     OUT  PULONG         ServerReturnValue,
     OUT  LDAPMessage    **result,
@@ -713,6 +710,8 @@ CheckPAMAuth(Port *port, char *user, char *password)
 static int
 CheckLDAPAuth(Port *port)
 {
+       static __ldap_start_tls_sA _ldap_start_tls_sA = NULL;
+
     char *passwd;
     char server[128];
     char basedn[128];
@@ -810,7 +809,38 @@ CheckLDAPAuth(Port *port)
 #ifndef WIN32
         if ((r = ldap_start_tls_s(ldap, NULL, NULL)) != LDAP_SUCCESS)
 #else
-        if ((r = ldap_start_tls_sA(ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS) 
+               if (_ldap_start_tls_sA == NULL)
+               {
+                       /*
+                        * Need to load this function dynamically because it does not
+                        * exist on Windows 2000, and causes a load error for the whole
+                        * exe if referenced.
+                        */
+                       HANDLE ldaphandle;
+                       
+                       ldaphandle = LoadLibrary("WLDAP32.DLL");
+                       if (ldaphandle == NULL)
+                       {
+                               /* should never happen since we import other files from wldap32, but check anyway */
+                               ereport(LOG,
+                                               (errmsg("could not load wldap32.dll")));
+                               return STATUS_ERROR;
+                       }
+                       _ldap_start_tls_sA = (__ldap_start_tls_sA)GetProcAddress(ldaphandle, "ldap_start_tls_sA");
+                       if (_ldap_start_tls_sA == NULL)
+                       {
+                               ereport(LOG,
+                                               (errmsg("could not load function _ldap_start_tls_sA in wldap32.dll. LDAP over SSL is not supported on this platform.")));
+                               return STATUS_ERROR;
+                       }
+
+                       /*
+                        * Leak ldaphandle on purpose, because we need the library to stay
+                        * open. This is ok because it will only ever be leaked once per
+                        * process and is automatically cleaned up on process exit.
+                        */
+               }
+        if ((r = _ldap_start_tls_sA(ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS) 
 #endif
         {
             ereport(LOG,