mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
Add support for GSSAPI authentication.
Documentation still being written, will be committed later. Henry B. Hotz and Magnus Hagander
This commit is contained in:
parent
ff481ca0d4
commit
6160106c74
334
configure
vendored
334
configure
vendored
@ -314,7 +314,7 @@ ac_includes_default="\
|
|||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif"
|
#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 enable_profiling DTRACE DTRACEFLAGS enable_dtrace 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_ossp_uuid XML2_CONFIG with_libxml with_libxslt with_zlib EGREP ELF_SYS LDFLAGS_SL AWK FLEX FLEXFLAGS LN_S LD with_gnu_ld ld_R_works RANLIB ac_ct_RANLIB 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 LDAP_LIBS_FE LDAP_LIBS_BE 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 enable_profiling DTRACE DTRACEFLAGS enable_dtrace CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP GCC TAS autodepend INCLUDES enable_thread_safety with_tcl with_perl with_python with_gssapi with_krb5 krb_srvtab with_pam with_ldap with_bonjour with_openssl with_ossp_uuid XML2_CONFIG with_libxml with_libxslt with_zlib EGREP ELF_SYS LDFLAGS_SL AWK FLEX FLEXFLAGS LN_S LD with_gnu_ld ld_R_works RANLIB ac_ct_RANLIB 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 LDAP_LIBS_FE LDAP_LIBS_BE 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=''
|
ac_subst_files=''
|
||||||
|
|
||||||
# Initialize some variables set by options.
|
# Initialize some variables set by options.
|
||||||
@ -887,6 +887,7 @@ Optional Packages:
|
|||||||
--with-tclconfig=DIR tclConfig.sh is in DIR
|
--with-tclconfig=DIR tclConfig.sh is in DIR
|
||||||
--with-perl build Perl modules (PL/Perl)
|
--with-perl build Perl modules (PL/Perl)
|
||||||
--with-python build Python modules (PL/Python)
|
--with-python build Python modules (PL/Python)
|
||||||
|
--with-gssapi build with GSSAPI support
|
||||||
--with-krb5 build with Kerberos 5 support
|
--with-krb5 build with Kerberos 5 support
|
||||||
--with-krb-srvnam=NAME default service principal name in Kerberos [postgres]
|
--with-krb-srvnam=NAME default service principal name in Kerberos [postgres]
|
||||||
--with-pam build with PAM support
|
--with-pam build with PAM support
|
||||||
@ -3919,6 +3920,50 @@ echo "$as_me:$LINENO: result: $with_python" >&5
|
|||||||
echo "${ECHO_T}$with_python" >&6
|
echo "${ECHO_T}$with_python" >&6
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# GSSAPI
|
||||||
|
#
|
||||||
|
echo "$as_me:$LINENO: checking wether to build with GSSAPI support" >&5
|
||||||
|
echo $ECHO_N "checking wether to build with GSSAPI support... $ECHO_C" >&6
|
||||||
|
|
||||||
|
pgac_args="$pgac_args with_gssapi"
|
||||||
|
|
||||||
|
|
||||||
|
# Check whether --with-gssapi or --without-gssapi was given.
|
||||||
|
if test "${with_gssapi+set}" = set; then
|
||||||
|
withval="$with_gssapi"
|
||||||
|
|
||||||
|
case $withval in
|
||||||
|
yes)
|
||||||
|
|
||||||
|
|
||||||
|
cat >>confdefs.h <<\_ACEOF
|
||||||
|
#define ENABLE_GSS 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
krb_srvtab="FILE:\$(sysconfdir)/krb5.keytab"
|
||||||
|
|
||||||
|
;;
|
||||||
|
no)
|
||||||
|
:
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
{ { echo "$as_me:$LINENO: error: no argument expected for --with-gssapi option" >&5
|
||||||
|
echo "$as_me: error: no argument expected for --with-gssapi option" >&2;}
|
||||||
|
{ (exit 1); exit 1; }; }
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
else
|
||||||
|
with_gssapi=no
|
||||||
|
|
||||||
|
fi;
|
||||||
|
|
||||||
|
echo "$as_me:$LINENO: result: $with_gssapi" >&5
|
||||||
|
echo "${ECHO_T}$with_gssapi" >&6
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Kerberos 5
|
# Kerberos 5
|
||||||
#
|
#
|
||||||
@ -6718,6 +6763,143 @@ echo "$as_me: WARNING:
|
|||||||
*** Not using spinlocks will cause poor performance." >&2;}
|
*** Not using spinlocks will cause poor performance." >&2;}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$with_gssapi" = yes ; then
|
||||||
|
if test "$PORTNAME" != "win32"; then
|
||||||
|
echo "$as_me:$LINENO: checking for library containing gss_init_sec_context" >&5
|
||||||
|
echo $ECHO_N "checking for library containing gss_init_sec_context... $ECHO_C" >&6
|
||||||
|
if test "${ac_cv_search_gss_init_sec_context+set}" = set; then
|
||||||
|
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||||
|
else
|
||||||
|
ac_func_search_save_LIBS=$LIBS
|
||||||
|
ac_cv_search_gss_init_sec_context=no
|
||||||
|
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 gss_init_sec_context ();
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
gss_init_sec_context ();
|
||||||
|
;
|
||||||
|
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_search_gss_init_sec_context="none required"
|
||||||
|
else
|
||||||
|
echo "$as_me: failed program was:" >&5
|
||||||
|
sed 's/^/| /' conftest.$ac_ext >&5
|
||||||
|
|
||||||
|
fi
|
||||||
|
rm -f conftest.err conftest.$ac_objext \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
if test "$ac_cv_search_gss_init_sec_context" = no; then
|
||||||
|
for ac_lib in gssapi_krb5; do
|
||||||
|
LIBS="-l$ac_lib $ac_func_search_save_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 gss_init_sec_context ();
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
gss_init_sec_context ();
|
||||||
|
;
|
||||||
|
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_search_gss_init_sec_context="-l$ac_lib"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
echo "$as_me: failed program was:" >&5
|
||||||
|
sed 's/^/| /' conftest.$ac_ext >&5
|
||||||
|
|
||||||
|
fi
|
||||||
|
rm -f conftest.err conftest.$ac_objext \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
LIBS=$ac_func_search_save_LIBS
|
||||||
|
fi
|
||||||
|
echo "$as_me:$LINENO: result: $ac_cv_search_gss_init_sec_context" >&5
|
||||||
|
echo "${ECHO_T}$ac_cv_search_gss_init_sec_context" >&6
|
||||||
|
if test "$ac_cv_search_gss_init_sec_context" != no; then
|
||||||
|
test "$ac_cv_search_gss_init_sec_context" = "none required" || LIBS="$ac_cv_search_gss_init_sec_context $LIBS"
|
||||||
|
|
||||||
|
else
|
||||||
|
{ { echo "$as_me:$LINENO: error: could not find function 'gss_init_sec_context' required for GSSAPI" >&5
|
||||||
|
echo "$as_me: error: could not find function 'gss_init_sec_context' required for GSSAPI" >&2;}
|
||||||
|
{ (exit 1); exit 1; }; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
LIBS="$LIBS -lgssapi32"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if test "$with_krb5" = yes ; then
|
if test "$with_krb5" = yes ; then
|
||||||
if test "$PORTNAME" != "win32"; then
|
if test "$PORTNAME" != "win32"; then
|
||||||
echo "$as_me:$LINENO: checking for library containing com_err" >&5
|
echo "$as_me:$LINENO: checking for library containing com_err" >&5
|
||||||
@ -10014,6 +10196,155 @@ Use --without-zlib to disable zlib support." >&2;}
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$with_gssapi" = yes ; then
|
||||||
|
if test "${ac_cv_header_gssapi_gssapi_h+set}" = set; then
|
||||||
|
echo "$as_me:$LINENO: checking for gssapi/gssapi.h" >&5
|
||||||
|
echo $ECHO_N "checking for gssapi/gssapi.h... $ECHO_C" >&6
|
||||||
|
if test "${ac_cv_header_gssapi_gssapi_h+set}" = set; then
|
||||||
|
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||||
|
fi
|
||||||
|
echo "$as_me:$LINENO: result: $ac_cv_header_gssapi_gssapi_h" >&5
|
||||||
|
echo "${ECHO_T}$ac_cv_header_gssapi_gssapi_h" >&6
|
||||||
|
else
|
||||||
|
# Is the header compilable?
|
||||||
|
echo "$as_me:$LINENO: checking gssapi/gssapi.h usability" >&5
|
||||||
|
echo $ECHO_N "checking gssapi/gssapi.h 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 <gssapi/gssapi.h>
|
||||||
|
_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 gssapi/gssapi.h presence" >&5
|
||||||
|
echo $ECHO_N "checking gssapi/gssapi.h 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 <gssapi/gssapi.h>
|
||||||
|
_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: gssapi/gssapi.h: accepted by the compiler, rejected by the preprocessor!" >&5
|
||||||
|
echo "$as_me: WARNING: gssapi/gssapi.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
|
||||||
|
{ echo "$as_me:$LINENO: WARNING: gssapi/gssapi.h: proceeding with the compiler's result" >&5
|
||||||
|
echo "$as_me: WARNING: gssapi/gssapi.h: proceeding with the compiler's result" >&2;}
|
||||||
|
ac_header_preproc=yes
|
||||||
|
;;
|
||||||
|
no:yes:* )
|
||||||
|
{ echo "$as_me:$LINENO: WARNING: gssapi/gssapi.h: present but cannot be compiled" >&5
|
||||||
|
echo "$as_me: WARNING: gssapi/gssapi.h: present but cannot be compiled" >&2;}
|
||||||
|
{ echo "$as_me:$LINENO: WARNING: gssapi/gssapi.h: check for missing prerequisite headers?" >&5
|
||||||
|
echo "$as_me: WARNING: gssapi/gssapi.h: check for missing prerequisite headers?" >&2;}
|
||||||
|
{ echo "$as_me:$LINENO: WARNING: gssapi/gssapi.h: see the Autoconf documentation" >&5
|
||||||
|
echo "$as_me: WARNING: gssapi/gssapi.h: see the Autoconf documentation" >&2;}
|
||||||
|
{ echo "$as_me:$LINENO: WARNING: gssapi/gssapi.h: section \"Present But Cannot Be Compiled\"" >&5
|
||||||
|
echo "$as_me: WARNING: gssapi/gssapi.h: section \"Present But Cannot Be Compiled\"" >&2;}
|
||||||
|
{ echo "$as_me:$LINENO: WARNING: gssapi/gssapi.h: proceeding with the preprocessor's result" >&5
|
||||||
|
echo "$as_me: WARNING: gssapi/gssapi.h: proceeding with the preprocessor's result" >&2;}
|
||||||
|
{ echo "$as_me:$LINENO: WARNING: gssapi/gssapi.h: in the future, the compiler will take precedence" >&5
|
||||||
|
echo "$as_me: WARNING: gssapi/gssapi.h: in the future, the compiler will take precedence" >&2;}
|
||||||
|
(
|
||||||
|
cat <<\_ASBOX
|
||||||
|
## ---------------------------------------- ##
|
||||||
|
## Report this to pgsql-bugs@postgresql.org ##
|
||||||
|
## ---------------------------------------- ##
|
||||||
|
_ASBOX
|
||||||
|
) |
|
||||||
|
sed "s/^/$as_me: WARNING: /" >&2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo "$as_me:$LINENO: checking for gssapi/gssapi.h" >&5
|
||||||
|
echo $ECHO_N "checking for gssapi/gssapi.h... $ECHO_C" >&6
|
||||||
|
if test "${ac_cv_header_gssapi_gssapi_h+set}" = set; then
|
||||||
|
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||||
|
else
|
||||||
|
ac_cv_header_gssapi_gssapi_h=$ac_header_preproc
|
||||||
|
fi
|
||||||
|
echo "$as_me:$LINENO: result: $ac_cv_header_gssapi_gssapi_h" >&5
|
||||||
|
echo "${ECHO_T}$ac_cv_header_gssapi_gssapi_h" >&6
|
||||||
|
|
||||||
|
fi
|
||||||
|
if test $ac_cv_header_gssapi_gssapi_h = yes; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
{ { echo "$as_me:$LINENO: error: header file <gssapi/gssapi.h> is required for GSSAPI" >&5
|
||||||
|
echo "$as_me: error: header file <gssapi/gssapi.h> is required for GSSAPI" >&2;}
|
||||||
|
{ (exit 1); exit 1; }; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$with_krb5" = yes ; then
|
if test "$with_krb5" = yes ; then
|
||||||
@ -24618,6 +24949,7 @@ s,@enable_thread_safety@,$enable_thread_safety,;t t
|
|||||||
s,@with_tcl@,$with_tcl,;t t
|
s,@with_tcl@,$with_tcl,;t t
|
||||||
s,@with_perl@,$with_perl,;t t
|
s,@with_perl@,$with_perl,;t t
|
||||||
s,@with_python@,$with_python,;t t
|
s,@with_python@,$with_python,;t t
|
||||||
|
s,@with_gssapi@,$with_gssapi,;t t
|
||||||
s,@with_krb5@,$with_krb5,;t t
|
s,@with_krb5@,$with_krb5,;t t
|
||||||
s,@krb_srvtab@,$krb_srvtab,;t t
|
s,@krb_srvtab@,$krb_srvtab,;t t
|
||||||
s,@with_pam@,$with_pam,;t t
|
s,@with_pam@,$with_pam,;t t
|
||||||
|
28
configure.in
28
configure.in
@ -1,5 +1,5 @@
|
|||||||
dnl Process this file with autoconf to produce a configure script.
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
dnl $PostgreSQL: pgsql/configure.in,v 1.516 2007/06/29 16:18:43 tgl Exp $
|
dnl $PostgreSQL: pgsql/configure.in,v 1.517 2007/07/10 13:14:20 mha Exp $
|
||||||
dnl
|
dnl
|
||||||
dnl Developers, please strive to achieve this order:
|
dnl Developers, please strive to achieve this order:
|
||||||
dnl
|
dnl
|
||||||
@ -462,6 +462,19 @@ PGAC_ARG_BOOL(with, python, no, [ --with-python build Python modules
|
|||||||
AC_MSG_RESULT([$with_python])
|
AC_MSG_RESULT([$with_python])
|
||||||
AC_SUBST(with_python)
|
AC_SUBST(with_python)
|
||||||
|
|
||||||
|
#
|
||||||
|
# GSSAPI
|
||||||
|
#
|
||||||
|
AC_MSG_CHECKING([wether to build with GSSAPI support])
|
||||||
|
PGAC_ARG_BOOL(with, gssapi, no, [ --with-gssapi build with GSSAPI support],
|
||||||
|
[
|
||||||
|
AC_DEFINE(ENABLE_GSS, 1, [Define to build with GSSAPI support. (--with-gssapi)])
|
||||||
|
krb_srvtab="FILE:\$(sysconfdir)/krb5.keytab"
|
||||||
|
])
|
||||||
|
AC_MSG_RESULT([$with_gssapi])
|
||||||
|
AC_SUBST(with_gssapi)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Kerberos 5
|
# Kerberos 5
|
||||||
#
|
#
|
||||||
@ -753,6 +766,15 @@ else
|
|||||||
*** Not using spinlocks will cause poor performance.])
|
*** Not using spinlocks will cause poor performance.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$with_gssapi" = yes ; then
|
||||||
|
if test "$PORTNAME" != "win32"; then
|
||||||
|
AC_SEARCH_LIBS(gss_init_sec_context, [gssapi_krb5], [],
|
||||||
|
[AC_MSG_ERROR([could not find function 'gss_init_sec_context' required for GSSAPI])])
|
||||||
|
else
|
||||||
|
LIBS="$LIBS -lgssapi32"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if test "$with_krb5" = yes ; then
|
if test "$with_krb5" = yes ; then
|
||||||
if test "$PORTNAME" != "win32"; then
|
if test "$PORTNAME" != "win32"; then
|
||||||
AC_SEARCH_LIBS(com_err, [krb5 'krb5 -lcrypto -ldes -lasn1 -lroken' com_err], [],
|
AC_SEARCH_LIBS(com_err, [krb5 'krb5 -lcrypto -ldes -lasn1 -lroken' com_err], [],
|
||||||
@ -848,6 +870,10 @@ failure. It is possible the compiler isn't looking in the proper directory.
|
|||||||
Use --without-zlib to disable zlib support.])])
|
Use --without-zlib to disable zlib support.])])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$with_gssapi" = yes ; then
|
||||||
|
AC_CHECK_HEADER(gssapi/gssapi.h, [], [AC_MSG_ERROR([header file <gssapi/gssapi.h> is required for GSSAPI])])
|
||||||
|
fi
|
||||||
|
|
||||||
if test "$with_krb5" = yes ; then
|
if test "$with_krb5" = yes ; then
|
||||||
AC_CHECK_HEADER(krb5.h, [], [AC_MSG_ERROR([header file <krb5.h> is required for Kerberos 5])])
|
AC_CHECK_HEADER(krb5.h, [], [AC_MSG_ERROR([header file <krb5.h> is required for Kerberos 5])])
|
||||||
fi
|
fi
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.148 2007/02/08 04:52:18 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.149 2007/07/10 13:14:20 mha Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -23,6 +23,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "libpq/auth.h"
|
#include "libpq/auth.h"
|
||||||
#include "libpq/crypt.h"
|
#include "libpq/crypt.h"
|
||||||
@ -295,6 +296,250 @@ pg_krb5_recvauth(Port *port)
|
|||||||
}
|
}
|
||||||
#endif /* KRB5 */
|
#endif /* KRB5 */
|
||||||
|
|
||||||
|
#ifdef ENABLE_GSS
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
* GSSAPI authentication system
|
||||||
|
*----------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gssapi/gssapi.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
/*
|
||||||
|
* MIT Kerberos GSSAPI DLL doesn't properly export the symbols
|
||||||
|
* that contain the OIDs required. Redefine here, values copied
|
||||||
|
* from src/athena/auth/krb5/src/lib/gssapi/generic/gssapi_generic.c
|
||||||
|
*/
|
||||||
|
static const gss_OID_desc GSS_C_NT_USER_NAME_desc =
|
||||||
|
{10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"};
|
||||||
|
static GSS_DLLIMP gss_OID GSS_C_NT_USER_NAME = &GSS_C_NT_USER_NAME_desc;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
pg_GSS_error(int severity, char *text, OM_uint32 maj_stat, OM_uint32 min_stat)
|
||||||
|
{
|
||||||
|
gss_buffer_desc gmsg;
|
||||||
|
OM_uint32 lmaj_s, lmin_s, msg_ctx;
|
||||||
|
char localmsg1[128],
|
||||||
|
localmsg2[128];
|
||||||
|
|
||||||
|
/* Fetch major status message */
|
||||||
|
msg_ctx = 0;
|
||||||
|
lmaj_s = gss_display_status(&lmin_s, maj_stat, GSS_C_GSS_CODE,
|
||||||
|
GSS_C_NO_OID, &msg_ctx, &gmsg);
|
||||||
|
strlcpy(localmsg1, gmsg.value, sizeof(localmsg1));
|
||||||
|
gss_release_buffer(&lmin_s, &gmsg);
|
||||||
|
|
||||||
|
if (msg_ctx)
|
||||||
|
/* More than one message available.
|
||||||
|
* XXX: Should we loop and read all messages?
|
||||||
|
* (same below)
|
||||||
|
*/
|
||||||
|
ereport(WARNING,
|
||||||
|
(errmsg_internal("incomplete GSS error report")));
|
||||||
|
|
||||||
|
/* Fetch mechanism minor status message */
|
||||||
|
msg_ctx = 0;
|
||||||
|
lmaj_s = gss_display_status(&lmin_s, min_stat, GSS_C_MECH_CODE,
|
||||||
|
GSS_C_NO_OID, &msg_ctx, &gmsg);
|
||||||
|
strlcpy(localmsg2, gmsg.value, sizeof(localmsg2));
|
||||||
|
gss_release_buffer(&lmin_s, &gmsg);
|
||||||
|
|
||||||
|
if (msg_ctx)
|
||||||
|
ereport(WARNING,
|
||||||
|
(errmsg_internal("incomplete GSS minor error report")));
|
||||||
|
|
||||||
|
/* errmsg_internal, since translation of the first part must be
|
||||||
|
* done before calling this function anyway. */
|
||||||
|
ereport(severity,
|
||||||
|
(errmsg_internal("%s:%s\n%s", text, localmsg1, localmsg2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pg_GSS_recvauth(Port *port)
|
||||||
|
{
|
||||||
|
OM_uint32 maj_stat, min_stat, lmin_s, gflags;
|
||||||
|
char *kt_path;
|
||||||
|
int mtype;
|
||||||
|
int ret;
|
||||||
|
StringInfoData buf;
|
||||||
|
gss_buffer_desc gbuf;
|
||||||
|
|
||||||
|
if (pg_krb_server_keyfile && strlen(pg_krb_server_keyfile) > 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Set default Kerberos keytab file for the Krb5 mechanism.
|
||||||
|
*
|
||||||
|
* setenv("KRB5_KTNAME", pg_krb_server_keyfile, 0);
|
||||||
|
* except setenv() not always available.
|
||||||
|
*/
|
||||||
|
if (!getenv("KRB5_KTNAME"))
|
||||||
|
{
|
||||||
|
kt_path = palloc(PATH_MAX + 13);
|
||||||
|
snprintf(kt_path, PATH_MAX + 13,
|
||||||
|
"KRB5_KTNAME=%s", pg_krb_server_keyfile);
|
||||||
|
putenv(kt_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We accept any service principal that's present in our
|
||||||
|
* keytab. This increases interoperability between kerberos
|
||||||
|
* implementations that see for example case sensitivity
|
||||||
|
* differently, while not really opening up any vector
|
||||||
|
* of attack.
|
||||||
|
*/
|
||||||
|
port->gss->cred = GSS_C_NO_CREDENTIAL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize sequence with an empty context
|
||||||
|
*/
|
||||||
|
port->gss->ctx = GSS_C_NO_CONTEXT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loop through GSSAPI message exchange. This exchange can consist
|
||||||
|
* of multiple messags sent in both directions. First message is always
|
||||||
|
* from the client. All messages from client to server are password
|
||||||
|
* packets (type 'p').
|
||||||
|
*/
|
||||||
|
do
|
||||||
|
{
|
||||||
|
mtype = pq_getbyte();
|
||||||
|
if (mtype != 'p')
|
||||||
|
{
|
||||||
|
/* Only log error if client didn't disconnect. */
|
||||||
|
if (mtype != EOF)
|
||||||
|
ereport(COMMERROR,
|
||||||
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
||||||
|
errmsg("expected GSS response, got message type %d",
|
||||||
|
mtype)));
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the actual GSS token */
|
||||||
|
initStringInfo(&buf);
|
||||||
|
if (pq_getmessage(&buf, 2000))
|
||||||
|
{
|
||||||
|
/* EOF - pq_getmessage already logged error */
|
||||||
|
pfree(buf.data);
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Map to GSSAPI style buffer */
|
||||||
|
gbuf.length = buf.len;
|
||||||
|
gbuf.value = buf.data;
|
||||||
|
|
||||||
|
ereport(DEBUG4,
|
||||||
|
(errmsg_internal("Processing received GSS token of length: %u",
|
||||||
|
gbuf.length)));
|
||||||
|
|
||||||
|
maj_stat = gss_accept_sec_context(
|
||||||
|
&min_stat,
|
||||||
|
&port->gss->ctx,
|
||||||
|
port->gss->cred,
|
||||||
|
&gbuf,
|
||||||
|
GSS_C_NO_CHANNEL_BINDINGS,
|
||||||
|
&port->gss->name,
|
||||||
|
NULL,
|
||||||
|
&port->gss->outbuf,
|
||||||
|
&gflags,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* gbuf no longer used */
|
||||||
|
pfree(buf.data);
|
||||||
|
|
||||||
|
ereport(DEBUG5,
|
||||||
|
(errmsg_internal("gss_accept_sec_context major: %i, "
|
||||||
|
"minor: %i, outlen: %u, outflags: %x",
|
||||||
|
maj_stat, min_stat,
|
||||||
|
port->gss->outbuf.length, gflags)));
|
||||||
|
|
||||||
|
if (port->gss->outbuf.length != 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Negotiation generated data to be sent to the client.
|
||||||
|
*/
|
||||||
|
ereport(DEBUG4,
|
||||||
|
(errmsg_internal("sending GSS response token of length %u",
|
||||||
|
port->gss->outbuf.length)));
|
||||||
|
sendAuthRequest(port, AUTH_REQ_GSS_CONT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
|
||||||
|
{
|
||||||
|
OM_uint32 lmin_s;
|
||||||
|
gss_delete_sec_context(&lmin_s, &port->gss->ctx, GSS_C_NO_BUFFER);
|
||||||
|
pg_GSS_error(ERROR,
|
||||||
|
gettext_noop("accepting GSS security context failed"),
|
||||||
|
maj_stat, min_stat);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maj_stat == GSS_S_CONTINUE_NEEDED)
|
||||||
|
ereport(DEBUG4,
|
||||||
|
(errmsg_internal("GSS continue needed")));
|
||||||
|
|
||||||
|
} while (maj_stat == GSS_S_CONTINUE_NEEDED);
|
||||||
|
|
||||||
|
if (port->gss->cred != GSS_C_NO_CREDENTIAL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Release service principal credentials
|
||||||
|
*/
|
||||||
|
gss_release_cred(&min_stat, port->gss->cred);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GSS_S_COMPLETE indicates that authentication is now complete.
|
||||||
|
*
|
||||||
|
* Get the name of the user that authenticated, and compare it to the
|
||||||
|
* pg username that was specified for the connection.
|
||||||
|
*/
|
||||||
|
maj_stat = gss_display_name(&min_stat, port->gss->name, &gbuf, NULL);
|
||||||
|
ereport(DEBUG1,
|
||||||
|
(errmsg("GSSAPI authenticated name: %s", (char *)gbuf.value)));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compare the part of the username that comes before the @
|
||||||
|
* sign only (ignore realm). The GSSAPI libraries won't have
|
||||||
|
* authenticated the user if he's from an invalid realm.
|
||||||
|
*/
|
||||||
|
if (strchr(gbuf.value, '@'))
|
||||||
|
{
|
||||||
|
char *cp = strchr(gbuf.value, '@');
|
||||||
|
*cp = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pg_krb_caseins_users)
|
||||||
|
ret = pg_strcasecmp(port->user_name, gbuf.value);
|
||||||
|
else
|
||||||
|
ret = strcmp(port->user_name, gbuf.value);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
/* GSS name and PGUSER are not equivalent */
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
|
||||||
|
errmsg("provided username and GSSAPI username don't match"),
|
||||||
|
errdetail("provided: %s, GSSAPI: %s",
|
||||||
|
port->user_name, (char *)gbuf.value)));
|
||||||
|
|
||||||
|
gss_release_buffer(&lmin_s, &gbuf);
|
||||||
|
|
||||||
|
return STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* no ENABLE_GSS */
|
||||||
|
static int
|
||||||
|
pg_GSS_recvauth(Port *port)
|
||||||
|
{
|
||||||
|
ereport(LOG,
|
||||||
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
errmsg("GSSAPI not implemented on this server.")));
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
#endif /* ENABLE_GSS */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tell the user the authentication failed, but not (much about) why.
|
* Tell the user the authentication failed, but not (much about) why.
|
||||||
@ -334,6 +579,9 @@ auth_failed(Port *port, int status)
|
|||||||
case uaKrb5:
|
case uaKrb5:
|
||||||
errstr = gettext_noop("Kerberos 5 authentication failed for user \"%s\"");
|
errstr = gettext_noop("Kerberos 5 authentication failed for user \"%s\"");
|
||||||
break;
|
break;
|
||||||
|
case uaGSS:
|
||||||
|
errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");
|
||||||
|
break;
|
||||||
case uaTrust:
|
case uaTrust:
|
||||||
errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
|
errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
|
||||||
break;
|
break;
|
||||||
@ -429,6 +677,11 @@ ClientAuthentication(Port *port)
|
|||||||
status = pg_krb5_recvauth(port);
|
status = pg_krb5_recvauth(port);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case uaGSS:
|
||||||
|
sendAuthRequest(port, AUTH_REQ_GSS);
|
||||||
|
status = pg_GSS_recvauth(port);
|
||||||
|
break;
|
||||||
|
|
||||||
case uaIdent:
|
case uaIdent:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -518,6 +771,24 @@ sendAuthRequest(Port *port, AuthRequest areq)
|
|||||||
else if (areq == AUTH_REQ_CRYPT)
|
else if (areq == AUTH_REQ_CRYPT)
|
||||||
pq_sendbytes(&buf, port->cryptSalt, 2);
|
pq_sendbytes(&buf, port->cryptSalt, 2);
|
||||||
|
|
||||||
|
#ifdef ENABLE_GSS
|
||||||
|
/* Add the authentication data for the next step of
|
||||||
|
* the GSSAPI negotiation. */
|
||||||
|
else if (areq == AUTH_REQ_GSS_CONT)
|
||||||
|
{
|
||||||
|
if (port->gss->outbuf.length > 0)
|
||||||
|
{
|
||||||
|
OM_uint32 lmin_s;
|
||||||
|
|
||||||
|
ereport(DEBUG4,
|
||||||
|
(errmsg_internal("sending GSS token of length %u",
|
||||||
|
port->gss->outbuf.length)));
|
||||||
|
pq_sendbytes(&buf, port->gss->outbuf.value, port->gss->outbuf.length);
|
||||||
|
gss_release_buffer(&lmin_s, &port->gss->outbuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
pq_endmessage(&buf);
|
pq_endmessage(&buf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.160 2007/02/10 14:58:54 petere Exp $
|
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.161 2007/07/10 13:14:20 mha Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -602,6 +602,8 @@ parse_hba_auth(ListCell **line_item, UserAuth *userauth_p,
|
|||||||
*userauth_p = uaPassword;
|
*userauth_p = uaPassword;
|
||||||
else if (strcmp(token, "krb5") == 0)
|
else if (strcmp(token, "krb5") == 0)
|
||||||
*userauth_p = uaKrb5;
|
*userauth_p = uaKrb5;
|
||||||
|
else if (strcmp(token, "gss") == 0)
|
||||||
|
*userauth_p = uaGSS;
|
||||||
else if (strcmp(token, "reject") == 0)
|
else if (strcmp(token, "reject") == 0)
|
||||||
*userauth_p = uaReject;
|
*userauth_p = uaReject;
|
||||||
else if (strcmp(token, "md5") == 0)
|
else if (strcmp(token, "md5") == 0)
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
# the number of significant bits in the mask. Alternatively, you can write
|
# the number of significant bits in the mask. Alternatively, you can write
|
||||||
# an IP address and netmask in separate columns to specify the set of hosts.
|
# an IP address and netmask in separate columns to specify the set of hosts.
|
||||||
#
|
#
|
||||||
# METHOD can be "trust", "reject", "md5", "crypt", "password",
|
# METHOD can be "trust", "reject", "md5", "crypt", "password", "gss",
|
||||||
# "krb5", "ident", "pam" or "ldap". 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.
|
# in clear text; "md5" is preferred since it sends encrypted passwords.
|
||||||
#
|
#
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.192 2007/06/04 11:59:20 mha Exp $
|
* $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.193 2007/07/10 13:14:20 mha Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -173,6 +173,16 @@ pq_close(int code, Datum arg)
|
|||||||
{
|
{
|
||||||
if (MyProcPort != NULL)
|
if (MyProcPort != NULL)
|
||||||
{
|
{
|
||||||
|
#ifdef ENABLE_GSS
|
||||||
|
OM_uint32 min_s;
|
||||||
|
/* Shutdown GSSAPI layer */
|
||||||
|
if (MyProcPort->gss->ctx)
|
||||||
|
gss_delete_sec_context(&min_s, MyProcPort->gss->ctx, NULL);
|
||||||
|
|
||||||
|
if (MyProcPort->gss->cred)
|
||||||
|
gss_release_cred(&min_s, MyProcPort->gss->cred);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Cleanly shut down SSL layer */
|
/* Cleanly shut down SSL layer */
|
||||||
secure_close(MyProcPort);
|
secure_close(MyProcPort);
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.530 2007/07/01 18:28:41 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.531 2007/07/10 13:14:21 mha Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
*
|
*
|
||||||
@ -1727,6 +1727,13 @@ ConnCreate(int serverFd)
|
|||||||
RandomSalt(port->cryptSalt, port->md5Salt);
|
RandomSalt(port->cryptSalt, port->md5Salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate GSSAPI specific state struct
|
||||||
|
*/
|
||||||
|
#ifdef ENABLE_GSS
|
||||||
|
port->gss = (pg_gssinfo *)calloc(1, sizeof(pg_gssinfo));
|
||||||
|
#endif
|
||||||
|
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1740,6 +1747,8 @@ ConnFree(Port *conn)
|
|||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
secure_close(conn);
|
secure_close(conn);
|
||||||
#endif
|
#endif
|
||||||
|
if (conn->gss)
|
||||||
|
free(conn->gss);
|
||||||
free(conn);
|
free(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.404 2007/06/30 19:12:02 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.405 2007/07/10 13:14:21 mha Exp $
|
||||||
*
|
*
|
||||||
*--------------------------------------------------------------------
|
*--------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1040,7 +1040,7 @@ static struct config_bool ConfigureNamesBool[] =
|
|||||||
|
|
||||||
{
|
{
|
||||||
{"krb_caseins_users", PGC_POSTMASTER, CONN_AUTH_SECURITY,
|
{"krb_caseins_users", PGC_POSTMASTER, CONN_AUTH_SECURITY,
|
||||||
gettext_noop("Sets whether Kerberos user names should be treated as case-insensitive."),
|
gettext_noop("Sets whether Kerberos and GSSAPI user names should be treated as case-insensitive."),
|
||||||
NULL
|
NULL
|
||||||
},
|
},
|
||||||
&pg_krb_caseins_users,
|
&pg_krb_caseins_users,
|
||||||
|
@ -79,11 +79,11 @@
|
|||||||
#password_encryption = on
|
#password_encryption = on
|
||||||
#db_user_namespace = off
|
#db_user_namespace = off
|
||||||
|
|
||||||
# Kerberos
|
# Kerberos and GSSAPI
|
||||||
#krb_server_keyfile = '' # (change requires restart)
|
#krb_server_keyfile = '' # (change requires restart)
|
||||||
#krb_srvname = 'postgres' # (change requires restart)
|
#krb_srvname = 'postgres' # (change requires restart, kerberos only)
|
||||||
#krb_server_hostname = '' # empty string matches any keytab entry
|
#krb_server_hostname = '' # empty string matches any keytab entry
|
||||||
# (change requires restart)
|
# (change requires restart, kerberos only)
|
||||||
#krb_caseins_users = off # (change requires restart)
|
#krb_caseins_users = off # (change requires restart)
|
||||||
|
|
||||||
# - TCP Keepalives -
|
# - TCP Keepalives -
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* Interface to hba.c
|
* Interface to hba.c
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.45 2006/11/05 22:42:10 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.46 2007/07/10 13:14:21 mha Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -22,7 +22,8 @@ typedef enum UserAuth
|
|||||||
uaIdent,
|
uaIdent,
|
||||||
uaPassword,
|
uaPassword,
|
||||||
uaCrypt,
|
uaCrypt,
|
||||||
uaMD5
|
uaMD5,
|
||||||
|
uaGSS
|
||||||
#ifdef USE_PAM
|
#ifdef USE_PAM
|
||||||
,uaPAM
|
,uaPAM
|
||||||
#endif /* USE_PAM */
|
#endif /* USE_PAM */
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/libpq/libpq-be.h,v 1.58 2007/01/05 22:19:55 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/libpq/libpq-be.h,v 1.59 2007/07/10 13:14:21 mha Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -29,6 +29,10 @@
|
|||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_GSS
|
||||||
|
#include <gssapi/gssapi.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "libpq/hba.h"
|
#include "libpq/hba.h"
|
||||||
#include "libpq/pqcomm.h"
|
#include "libpq/pqcomm.h"
|
||||||
#include "utils/timestamp.h"
|
#include "utils/timestamp.h"
|
||||||
@ -39,6 +43,20 @@ typedef enum CAC_state
|
|||||||
CAC_OK, CAC_STARTUP, CAC_SHUTDOWN, CAC_RECOVERY, CAC_TOOMANY
|
CAC_OK, CAC_STARTUP, CAC_SHUTDOWN, CAC_RECOVERY, CAC_TOOMANY
|
||||||
} CAC_state;
|
} CAC_state;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GSSAPI specific state information
|
||||||
|
*/
|
||||||
|
#ifdef ENABLE_GSS
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gss_cred_id_t cred; /* GSSAPI connection cred's */
|
||||||
|
gss_ctx_id_t ctx; /* GSSAPI connection context */
|
||||||
|
gss_name_t name; /* GSSAPI client name */
|
||||||
|
gss_buffer_desc outbuf; /* GSSAPI output token buffer */
|
||||||
|
} pg_gssinfo;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is used by the postmaster in its communication with frontends. It
|
* This is used by the postmaster in its communication with frontends. It
|
||||||
* contains all state information needed during this communication before the
|
* contains all state information needed during this communication before the
|
||||||
@ -98,6 +116,17 @@ typedef struct Port
|
|||||||
int keepalives_interval;
|
int keepalives_interval;
|
||||||
int keepalives_count;
|
int keepalives_count;
|
||||||
|
|
||||||
|
#ifdef ENABLE_GSS
|
||||||
|
/*
|
||||||
|
* If GSSAPI is supported, store GSSAPI information.
|
||||||
|
* Oterwise, store a NULL pointer to make sure offsets
|
||||||
|
* in the struct remain the same.
|
||||||
|
*/
|
||||||
|
pg_gssinfo *gss;
|
||||||
|
#else
|
||||||
|
void *gss;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SSL structures (keep these last so that USE_SSL doesn't affect
|
* SSL structures (keep these last so that USE_SSL doesn't affect
|
||||||
* locations of other fields)
|
* locations of other fields)
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/libpq/pqcomm.h,v 1.104 2007/07/08 18:28:55 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/libpq/pqcomm.h,v 1.105 2007/07/10 13:14:21 mha Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -156,6 +156,8 @@ extern bool Db_user_namespace;
|
|||||||
#define AUTH_REQ_CRYPT 4 /* crypt password */
|
#define AUTH_REQ_CRYPT 4 /* crypt password */
|
||||||
#define AUTH_REQ_MD5 5 /* md5 password */
|
#define AUTH_REQ_MD5 5 /* md5 password */
|
||||||
#define AUTH_REQ_SCM_CREDS 6 /* transfer SCM credentials */
|
#define AUTH_REQ_SCM_CREDS 6 /* transfer SCM credentials */
|
||||||
|
#define AUTH_REQ_GSS 7 /* GSSAPI without wrap() */
|
||||||
|
#define AUTH_REQ_GSS_CONT 8 /* Continue GSS exchanges */
|
||||||
|
|
||||||
typedef uint32 AuthRequest;
|
typedef uint32 AuthRequest;
|
||||||
|
|
||||||
|
@ -568,6 +568,9 @@
|
|||||||
/* Define to the appropriate snprintf format for 64-bit ints, if any. */
|
/* Define to the appropriate snprintf format for 64-bit ints, if any. */
|
||||||
#undef INT64_FORMAT
|
#undef INT64_FORMAT
|
||||||
|
|
||||||
|
/* Define to build with GSSAPI support. (--with-gssapi) */
|
||||||
|
#undef ENABLE_GSS
|
||||||
|
|
||||||
/* Define to build with Kerberos 5 support. (--with-krb5) */
|
/* Define to build with Kerberos 5 support. (--with-krb5) */
|
||||||
#undef KRB5
|
#undef KRB5
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
# Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
# Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
# Portions Copyright (c) 1994, Regents of the University of California
|
# Portions Copyright (c) 1994, Regents of the University of California
|
||||||
#
|
#
|
||||||
# $PostgreSQL: pgsql/src/interfaces/libpq/Makefile,v 1.154 2007/01/07 08:49:31 petere Exp $
|
# $PostgreSQL: pgsql/src/interfaces/libpq/Makefile,v 1.155 2007/07/10 13:14:21 mha Exp $
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -57,9 +57,9 @@ endif
|
|||||||
# shared library link. (The order in which you list them here doesn't
|
# shared library link. (The order in which you list them here doesn't
|
||||||
# matter.)
|
# matter.)
|
||||||
ifneq ($(PORTNAME), win32)
|
ifneq ($(PORTNAME), win32)
|
||||||
SHLIB_LINK += $(filter -lcrypt -ldes -lcom_err -lcrypto -lk5crypto -lkrb5 -lssl -lsocket -lnsl -lresolv -lintl, $(LIBS)) $(LDAP_LIBS_FE) $(PTHREAD_LIBS)
|
SHLIB_LINK += $(filter -lcrypt -ldes -lcom_err -lcrypto -lk5crypto -lkrb5 -lgssapi_krb5 -lssl -lsocket -lnsl -lresolv -lintl, $(LIBS)) $(LDAP_LIBS_FE) $(PTHREAD_LIBS)
|
||||||
else
|
else
|
||||||
SHLIB_LINK += $(filter -lcrypt -ldes -lcom_err -lcrypto -lk5crypto -lkrb5 -lssl -lsocket -lnsl -lresolv -lintl $(PTHREAD_LIBS), $(LIBS)) $(LDAP_LIBS_FE)
|
SHLIB_LINK += $(filter -lcrypt -ldes -lcom_err -lcrypto -lk5crypto -lkrb5 -lgssapi32 -lssl -lsocket -lnsl -lresolv -lintl $(PTHREAD_LIBS), $(LIBS)) $(LDAP_LIBS_FE)
|
||||||
endif
|
endif
|
||||||
ifeq ($(PORTNAME), win32)
|
ifeq ($(PORTNAME), win32)
|
||||||
SHLIB_LINK += -lshfolder -lwsock32 -lws2_32 $(filter -leay32 -lssleay32 -lcomerr32 -lkrb5_32, $(LIBS))
|
SHLIB_LINK += -lshfolder -lwsock32 -lws2_32 $(filter -leay32 -lssleay32 -lcomerr32 -lkrb5_32, $(LIBS))
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* exceed INITIAL_EXPBUFFER_SIZE (currently 256 bytes).
|
* exceed INITIAL_EXPBUFFER_SIZE (currently 256 bytes).
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-auth.c,v 1.123 2007/02/10 14:58:55 petere Exp $
|
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-auth.c,v 1.124 2007/07/10 13:14:21 mha Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -313,6 +313,182 @@ pg_krb5_sendauth(char *PQerrormsg, int sock, const char *hostname, const char *s
|
|||||||
}
|
}
|
||||||
#endif /* KRB5 */
|
#endif /* KRB5 */
|
||||||
|
|
||||||
|
#ifdef ENABLE_GSS
|
||||||
|
/*
|
||||||
|
* GSSAPI authentication system.
|
||||||
|
*/
|
||||||
|
#include <gssapi/gssapi.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
/*
|
||||||
|
* MIT Kerberos GSSAPI DLL doesn't properly export the symbols
|
||||||
|
* that contain the OIDs required. Redefine here, values copied
|
||||||
|
* from src/athena/auth/krb5/src/lib/gssapi/generic/gssapi_generic.c
|
||||||
|
*/
|
||||||
|
static const gss_OID_desc GSS_C_NT_HOSTBASED_SERVICE_desc =
|
||||||
|
{10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"};
|
||||||
|
static GSS_DLLIMP gss_OID GSS_C_NT_HOSTBASED_SERVICE = &GSS_C_NT_HOSTBASED_SERVICE_desc;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fetch all errors of a specific type that fit into a buffer
|
||||||
|
* and append them.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
pg_GSS_error_int(char *mprefix, char *msg, int msglen,
|
||||||
|
OM_uint32 stat, int type)
|
||||||
|
{
|
||||||
|
int curlen = 0;
|
||||||
|
OM_uint32 lmaj_s, lmin_s;
|
||||||
|
gss_buffer_desc lmsg;
|
||||||
|
OM_uint32 msg_ctx = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
lmaj_s = gss_display_status(&lmin_s, stat, type,
|
||||||
|
GSS_C_NO_OID, &msg_ctx, &lmsg);
|
||||||
|
|
||||||
|
if (curlen < msglen)
|
||||||
|
{
|
||||||
|
snprintf(msg + curlen, msglen - curlen, "%s: %s\n",
|
||||||
|
mprefix, (char *)lmsg.value);
|
||||||
|
curlen += lmsg.length;
|
||||||
|
}
|
||||||
|
gss_release_buffer(&lmin_s, &lmsg);
|
||||||
|
} while (msg_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GSSAPI errors contains two parts. Put as much as possible of
|
||||||
|
* both parts into the string.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
pg_GSS_error(char *mprefix, char *msg, int msglen,
|
||||||
|
OM_uint32 maj_stat, OM_uint32 min_stat)
|
||||||
|
{
|
||||||
|
int mlen;
|
||||||
|
|
||||||
|
/* Fetch major error codes */
|
||||||
|
pg_GSS_error_int(mprefix, msg, msglen, maj_stat, GSS_C_GSS_CODE);
|
||||||
|
mlen = strlen(msg);
|
||||||
|
|
||||||
|
/* If there is room left, try to add the minor codes as well */
|
||||||
|
if (mlen < msglen-1)
|
||||||
|
pg_GSS_error_int(mprefix, msg + mlen, msglen - mlen,
|
||||||
|
min_stat, GSS_C_MECH_CODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Continue GSS authentication with next token as needed.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
pg_GSS_continue(char *PQerrormsg, PGconn *conn)
|
||||||
|
{
|
||||||
|
OM_uint32 maj_stat, min_stat, lmin_s;
|
||||||
|
|
||||||
|
maj_stat = gss_init_sec_context(&min_stat,
|
||||||
|
GSS_C_NO_CREDENTIAL,
|
||||||
|
&conn->gctx,
|
||||||
|
conn->gtarg_nam,
|
||||||
|
GSS_C_NO_OID,
|
||||||
|
conn->gflags,
|
||||||
|
0,
|
||||||
|
GSS_C_NO_CHANNEL_BINDINGS,
|
||||||
|
(conn->gctx==GSS_C_NO_CONTEXT)?GSS_C_NO_BUFFER:&conn->ginbuf,
|
||||||
|
NULL,
|
||||||
|
&conn->goutbuf,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (conn->gctx != GSS_C_NO_CONTEXT)
|
||||||
|
{
|
||||||
|
free(conn->ginbuf.value);
|
||||||
|
conn->ginbuf.value = NULL;
|
||||||
|
conn->ginbuf.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn->goutbuf.length != 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* GSS generated data to send to the server. We don't care if it's
|
||||||
|
* the first or subsequent packet, just send the same kind of
|
||||||
|
* password packet.
|
||||||
|
*/
|
||||||
|
if (pqPacketSend(conn, 'p',
|
||||||
|
conn->goutbuf.value, conn->goutbuf.length)
|
||||||
|
!= STATUS_OK)
|
||||||
|
{
|
||||||
|
gss_release_buffer(&lmin_s, &conn->goutbuf);
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gss_release_buffer(&lmin_s, &conn->goutbuf);
|
||||||
|
|
||||||
|
if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
|
||||||
|
{
|
||||||
|
pg_GSS_error(libpq_gettext("GSSAPI continuation error"),
|
||||||
|
PQerrormsg, PQERRORMSG_LENGTH,
|
||||||
|
maj_stat, min_stat);
|
||||||
|
gss_release_name(&lmin_s, &conn->gtarg_nam);
|
||||||
|
if (conn->gctx)
|
||||||
|
gss_delete_sec_context(&lmin_s, &conn->gctx, GSS_C_NO_BUFFER);
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maj_stat == GSS_S_COMPLETE)
|
||||||
|
gss_release_name(&lmin_s, &conn->gtarg_nam);
|
||||||
|
|
||||||
|
return STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send initial GSS authentication token
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
pg_GSS_startup(char *PQerrormsg, PGconn *conn)
|
||||||
|
{
|
||||||
|
OM_uint32 maj_stat, min_stat;
|
||||||
|
int maxlen;
|
||||||
|
gss_buffer_desc temp_gbuf;
|
||||||
|
|
||||||
|
if (conn->gctx)
|
||||||
|
{
|
||||||
|
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
|
||||||
|
libpq_gettext("duplicate GSS auth request\n"));
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Import service principal name so the proper ticket can be
|
||||||
|
* acquired by the GSSAPI system.
|
||||||
|
*/
|
||||||
|
maxlen = NI_MAXHOST + strlen(conn->krbsrvname) + 2;
|
||||||
|
temp_gbuf.value = (char*)malloc(maxlen);
|
||||||
|
snprintf(temp_gbuf.value, maxlen, "%s@%s",
|
||||||
|
conn->krbsrvname, conn->pghost);
|
||||||
|
temp_gbuf.length = strlen(temp_gbuf.value);
|
||||||
|
|
||||||
|
maj_stat = gss_import_name(&min_stat, &temp_gbuf,
|
||||||
|
GSS_C_NT_HOSTBASED_SERVICE, &conn->gtarg_nam);
|
||||||
|
free(temp_gbuf.value);
|
||||||
|
|
||||||
|
if (maj_stat != GSS_S_COMPLETE)
|
||||||
|
{
|
||||||
|
pg_GSS_error(libpq_gettext("GSSAPI name import error"),
|
||||||
|
PQerrormsg, PQERRORMSG_LENGTH,
|
||||||
|
maj_stat, min_stat);
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initial packet is the same as a continuation packet with
|
||||||
|
* no initial context.
|
||||||
|
*/
|
||||||
|
conn->gctx = GSS_C_NO_CONTEXT;
|
||||||
|
|
||||||
|
return pg_GSS_continue(PQerrormsg, conn);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Respond to AUTH_REQ_SCM_CREDS challenge.
|
* Respond to AUTH_REQ_SCM_CREDS challenge.
|
||||||
@ -479,6 +655,37 @@ pg_fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
|
|||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_GSS
|
||||||
|
case AUTH_REQ_GSS:
|
||||||
|
pglock_thread();
|
||||||
|
if (pg_GSS_startup(PQerrormsg, conn) != STATUS_OK)
|
||||||
|
{
|
||||||
|
/* PQerrormsg already filled in. */
|
||||||
|
pgunlock_thread();
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
pgunlock_thread();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUTH_REQ_GSS_CONT:
|
||||||
|
pglock_thread();
|
||||||
|
if (pg_GSS_continue(PQerrormsg, conn) != STATUS_OK)
|
||||||
|
{
|
||||||
|
/* PQerrormsg already filled in. */
|
||||||
|
pgunlock_thread();
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
pgunlock_thread();
|
||||||
|
break;
|
||||||
|
|
||||||
|
#else
|
||||||
|
case AUTH_REQ_GSS:
|
||||||
|
case AUTH_REQ_GSS_CONT:
|
||||||
|
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
|
||||||
|
libpq_gettext("GSSAPI authentication not supported\n"));
|
||||||
|
return STATUS_ERROR;
|
||||||
|
#endif
|
||||||
|
|
||||||
case AUTH_REQ_MD5:
|
case AUTH_REQ_MD5:
|
||||||
case AUTH_REQ_CRYPT:
|
case AUTH_REQ_CRYPT:
|
||||||
case AUTH_REQ_PASSWORD:
|
case AUTH_REQ_PASSWORD:
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.347 2007/07/08 18:28:55 tgl Exp $
|
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.348 2007/07/10 13:14:21 mha Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -181,8 +181,8 @@ static const PQconninfoOption PQconninfoOptions[] = {
|
|||||||
{"sslmode", "PGSSLMODE", DefaultSSLMode, NULL,
|
{"sslmode", "PGSSLMODE", DefaultSSLMode, NULL,
|
||||||
"SSL-Mode", "", 8}, /* sizeof("disable") == 8 */
|
"SSL-Mode", "", 8}, /* sizeof("disable") == 8 */
|
||||||
|
|
||||||
#ifdef KRB5
|
#if defined(KRB5) || defined(ENABLE_GSS)
|
||||||
/* Kerberos authentication supports specifying the service name */
|
/* Kerberos and GSSAPI authentication support specifying the service name */
|
||||||
{"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL,
|
{"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL,
|
||||||
"Kerberos-service-name", "", 20},
|
"Kerberos-service-name", "", 20},
|
||||||
#endif
|
#endif
|
||||||
@ -412,7 +412,7 @@ connectOptions1(PGconn *conn, const char *conninfo)
|
|||||||
conn->sslmode = strdup("require");
|
conn->sslmode = strdup("require");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef KRB5
|
#if defined(KRB5) || defined(ENABLE_GSS)
|
||||||
tmp = conninfo_getval(connOptions, "krbsrvname");
|
tmp = conninfo_getval(connOptions, "krbsrvname");
|
||||||
conn->krbsrvname = tmp ? strdup(tmp) : NULL;
|
conn->krbsrvname = tmp ? strdup(tmp) : NULL;
|
||||||
#endif
|
#endif
|
||||||
@ -1496,12 +1496,13 @@ keep_going: /* We will come back to here until there is
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to validate message length before using it.
|
* Try to validate message length before using it.
|
||||||
* Authentication requests can't be very large. Errors can be
|
* Authentication requests can't be very large, although GSS
|
||||||
|
* auth requests may not be that small. Errors can be
|
||||||
* a little larger, but not huge. If we see a large apparent
|
* a little larger, but not huge. If we see a large apparent
|
||||||
* length in an error, it means we're really talking to a
|
* length in an error, it means we're really talking to a
|
||||||
* pre-3.0-protocol server; cope.
|
* pre-3.0-protocol server; cope.
|
||||||
*/
|
*/
|
||||||
if (beresp == 'R' && (msgLength < 8 || msgLength > 100))
|
if (beresp == 'R' && (msgLength < 8 || msgLength > 2000))
|
||||||
{
|
{
|
||||||
printfPQExpBuffer(&conn->errorMessage,
|
printfPQExpBuffer(&conn->errorMessage,
|
||||||
libpq_gettext(
|
libpq_gettext(
|
||||||
@ -1660,6 +1661,43 @@ keep_going: /* We will come back to here until there is
|
|||||||
return PGRES_POLLING_READING;
|
return PGRES_POLLING_READING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef ENABLE_GSS
|
||||||
|
/*
|
||||||
|
* AUTH_REQ_GSS provides no input data
|
||||||
|
* Just set the request flags
|
||||||
|
*/
|
||||||
|
if (areq == AUTH_REQ_GSS)
|
||||||
|
conn->gflags = GSS_C_MUTUAL_FLAG;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read GSSAPI data packets
|
||||||
|
*/
|
||||||
|
if (areq == AUTH_REQ_GSS_CONT)
|
||||||
|
{
|
||||||
|
/* Continue GSSAPI authentication */
|
||||||
|
int llen = msgLength - 4;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can be called repeatedly for the same buffer.
|
||||||
|
* Avoid re-allocating the buffer in this case -
|
||||||
|
* just re-use the old buffer.
|
||||||
|
*/
|
||||||
|
if (llen != conn->ginbuf.length)
|
||||||
|
{
|
||||||
|
if (conn->ginbuf.value)
|
||||||
|
free(conn->ginbuf.value);
|
||||||
|
|
||||||
|
conn->ginbuf.length = llen;
|
||||||
|
conn->ginbuf.value = malloc(llen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pqGetnchar(conn->ginbuf.value, llen, conn))
|
||||||
|
{
|
||||||
|
/* We'll come back when there is more data. */
|
||||||
|
return PGRES_POLLING_READING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OK, we successfully read the message; mark data consumed
|
* OK, we successfully read the message; mark data consumed
|
||||||
@ -1957,7 +1995,7 @@ freePGconn(PGconn *conn)
|
|||||||
free(conn->pgpass);
|
free(conn->pgpass);
|
||||||
if (conn->sslmode)
|
if (conn->sslmode)
|
||||||
free(conn->sslmode);
|
free(conn->sslmode);
|
||||||
#ifdef KRB5
|
#if defined(KRB5) || defined(ENABLE_GSS)
|
||||||
if (conn->krbsrvname)
|
if (conn->krbsrvname)
|
||||||
free(conn->krbsrvname);
|
free(conn->krbsrvname);
|
||||||
#endif
|
#endif
|
||||||
@ -1973,6 +2011,19 @@ freePGconn(PGconn *conn)
|
|||||||
notify = notify->next;
|
notify = notify->next;
|
||||||
free(prev);
|
free(prev);
|
||||||
}
|
}
|
||||||
|
#ifdef ENABLE_GSS
|
||||||
|
{
|
||||||
|
OM_uint32 min_s;
|
||||||
|
if (conn->gctx)
|
||||||
|
gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
|
||||||
|
if (conn->gtarg_nam)
|
||||||
|
gss_release_name(&min_s, &conn->gtarg_nam);
|
||||||
|
if (conn->ginbuf.length)
|
||||||
|
gss_release_buffer(&min_s, &conn->ginbuf);
|
||||||
|
if (conn->goutbuf.length)
|
||||||
|
gss_release_buffer(&min_s, &conn->goutbuf);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
pstatus = conn->pstatus;
|
pstatus = conn->pstatus;
|
||||||
while (pstatus != NULL)
|
while (pstatus != NULL)
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.121 2007/07/08 18:28:56 tgl Exp $
|
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.122 2007/07/10 13:14:22 mha Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -44,6 +44,10 @@
|
|||||||
/* include stuff found in fe only */
|
/* include stuff found in fe only */
|
||||||
#include "pqexpbuffer.h"
|
#include "pqexpbuffer.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_GSS
|
||||||
|
#include <gssapi/gssapi.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
@ -268,7 +272,7 @@ struct pg_conn
|
|||||||
char *pguser; /* Postgres username and password, if any */
|
char *pguser; /* Postgres username and password, if any */
|
||||||
char *pgpass;
|
char *pgpass;
|
||||||
char *sslmode; /* SSL mode (require,prefer,allow,disable) */
|
char *sslmode; /* SSL mode (require,prefer,allow,disable) */
|
||||||
#ifdef KRB5
|
#if defined(KRB5) || defined(ENABLE_GSS)
|
||||||
char *krbsrvname; /* Kerberos service name */
|
char *krbsrvname; /* Kerberos service name */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -350,6 +354,14 @@ struct pg_conn
|
|||||||
char peer_cn[SM_USER + 1]; /* peer common name */
|
char peer_cn[SM_USER + 1]; /* peer common name */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_GSS
|
||||||
|
gss_ctx_id_t gctx; /* GSS context */
|
||||||
|
gss_name_t gtarg_nam; /* GSS target name */
|
||||||
|
OM_uint32 gflags; /* GSS service request flags */
|
||||||
|
gss_buffer_desc ginbuf; /* GSS input token */
|
||||||
|
gss_buffer_desc goutbuf; /* GSS output token */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Buffer for current error message */
|
/* Buffer for current error message */
|
||||||
PQExpBufferData errorMessage; /* expansible string */
|
PQExpBufferData errorMessage; /* expansible string */
|
||||||
|
|
||||||
@ -399,6 +411,11 @@ extern pgthreadlock_t pg_g_threadlock;
|
|||||||
#define pgunlock_thread() ((void) 0)
|
#define pgunlock_thread() ((void) 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* === in fe-auth.c === */
|
||||||
|
#ifdef ENABLE_GSS
|
||||||
|
extern void pg_GSS_error(char *mprefix, char *msg, int msglen,
|
||||||
|
OM_uint32 maj_stat, OM_uint32 min_stat);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* === in fe-exec.c === */
|
/* === in fe-exec.c === */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user