From bc042e0a775040927b194473b4abf9c48e56d0a5 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 1 Aug 2001 23:25:39 +0000 Subject: [PATCH] Support ident authentication on local (Unix) socket connections, if the system supports SO_PEERCRED requests for Unix sockets. This is an amalgamation of patches submitted by Helge Bahmann and Oliver Elphick, with some editorializing by yours truly. --- configure | 298 +++++++++++++++++++---------------- configure.in | 13 ++ doc/src/sgml/client-auth.sgml | 58 +++++-- src/backend/libpq/auth.c | 8 +- src/backend/libpq/hba.c | 136 +++++++++++++--- src/backend/libpq/pg_hba.conf.sample | 35 ++-- src/include/config.h.in | 5 +- src/include/libpq/hba.h | 5 +- 8 files changed, 360 insertions(+), 198 deletions(-) diff --git a/configure b/configure index ca8f2b00b0..12e0a3cc82 100755 --- a/configure +++ b/configure @@ -5913,13 +5913,41 @@ fi rm -f conftest* +echo $ac_n "checking for SO_PEERCRED""... $ac_c" 1>&6 +echo "configure:5918: checking for SO_PEERCRED" >&5 +cat > conftest.$ac_ext < +#ifdef SO_PEERCRED +HAVE_SO_PEERCRED +#endif +] +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "HAVE_SO_PEERCRED" >/dev/null 2>&1; then + rm -rf conftest* + + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_SO_PEERCRED 1 +EOF + + +else + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + + echo $ac_n "checking for PS_STRINGS""... $ac_c" 1>&6 -echo "configure:5918: checking for PS_STRINGS" >&5 +echo "configure:5946: checking for PS_STRINGS" >&5 if eval "test \"`echo '$''{'pgac_cv_var_PS_STRINGS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5929,7 +5957,7 @@ PS_STRINGS->ps_nargvstr = 1; PS_STRINGS->ps_argvstr = "foo"; ; return 0; } EOF -if { (eval echo configure:5933: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5961: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* pgac_cv_var_PS_STRINGS=yes else @@ -5951,12 +5979,12 @@ fi SNPRINTF='' echo $ac_n "checking for snprintf""... $ac_c" 1>&6 -echo "configure:5955: checking for snprintf" >&5 +echo "configure:5983: checking for snprintf" >&5 if eval "test \"`echo '$''{'ac_cv_func_snprintf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6011: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_snprintf=yes" else @@ -6003,12 +6031,12 @@ SNPRINTF='snprintf.o' fi echo $ac_n "checking for vsnprintf""... $ac_c" 1>&6 -echo "configure:6007: checking for vsnprintf" >&5 +echo "configure:6035: checking for vsnprintf" >&5 if eval "test \"`echo '$''{'ac_cv_func_vsnprintf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6063: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_vsnprintf=yes" else @@ -6056,7 +6084,7 @@ fi cat > conftest.$ac_ext < EOF @@ -6071,7 +6099,7 @@ fi rm -f conftest* cat > conftest.$ac_ext < EOF @@ -6088,12 +6116,12 @@ rm -f conftest* # do this one the hard way in case isinf() is a macro echo $ac_n "checking for isinf""... $ac_c" 1>&6 -echo "configure:6092: checking for isinf" >&5 +echo "configure:6120: checking for isinf" >&5 if eval "test \"`echo '$''{'ac_cv_func_isinf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -6101,7 +6129,7 @@ int main() { double x = 0.0; int res = isinf(x); ; return 0; } EOF -if { (eval echo configure:6105: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6133: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_func_isinf=yes else @@ -6127,12 +6155,12 @@ else for ac_func in fpclass fp_class fp_class_d class do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:6131: checking for $ac_func" >&5 +echo "configure:6159: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6187: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -6183,12 +6211,12 @@ fi echo $ac_n "checking for getrusage""... $ac_c" 1>&6 -echo "configure:6187: checking for getrusage" >&5 +echo "configure:6215: checking for getrusage" >&5 if eval "test \"`echo '$''{'ac_cv_func_getrusage'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6243: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_getrusage=yes" else @@ -6236,12 +6264,12 @@ fi echo $ac_n "checking for srandom""... $ac_c" 1>&6 -echo "configure:6240: checking for srandom" >&5 +echo "configure:6268: checking for srandom" >&5 if eval "test \"`echo '$''{'ac_cv_func_srandom'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6296: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_srandom=yes" else @@ -6289,12 +6317,12 @@ fi echo $ac_n "checking for gethostname""... $ac_c" 1>&6 -echo "configure:6293: checking for gethostname" >&5 +echo "configure:6321: checking for gethostname" >&5 if eval "test \"`echo '$''{'ac_cv_func_gethostname'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6349: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_gethostname=yes" else @@ -6342,12 +6370,12 @@ fi echo $ac_n "checking for random""... $ac_c" 1>&6 -echo "configure:6346: checking for random" >&5 +echo "configure:6374: checking for random" >&5 if eval "test \"`echo '$''{'ac_cv_func_random'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6402: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_random=yes" else @@ -6395,12 +6423,12 @@ fi echo $ac_n "checking for inet_aton""... $ac_c" 1>&6 -echo "configure:6399: checking for inet_aton" >&5 +echo "configure:6427: checking for inet_aton" >&5 if eval "test \"`echo '$''{'ac_cv_func_inet_aton'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6455: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_inet_aton=yes" else @@ -6448,12 +6476,12 @@ fi echo $ac_n "checking for strerror""... $ac_c" 1>&6 -echo "configure:6452: checking for strerror" >&5 +echo "configure:6480: checking for strerror" >&5 if eval "test \"`echo '$''{'ac_cv_func_strerror'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6508: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_strerror=yes" else @@ -6501,12 +6529,12 @@ fi echo $ac_n "checking for strdup""... $ac_c" 1>&6 -echo "configure:6505: checking for strdup" >&5 +echo "configure:6533: checking for strdup" >&5 if eval "test \"`echo '$''{'ac_cv_func_strdup'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6561: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_strdup=yes" else @@ -6554,12 +6582,12 @@ fi echo $ac_n "checking for strtol""... $ac_c" 1>&6 -echo "configure:6558: checking for strtol" >&5 +echo "configure:6586: checking for strtol" >&5 if eval "test \"`echo '$''{'ac_cv_func_strtol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6614: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_strtol=yes" else @@ -6607,12 +6635,12 @@ fi echo $ac_n "checking for strtoul""... $ac_c" 1>&6 -echo "configure:6611: checking for strtoul" >&5 +echo "configure:6639: checking for strtoul" >&5 if eval "test \"`echo '$''{'ac_cv_func_strtoul'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6667: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_strtoul=yes" else @@ -6660,12 +6688,12 @@ fi echo $ac_n "checking for strcasecmp""... $ac_c" 1>&6 -echo "configure:6664: checking for strcasecmp" >&5 +echo "configure:6692: checking for strcasecmp" >&5 if eval "test \"`echo '$''{'ac_cv_func_strcasecmp'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6720: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_strcasecmp=yes" else @@ -6713,12 +6741,12 @@ fi echo $ac_n "checking for cbrt""... $ac_c" 1>&6 -echo "configure:6717: checking for cbrt" >&5 +echo "configure:6745: checking for cbrt" >&5 if eval "test \"`echo '$''{'ac_cv_func_cbrt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6773: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_cbrt=yes" else @@ -6762,7 +6790,7 @@ EOF else echo "$ac_t""no" 1>&6 echo $ac_n "checking for cbrt in -lm""... $ac_c" 1>&6 -echo "configure:6766: checking for cbrt in -lm" >&5 +echo "configure:6794: checking for cbrt in -lm" >&5 ac_lib_var=`echo m'_'cbrt | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -6770,7 +6798,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lm $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6813: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6819,12 +6847,12 @@ esac echo $ac_n "checking for rint""... $ac_c" 1>&6 -echo "configure:6823: checking for rint" >&5 +echo "configure:6851: checking for rint" >&5 if eval "test \"`echo '$''{'ac_cv_func_rint'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6879: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_rint=yes" else @@ -6868,7 +6896,7 @@ EOF else echo "$ac_t""no" 1>&6 echo $ac_n "checking for rint in -lm""... $ac_c" 1>&6 -echo "configure:6872: checking for rint in -lm" >&5 +echo "configure:6900: checking for rint in -lm" >&5 ac_lib_var=`echo m'_'rint | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -6876,7 +6904,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lm $HPUXMATHLIB $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6919: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6916,9 +6944,9 @@ fi # Readline versions < 2.1 don't have rl_completion_append_character echo $ac_n "checking for rl_completion_append_character""... $ac_c" 1>&6 -echo "configure:6920: checking for rl_completion_append_character" >&5 +echo "configure:6948: checking for rl_completion_append_character" >&5 cat > conftest.$ac_ext < #ifdef HAVE_READLINE_READLINE_H @@ -6931,7 +6959,7 @@ int main() { rl_completion_append_character = 'x'; ; return 0; } EOF -if { (eval echo configure:6935: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6963: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* echo "$ac_t""yes" 1>&6 cat >> confdefs.h <<\EOF @@ -6949,12 +6977,12 @@ rm -f conftest* for ac_func in rl_completion_matches rl_filename_completion_function do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:6953: checking for $ac_func" >&5 +echo "configure:6981: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7009: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -7004,16 +7032,16 @@ done echo $ac_n "checking for finite""... $ac_c" 1>&6 -echo "configure:7008: checking for finite" >&5 +echo "configure:7036: checking for finite" >&5 cat > conftest.$ac_ext < int main() { int dummy=finite(1.0); ; return 0; } EOF -if { (eval echo configure:7017: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7045: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* cat >> confdefs.h <<\EOF #define HAVE_FINITE 1 @@ -7028,16 +7056,16 @@ fi rm -f conftest* echo $ac_n "checking for sigsetjmp""... $ac_c" 1>&6 -echo "configure:7032: checking for sigsetjmp" >&5 +echo "configure:7060: checking for sigsetjmp" >&5 cat > conftest.$ac_ext < int main() { sigjmp_buf x; sigsetjmp(x, 1); ; return 0; } EOF -if { (eval echo configure:7041: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7069: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* cat >> confdefs.h <<\EOF #define HAVE_SIGSETJMP 1 @@ -7057,12 +7085,12 @@ if test x"${enable_syslog+set}" = xset; then case $enable_syslog in yes) echo $ac_n "checking for syslog""... $ac_c" 1>&6 -echo "configure:7061: checking for syslog" >&5 +echo "configure:7089: checking for syslog" >&5 if eval "test \"`echo '$''{'ac_cv_func_syslog'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7117: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_syslog=yes" else @@ -7124,19 +7152,19 @@ fi echo $ac_n "checking for optreset""... $ac_c" 1>&6 -echo "configure:7128: checking for optreset" >&5 +echo "configure:7156: checking for optreset" >&5 if eval "test \"`echo '$''{'pgac_cv_var_int_optreset'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { extern int optreset; optreset = 1; ; return 0; } EOF -if { (eval echo configure:7140: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7168: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* pgac_cv_var_int_optreset=yes else @@ -7162,16 +7190,16 @@ fi # This check should come after all modifications of compiler or linker # variables, and before any other run tests. echo $ac_n "checking test program""... $ac_c" 1>&6 -echo "configure:7166: checking test program" >&5 +echo "configure:7194: checking test program" >&5 if test "$cross_compiling" = yes; then echo "$ac_t""cross-compiling" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7203: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then echo "$ac_t""ok" 1>&6 else @@ -7191,7 +7219,7 @@ fi echo $ac_n "checking whether long int is 64 bits""... $ac_c" 1>&6 -echo "configure:7195: checking whether long int is 64 bits" >&5 +echo "configure:7223: checking whether long int is 64 bits" >&5 if eval "test \"`echo '$''{'pgac_cv_type_long_int_64'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7200,7 +7228,7 @@ else echo "configure: warning: 64 bit arithmetic disabled when cross-compiling" 1>&2 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7261: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then pgac_cv_type_long_int_64=yes else @@ -7256,7 +7284,7 @@ fi if test x"$HAVE_LONG_INT_64" = x"no" ; then echo $ac_n "checking whether long long int is 64 bits""... $ac_c" 1>&6 -echo "configure:7260: checking whether long long int is 64 bits" >&5 +echo "configure:7288: checking whether long long int is 64 bits" >&5 if eval "test \"`echo '$''{'pgac_cv_type_long_long_int_64'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7265,7 +7293,7 @@ else echo "configure: warning: 64 bit arithmetic disabled when cross-compiling" 1>&2 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7326: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then pgac_cv_type_long_long_int_64=yes else @@ -7324,7 +7352,7 @@ fi if [ x"$HAVE_LONG_LONG_INT_64" = xyes ] ; then cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7366: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* cat >> confdefs.h <<\EOF #define HAVE_LL_CONSTANTS 1 @@ -7352,7 +7380,7 @@ fi if [ x"$HAVE_LONG_LONG_INT_64" = xyes ] ; then if [ x$SNPRINTF = x ] ; then echo $ac_n "checking whether snprintf handles 'long long int' as %lld""... $ac_c" 1>&6 -echo "configure:7356: checking whether snprintf handles 'long long int' as %lld" >&5 +echo "configure:7384: checking whether snprintf handles 'long long int' as %lld" >&5 if test "$cross_compiling" = yes; then echo "$ac_t""assuming not on target machine" 1>&6 # Force usage of our own snprintf, since we cannot test foreign snprintf @@ -7361,7 +7389,7 @@ echo "configure:7356: checking whether snprintf handles 'long long int' as %lld" else cat > conftest.$ac_ext < typedef long long int int64; @@ -7388,7 +7416,7 @@ main() { exit(! does_int64_snprintf_work()); } EOF -if { (eval echo configure:7392: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7420: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then echo "$ac_t""yes" 1>&6 INT64_FORMAT='"%lld"' @@ -7399,7 +7427,7 @@ else rm -fr conftest* echo "$ac_t""no" 1>&6 echo $ac_n "checking whether snprintf handles 'long long int' as %qd""... $ac_c" 1>&6 -echo "configure:7403: checking whether snprintf handles 'long long int' as %qd" >&5 +echo "configure:7431: checking whether snprintf handles 'long long int' as %qd" >&5 if test "$cross_compiling" = yes; then echo "$ac_t""assuming not on target machine" 1>&6 # Force usage of our own snprintf, since we cannot test foreign snprintf @@ -7408,7 +7436,7 @@ echo "configure:7403: checking whether snprintf handles 'long long int' as %qd" else cat > conftest.$ac_ext < typedef long long int int64; @@ -7435,7 +7463,7 @@ main() { exit(! does_int64_snprintf_work()); } EOF -if { (eval echo configure:7439: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7467: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then echo "$ac_t""yes" 1>&6 INT64_FORMAT='"%qd"' @@ -7475,12 +7503,12 @@ EOF for ac_func in strtoll strtoq do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7479: checking for $ac_func" >&5 +echo "configure:7507: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7535: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -7530,12 +7558,12 @@ done for ac_func in strtoull strtouq do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7534: checking for $ac_func" >&5 +echo "configure:7562: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7590: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -7584,12 +7612,12 @@ done echo $ac_n "checking for atexit""... $ac_c" 1>&6 -echo "configure:7588: checking for atexit" >&5 +echo "configure:7616: checking for atexit" >&5 if eval "test \"`echo '$''{'ac_cv_func_atexit'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7644: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_atexit=yes" else @@ -7635,12 +7663,12 @@ else for ac_func in on_exit do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7639: checking for $ac_func" >&5 +echo "configure:7667: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7695: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -7696,7 +7724,7 @@ fi echo $ac_n "checking size of unsigned long""... $ac_c" 1>&6 -echo "configure:7700: checking size of unsigned long" >&5 +echo "configure:7728: checking size of unsigned long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_unsigned_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7704,7 +7732,7 @@ else ac_cv_sizeof_unsigned_long=4 else cat > conftest.$ac_ext < main() @@ -7715,7 +7743,7 @@ main() exit(0); } EOF -if { (eval echo configure:7719: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7747: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_unsigned_long=`cat conftestval` else @@ -7741,7 +7769,7 @@ EOF echo $ac_n "checking alignment of short""... $ac_c" 1>&6 -echo "configure:7745: checking alignment of short" >&5 +echo "configure:7773: checking alignment of short" >&5 if eval "test \"`echo '$''{'pgac_cv_alignof_short'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7749,7 +7777,7 @@ else pgac_cv_alignof_short='sizeof(short)' else cat > conftest.$ac_ext < struct { char filler; short field; } mystruct; @@ -7761,7 +7789,7 @@ main() exit(0); } EOF -if { (eval echo configure:7765: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7793: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then pgac_cv_alignof_short=`cat conftestval` else @@ -7781,7 +7809,7 @@ EOF echo $ac_n "checking alignment of int""... $ac_c" 1>&6 -echo "configure:7785: checking alignment of int" >&5 +echo "configure:7813: checking alignment of int" >&5 if eval "test \"`echo '$''{'pgac_cv_alignof_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7789,7 +7817,7 @@ else pgac_cv_alignof_int='sizeof(int)' else cat > conftest.$ac_ext < struct { char filler; int field; } mystruct; @@ -7801,7 +7829,7 @@ main() exit(0); } EOF -if { (eval echo configure:7805: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7833: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then pgac_cv_alignof_int=`cat conftestval` else @@ -7821,7 +7849,7 @@ EOF echo $ac_n "checking alignment of long""... $ac_c" 1>&6 -echo "configure:7825: checking alignment of long" >&5 +echo "configure:7853: checking alignment of long" >&5 if eval "test \"`echo '$''{'pgac_cv_alignof_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7829,7 +7857,7 @@ else pgac_cv_alignof_long='sizeof(long)' else cat > conftest.$ac_ext < struct { char filler; long field; } mystruct; @@ -7841,7 +7869,7 @@ main() exit(0); } EOF -if { (eval echo configure:7845: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7873: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then pgac_cv_alignof_long=`cat conftestval` else @@ -7862,7 +7890,7 @@ EOF if [ x"$HAVE_LONG_LONG_INT_64" = xyes ] ; then echo $ac_n "checking alignment of long long int""... $ac_c" 1>&6 -echo "configure:7866: checking alignment of long long int" >&5 +echo "configure:7894: checking alignment of long long int" >&5 if eval "test \"`echo '$''{'pgac_cv_alignof_long_long_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7870,7 +7898,7 @@ else pgac_cv_alignof_long_long_int='sizeof(long long int)' else cat > conftest.$ac_ext < struct { char filler; long long int field; } mystruct; @@ -7882,7 +7910,7 @@ main() exit(0); } EOF -if { (eval echo configure:7886: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7914: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then pgac_cv_alignof_long_long_int=`cat conftestval` else @@ -7903,7 +7931,7 @@ EOF fi echo $ac_n "checking alignment of double""... $ac_c" 1>&6 -echo "configure:7907: checking alignment of double" >&5 +echo "configure:7935: checking alignment of double" >&5 if eval "test \"`echo '$''{'pgac_cv_alignof_double'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7911,7 +7939,7 @@ else pgac_cv_alignof_double='sizeof(double)' else cat > conftest.$ac_ext < struct { char filler; double field; } mystruct; @@ -7923,7 +7951,7 @@ main() exit(0); } EOF -if { (eval echo configure:7927: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7955: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then pgac_cv_alignof_double=`cat conftestval` else @@ -7961,12 +7989,12 @@ EOF echo $ac_n "checking for POSIX signal interface""... $ac_c" 1>&6 -echo "configure:7965: checking for POSIX signal interface" >&5 +echo "configure:7993: checking for POSIX signal interface" >&5 if eval "test \"`echo '$''{'pgac_cv_func_posix_signals'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -7977,7 +8005,7 @@ act.sa_flags = SA_RESTART; sigaction(0, &act, &oact); ; return 0; } EOF -if { (eval echo configure:7981: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8009: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* pgac_cv_func_posix_signals=yes else @@ -8007,7 +8035,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:8011: checking for $ac_word" >&5 +echo "configure:8039: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_TCLSH'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -8043,7 +8071,7 @@ test -n "$TCLSH" && break done echo $ac_n "checking for tclConfig.sh""... $ac_c" 1>&6 -echo "configure:8047: checking for tclConfig.sh" >&5 +echo "configure:8075: checking for tclConfig.sh" >&5 # Let user override test if test -z "$TCL_CONFIG_SH"; then pgac_test_dirs="$with_tclconfig" @@ -8076,7 +8104,7 @@ fi # Check for Tk configuration script tkConfig.sh if test "$with_tk" = yes; then echo $ac_n "checking for tkConfig.sh""... $ac_c" 1>&6 -echo "configure:8080: checking for tkConfig.sh" >&5 +echo "configure:8108: checking for tkConfig.sh" >&5 # Let user override test if test -z "$TK_CONFIG_SH"; then pgac_test_dirs="$with_tkconfig $with_tclconfig" @@ -8115,7 +8143,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:8119: checking for $ac_word" >&5 +echo "configure:8147: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_NSGMLS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -8151,7 +8179,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:8155: checking for $ac_word" >&5 +echo "configure:8183: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_JADE'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -8182,7 +8210,7 @@ done echo $ac_n "checking for DocBook V3.1""... $ac_c" 1>&6 -echo "configure:8186: checking for DocBook V3.1" >&5 +echo "configure:8214: checking for DocBook V3.1" >&5 if eval "test \"`echo '$''{'pgac_cv_check_docbook'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -8215,7 +8243,7 @@ have_docbook=$pgac_cv_check_docbook echo $ac_n "checking for DocBook stylesheets""... $ac_c" 1>&6 -echo "configure:8219: checking for DocBook stylesheets" >&5 +echo "configure:8247: checking for DocBook stylesheets" >&5 if eval "test \"`echo '$''{'pgac_cv_path_stylesheets'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -8254,7 +8282,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:8258: checking for $ac_word" >&5 +echo "configure:8286: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_SGMLSPL'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else diff --git a/configure.in b/configure.in index 076fd8a0fd..c9af97065f 100644 --- a/configure.in +++ b/configure.in @@ -801,6 +801,19 @@ AC_CHECK_FUNCS([fcvt getopt_long memmove pstat setproctitle setsid sigprocmask s dnl Check whether declares fdatasync(). AC_EGREP_HEADER(fdatasync, unistd.h, AC_DEFINE(HAVE_FDATASYNC_DECL)) +AC_MSG_CHECKING([for SO_PEERCRED]) +AC_EGREP_CPP(HAVE_SO_PEERCRED, +#include +#ifdef SO_PEERCRED +HAVE_SO_PEERCRED +#endif +], +[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SO_PEERCRED) +], +[AC_MSG_RESULT(no)]) + AC_CACHE_CHECK([for PS_STRINGS], [pgac_cv_var_PS_STRINGS], [AC_TRY_LINK( [#include diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index bb5a560ad6..6e7a1d834d 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -1,4 +1,4 @@ - + Client Authentication @@ -237,14 +237,28 @@ hostssl database IP-address ident + + The identity of the user as determined on login to the + operating system is used by Postgres + to determine whether the user + is allowed to connect as the requested database user. + For TCP/IP connections the user's identity is determined by + contacting the ident server on the client + host. (Note that this is only as reliable as the remote ident + server; ident authentication should never be used for remote hosts + whose administrators are not trustworthy.) + On operating systems + supporting SO_PEERCRED requests for Unix domain sockets, + ident authentication is possible for local connections; + the system is then asked for the connecting user's identity. + - The ident server on the client host is asked for the identity - of the connecting user. Postgres - then verifies whether the so identified operating system user - is allowed to connect as the database user that is requested. - This is only available for TCP/IP connections. It can be used - on the local machine by specifying the localhost address 127.0.0.1. - + On systems without SO_PEERCRED requests, ident authentication + is only available for TCP/IP connections. As a workaround, + it is possible to + specify the localhost address 127.0.0.1 and make connections + to this address. + The authentication option following the ident keyword specifies the name of an @@ -283,7 +297,8 @@ hostssl database IP-addresspg_hba.conf file is loaded only on startup and when the postmaster receives a SIGHUP signal. If you edit the file on an active system, you will need to issue a - SIGHUP to the postmaster using kill. + SIGHUP to the postmaster using kill + to make it re-read the file. @@ -564,10 +579,18 @@ host all 192.168.0.0 255.255.0.0 ident omicron + On systems supporting SO_PEERCRED requests for Unix-domain sockets, + ident authentication can also be applied to local connections. In this + case, no security risk is added by using ident authentication; indeed + it is a preferable choice for such a system. + + + When using ident-based authentication, after having determined the - operating system user that initiated the connection, - Postgres determines as what database - system user he may connect. This is controlled by the ident map + name of the operating system user that initiated the connection, + Postgres checks whether that user is allowed + to connect as the database user he is requesting to connect as. + This is controlled by the ident map argument that follows the ident keyword in the pg_hba.conf file. The simplest ident map is sameuser, which allows any operating system @@ -588,8 +611,9 @@ host all 192.168.0.0 255.255.0.0 ident omicron The other two fields specify which operating system user is allowed to connect as which database user. The same map-name can be used repeatedly to specify more - user-mappings. There is also no restriction regarding how many - database users a given operating system may correspond to and vice + user-mappings within a single map. There is no restriction regarding + how many + database users a given operating system user may correspond to and vice versa. @@ -669,6 +693,12 @@ FATAL 1: Database "testdb" does not exist in the system catalog. if you don't specify a database name, it defaults to the database user name, which may or may not be the right thing. + + + Note that the postmaster's stderr log may contain more information + about an authentication failure than is reported to the client. + If you are confused about the reason for a failure, check the log. + diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 6cf122119f..77bcc4ef23 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.54 2001/07/21 00:29:56 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.55 2001/08/01 23:25:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -494,8 +494,7 @@ ClientAuthentication(Port *port) break; case uaIdent: - status = authident(&port->raddr.in, &port->laddr.in, - port->user, port->auth_arg); + status = authident(port); break; case uaPassword: @@ -654,8 +653,7 @@ map_old_to_new(Port *port, UserAuth old, int status) break; case uaIdent: - status = authident(&port->raddr.in, &port->laddr.in, - port->user, port->auth_arg); + status = authident(port); break; case uaPassword: diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index a2f31c9244..905cb61121 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -5,7 +5,7 @@ * wherein you authenticate a user by seeing what IP address the system * says he comes from and possibly using ident). * - * $Id: hba.c,v 1.57 2001/07/31 22:55:45 tgl Exp $ + * $Id: hba.c,v 1.58 2001/08/01 23:25:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -286,12 +286,25 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) /* * Disallow auth methods that need AF_INET sockets to work. + * Allow "ident" if we can get the identity of the connection + * peer on Unix domain sockets from the OS. */ - if (!*error_p && - (port->auth_method == uaIdent || - port->auth_method == uaKrb4 || - port->auth_method == uaKrb5)) + if (port->auth_method == uaKrb4 || + port->auth_method == uaKrb5) goto hba_syntax; +#ifndef HAVE_SO_PEERCRED + if (port->auth_method == uaIdent) + { + /* Give a special error message for this case... */ + snprintf(PQerrormsg, PQERRORMSG_LENGTH, + "parse_hba: \"ident\" auth is not supported on local connections on this platform\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + + *error_p = true; + return; + } +#endif /* * If this record doesn't match the parameters of the connection @@ -732,12 +745,12 @@ interpret_ident_response(char *ident_response, * * But iff we're unable to get the information from ident, return false. */ -static int -ident(const struct in_addr remote_ip_addr, - const struct in_addr local_ip_addr, - const ushort remote_port, - const ushort local_port, - char *ident_user) +static bool +ident_inet(const struct in_addr remote_ip_addr, + const struct in_addr local_ip_addr, + const ushort remote_port, + const ushort local_port, + char *ident_user) { int sock_fd, /* File descriptor for socket on which we * talk to Ident */ @@ -848,28 +861,103 @@ ident(const struct in_addr remote_ip_addr, return ident_return; } +#ifdef HAVE_SO_PEERCRED +/* + * Ask kernel about the credentials of the connecting process and + * determine the symbolic name of the corresponding user. + * + * Returns either true and the username put into "ident_user", + * or false if we were unable to determine the username. + */ +static bool +ident_unix(int sock, char *ident_user) +{ + struct ucred peercred; + socklen_t so_len; + struct passwd *pass; + +#ifdef SO_PASSCRED + int passcred = -1; + + so_len = sizeof(passcred); + if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &passcred, so_len) != 0) + { + /* We could not set the socket to pass credentials */ + snprintf(PQerrormsg, PQERRORMSG_LENGTH, + "Could not set the UNIX socket to pass credentials: %s\n", + strerror(errno)); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return false; + } +#endif /* SO_PASSCRED */ + + errno = 0; + so_len = sizeof(peercred); + if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 || + so_len != sizeof(peercred)) + { + /* We didn't get a valid credentials struct. */ + snprintf(PQerrormsg, PQERRORMSG_LENGTH, + "Could not get valid credentials from the UNIX socket: %s\n", + strerror(errno)); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return false; + } + + /* Convert UID to user login name */ + pass = getpwuid(peercred.uid); + + if (pass == NULL) + { + /* Error - no username with the given uid */ + snprintf(PQerrormsg, PQERRORMSG_LENGTH, + "There is no entry in /etc/passwd with the socket's uid\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return false; + } + + StrNCpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX); + + return true; +} +#endif /* - * Talk to the ident server on the remote host and find out who owns the - * connection described by "port". Then look in the usermap file under - * the usermap *auth_arg and see if that user is equivalent to - * Postgres user *user. + * Determine the username of the initiator of the connection described + * by "port". Then look in the usermap file under the usermap + * port->auth_arg and see if that user is equivalent to Postgres user + * port->user. * - * Return STATUS_OK if yes. + * Return STATUS_OK if yes, STATUS_ERROR if no match (or couldn't get info). */ int -authident(struct sockaddr_in *raddr, struct sockaddr_in *laddr, - const char *pg_user, const char *auth_arg) +authident(hbaPort *port) { - /* We were unable to get ident to give us a username */ char ident_user[IDENT_USERNAME_MAX + 1]; - /* The username returned by ident */ - if (!ident(raddr->sin_addr, laddr->sin_addr, - raddr->sin_port, laddr->sin_port, ident_user)) - return STATUS_ERROR; + switch (port->raddr.sa.sa_family) + { + case AF_INET: + if (!ident_inet(port->raddr.in.sin_addr, + port->laddr.in.sin_addr, + port->raddr.in.sin_port, + port->laddr.in.sin_port, ident_user)) + return STATUS_ERROR; + break; +#ifdef HAVE_SO_PEERCRED + case AF_UNIX: + if (!ident_unix(port->sock, ident_user)) + return STATUS_ERROR; + break; +#endif + default: + return STATUS_ERROR; + } - if (check_ident_usermap(auth_arg, pg_user, ident_user)) + if (check_ident_usermap(port->auth_arg, port->user, ident_user)) return STATUS_OK; else return STATUS_ERROR; diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample index 9c8d8ae74d..7dc39ee67b 100644 --- a/src/backend/libpq/pg_hba.conf.sample +++ b/src/backend/libpq/pg_hba.conf.sample @@ -126,28 +126,31 @@ # usernames stored in secondary password files but not # secondary passwords. # -# ident: Authentication is done by the ident server on the local -# (127.0.0.1) or remote host. AUTH_ARGUMENT is required and -# maps names found in the $PGDATA/pg_ident.conf file. The -# connection is accepted if the file contains an entry for -# this map name with the ident-supplied username and the -# requested PostgreSQL username. The special map name -# "sameuser" indicates an implied map (not in pg_ident.conf) -# that maps each ident username to the identical PostgreSQL -# username. -# -# krb4: Kerberos V4 authentication is used. -# -# krb5: Kerberos V5 authentication is used. +# ident: For TCP/IP connections, authentication is done by contacting +# the ident server on the client host. (CAUTION: this is only +# as secure as the client machine!) On machines that support +# SO_PEERCRED socket requests, this method also works for +# local Unix-domain connections. AUTH_ARGUMENT is required: +# it determines how to map remote user names to Postgres user +# names. The AUTH_ARGUMENT is a map name found in the +# $PGDATA/pg_ident.conf file. The connection is accepted if +# that file contains an entry for this map name with the +# ident-supplied username and the requested Postgres username. +# The special map name "sameuser" indicates an implied map +# (not in pg_ident.conf) that maps each ident username to the +# identical PostgreSQL username. +# +# krb4: Kerberos V4 authentication is used. Allowed only for +# TCP/IP connections, not for local UNIX-domain sockets. +# +# krb5: Kerberos V5 authentication is used. Allowed only for +# TCP/IP connections, not for local UNIX-domain sockets. # # reject: Reject the connection. This is used to reject certain hosts # that are part of a network specified later in the file. # To be effective, "reject" must appear before the later # entries. # -# Local UNIX-domain socket connections support only the AUTH_TYPEs of -# "trust", "password", "crypt", and "reject". -# # # # Examples diff --git a/src/include/config.h.in b/src/include/config.h.in index 70e9d6aa92..971a32a3ac 100644 --- a/src/include/config.h.in +++ b/src/include/config.h.in @@ -8,7 +8,7 @@ * or in config.h afterwards. Of course, if you edit config.h, then your * changes will be overwritten the next time you run configure. * - * $Id: config.h.in,v 1.168 2001/07/16 05:07:00 tgl Exp $ + * $Id: config.h.in,v 1.169 2001/08/01 23:25:39 tgl Exp $ */ #ifndef CONFIG_H @@ -685,6 +685,9 @@ extern int fdatasync(int fildes); /* Define if you have on_exit() */ #undef HAVE_ON_EXIT +/* Define if you have SO_PEERCRED */ +#undef HAVE_SO_PEERCRED + /* *------------------------------------------------------------------------ * Part 4: pull in system-specific declarations. diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h index c1524946e3..0d792da3d3 100644 --- a/src/include/libpq/hba.h +++ b/src/include/libpq/hba.h @@ -4,7 +4,7 @@ * Interface to hba.c * * - * $Id: hba.h,v 1.21 2001/07/31 22:55:45 tgl Exp $ + * $Id: hba.h,v 1.22 2001/08/01 23:25:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -41,8 +41,7 @@ typedef enum UserAuth typedef struct Port hbaPort; extern int hba_getauthmethod(hbaPort *port); -extern int authident(struct sockaddr_in *raddr, struct sockaddr_in *laddr, - const char *postgres_username, const char *auth_arg); +extern int authident(hbaPort *port); extern void load_hba_and_ident(void); #endif -- 2.11.0