38ce593bec
Makefile. Bump both PKGREVISIONs.
306 lines
8.6 KiB
Text
306 lines
8.6 KiB
Text
$NetBSD: patch-af,v 1.2 2009/03/17 13:34:06 jmcneill Exp $
|
|
|
|
--- server/gam_channel.c.orig 2007-07-04 09:36:49.000000000 -0400
|
|
+++ server/gam_channel.c
|
|
@@ -1,8 +1,10 @@
|
|
#include "server_config.h"
|
|
+#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <glib.h>
|
|
+#include <sys/param.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/un.h>
|
|
@@ -12,6 +14,37 @@
|
|
#include "gam_channel.h"
|
|
#include "gam_protocol.h"
|
|
|
|
+#if defined(LOCAL_PEEREID)
|
|
+static gboolean
|
|
+gam_nb_getpeereid(int fd, pid_t *pid, uid_t *uid, gid_t *gid)
|
|
+{
|
|
+ struct unpcbid cred;
|
|
+ socklen_t len = sizeof(cred);
|
|
+
|
|
+ if (getsockopt(fd, 0, LOCAL_PEEREID, &cred, &len) < 0)
|
|
+ return FALSE;
|
|
+ if (pid)
|
|
+ *pid = cred.unp_pid;
|
|
+ if (uid)
|
|
+ *uid = cred.unp_euid;
|
|
+ if (gid)
|
|
+ *gid = cred.unp_egid;
|
|
+ return TRUE;
|
|
+}
|
|
+#elif defined(SOCKCREDSIZE)
|
|
+#define BSDCRED struct sockcred
|
|
+#define CRED_DATASIZE (SOCKCREDSIZE(NGROUPS))
|
|
+#define credpid(c,p) (p)
|
|
+#define creduid(c) (c->sc_euid)
|
|
+#define credgid(c) (c->sc_egid)
|
|
+#elif defined(HAVE_CMSGCRED)
|
|
+#define BSDCRED struct cmsgcred
|
|
+#define CRED_DATASIZE (sizeof(struct cmsgcred))
|
|
+#define credpid(c,p) (c->cmcred_pid)
|
|
+#define creduid(c) (c->cmcred_euid)
|
|
+#define credgid(c) (c->cmcred_groups[0])
|
|
+#endif
|
|
+
|
|
/* #define CHANNEL_VERBOSE_DEBUGGING */
|
|
/************************************************************************
|
|
* *
|
|
@@ -28,37 +61,35 @@
|
|
static gboolean
|
|
gam_client_conn_send_cred(int fd)
|
|
{
|
|
- char data[2] = { 0, 0 };
|
|
- int written;
|
|
-#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
|
|
- struct {
|
|
- struct cmsghdr hdr;
|
|
- struct cmsgcred cred;
|
|
- } cmsg;
|
|
- struct iovec iov;
|
|
struct msghdr msg;
|
|
+ struct iovec iov;
|
|
+ pid_t pid = getpid();
|
|
+ int written;
|
|
+
|
|
+#if defined(BSDCRED) && !defined(LOCAL_CREDS)
|
|
+ struct cmsghdr *cmsg;
|
|
+ char cmsgbuf[CMSG_SPACE(CRED_DATASIZE)];
|
|
+#endif
|
|
|
|
- iov.iov_base = &data[0];
|
|
- iov.iov_len = 1;
|
|
+ iov.iov_base = &pid;
|
|
+ iov.iov_len = sizeof(pid_t);
|
|
|
|
memset (&msg, 0, sizeof (msg));
|
|
msg.msg_iov = &iov;
|
|
msg.msg_iovlen = 1;
|
|
|
|
- msg.msg_control = &cmsg;
|
|
- msg.msg_controllen = sizeof (cmsg);
|
|
- memset (&cmsg, 0, sizeof (cmsg));
|
|
- cmsg.hdr.cmsg_len = sizeof (cmsg);
|
|
- cmsg.hdr.cmsg_level = SOL_SOCKET;
|
|
- cmsg.hdr.cmsg_type = SCM_CREDS;
|
|
+#if defined(BSDCRED) && !defined(LOCAL_CREDS)
|
|
+ memset(cmsgbuf, 0, CMSG_SPACE(CRED_DATASIZE));
|
|
+ msg.msg_control = (void *)cmsgbuf;
|
|
+ msg.msg_controllen = CMSG_LEN(CRED_DATASIZE);
|
|
+ cmsg = CMSG_FIRSTHDR(&msg);
|
|
+ cmsg->cmsg_len = CMSG_LEN(CRED_DATASIZE);
|
|
+ cmsg->cmsg_level = SOL_SOCKET;
|
|
+ cmsg->cmsg_type = SCM_CREDS;
|
|
#endif
|
|
|
|
retry:
|
|
-#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
|
|
written = sendmsg(fd, &msg, 0);
|
|
-#else
|
|
- written = write(fd, &data[0], 1);
|
|
-#endif
|
|
if (written < 0) {
|
|
if (errno == EINTR)
|
|
goto retry;
|
|
@@ -66,7 +97,7 @@ retry:
|
|
"Failed to write credential bytes to socket %d\n", fd);
|
|
return (-1);
|
|
}
|
|
- if (written != 1) {
|
|
+ if (written != iov.iov_len) {
|
|
gam_error(DEBUG_INFO, "Wrote %d credential bytes to socket %d\n",
|
|
written, fd);
|
|
return (-1);
|
|
@@ -89,43 +120,26 @@ gam_client_conn_check_cred(GIOChannel *
|
|
{
|
|
struct msghdr msg;
|
|
struct iovec iov;
|
|
- char buf;
|
|
- pid_t c_pid;
|
|
+ pid_t c_pid, pid;
|
|
uid_t c_uid, s_uid;
|
|
gid_t c_gid;
|
|
|
|
-#ifdef HAVE_CMSGCRED
|
|
- struct {
|
|
- struct cmsghdr hdr;
|
|
- struct cmsgcred cred;
|
|
- } cmsg;
|
|
-#endif
|
|
-
|
|
- s_uid = getuid();
|
|
-
|
|
-#if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
|
|
- /* Set the socket to receive credentials on the next message */
|
|
- {
|
|
- int on = 1;
|
|
-
|
|
- if (setsockopt(fd, 0, LOCAL_CREDS, &on, sizeof(on)) < 0) {
|
|
- gam_error(DEBUG_INFO, "Unable to set LOCAL_CREDS socket option\n");
|
|
- return FALSE;
|
|
- }
|
|
- }
|
|
+#if defined(BSDCRED)
|
|
+ struct cmsghdr *cmsg;
|
|
+ char cmsgbuf[CMSG_SPACE(CRED_DATASIZE)];
|
|
#endif
|
|
|
|
- iov.iov_base = &buf;
|
|
- iov.iov_len = 1;
|
|
+ iov.iov_base = &pid;
|
|
+ iov.iov_len = sizeof(pid_t);
|
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
msg.msg_iov = &iov;
|
|
msg.msg_iovlen = 1;
|
|
|
|
-#ifdef HAVE_CMSGCRED
|
|
- memset(&cmsg, 0, sizeof(cmsg));
|
|
- msg.msg_control = &cmsg;
|
|
- msg.msg_controllen = sizeof(cmsg);
|
|
+#if defined(BSDCRED)
|
|
+ memset(cmsgbuf, 0, sizeof(cmsgbuf));
|
|
+ msg.msg_control = (void *)cmsgbuf;
|
|
+ msg.msg_controllen = sizeof(cmsgbuf);
|
|
#endif
|
|
|
|
retry:
|
|
@@ -133,26 +147,33 @@ gam_client_conn_check_cred(GIOChannel *
|
|
if (errno == EINTR)
|
|
goto retry;
|
|
|
|
- GAM_DEBUG(DEBUG_INFO, "Failed to read credentials byte on %d\n", fd);
|
|
+ GAM_DEBUG(DEBUG_INFO, "Failed to read credential bytes on %d\n", fd);
|
|
goto failed;
|
|
}
|
|
-
|
|
- if (buf != '\0') {
|
|
- GAM_DEBUG(DEBUG_INFO, "Credentials byte was not nul on %d\n", fd);
|
|
+ GAM_DEBUG(DEBUG_INFO, "Read pid %d on %d\n", pid, fd);
|
|
+#if defined(BSDCRED)
|
|
+ if (msg.msg_controllen == 0) {
|
|
+ GAM_DEBUG(DEBUG_INFO,
|
|
+ "No control message received over recvmsg()\n");
|
|
goto failed;
|
|
}
|
|
-#ifdef HAVE_CMSGCRED
|
|
- if (cmsg.hdr.cmsg_len < sizeof(cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS) {
|
|
+ if ((msg.msg_flags & MSG_CTRUNC) != 0) {
|
|
+ GAM_DEBUG(DEBUG_INFO,
|
|
+ "Lost control message data over recvmsg()\n");
|
|
+ goto failed;
|
|
+ }
|
|
+ cmsg = CMSG_FIRSTHDR(&msg);
|
|
+ if (cmsg->cmsg_type != SCM_CREDS) {
|
|
GAM_DEBUG(DEBUG_INFO,
|
|
"Message from recvmsg() was not SCM_CREDS\n");
|
|
goto failed;
|
|
}
|
|
#endif
|
|
|
|
- GAM_DEBUG(DEBUG_INFO, "read credentials byte\n");
|
|
+ GAM_DEBUG(DEBUG_INFO, "read credential bytes\n");
|
|
|
|
{
|
|
-#ifdef SO_PEERCRED
|
|
+#if defined(SO_PEERCRED)
|
|
struct ucred cr;
|
|
socklen_t cr_len = sizeof(cr);
|
|
|
|
@@ -167,23 +188,37 @@ gam_client_conn_check_cred(GIOChannel *
|
|
fd, cr_len, (int) sizeof(cr));
|
|
goto failed;
|
|
}
|
|
-#elif defined(HAVE_CMSGCRED)
|
|
- c_pid = cmsg.cred.cmcred_pid;
|
|
- c_uid = cmsg.cred.cmcred_euid;
|
|
- c_gid = cmsg.cred.cmcred_groups[0];
|
|
-#else /* !SO_PEERCRED && !HAVE_CMSGCRED */
|
|
+#elif defined(LOCAL_PEEREID)
|
|
+ if (gam_nb_getpeereid(fd, &c_pid, &c_uid, &c_gid) == FALSE) {
|
|
+ GAM_DEBUG(DEBUG_INFO,
|
|
+ "Failed to gam_nb_getpeereid() credentials on %d\n", fd);
|
|
+ goto failed;
|
|
+ }
|
|
+#elif defined(BSDCRED)
|
|
+ BSDCRED *cr = (BSDCRED *)CMSG_DATA(cmsg);
|
|
+ c_pid = credpid(cr, pid);
|
|
+ c_uid = creduid(cr);
|
|
+ c_gid = credgid(cr);
|
|
+#else
|
|
GAM_DEBUG(DEBUG_INFO,
|
|
"Socket credentials not supported on this OS\n");
|
|
goto failed;
|
|
#endif
|
|
}
|
|
|
|
+ s_uid = getuid();
|
|
if (s_uid != c_uid) {
|
|
GAM_DEBUG(DEBUG_INFO,
|
|
"Credentials check failed: s_uid %d, c_uid %d\n",
|
|
(int) s_uid, (int) c_uid);
|
|
goto failed;
|
|
}
|
|
+ if (pid != c_pid) {
|
|
+ GAM_DEBUG(DEBUG_INFO,
|
|
+ "read credentials do not match: pid %d, c_pid %d\n",
|
|
+ (int) pid, (int) c_pid);
|
|
+ goto failed;
|
|
+ }
|
|
GAM_DEBUG(DEBUG_INFO,
|
|
"Credentials: s_uid %d, c_uid %d, c_gid %d, c_pid %d\n",
|
|
(int) s_uid, (int) c_uid, (int) c_gid, (int) c_pid);
|
|
@@ -194,7 +229,7 @@ gam_client_conn_check_cred(GIOChannel *
|
|
}
|
|
|
|
if (!gam_client_conn_send_cred(fd)) {
|
|
- GAM_DEBUG(DEBUG_INFO, "Failed to send credential byte to client\n");
|
|
+ GAM_DEBUG(DEBUG_INFO, "Failed to send credential bytes to client\n");
|
|
goto failed;
|
|
}
|
|
|
|
@@ -551,12 +586,6 @@ gam_check_secure_path(const char *path)
|
|
goto cleanup;
|
|
}
|
|
#endif
|
|
- if (st.st_mode & (S_IRWXG|S_IRWXO)) {
|
|
- gam_error(DEBUG_INFO,
|
|
- "Socket %s has wrong permissions\n",
|
|
- path);
|
|
- goto cleanup;
|
|
- }
|
|
/*
|
|
* Looks good though binding may fail due to an existing server
|
|
*/
|
|
@@ -620,6 +649,7 @@ gam_listen_unix_socket(const char *path)
|
|
{
|
|
int fd;
|
|
struct sockaddr_un addr;
|
|
+ struct stat st;
|
|
|
|
fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
|
if (fd < 0) {
|
|
@@ -646,6 +676,18 @@ gam_listen_unix_socket(const char *path)
|
|
strncpy(&addr.sun_path[0], path, (sizeof(addr) - 4) - 1);
|
|
umask(0077);
|
|
#endif
|
|
+#if defined(BSDCRED) && defined(LOCAL_CREDS)
|
|
+ /* Set the socket to receive credentials. */
|
|
+ {
|
|
+ int on = 1;
|
|
+
|
|
+ if (setsockopt(fd, 0, LOCAL_CREDS, &on, sizeof(on)) < 0) {
|
|
+ gam_error(DEBUG_INFO,
|
|
+ "Unable to setsockopt() LOCAL_CREDS on %d\n", fd);
|
|
+ return(-1);
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
|
|
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
|
GAM_DEBUG(DEBUG_INFO, "Failed to bind to socket %s\n", path);
|