This patch adds native LDAP auth, for those platforms that don't have
authorBruce Momjian
Mon, 6 Mar 2006 17:41:44 +0000 (17:41 +0000)
committerBruce Momjian
Mon, 6 Mar 2006 17:41:44 +0000 (17:41 +0000)
PAM (such as Win32, but also unixen without PAM). On Unix, uses
OpenLDAP. On win32, uses the builin WinLDAP library.

Magnus Hagander

configure
configure.in
src/backend/libpq/auth.c
src/backend/libpq/hba.c
src/backend/libpq/pg_hba.conf.sample
src/include/libpq/hba.h
src/include/pg_config.h.in

index 3fe6e12345a90b440175b75380a0e610466c5440..1ae425ebfbf48e6c0d10f5527668ae4c4b6fdd3a 100755 (executable)
--- a/configure
+++ b/configure
@@ -314,7 +314,7 @@ ac_includes_default="\
 # include 
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS configure_args build build_cpu build_vendor build_os host host_cpu host_vendor host_os PORTNAME docdir enable_nls WANTED_LANGUAGES default_port enable_shared enable_rpath enable_debug CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP GCC TAS autodepend INCLUDES enable_thread_safety with_tcl with_perl with_python with_krb5 krb_srvtab with_pam with_bonjour with_openssl with_zlib EGREP ELF_SYS LDFLAGS_SL AWK FLEX FLEXFLAGS LN_S LD with_gnu_ld ld_R_works RANLIB ac_ct_RANLIB LORDER TAR STRIP ac_ct_STRIP STRIP_STATIC_LIB STRIP_SHARED_LIB YACC YFLAGS PERL perl_archlibexp perl_privlibexp perl_useshrplib perl_embed_ldflags PYTHON python_version python_configdir python_includespec python_libdir python_libspec python_additional_libs HAVE_IPV6 LIBOBJS acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS HAVE_POSIX_SIGNALS MSGFMT MSGMERGE XGETTEXT localedir TCLSH TCL_CONFIG_SH TCL_INCLUDE_SPEC TCL_LIB_FILE TCL_LIBS TCL_LIB_SPEC TCL_SHARED_BUILD TCL_SHLIB_LD_LIBS NSGMLS JADE have_docbook DOCBOOKSTYLE COLLATEINDEX SGMLSPL vpath_build LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS configure_args build build_cpu build_vendor build_os host host_cpu host_vendor host_os PORTNAME docdir enable_nls WANTED_LANGUAGES default_port enable_shared enable_rpath enable_debug CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP GCC TAS autodepend INCLUDES enable_thread_safety with_tcl with_perl with_python with_krb5 krb_srvtab with_pam with_ldap with_bonjour with_openssl with_zlib EGREP ELF_SYS LDFLAGS_SL AWK FLEX FLEXFLAGS LN_S LD with_gnu_ld ld_R_works RANLIB ac_ct_RANLIB LORDER TAR STRIP ac_ct_STRIP STRIP_STATIC_LIB STRIP_SHARED_LIB YACC YFLAGS PERL perl_archlibexp perl_privlibexp perl_useshrplib perl_embed_ldflags PYTHON python_version python_configdir python_includespec python_libdir python_libspec python_additional_libs HAVE_IPV6 LIBOBJS acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS HAVE_POSIX_SIGNALS MSGFMT MSGMERGE XGETTEXT localedir TCLSH TCL_CONFIG_SH TCL_INCLUDE_SPEC TCL_LIB_FILE TCL_LIBS TCL_LIB_SPEC TCL_SHARED_BUILD TCL_SHLIB_LD_LIBS NSGMLS JADE have_docbook DOCBOOKSTYLE COLLATEINDEX SGMLSPL vpath_build LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -888,6 +888,7 @@ Optional Packages:
   --with-krb5             build with Kerberos 5 support
   --with-krb-srvnam=NAME  name of the default service principal in Kerberos [postgres]
   --with-pam              build with PAM support
+  --with-ldap             build with LDAP support
   --with-bonjour          build with Bonjour support
   --with-openssl          build with OpenSSL support
   --with-libedit-preferred  prefer BSD Libedit over GNU Readline
@@ -3690,6 +3691,46 @@ echo "${ECHO_T}$with_pam" >&6
 
 
 
+#
+# LDAP
+#
+echo "$as_me:$LINENO: checking whether to build with LDAP support" >&5
+echo $ECHO_N "checking whether to build with LDAP support... $ECHO_C" >&6
+
+
+
+# Check whether --with-ldap or --without-ldap was given.
+if test "${with_ldap+set}" = set; then
+  withval="$with_ldap"
+
+  case $withval in
+    yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_LDAP 1
+_ACEOF
+
+      ;;
+    no)
+      :
+      ;;
+    *)
+      { { echo "$as_me:$LINENO: error: no argument expected for --with-ldap option" >&5
+echo "$as_me: error: no argument expected for --with-ldap option" >&2;}
+   { (exit 1); exit 1; }; }
+      ;;
+  esac
+
+else
+  with_ldap=no
+
+fi;
+
+echo "$as_me:$LINENO: result: $with_ldap" >&5
+echo "${ECHO_T}$with_ldap" >&6
+
+
+
 #
 # Bonjour
 #
@@ -7170,6 +7211,168 @@ fi
 fi
 
 
+if test "$with_ldap" = yes ; then
+  if test "$PORTNAME" != "win32"; then
+
+echo "$as_me:$LINENO: checking for ldap_bind in -lldap" >&5
+echo $ECHO_N "checking for ldap_bind in -lldap... $ECHO_C" >&6
+if test "${ac_cv_lib_ldap_ldap_bind+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lldap  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char ldap_bind ();
+int
+main ()
+{
+ldap_bind ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+    { ac_try='test -z "$ac_c_werror_flag"
+            || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+    { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_ldap_ldap_bind=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_ldap_ldap_bind=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_ldap_ldap_bind" >&5
+echo "${ECHO_T}$ac_cv_lib_ldap_ldap_bind" >&6
+if test $ac_cv_lib_ldap_ldap_bind = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBLDAP 1
+_ACEOF
+
+  LIBS="-lldap $LIBS"
+
+else
+  { { echo "$as_me:$LINENO: error: library 'ldap' is required for LDAP" >&5
+echo "$as_me: error: library 'ldap' is required for LDAP" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+  else
+
+echo "$as_me:$LINENO: checking for ldap_bind in -lwldap32" >&5
+echo $ECHO_N "checking for ldap_bind in -lwldap32... $ECHO_C" >&6
+if test "${ac_cv_lib_wldap32_ldap_bind+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lwldap32  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char ldap_bind ();
+int
+main ()
+{
+ldap_bind ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+    { ac_try='test -z "$ac_c_werror_flag"
+            || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+    { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_wldap32_ldap_bind=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_wldap32_ldap_bind=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_wldap32_ldap_bind" >&5
+echo "${ECHO_T}$ac_cv_lib_wldap32_ldap_bind" >&6
+if test $ac_cv_lib_wldap32_ldap_bind = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBWLDAP32 1
+_ACEOF
+
+  LIBS="-lwldap32 $LIBS"
+
+else
+  { { echo "$as_me:$LINENO: error: library 'wldap32' is required for LDAP" >&5
+echo "$as_me: error: library 'wldap32' is required for LDAP" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+  fi
+fi
+
 ##
 ## Header files
 ##
@@ -10268,6 +10471,233 @@ done
 
 fi
 
+if test "$with_ldap" = yes ; then
+  if test "$PORTNAME" != "win32"; then
+
+for ac_header in ldap.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+    { ac_try='test -z "$ac_c_werror_flag"
+            || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+    { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ---------------------------------------- ##
+## Report this to [email protected] ##
+## ---------------------------------------- ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: header file  is required for LDAP" >&5
+echo "$as_me: error: header file  is required for LDAP" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+done
+
+  else
+
+for ac_header in winldap.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include 
+
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+    { ac_try='test -z "$ac_c_werror_flag"
+            || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+    { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: header file  is required for LDAP" >&5
+echo "$as_me: error: header file  is required for LDAP" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+done
+
+  fi
+fi
+
 if test "$with_bonjour" = yes ; then
   if test "${ac_cv_header_DNSServiceDiscovery_DNSServiceDiscovery_h+set}" = set; then
   echo "$as_me:$LINENO: checking for DNSServiceDiscovery/DNSServiceDiscovery.h" >&5
@@ -22822,6 +23252,7 @@ s,@with_python@,$with_python,;t t
 s,@with_krb5@,$with_krb5,;t t
 s,@krb_srvtab@,$krb_srvtab,;t t
 s,@with_pam@,$with_pam,;t t
+s,@with_ldap@,$with_ldap,;t t
 s,@with_bonjour@,$with_bonjour,;t t
 s,@with_openssl@,$with_openssl,;t t
 s,@with_zlib@,$with_zlib,;t t
index 0eec99433d923a7bc8ceeee81614cb21a9d855cc..d4a11f2ba0ef12c27b4941b449ff0400182dec7a 100644 (file)
@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
-dnl $PostgreSQL: pgsql/configure.in,v 1.454 2006/03/05 15:58:18 momjian Exp $
+dnl $PostgreSQL: pgsql/configure.in,v 1.455 2006/03/06 17:41:43 momjian Exp $
 dnl
 dnl Developers, please strive to achieve this order:
 dnl
@@ -444,6 +444,17 @@ AC_MSG_RESULT([$with_pam])
 AC_SUBST(with_pam)
 
 
+#
+# 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
 #
@@ -669,6 +680,14 @@ if test "$with_pam" = yes ; then
 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
 ##
@@ -744,6 +763,19 @@ if test "$with_pam" = yes ; then
                                      [AC_MSG_ERROR([header file  or  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  is required for LDAP])])
+  else
+     AC_CHECK_HEADERS(winldap.h, [],
+                      [AC_MSG_ERROR([header file  is required for LDAP])],
+                      [AC_INCLUDES_DEFAULT
+#include 
+                      ])
+  fi
+fi
+
 if test "$with_bonjour" = yes ; then
   AC_CHECK_HEADER(DNSServiceDiscovery/DNSServiceDiscovery.h, [], [AC_MSG_ERROR([header file  is required for Bonjour])])
 fi
index 4d4e93943e54fca3eb6c21b008f85100d55e42e2..60a5c857286b81bedbfb0c7192a61350639477e7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.134 2006/03/05 15:58:27 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.135 2006/03/06 17:41:43 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -69,6 +69,32 @@ static Port *pam_port_cludge;    /* Workaround for passing "Port *port" into
                                 * 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 
+#else
+/* Header broken in MingW */
+#define ldap_start_tls_sA __BROKEN_LDAP_HEADER
+#include 
+#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,6 +353,11 @@ auth_failed(Port *port, int status)
            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,6 +486,12 @@ ClientAuthentication(Port *port)
            break;
 #endif   /* USE_PAM */
 
+#ifdef USE_LDAP
+        case uaLDAP:
+            status = CheckLDAPAuth(port);
+            break;
+#endif
+
        case uaTrust:
            status = STATUS_OK;
            break;
@@ -674,6 +711,132 @@ CheckPAMAuth(Port *port, char *user, char *password)
 #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]://[:]/[;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 31be6ba33eb833858824b48a85114e50dee432b1..a31f968baab7342505a92b491c4a787849365f27 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.150 2006/03/05 15:58:27 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.151 2006/03/06 17:41:43 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -612,6 +612,10 @@ parse_hba_auth(ListCell **line_item, UserAuth *userauth_p,
 #ifdef USE_PAM
    else if (strcmp(token, "pam") == 0)
        *userauth_p = uaPAM;
+#endif
+#ifdef USE_LDAP
+    else if (strcmp(token,"ldap") == 0)
+        *userauth_p = uaLDAP;
 #endif
    else
    {
index 521ce4ef096c63c52236665ecbf9157bc01c8213..abf4e827f13506b38f5fe6f235a9eebf34e94ef6 100644 (file)
@@ -35,7 +35,7 @@
 # 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
+# "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 5251db1c05416c4d828edac4593cd89752098622..eaa3cf529cebf5b01f3e71fb4a272c42c19339a5 100644 (file)
@@ -4,7 +4,7 @@
  *   Interface to hba.c
  *
  *
- * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.41 2005/10/15 02:49:44 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.42 2006/03/06 17:41:44 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,6 +26,9 @@ typedef enum UserAuth
 #ifdef USE_PAM
    ,uaPAM
 #endif   /* USE_PAM */
+#ifdef USE_LDAP
+    ,uaLDAP
+#endif
 } UserAuth;
 
 typedef struct Port hbaPort;
index e948cb207ad7140823df4cc86f8bd1a50b9058e7..16d38f71b8fd8e3afa7c17614753a5b6b4c513e8 100644 (file)
 /* Define to 1 if you have the  header file. */
 #undef HAVE_LANGINFO_H
 
+/* Define to 1 if you have the  header file. */
+#undef HAVE_LDAP_H
+
 /* Define to 1 if you have the `crypto' library (-lcrypto). */
 #undef HAVE_LIBCRYPTO
 
 /* Define to 1 if you have the `eay32' library (-leay32). */
 #undef HAVE_LIBEAY32
 
+/* Define to 1 if you have the `ldap' library (-lldap). */
+#undef HAVE_LIBLDAP
+
 /* Define to 1 if you have the `pam' library (-lpam). */
 #undef HAVE_LIBPAM
 
 /* Define to 1 if you have the `ssleay32' library (-lssleay32). */
 #undef HAVE_LIBSSLEAY32
 
+/* Define to 1 if you have the `wldap32' library (-lwldap32). */
+#undef HAVE_LIBWLDAP32
+
 /* Define to 1 if you have the `z' library (-lz). */
 #undef HAVE_LIBZ
 
 /* Define to 1 if you have the  header file. */
 #undef HAVE_WCTYPE_H
 
+/* Define to 1 if you have the  header file. */
+#undef HAVE_WINLDAP_H
+
 /* Define to the appropriate snprintf format for 64-bit ints, if any. */
 #undef INT64_FORMAT
 
    (--enable-integer-datetimes) */
 #undef USE_INTEGER_DATETIMES
 
+/* Define to 1 to build with LDAP support. (--with-ldap) */
+#undef USE_LDAP
+
 /* Define to select named POSIX semaphores. */
 #undef USE_NAMED_POSIX_SEMAPHORES