Index: configure.in
===================================================================
RCS file: /projects/cvsroot/pgsql/configure.in,v
retrieving revision 1.432
diff -c -r1.432 configure.in
*** configure.in	5 Nov 2005 16:42:01 -0000	1.432
--- configure.in	31 Dec 2005 16:11:37 -0000
***************
*** 447,452 ****
--- 447,463 ----
  
  
  #
+ # LDAP
+ #
+ AC_MSG_CHECKING([whether to build with LDAP support])
+ PGAC_ARG_BOOL(with, ldap, no,
+               [  --with-ldap             build with LDAP support],
+               [AC_DEFINE([USE_LDAP], 1, [Define to 1 to build with LDAP support. (--with-ldap)])])
+ AC_MSG_RESULT([$with_ldap])
+ AC_SUBST(with_ldap)
+ 
+ 
+ #
  # Bonjour
  #
  AC_MSG_CHECKING([whether to build with Bonjour support])
***************
*** 678,683 ****
--- 689,702 ----
  fi
  
  
+ if test "$with_ldap" = yes ; then
+   if test "$PORTNAME" != "win32"; then
+      AC_CHECK_LIB(ldap,    ldap_bind, [], [AC_MSG_ERROR([library 'ldap' is required for LDAP])])
+   else
+      AC_CHECK_LIB(wldap32, ldap_bind, [], [AC_MSG_ERROR([library 'wldap32' is required for LDAP])])
+   fi
+ fi
+ 
  ##
  ## Header files
  ##
***************
*** 753,758 ****
--- 772,790 ----
                                       [AC_MSG_ERROR([header file <security/pam_appl.h> or <pam/pam_appl.h> is required for PAM.])])])
  fi
  
+ if test "$with_ldap" = yes ; then
+   if test "$PORTNAME" != "win32"; then
+      AC_CHECK_HEADERS(ldap.h, [],
+                       [AC_MSG_ERROR([header file <ldap.h> is required for LDAP])])
+   else
+      AC_CHECK_HEADERS(winldap.h, [],
+                       [AC_MSG_ERROR([header file <winldap.h> is required for LDAP])],
+                       [AC_INCLUDES_DEFAULT
+ #include <windows.h>
+                       ])
+   fi
+ fi
+ 
  if test "$with_bonjour" = yes ; then
    AC_CHECK_HEADER(DNSServiceDiscovery/DNSServiceDiscovery.h, [], [AC_MSG_ERROR([header file <DNSServiceDiscovery/DNSServiceDiscovery.h> is required for Bonjour])])
  fi
Index: src/backend/libpq/auth.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/libpq/auth.c,v
retrieving revision 1.132
diff -c -r1.132 auth.c
*** src/backend/libpq/auth.c	17 Oct 2005 16:24:19 -0000	1.132
--- src/backend/libpq/auth.c	31 Dec 2005 16:11:37 -0000
***************
*** 69,74 ****
--- 69,100 ----
  								 * pam_passwd_conv_proc */
  #endif   /* USE_PAM */
  
+ #ifdef USE_LDAP
+ #ifndef WIN32
+ /* We use a deprecated function to keep the codepaths the same as the
+  * win32 one. */
+ #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 (
+     IN   PLDAP          ExternalHandle,
+     OUT  PULONG         ServerReturnValue,
+     OUT  LDAPMessage    **result,
+     IN   PLDAPControlA  *ServerControls,
+     IN   PLDAPControlA  *ClientControls
+ );
+ #endif
+ 
+ static int CheckLDAPAuth(Port *port);
+ #endif
+ 
+ 
  #ifdef KRB5
  /*----------------------------------------------------------------
   * MIT Kerberos authentication system - protocol version 5
***************
*** 327,332 ****
--- 353,363 ----
  			errstr = gettext_noop("PAM authentication failed for user \"%s\"");
  			break;
  #endif   /* USE_PAM */
+ #ifdef USE_LDAP
+         case uaLDAP:
+             errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
+             break;
+ #endif   /* USE_LDAP */
  		default:
  			errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
  			break;
***************
*** 455,460 ****
--- 486,497 ----
  			break;
  #endif   /* USE_PAM */
  
+ #ifdef USE_LDAP
+         case uaLDAP:
+             status = CheckLDAPAuth(port);
+             break;
+ #endif
+ 
  		case uaTrust:
  			status = STATUS_OK;
  			break;
***************
*** 674,679 ****
--- 711,842 ----
  #endif   /* USE_PAM */
  
  
+ #ifdef USE_LDAP
+ static int
+ CheckLDAPAuth(Port *port)
+ {
+     char *passwd;
+     char server[128];
+     char basedn[128];
+     char prefix[128];
+     char suffix[128];
+     LDAP *ldap;
+     int  ssl = 0;
+     int  r;
+     int  ldapversion = LDAP_VERSION3;
+     int  ldapport = LDAP_PORT;
+     char fulluser[128];
+ 
+     if (!port->auth_arg || port->auth_arg[0] == '\0')
+     {
+         ereport(LOG,
+                 (errmsg("LDAP configuration URL not specified")));
+         return STATUS_ERROR;
+     }
+ 
+     /* 
+      * Crack the LDAP url. We do a very trivial parse..
+      * ldap[s]://<server>[:<port>]/<basedn>[;prefix[;suffix]]
+      */
+ 
+     server[0] = '\0';
+     basedn[0] = '\0';
+     prefix[0] = '\0';
+     suffix[0] = '\0';
+ 
+     /* ldap, including port number */
+     r = sscanf(port->auth_arg, 
+             "ldap://%127[^:]:%i/%127[^;];%127[^;];%127s",
+             server, &ldapport, basedn, prefix, suffix);
+     if (r < 3)
+     {
+         /* ldaps, including port number */
+         r = sscanf(port->auth_arg,
+                 "ldaps://%127[^:]:%i/%127[^;];%127[^;];%127s",
+                 server, &ldapport, basedn, prefix, suffix);
+         if (r >=3) ssl = 1;
+     }
+     if (r < 3)
+     {
+         /* ldap, no port number */
+         r = sscanf(port->auth_arg,
+                 "ldap://%127[^/]/%127[^;];%127[^;];%127s",
+                 server, basedn, prefix, suffix);
+     }
+     if (r < 2)
+     {
+         /* ldaps, no port number */
+         r = sscanf(port->auth_arg,
+                 "ldaps://%127[^/]/%127[^;];%127[^;];%127s",
+                 server, basedn, prefix, suffix);
+         if (r >= 2) ssl = 1;
+     }
+     if (r < 2)
+     {
+         ereport(LOG,
+                 (errmsg("Invalid LDAP url: '%s'", port->auth_arg)));
+         return STATUS_ERROR;
+     }
+ 
+     sendAuthRequest(port, AUTH_REQ_PASSWORD);
+     
+     passwd = recv_password_packet(port);
+     if (passwd == NULL)
+         return STATUS_EOF; /* client wouldn't send password */
+ 
+    
+     ldap = ldap_init(server, ldapport);
+     if (!ldap)
+     {
+         ereport(LOG,
+                 (errmsg("Failed to initialize LDAP: %i", 
+ #ifndef WIN32
+                         errno
+ #else
+                         (int)LdapGetLastError()
+ #endif
+                         )));
+         return STATUS_ERROR;
+     }
+ 
+     if ((r = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
+     {
+         ereport(LOG,
+                 (errmsg("Failed to set LDAP version: %i", r)));
+         return STATUS_ERROR;
+     }
+     
+     if (ssl)
+     {
+ #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) 
+ #endif
+         {
+             ereport(LOG,
+                     (errmsg("Failed to start LDAP TLS session: %i", r)));
+             return STATUS_ERROR;
+         }
+     }
+ 
+     snprintf(fulluser, sizeof(fulluser)-1, "%s%s%s", prefix, port->user_name, suffix);
+     fulluser[sizeof(fulluser)-1] = '\0';
+ 
+     r = ldap_simple_bind_s(ldap, fulluser, passwd);
+     ldap_unbind(ldap);
+ 
+     if (r != LDAP_SUCCESS)
+     {
+         ereport(LOG,
+                 (errmsg("LDAP login failed for user '%s' on server '%s': %i",fulluser,server,r)));
+         return STATUS_ERROR;
+     }
+     
+     return STATUS_OK;
+ }
+ #endif   /* USE_LDAP */
+ 
  /*
   * Collect password response packet from frontend.
   *
Index: src/backend/libpq/hba.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/libpq/hba.c,v
retrieving revision 1.149
diff -c -r1.149 hba.c
*** src/backend/libpq/hba.c	17 Oct 2005 16:24:19 -0000	1.149
--- src/backend/libpq/hba.c	31 Dec 2005 16:11:38 -0000
***************
*** 613,618 ****
--- 613,622 ----
  	else if (strcmp(token, "pam") == 0)
  		*userauth_p = uaPAM;
  #endif
+ #ifdef USE_LDAP
+     else if (strcmp(token,"ldap") == 0)
+         *userauth_p = uaLDAP;
+ #endif
  	else
  	{
  		*error_p = true;
Index: src/backend/libpq/pg_hba.conf.sample
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/libpq/pg_hba.conf.sample,v
retrieving revision 1.60
diff -c -r1.60 pg_hba.conf.sample
*** src/backend/libpq/pg_hba.conf.sample	11 Oct 2005 22:58:15 -0000	1.60
--- src/backend/libpq/pg_hba.conf.sample	31 Dec 2005 16:11:38 -0000
***************
*** 35,41 ****
  # an IP address and netmask in separate columns to specify the set of hosts.
  #
  # METHOD can be "trust", "reject", "md5", "crypt", "password",
! # "krb5", "ident", or "pam".  Note that "password" sends passwords
  # in clear text; "md5" is preferred since it sends encrypted passwords.
  #
  # OPTION is the ident map or the name of the PAM service, depending on METHOD.
--- 35,41 ----
  # an IP address and netmask in separate columns to specify the set of hosts.
  #
  # METHOD can be "trust", "reject", "md5", "crypt", "password",
! # "krb5", "ident", "pam" or "ldap".  Note that "password" sends passwords
  # in clear text; "md5" is preferred since it sends encrypted passwords.
  #
  # OPTION is the ident map or the name of the PAM service, depending on METHOD.
Index: src/include/pg_config.h.in
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/pg_config.h.in,v
retrieving revision 1.87
diff -c -r1.87 pg_config.h.in
*** src/include/pg_config.h.in	20 Aug 2005 23:26:32 -0000	1.87
--- src/include/pg_config.h.in	31 Dec 2005 16:11:38 -0000
***************
*** 639,644 ****
--- 639,647 ----
  /* Define to 1 to build with PAM support. (--with-pam) */
  #undef USE_PAM
  
+ /* Define to 1 to build with LDAP support. (--with-ldap) */
+ #undef USE_LDAP
+ 
  /* Use replacement snprintf() functions. */
  #undef USE_SNPRINTF
  
Index: src/include/libpq/hba.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/libpq/hba.h,v
retrieving revision 1.41
diff -c -r1.41 hba.h
*** src/include/libpq/hba.h	15 Oct 2005 02:49:44 -0000	1.41
--- src/include/libpq/hba.h	31 Dec 2005 16:11:38 -0000
***************
*** 26,31 ****
--- 26,34 ----
  #ifdef USE_PAM
  	,uaPAM
  #endif   /* USE_PAM */
+ #ifdef USE_LDAP
+     ,uaLDAP
+ #endif
  } UserAuth;
  
  typedef struct Port hbaPort;
