diff options
Diffstat (limited to 'src/interfaces')
-rw-r--r-- | src/interfaces/libpq/fe-auth.c | 22 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-connect.c | 32 |
2 files changed, 38 insertions, 16 deletions
diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c index 094926b4e61..9a0317ba4af 100644 --- a/src/interfaces/libpq/fe-auth.c +++ b/src/interfaces/libpq/fe-auth.c @@ -27,11 +27,9 @@ #else #include <unistd.h> #include <fcntl.h> -#include <sys/types.h> #include <sys/param.h> /* for MAXHOSTNAMELEN on most */ #include <sys/socket.h> -#if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED) -#include <sys/uio.h> +#ifdef HAVE_SYS_UCRED_H #include <sys/ucred.h> #endif #ifndef MAXHOSTNAMELEN @@ -679,27 +677,25 @@ pg_SSPI_startup(PGconn *conn, int use_negotiate) /* * Respond to AUTH_REQ_SCM_CREDS challenge. * - * Note: current backends will not use this challenge if HAVE_GETPEEREID - * or SO_PEERCRED is defined, but pre-7.4 backends might, so compile the - * code anyway. + * Note: this is dead code as of Postgres 9.1, because current backends will + * never send this challenge. But we must keep it as long as libpq needs to + * 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 pg_local_sendauth(PGconn *conn) { -#if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || \ - (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS)) +#ifdef HAVE_STRUCT_CMSGCRED char buf; struct iovec iov; struct msghdr msg; - -#ifdef HAVE_STRUCT_CMSGCRED struct cmsghdr *cmsg; union { struct cmsghdr hdr; unsigned char buf[CMSG_SPACE(sizeof(struct cmsgcred))]; } cmsgbuf; -#endif /* * 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_iovlen = 1; -#ifdef HAVE_STRUCT_CMSGCRED - /* FreeBSD needs us to set up a message that will be filled in by kernel */ + /* We must set up a message that will be filled in by kernel */ memset(&cmsgbuf, 0, sizeof(cmsgbuf)); msg.msg_control = &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_level = SOL_SOCKET; cmsg->cmsg_type = SCM_CREDS; -#endif if (sendmsg(conn->sock, &msg, 0) == -1) { diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index f89ceb96642..5a6502fff4d 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -24,6 +24,9 @@ #ifdef HAVE_UCRED_H #include <ucred.h> #endif +#ifdef HAVE_SYS_UCRED_H +#include <sys/ucred.h> +#endif #include "libpq-fe.h" #include "libpq-int.h" @@ -1856,15 +1859,21 @@ keep_going: /* We will come back to here until there is char *startpacket; 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]; struct passwd pass_buf; struct passwd *pass; uid_t uid; #if defined(HAVE_GETPEEREID) + /* Most BSDen, including OS X: use getpeereid() */ gid_t gid; errno = 0; @@ -1876,6 +1885,7 @@ keep_going: /* We will come back to here until there is goto error_return; } #elif defined(SO_PEERCRED) + /* Linux: use getsockopt(SO_PEERCRED) */ struct ucred 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; } 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) + /* Solaris: use getpeerucred() */ ucred_t *ucred; ucred = NULL; /* must be initialized to NULL */ |