mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
Replace use of credential control messages with getsockopt(LOCAL_PEERCRED).
It turns out the reason we hadn't found out about the portability issues with our credential-control-message code is that almost no modern platforms use that code at all; the ones that used to need it now offer getpeereid(), which we choose first. The last holdout was NetBSD, and they added getpeereid() as of 5.0. So far as I can tell, the only live platform on which that code was being exercised was Debian/kFreeBSD, ie, FreeBSD kernel with Linux userland --- since glibc doesn't provide getpeereid(), we fell back to the control message code. However, the FreeBSD kernel provides a LOCAL_PEERCRED socket parameter that's functionally equivalent to Linux's SO_PEERCRED. That is both much simpler to use than control messages, and superior because it doesn't require receiving a message from the other end at just the right time. Therefore, add code to use LOCAL_PEERCRED when necessary, and rip out all the credential-control-message code in the backend. (libpq still has such code so that it can still talk to pre-9.1 servers ... but eventually we can get rid of it there too.) Clean up related autoconf probes, too. This means that libpq's requirepeer parameter now works on exactly the same platforms where the backend supports peer authentication, so adjust the documentation accordingly.
This commit is contained in:
231
configure
vendored
231
configure
vendored
@ -9990,7 +9990,8 @@ done
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
for ac_header in crypt.h dld.h fp_class.h getopt.h ieeefp.h ifaddrs.h langinfo.h poll.h pwd.h sys/ioctl.h sys/ipc.h sys/poll.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/socket.h sys/sockio.h sys/tas.h sys/time.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h kernel/OS.h kernel/image.h SupportDefs.h
|
|
||||||
|
for ac_header in crypt.h dld.h fp_class.h getopt.h ieeefp.h ifaddrs.h langinfo.h poll.h pwd.h sys/ioctl.h sys/ipc.h sys/poll.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/socket.h sys/sockio.h sys/tas.h sys/time.h sys/ucred.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h kernel/OS.h kernel/image.h SupportDefs.h
|
||||||
do
|
do
|
||||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||||
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||||
@ -17037,10 +17038,10 @@ _ACEOF
|
|||||||
cat confdefs.h >>conftest.$ac_ext
|
cat confdefs.h >>conftest.$ac_ext
|
||||||
cat >>conftest.$ac_ext <<_ACEOF
|
cat >>conftest.$ac_ext <<_ACEOF
|
||||||
/* end confdefs.h. */
|
/* end confdefs.h. */
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#ifdef HAVE_SYS_UCRED_H
|
||||||
#include <sys/ucred.h>
|
#include <sys/ucred.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
main ()
|
main ()
|
||||||
@ -17075,10 +17076,10 @@ _ACEOF
|
|||||||
cat confdefs.h >>conftest.$ac_ext
|
cat confdefs.h >>conftest.$ac_ext
|
||||||
cat >>conftest.$ac_ext <<_ACEOF
|
cat >>conftest.$ac_ext <<_ACEOF
|
||||||
/* end confdefs.h. */
|
/* end confdefs.h. */
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#ifdef HAVE_SYS_UCRED_H
|
||||||
#include <sys/ucred.h>
|
#include <sys/ucred.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
main ()
|
main ()
|
||||||
@ -17134,226 +17135,6 @@ cat >>confdefs.h <<_ACEOF
|
|||||||
_ACEOF
|
_ACEOF
|
||||||
|
|
||||||
|
|
||||||
fi
|
|
||||||
{ $as_echo "$as_me:$LINENO: checking for struct fcred" >&5
|
|
||||||
$as_echo_n "checking for struct fcred... " >&6; }
|
|
||||||
if test "${ac_cv_type_struct_fcred+set}" = set; then
|
|
||||||
$as_echo_n "(cached) " >&6
|
|
||||||
else
|
|
||||||
ac_cv_type_struct_fcred=no
|
|
||||||
cat >conftest.$ac_ext <<_ACEOF
|
|
||||||
/* confdefs.h. */
|
|
||||||
_ACEOF
|
|
||||||
cat confdefs.h >>conftest.$ac_ext
|
|
||||||
cat >>conftest.$ac_ext <<_ACEOF
|
|
||||||
/* end confdefs.h. */
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ucred.h>
|
|
||||||
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
if (sizeof (struct fcred))
|
|
||||||
return 0;
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
_ACEOF
|
|
||||||
rm -f conftest.$ac_objext
|
|
||||||
if { (ac_try="$ac_compile"
|
|
||||||
case "(($ac_try" in
|
|
||||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
|
||||||
*) ac_try_echo=$ac_try;;
|
|
||||||
esac
|
|
||||||
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
|
|
||||||
$as_echo "$ac_try_echo") >&5
|
|
||||||
(eval "$ac_compile") 2>conftest.er1
|
|
||||||
ac_status=$?
|
|
||||||
grep -v '^ *+' conftest.er1 >conftest.err
|
|
||||||
rm -f conftest.er1
|
|
||||||
cat conftest.err >&5
|
|
||||||
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
|
||||||
(exit $ac_status); } && {
|
|
||||||
test -z "$ac_c_werror_flag" ||
|
|
||||||
test ! -s conftest.err
|
|
||||||
} && test -s conftest.$ac_objext; then
|
|
||||||
cat >conftest.$ac_ext <<_ACEOF
|
|
||||||
/* confdefs.h. */
|
|
||||||
_ACEOF
|
|
||||||
cat confdefs.h >>conftest.$ac_ext
|
|
||||||
cat >>conftest.$ac_ext <<_ACEOF
|
|
||||||
/* end confdefs.h. */
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ucred.h>
|
|
||||||
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
if (sizeof ((struct fcred)))
|
|
||||||
return 0;
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
_ACEOF
|
|
||||||
rm -f conftest.$ac_objext
|
|
||||||
if { (ac_try="$ac_compile"
|
|
||||||
case "(($ac_try" in
|
|
||||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
|
||||||
*) ac_try_echo=$ac_try;;
|
|
||||||
esac
|
|
||||||
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
|
|
||||||
$as_echo "$ac_try_echo") >&5
|
|
||||||
(eval "$ac_compile") 2>conftest.er1
|
|
||||||
ac_status=$?
|
|
||||||
grep -v '^ *+' conftest.er1 >conftest.err
|
|
||||||
rm -f conftest.er1
|
|
||||||
cat conftest.err >&5
|
|
||||||
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
|
||||||
(exit $ac_status); } && {
|
|
||||||
test -z "$ac_c_werror_flag" ||
|
|
||||||
test ! -s conftest.err
|
|
||||||
} && test -s conftest.$ac_objext; then
|
|
||||||
:
|
|
||||||
else
|
|
||||||
$as_echo "$as_me: failed program was:" >&5
|
|
||||||
sed 's/^/| /' conftest.$ac_ext >&5
|
|
||||||
|
|
||||||
ac_cv_type_struct_fcred=yes
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|
||||||
else
|
|
||||||
$as_echo "$as_me: failed program was:" >&5
|
|
||||||
sed 's/^/| /' conftest.$ac_ext >&5
|
|
||||||
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|
||||||
fi
|
|
||||||
{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_struct_fcred" >&5
|
|
||||||
$as_echo "$ac_cv_type_struct_fcred" >&6; }
|
|
||||||
if test "x$ac_cv_type_struct_fcred" = x""yes; then
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
|
||||||
#define HAVE_STRUCT_FCRED 1
|
|
||||||
_ACEOF
|
|
||||||
|
|
||||||
|
|
||||||
fi
|
|
||||||
{ $as_echo "$as_me:$LINENO: checking for struct sockcred" >&5
|
|
||||||
$as_echo_n "checking for struct sockcred... " >&6; }
|
|
||||||
if test "${ac_cv_type_struct_sockcred+set}" = set; then
|
|
||||||
$as_echo_n "(cached) " >&6
|
|
||||||
else
|
|
||||||
ac_cv_type_struct_sockcred=no
|
|
||||||
cat >conftest.$ac_ext <<_ACEOF
|
|
||||||
/* confdefs.h. */
|
|
||||||
_ACEOF
|
|
||||||
cat confdefs.h >>conftest.$ac_ext
|
|
||||||
cat >>conftest.$ac_ext <<_ACEOF
|
|
||||||
/* end confdefs.h. */
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ucred.h>
|
|
||||||
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
if (sizeof (struct sockcred))
|
|
||||||
return 0;
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
_ACEOF
|
|
||||||
rm -f conftest.$ac_objext
|
|
||||||
if { (ac_try="$ac_compile"
|
|
||||||
case "(($ac_try" in
|
|
||||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
|
||||||
*) ac_try_echo=$ac_try;;
|
|
||||||
esac
|
|
||||||
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
|
|
||||||
$as_echo "$ac_try_echo") >&5
|
|
||||||
(eval "$ac_compile") 2>conftest.er1
|
|
||||||
ac_status=$?
|
|
||||||
grep -v '^ *+' conftest.er1 >conftest.err
|
|
||||||
rm -f conftest.er1
|
|
||||||
cat conftest.err >&5
|
|
||||||
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
|
||||||
(exit $ac_status); } && {
|
|
||||||
test -z "$ac_c_werror_flag" ||
|
|
||||||
test ! -s conftest.err
|
|
||||||
} && test -s conftest.$ac_objext; then
|
|
||||||
cat >conftest.$ac_ext <<_ACEOF
|
|
||||||
/* confdefs.h. */
|
|
||||||
_ACEOF
|
|
||||||
cat confdefs.h >>conftest.$ac_ext
|
|
||||||
cat >>conftest.$ac_ext <<_ACEOF
|
|
||||||
/* end confdefs.h. */
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ucred.h>
|
|
||||||
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
if (sizeof ((struct sockcred)))
|
|
||||||
return 0;
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
_ACEOF
|
|
||||||
rm -f conftest.$ac_objext
|
|
||||||
if { (ac_try="$ac_compile"
|
|
||||||
case "(($ac_try" in
|
|
||||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
|
||||||
*) ac_try_echo=$ac_try;;
|
|
||||||
esac
|
|
||||||
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
|
|
||||||
$as_echo "$ac_try_echo") >&5
|
|
||||||
(eval "$ac_compile") 2>conftest.er1
|
|
||||||
ac_status=$?
|
|
||||||
grep -v '^ *+' conftest.er1 >conftest.err
|
|
||||||
rm -f conftest.er1
|
|
||||||
cat conftest.err >&5
|
|
||||||
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
|
||||||
(exit $ac_status); } && {
|
|
||||||
test -z "$ac_c_werror_flag" ||
|
|
||||||
test ! -s conftest.err
|
|
||||||
} && test -s conftest.$ac_objext; then
|
|
||||||
:
|
|
||||||
else
|
|
||||||
$as_echo "$as_me: failed program was:" >&5
|
|
||||||
sed 's/^/| /' conftest.$ac_ext >&5
|
|
||||||
|
|
||||||
ac_cv_type_struct_sockcred=yes
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|
||||||
else
|
|
||||||
$as_echo "$as_me: failed program was:" >&5
|
|
||||||
sed 's/^/| /' conftest.$ac_ext >&5
|
|
||||||
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|
||||||
fi
|
|
||||||
{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_struct_sockcred" >&5
|
|
||||||
$as_echo "$ac_cv_type_struct_sockcred" >&6; }
|
|
||||||
if test "x$ac_cv_type_struct_sockcred" = x""yes; then
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
|
||||||
#define HAVE_STRUCT_SOCKCRED 1
|
|
||||||
_ACEOF
|
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
12
configure.in
12
configure.in
@ -984,7 +984,7 @@ AC_SUBST(OSSP_UUID_LIBS)
|
|||||||
##
|
##
|
||||||
|
|
||||||
dnl sys/socket.h is required by AC_FUNC_ACCEPT_ARGTYPES
|
dnl sys/socket.h is required by AC_FUNC_ACCEPT_ARGTYPES
|
||||||
AC_CHECK_HEADERS([crypt.h dld.h fp_class.h getopt.h ieeefp.h ifaddrs.h langinfo.h poll.h pwd.h sys/ioctl.h sys/ipc.h sys/poll.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/socket.h sys/sockio.h sys/tas.h sys/time.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h kernel/OS.h kernel/image.h SupportDefs.h])
|
AC_CHECK_HEADERS([crypt.h dld.h fp_class.h getopt.h ieeefp.h ifaddrs.h langinfo.h poll.h pwd.h sys/ioctl.h sys/ipc.h sys/poll.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/socket.h sys/sockio.h sys/tas.h sys/time.h sys/ucred.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h kernel/OS.h kernel/image.h SupportDefs.h])
|
||||||
|
|
||||||
# On BSD, cpp test for net/if.h will fail unless sys/socket.h
|
# On BSD, cpp test for net/if.h will fail unless sys/socket.h
|
||||||
# is included first.
|
# is included first.
|
||||||
@ -1125,11 +1125,11 @@ AC_TYPE_LONG_LONG_INT
|
|||||||
|
|
||||||
PGAC_TYPE_LOCALE_T
|
PGAC_TYPE_LOCALE_T
|
||||||
|
|
||||||
AC_CHECK_TYPES([struct cmsgcred, struct fcred, struct sockcred], [], [],
|
AC_CHECK_TYPES([struct cmsgcred], [], [],
|
||||||
[#include <sys/param.h>
|
[#include <sys/socket.h>
|
||||||
#include <sys/types.h>
|
#ifdef HAVE_SYS_UCRED_H
|
||||||
#include <sys/socket.h>
|
#include <sys/ucred.h>
|
||||||
#include <sys/ucred.h>])
|
#endif])
|
||||||
|
|
||||||
AC_CHECK_TYPES([struct option], [], [],
|
AC_CHECK_TYPES([struct option], [], [],
|
||||||
[#ifdef HAVE_GETOPT_H
|
[#ifdef HAVE_GETOPT_H
|
||||||
|
@ -48,7 +48,8 @@
|
|||||||
runs. If all the users of a particular server also have accounts on
|
runs. If all the users of a particular server also have accounts on
|
||||||
the server's machine, it makes sense to assign database user names
|
the server's machine, it makes sense to assign database user names
|
||||||
that match their operating system user names. However, a server that
|
that match their operating system user names. However, a server that
|
||||||
accepts remote connections might have many database users who have no local operating system
|
accepts remote connections might have many database users who have no local
|
||||||
|
operating system
|
||||||
account, and in such cases there need be no connection between
|
account, and in such cases there need be no connection between
|
||||||
database user names and OS user names.
|
database user names and OS user names.
|
||||||
</para>
|
</para>
|
||||||
@ -472,8 +473,8 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
|
|||||||
<term><literal>peer</></term>
|
<term><literal>peer</></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Obtain the operating system user name from the operating system
|
Obtain the client's operating system user name from the operating
|
||||||
and check if it matches the requested database user name.
|
system and check if it matches the requested database user name.
|
||||||
This is only available for local connections.
|
This is only available for local connections.
|
||||||
See <xref linkend="auth-peer"> for details.
|
See <xref linkend="auth-peer"> for details.
|
||||||
</para>
|
</para>
|
||||||
@ -1304,7 +1305,7 @@ omicron bryanh guest1
|
|||||||
The peer authentication method works by obtaining the client's
|
The peer authentication method works by obtaining the client's
|
||||||
operating system user name from the kernel and using it as the
|
operating system user name from the kernel and using it as the
|
||||||
allowed database user name (with optional user name mapping). This
|
allowed database user name (with optional user name mapping). This
|
||||||
is only supported on local connections.
|
method is only supported on local connections.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -1323,14 +1324,13 @@ omicron bryanh guest1
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Peer authentication is only available on systems supporting
|
Peer authentication is only available on operating systems providing
|
||||||
<symbol>SO_PEERCRED</symbol> requests for
|
the <function>getpeereid()</> function, the <symbol>SO_PEERCRED</symbol>
|
||||||
Unix-domain sockets (currently <systemitem
|
socket parameter, or similar mechanisms. Currently that includes
|
||||||
class="osname">Linux</>, <systemitem class="osname">FreeBSD</>,
|
<systemitem class="osname">Linux</>,
|
||||||
<systemitem class="osname">NetBSD</>, <systemitem class="osname">OpenBSD</>,
|
most flavors of <systemitem class="osname">BSD</> including
|
||||||
<systemitem class="osname">BSD/OS</>, and <systemitem class="osname">Solaris</systemitem>).
|
<systemitem class="osname">Mac OS X</>,
|
||||||
<productname>PostgreSQL</> uses <symbol>SO_PEERCRED</symbol> to find out
|
and <systemitem class="osname">Solaris</systemitem>.
|
||||||
the operating system name of the connected client process.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
@ -549,20 +549,21 @@ PGconn *PQconnectdbParams(const char **keywords, const char **values, int expand
|
|||||||
<term><literal>requirepeer</literal></term>
|
<term><literal>requirepeer</literal></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
For Unix-domain socket connections, if this parameter is
|
This parameter specifies the operating-system user name of the
|
||||||
set, the client checks at the beginning of the connection
|
server, for example <literal>requirepeer=postgres</literal>.
|
||||||
that the server process runs under the specified user name,
|
When making a Unix-domain socket connection, if this
|
||||||
otherwise the connection is aborted with an error. This
|
parameter is set, the client checks at the beginning of the
|
||||||
parameter can be used to achieve the kind of server
|
connection that the server process is running under the specified
|
||||||
authentication that SSL certificates achieve on TCP/IP
|
user name; if it is not, the connection is aborted with an error.
|
||||||
connections. (Note that if the Unix-domain socket is
|
This parameter can be used to provide server authentication similar
|
||||||
in <filename>/tmp</filename> or another publicly writable
|
to that available with SSL certificates on TCP/IP connections.
|
||||||
location, any user could start a server there. Use this
|
(Note that if the Unix-domain socket is in
|
||||||
parameter to ensure that you are connected to a server run
|
<filename>/tmp</filename> or another publicly writable location,
|
||||||
by a trusted user,
|
any user could start a server listening there. Use this parameter
|
||||||
e.g., <literal>requirepeer=postgres</literal>.) This
|
to ensure that you are connected to a server run by a trusted user.)
|
||||||
option is only supported on some platforms, currently
|
This option is only supported on platforms for which the
|
||||||
Linux, FreeBSD, NetBSD, OpenBSD, and Solaris.
|
<literal>peer</> authentication method is implemented; see
|
||||||
|
<xref linkend="auth-peer">.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -314,6 +314,8 @@
|
|||||||
the credential message.) If the credential is acceptable,
|
the credential message.) If the credential is acceptable,
|
||||||
the server responds with an
|
the server responds with an
|
||||||
AuthenticationOk, otherwise it responds with an ErrorResponse.
|
AuthenticationOk, otherwise it responds with an ErrorResponse.
|
||||||
|
(This message type is only issued by pre-9.1 servers. It may
|
||||||
|
eventually be removed from the protocol specification.)
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -17,17 +17,15 @@
|
|||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED)
|
|
||||||
#include <sys/uio.h>
|
|
||||||
#include <sys/ucred.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_UCRED_H
|
#ifdef HAVE_UCRED_H
|
||||||
#include <ucred.h>
|
#include <ucred.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SYS_UCRED_H
|
||||||
|
#include <sys/ucred.h>
|
||||||
|
#endif
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include "libpq/auth.h"
|
#include "libpq/auth.h"
|
||||||
#include "libpq/crypt.h"
|
#include "libpq/crypt.h"
|
||||||
@ -515,36 +513,8 @@ ClientAuthentication(Port *port)
|
|||||||
|
|
||||||
case uaPeer:
|
case uaPeer:
|
||||||
#ifdef HAVE_UNIX_SOCKETS
|
#ifdef HAVE_UNIX_SOCKETS
|
||||||
|
|
||||||
/*
|
|
||||||
* If we are doing peer on unix-domain sockets, use SCM_CREDS only
|
|
||||||
* if it is defined and SO_PEERCRED isn't.
|
|
||||||
*/
|
|
||||||
#if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && \
|
|
||||||
(defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || \
|
|
||||||
(defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS)))
|
|
||||||
if (port->raddr.addr.ss_family == AF_UNIX)
|
|
||||||
{
|
|
||||||
#if defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Receive credentials on next message receipt, BSD/OS,
|
|
||||||
* NetBSD. We need to set this before the client sends the
|
|
||||||
* next packet.
|
|
||||||
*/
|
|
||||||
int on = 1;
|
|
||||||
|
|
||||||
if (setsockopt(port->sock, 0, LOCAL_CREDS, &on, sizeof(on)) < 0)
|
|
||||||
ereport(FATAL,
|
|
||||||
(errcode_for_socket_access(),
|
|
||||||
errmsg("could not enable credential reception: %m")));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sendAuthRequest(port, AUTH_REQ_SCM_CREDS);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
status = auth_peer(port);
|
status = auth_peer(port);
|
||||||
#else /* HAVE_UNIX_SOCKETS */
|
#else
|
||||||
Assert(false);
|
Assert(false);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@ -1774,11 +1744,11 @@ ident_inet_done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ask kernel about the credentials of the connecting process and
|
* Ask kernel about the credentials of the connecting process,
|
||||||
* determine the symbolic name of the corresponding user.
|
* determine the symbolic name of the corresponding user, and check
|
||||||
|
* if valid per the usermap.
|
||||||
*
|
*
|
||||||
* Returns either true and the username put into "ident_user",
|
* Iff authorized, return STATUS_OK, otherwise return STATUS_ERROR.
|
||||||
* or false if we were unable to determine the username.
|
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_UNIX_SOCKETS
|
#ifdef HAVE_UNIX_SOCKETS
|
||||||
|
|
||||||
@ -1786,12 +1756,12 @@ static int
|
|||||||
auth_peer(hbaPort *port)
|
auth_peer(hbaPort *port)
|
||||||
{
|
{
|
||||||
char ident_user[IDENT_USERNAME_MAX + 1];
|
char ident_user[IDENT_USERNAME_MAX + 1];
|
||||||
|
uid_t uid = 0;
|
||||||
|
struct passwd *pass;
|
||||||
|
|
||||||
#if defined(HAVE_GETPEEREID)
|
#if defined(HAVE_GETPEEREID)
|
||||||
/* OpenBSD (also Mac OS X) style: use getpeereid() */
|
/* Most BSDen, including OS X: use getpeereid() */
|
||||||
uid_t uid;
|
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
struct passwd *pass;
|
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (getpeereid(port->sock, &uid, &gid) != 0)
|
if (getpeereid(port->sock, &uid, &gid) != 0)
|
||||||
@ -1802,23 +1772,10 @@ auth_peer(hbaPort *port)
|
|||||||
errmsg("could not get peer credentials: %m")));
|
errmsg("could not get peer credentials: %m")));
|
||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
pass = getpwuid(uid);
|
|
||||||
|
|
||||||
if (pass == NULL)
|
|
||||||
{
|
|
||||||
ereport(LOG,
|
|
||||||
(errmsg("local user with ID %d does not exist",
|
|
||||||
(int) uid)));
|
|
||||||
return STATUS_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1);
|
|
||||||
#elif defined(SO_PEERCRED)
|
#elif defined(SO_PEERCRED)
|
||||||
/* Linux style: use getsockopt(SO_PEERCRED) */
|
/* Linux: use getsockopt(SO_PEERCRED) */
|
||||||
struct ucred peercred;
|
struct ucred peercred;
|
||||||
ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
|
ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
|
||||||
struct passwd *pass;
|
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (getsockopt(port->sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
|
if (getsockopt(port->sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
|
||||||
@ -1830,22 +1787,26 @@ auth_peer(hbaPort *port)
|
|||||||
errmsg("could not get peer credentials: %m")));
|
errmsg("could not get peer credentials: %m")));
|
||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
uid = peercred.uid;
|
||||||
|
#elif defined(LOCAL_PEERCRED)
|
||||||
|
/* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */
|
||||||
|
struct xucred peercred;
|
||||||
|
ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
|
||||||
|
|
||||||
pass = getpwuid(peercred.uid);
|
errno = 0;
|
||||||
|
if (getsockopt(port->sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
|
||||||
if (pass == NULL)
|
so_len != sizeof(peercred) ||
|
||||||
|
peercred.cr_version != XUCRED_VERSION)
|
||||||
{
|
{
|
||||||
|
/* We didn't get a valid credentials struct. */
|
||||||
ereport(LOG,
|
ereport(LOG,
|
||||||
(errmsg("local user with ID %d does not exist",
|
(errcode_for_socket_access(),
|
||||||
(int) peercred.uid)));
|
errmsg("could not get peer credentials: %m")));
|
||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
uid = peercred.cr_uid;
|
||||||
strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1);
|
|
||||||
#elif defined(HAVE_GETPEERUCRED)
|
#elif defined(HAVE_GETPEERUCRED)
|
||||||
/* Solaris > 10: use getpeerucred() */
|
/* Solaris: use getpeerucred() */
|
||||||
uid_t uid;
|
|
||||||
struct passwd *pass;
|
|
||||||
ucred_t *ucred;
|
ucred_t *ucred;
|
||||||
|
|
||||||
ucred = NULL; /* must be initialized to NULL */
|
ucred = NULL; /* must be initialized to NULL */
|
||||||
@ -1866,8 +1827,16 @@ auth_peer(hbaPort *port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ucred_free(ucred);
|
ucred_free(ucred);
|
||||||
|
#else
|
||||||
|
ereport(LOG,
|
||||||
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
errmsg("Peer authentication is not supported on local connections on this platform")));
|
||||||
|
|
||||||
|
return STATUS_ERROR;
|
||||||
|
#endif
|
||||||
|
|
||||||
pass = getpwuid(uid);
|
pass = getpwuid(uid);
|
||||||
|
|
||||||
if (pass == NULL)
|
if (pass == NULL)
|
||||||
{
|
{
|
||||||
ereport(LOG,
|
ereport(LOG,
|
||||||
@ -1877,90 +1846,6 @@ auth_peer(hbaPort *port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1);
|
strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1);
|
||||||
#elif defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
|
|
||||||
/* Assorted BSDen: use a credentials control message */
|
|
||||||
#if defined(HAVE_STRUCT_CMSGCRED)
|
|
||||||
typedef struct cmsgcred Cred;
|
|
||||||
|
|
||||||
#define cruid cmcred_uid
|
|
||||||
#elif defined(HAVE_STRUCT_FCRED)
|
|
||||||
typedef struct fcred Cred;
|
|
||||||
|
|
||||||
#define cruid fc_uid
|
|
||||||
#elif defined(HAVE_STRUCT_SOCKCRED)
|
|
||||||
typedef struct sockcred Cred;
|
|
||||||
|
|
||||||
#define cruid sc_uid
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct msghdr msg;
|
|
||||||
struct cmsghdr *cmsg;
|
|
||||||
union
|
|
||||||
{
|
|
||||||
struct cmsghdr hdr;
|
|
||||||
unsigned char buf[CMSG_SPACE(sizeof(Cred))];
|
|
||||||
} cmsgbuf;
|
|
||||||
struct iovec iov;
|
|
||||||
char buf;
|
|
||||||
Cred *cred;
|
|
||||||
struct passwd *pw;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The one character that is received here is not meaningful; its purpose
|
|
||||||
* is only to make sure that recvmsg() blocks long enough for the other
|
|
||||||
* side to send its credentials.
|
|
||||||
*/
|
|
||||||
iov.iov_base = &buf;
|
|
||||||
iov.iov_len = 1;
|
|
||||||
|
|
||||||
memset(&msg, 0, sizeof(msg));
|
|
||||||
msg.msg_iov = &iov;
|
|
||||||
msg.msg_iovlen = 1;
|
|
||||||
msg.msg_control = &cmsgbuf.buf;
|
|
||||||
msg.msg_controllen = sizeof(cmsgbuf.buf);
|
|
||||||
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
|
|
||||||
|
|
||||||
if (recvmsg(port->sock, &msg, 0) < 0)
|
|
||||||
{
|
|
||||||
ereport(LOG,
|
|
||||||
(errcode_for_socket_access(),
|
|
||||||
errmsg("could not get peer credentials: %m")));
|
|
||||||
return STATUS_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmsg = CMSG_FIRSTHDR(&msg);
|
|
||||||
if (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC) ||
|
|
||||||
cmsg == NULL ||
|
|
||||||
cmsg->cmsg_len < CMSG_LEN(sizeof(Cred)) ||
|
|
||||||
cmsg->cmsg_level != SOL_SOCKET ||
|
|
||||||
cmsg->cmsg_type != SCM_CREDS)
|
|
||||||
{
|
|
||||||
ereport(LOG,
|
|
||||||
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
||||||
errmsg("could not get peer credentials: incorrect control message")));
|
|
||||||
return STATUS_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
cred = (Cred *) CMSG_DATA(cmsg);
|
|
||||||
|
|
||||||
pw = getpwuid(cred->cruid);
|
|
||||||
|
|
||||||
if (pw == NULL)
|
|
||||||
{
|
|
||||||
ereport(LOG,
|
|
||||||
(errmsg("local user with ID %d does not exist",
|
|
||||||
(int) cred->cruid)));
|
|
||||||
return STATUS_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
strlcpy(ident_user, pw->pw_name, IDENT_USERNAME_MAX + 1);
|
|
||||||
#else
|
|
||||||
ereport(LOG,
|
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
||||||
errmsg("Ident authentication is not supported on local connections on this platform")));
|
|
||||||
|
|
||||||
return STATUS_ERROR;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
|
return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
|
||||||
}
|
}
|
||||||
|
@ -505,9 +505,6 @@
|
|||||||
/* Define to 1 if the system has the type `struct cmsgcred'. */
|
/* Define to 1 if the system has the type `struct cmsgcred'. */
|
||||||
#undef HAVE_STRUCT_CMSGCRED
|
#undef HAVE_STRUCT_CMSGCRED
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `struct fcred'. */
|
|
||||||
#undef HAVE_STRUCT_FCRED
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `struct option'. */
|
/* Define to 1 if the system has the type `struct option'. */
|
||||||
#undef HAVE_STRUCT_OPTION
|
#undef HAVE_STRUCT_OPTION
|
||||||
|
|
||||||
@ -532,9 +529,6 @@
|
|||||||
/* Define to 1 if the system has the type `struct sockaddr_un'. */
|
/* Define to 1 if the system has the type `struct sockaddr_un'. */
|
||||||
#undef HAVE_STRUCT_SOCKADDR_UN
|
#undef HAVE_STRUCT_SOCKADDR_UN
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `struct sockcred'. */
|
|
||||||
#undef HAVE_STRUCT_SOCKCRED
|
|
||||||
|
|
||||||
/* Define to 1 if `tm_zone' is member of `struct tm'. */
|
/* Define to 1 if `tm_zone' is member of `struct tm'. */
|
||||||
#undef HAVE_STRUCT_TM_TM_ZONE
|
#undef HAVE_STRUCT_TM_TM_ZONE
|
||||||
|
|
||||||
@ -592,6 +586,9 @@
|
|||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
#undef HAVE_SYS_TYPES_H
|
#undef HAVE_SYS_TYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/ucred.h> header file. */
|
||||||
|
#undef HAVE_SYS_UCRED_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/un.h> header file. */
|
/* Define to 1 if you have the <sys/un.h> header file. */
|
||||||
#undef HAVE_SYS_UN_H
|
#undef HAVE_SYS_UN_H
|
||||||
|
|
||||||
|
@ -404,9 +404,6 @@
|
|||||||
/* Define to 1 if the system has the type `struct cmsgcred'. */
|
/* Define to 1 if the system has the type `struct cmsgcred'. */
|
||||||
/* #undef HAVE_STRUCT_CMSGCRED */
|
/* #undef HAVE_STRUCT_CMSGCRED */
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `struct fcred'. */
|
|
||||||
/* #undef HAVE_STRUCT_FCRED */
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `struct option'. */
|
/* Define to 1 if the system has the type `struct option'. */
|
||||||
//#define HAVE_STRUCT_OPTION 1
|
//#define HAVE_STRUCT_OPTION 1
|
||||||
|
|
||||||
@ -435,9 +432,6 @@
|
|||||||
/* Define to 1 if the system has the type `struct sockaddr_un'. */
|
/* Define to 1 if the system has the type `struct sockaddr_un'. */
|
||||||
/* #undef HAVE_STRUCT_SOCKADDR_UN */
|
/* #undef HAVE_STRUCT_SOCKADDR_UN */
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `struct sockcred'. */
|
|
||||||
/* #undef HAVE_STRUCT_SOCKCRED */
|
|
||||||
|
|
||||||
/* Define to 1 if `tm_zone' is member of `struct tm'. */
|
/* Define to 1 if `tm_zone' is member of `struct tm'. */
|
||||||
/* #undef HAVE_STRUCT_TM_TM_ZONE */
|
/* #undef HAVE_STRUCT_TM_TM_ZONE */
|
||||||
|
|
||||||
@ -483,6 +477,9 @@
|
|||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
#define HAVE_SYS_TYPES_H 1
|
#define HAVE_SYS_TYPES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/ucred.h> header file. */
|
||||||
|
/* #undef HAVE_SYS_UCRED_H */
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/un.h> header file. */
|
/* Define to 1 if you have the <sys/un.h> header file. */
|
||||||
/* #undef HAVE_SYS_UN_H */
|
/* #undef HAVE_SYS_UN_H */
|
||||||
|
|
||||||
|
@ -27,11 +27,9 @@
|
|||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/param.h> /* for MAXHOSTNAMELEN on most */
|
#include <sys/param.h> /* for MAXHOSTNAMELEN on most */
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED)
|
#ifdef HAVE_SYS_UCRED_H
|
||||||
#include <sys/uio.h>
|
|
||||||
#include <sys/ucred.h>
|
#include <sys/ucred.h>
|
||||||
#endif
|
#endif
|
||||||
#ifndef MAXHOSTNAMELEN
|
#ifndef MAXHOSTNAMELEN
|
||||||
@ -679,27 +677,25 @@ pg_SSPI_startup(PGconn *conn, int use_negotiate)
|
|||||||
/*
|
/*
|
||||||
* Respond to AUTH_REQ_SCM_CREDS challenge.
|
* Respond to AUTH_REQ_SCM_CREDS challenge.
|
||||||
*
|
*
|
||||||
* Note: current backends will not use this challenge if HAVE_GETPEEREID
|
* Note: this is dead code as of Postgres 9.1, because current backends will
|
||||||
* or SO_PEERCRED is defined, but pre-7.4 backends might, so compile the
|
* never send this challenge. But we must keep it as long as libpq needs to
|
||||||
* code anyway.
|
* interoperate with pre-9.1 servers. It is believed to be needed only on
|
||||||
|
* Debian/kFreeBSD (ie, FreeBSD kernel with Linux userland, so that the
|
||||||
|
* getpeereid() function isn't provided by libc).
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
pg_local_sendauth(PGconn *conn)
|
pg_local_sendauth(PGconn *conn)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || \
|
#ifdef HAVE_STRUCT_CMSGCRED
|
||||||
(defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
|
|
||||||
char buf;
|
char buf;
|
||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
|
|
||||||
#ifdef HAVE_STRUCT_CMSGCRED
|
|
||||||
struct cmsghdr *cmsg;
|
struct cmsghdr *cmsg;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct cmsghdr hdr;
|
struct cmsghdr hdr;
|
||||||
unsigned char buf[CMSG_SPACE(sizeof(struct cmsgcred))];
|
unsigned char buf[CMSG_SPACE(sizeof(struct cmsgcred))];
|
||||||
} cmsgbuf;
|
} cmsgbuf;
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The backend doesn't care what we send here, but it wants exactly one
|
* The backend doesn't care what we send here, but it wants exactly one
|
||||||
@ -713,8 +709,7 @@ pg_local_sendauth(PGconn *conn)
|
|||||||
msg.msg_iov = &iov;
|
msg.msg_iov = &iov;
|
||||||
msg.msg_iovlen = 1;
|
msg.msg_iovlen = 1;
|
||||||
|
|
||||||
#ifdef HAVE_STRUCT_CMSGCRED
|
/* We must set up a message that will be filled in by kernel */
|
||||||
/* FreeBSD needs us to set up a message that will be filled in by kernel */
|
|
||||||
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
|
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
|
||||||
msg.msg_control = &cmsgbuf.buf;
|
msg.msg_control = &cmsgbuf.buf;
|
||||||
msg.msg_controllen = sizeof(cmsgbuf.buf);
|
msg.msg_controllen = sizeof(cmsgbuf.buf);
|
||||||
@ -722,7 +717,6 @@ pg_local_sendauth(PGconn *conn)
|
|||||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct cmsgcred));
|
cmsg->cmsg_len = CMSG_LEN(sizeof(struct cmsgcred));
|
||||||
cmsg->cmsg_level = SOL_SOCKET;
|
cmsg->cmsg_level = SOL_SOCKET;
|
||||||
cmsg->cmsg_type = SCM_CREDS;
|
cmsg->cmsg_type = SCM_CREDS;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (sendmsg(conn->sock, &msg, 0) == -1)
|
if (sendmsg(conn->sock, &msg, 0) == -1)
|
||||||
{
|
{
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
#ifdef HAVE_UCRED_H
|
#ifdef HAVE_UCRED_H
|
||||||
#include <ucred.h>
|
#include <ucred.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SYS_UCRED_H
|
||||||
|
#include <sys/ucred.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "libpq-fe.h"
|
#include "libpq-fe.h"
|
||||||
#include "libpq-int.h"
|
#include "libpq-int.h"
|
||||||
@ -1856,15 +1859,21 @@ keep_going: /* We will come back to here until there is
|
|||||||
char *startpacket;
|
char *startpacket;
|
||||||
int packetlen;
|
int packetlen;
|
||||||
|
|
||||||
if (conn->requirepeer && conn->requirepeer[0])
|
/*
|
||||||
|
* Implement requirepeer check, if requested and it's a
|
||||||
|
* Unix-domain socket.
|
||||||
|
*/
|
||||||
|
if (conn->requirepeer && conn->requirepeer[0] &&
|
||||||
|
IS_AF_UNIX(conn->raddr.addr.ss_family))
|
||||||
{
|
{
|
||||||
#if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(HAVE_GETPEERUCRED)
|
#if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(LOCAL_PEERCRED) || defined(HAVE_GETPEERUCRED)
|
||||||
char pwdbuf[BUFSIZ];
|
char pwdbuf[BUFSIZ];
|
||||||
struct passwd pass_buf;
|
struct passwd pass_buf;
|
||||||
struct passwd *pass;
|
struct passwd *pass;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
|
|
||||||
#if defined(HAVE_GETPEEREID)
|
#if defined(HAVE_GETPEEREID)
|
||||||
|
/* Most BSDen, including OS X: use getpeereid() */
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
@ -1876,6 +1885,7 @@ keep_going: /* We will come back to here until there is
|
|||||||
goto error_return;
|
goto error_return;
|
||||||
}
|
}
|
||||||
#elif defined(SO_PEERCRED)
|
#elif defined(SO_PEERCRED)
|
||||||
|
/* Linux: use getsockopt(SO_PEERCRED) */
|
||||||
struct ucred peercred;
|
struct ucred peercred;
|
||||||
ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
|
ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
|
||||||
|
|
||||||
@ -1890,7 +1900,25 @@ keep_going: /* We will come back to here until there is
|
|||||||
goto error_return;
|
goto error_return;
|
||||||
}
|
}
|
||||||
uid = peercred.uid;
|
uid = peercred.uid;
|
||||||
|
#elif defined(LOCAL_PEERCRED)
|
||||||
|
/* Debian with FreeBSD kernel: use LOCAL_PEERCRED */
|
||||||
|
struct xucred peercred;
|
||||||
|
ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
if (getsockopt(conn->sock, 0, LOCAL_PEERCRED,
|
||||||
|
&peercred, &so_len) != 0 ||
|
||||||
|
so_len != sizeof(peercred) ||
|
||||||
|
peercred.cr_version != XUCRED_VERSION)
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&conn->errorMessage,
|
||||||
|
libpq_gettext("could not get peer credentials: %s\n"),
|
||||||
|
pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||||
|
goto error_return;
|
||||||
|
}
|
||||||
|
uid = peercred.cr_uid;
|
||||||
#elif defined(HAVE_GETPEERUCRED)
|
#elif defined(HAVE_GETPEERUCRED)
|
||||||
|
/* Solaris: use getpeerucred() */
|
||||||
ucred_t *ucred;
|
ucred_t *ucred;
|
||||||
|
|
||||||
ucred = NULL; /* must be initialized to NULL */
|
ucred = NULL; /* must be initialized to NULL */
|
||||||
|
Reference in New Issue
Block a user