aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/libpq/auth.c60
-rw-r--r--src/interfaces/libpq/fe-auth.c22
2 files changed, 47 insertions, 35 deletions
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 618f007827d..e6ab659f4b1 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -1788,7 +1788,7 @@ auth_peer(hbaPort *port)
char ident_user[IDENT_USERNAME_MAX + 1];
#if defined(HAVE_GETPEEREID)
- /* OpenBSD style: */
+ /* OpenBSD (also Mac OS X) style: use getpeereid() */
uid_t uid;
gid_t gid;
struct passwd *pass;
@@ -1843,7 +1843,7 @@ auth_peer(hbaPort *port)
strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1);
#elif defined(HAVE_GETPEERUCRED)
- /* Solaris > 10 */
+ /* Solaris > 10: use getpeerucred() */
uid_t uid;
struct passwd *pass;
ucred_t *ucred;
@@ -1878,9 +1878,7 @@ auth_peer(hbaPort *port)
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))
- struct msghdr msg;
-
-/* Credentials structure */
+ /* Assorted BSDen: use a credentials control message */
#if defined(HAVE_STRUCT_CMSGCRED)
typedef struct cmsgcred Cred;
@@ -1894,36 +1892,35 @@ auth_peer(hbaPort *port)
#define cruid sc_uid
#endif
- Cred *cred;
-
- /* Compute size without padding */
- char cmsgmem[ALIGN(sizeof(struct cmsghdr)) + ALIGN(sizeof(Cred))]; /* for NetBSD */
-
- /* Point to start of first structure */
- struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
+ 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;
- memset(&msg, 0, sizeof(msg));
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = (char *) cmsg;
- msg.msg_controllen = sizeof(cmsgmem);
- memset(cmsg, 0, sizeof(cmsgmem));
-
/*
- * The one character which is received here is not meaningful; its
- * purposes is only to make sure that recvmsg() blocks long enough for the
- * other side to send its credentials.
+ * 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;
- if (recvmsg(port->sock, &msg, 0) < 0 ||
- cmsg->cmsg_len < sizeof(cmsgmem) ||
- cmsg->cmsg_type != SCM_CREDS)
+ 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(),
@@ -1931,6 +1928,19 @@ auth_peer(hbaPort *port)
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);
diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c
index 6f1a163a100..094926b4e61 100644
--- a/src/interfaces/libpq/fe-auth.c
+++ b/src/interfaces/libpq/fe-auth.c
@@ -693,11 +693,12 @@ pg_local_sendauth(PGconn *conn)
struct msghdr msg;
#ifdef HAVE_STRUCT_CMSGCRED
- /* Prevent padding */
- char cmsgmem[sizeof(struct cmsghdr) + sizeof(struct cmsgcred)];
-
- /* Point to start of first structure */
- struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
+ struct cmsghdr *cmsg;
+ union
+ {
+ struct cmsghdr hdr;
+ unsigned char buf[CMSG_SPACE(sizeof(struct cmsgcred))];
+ } cmsgbuf;
#endif
/*
@@ -713,11 +714,12 @@ pg_local_sendauth(PGconn *conn)
msg.msg_iovlen = 1;
#ifdef HAVE_STRUCT_CMSGCRED
- /* Create control header, FreeBSD */
- msg.msg_control = cmsg;
- msg.msg_controllen = sizeof(cmsgmem);
- memset(cmsg, 0, sizeof(cmsgmem));
- cmsg->cmsg_len = sizeof(cmsgmem);
+ /* FreeBSD needs us to 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);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct cmsgcred));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_CREDS;
#endif