summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoe Shaw <joeshaw@novell.com>2003-03-01 20:50:18 +0000
committerJoe Shaw <joeshaw@novell.com>2003-03-01 20:50:18 +0000
commite0db9aa1f9521d8115d95bc17690337e25b95ab2 (patch)
tree3aead73451efe526b37cc39827bfeae892c71ba8
parent83087f783bb067e0809a6648a8bdb14e8e49efbf (diff)
2003-03-01 Joe Shaw <joe@ximian.com>
* configure.in: Check for "struct cmsgcred" and try to access its members for BSD-like unices. * dbus/dbus-sysdeps.c (read_credentials_byte): Fold this back into _dbus_read_credentials_unix_socket(). (_dbus_read_credentials_unix_socket): Use recvmsg() instead of read() for reading the credential byte off the unix socket. Use struct cmsgcred on systems that support it.
-rw-r--r--ChangeLog11
-rw-r--r--configure.in15
-rw-r--r--dbus/dbus-sysdeps.c169
3 files changed, 122 insertions, 73 deletions
diff --git a/ChangeLog b/ChangeLog
index f533891f..e8160275 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2003-03-01 Joe Shaw <joe@ximian.com>
+
+ * configure.in: Check for "struct cmsgcred" and try to access its
+ members for BSD-like unices.
+
+ * dbus/dbus-sysdeps.c (read_credentials_byte): Fold this back into
+ _dbus_read_credentials_unix_socket().
+ (_dbus_read_credentials_unix_socket): Use recvmsg() instead of
+ read() for reading the credential byte off the unix socket. Use
+ struct cmsgcred on systems that support it.
+
2003-02-27 Alexander Larsson <alexl@redhat.com>
* glib/Makefile.am:
diff --git a/configure.in b/configure.in
index 9b969bad..86db3cfc 100644
--- a/configure.in
+++ b/configure.in
@@ -200,6 +200,21 @@ if test x$dbus_have_gnuc_varargs = xyes; then
AC_DEFINE(HAVE_GNUC_VARARGS,1,[Have GNU-style varargs macros])
fi
+dnl Check for various credentials.
+AC_MSG_CHECKING(for struct cmsgcred)
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/socket.h>
+],[
+struct cmsgcred cred;
+
+cred.cmcred_pid = 0;
+],dbus_have_struct_cmsgcred=yes,dbus_have_struct_cmsgcred=no)
+AC_MSG_RESULT($dbus_have_struct_cmsgcred)
+
+if test x$dbus_have_struct_cmsgcred = xyes; then
+ AC_DEFINE(HAVE_CMSGCRED,1,[Have cmsgcred structure])
+fi
DBUS_CLIENT_CFLAGS=
DBUS_CLIENT_LIBS=
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
index 4d610a4d..2310b000 100644
--- a/dbus/dbus-sysdeps.c
+++ b/dbus/dbus-sysdeps.c
@@ -579,53 +579,6 @@ _dbus_listen_tcp_socket (const char *host,
return listen_fd;
}
-/* try to read a single byte and return #TRUE if we read it
- * and it's equal to nul.
- */
-static dbus_bool_t
-read_credentials_byte (int client_fd,
- DBusResultCode *result)
-{
- char buf[1];
- int bytes_read;
-
- again:
- bytes_read = read (client_fd, buf, 1);
- if (bytes_read < 0)
- {
- if (errno == EINTR)
- goto again;
- else
- {
- dbus_set_result (result, _dbus_result_from_errno (errno));
- _dbus_verbose ("Failed to read credentials byte: %s\n",
- _dbus_strerror (errno));
- return FALSE;
- }
- }
- else if (bytes_read == 0)
- {
- dbus_set_result (result, DBUS_RESULT_IO_ERROR);
- _dbus_verbose ("EOF reading credentials byte\n");
- return FALSE;
- }
- else
- {
- _dbus_assert (bytes_read == 1);
-
- if (buf[0] != '\0')
- {
- dbus_set_result (result, DBUS_RESULT_FAILED);
- _dbus_verbose ("Credentials byte was not nul\n");
- return FALSE;
- }
-
- _dbus_verbose ("read credentials byte\n");
-
- return TRUE;
- }
-}
-
static dbus_bool_t
write_credentials_byte (int server_fd,
DBusResultCode *result)
@@ -684,40 +637,110 @@ _dbus_read_credentials_unix_socket (int client_fd,
DBusCredentials *credentials,
DBusResultCode *result)
{
+ struct msghdr msg;
+ struct iovec iov;
+ char buf;
+
+#ifdef HAVE_CMSGCRED
+ char cmsgmem[CMSG_SPACE (sizeof (struct cmsgcred))];
+ struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
+#endif
+
credentials->pid = -1;
credentials->uid = -1;
credentials->gid = -1;
-
- if (read_credentials_byte (client_fd, result))
+
+#if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
+ /* Set the socket to receive credentials on the next message */
+ {
+ int on = 1;
+ if (setsockopt (client_fd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
+ {
+ _dbus_verbose ("Unable to set LOCAL_CREDS socket option\n");
+ return FALSE;
+ }
+ }
+#endif
+
+ iov.iov_base = &buf;
+ iov.iov_len = 1;
+
+ memset (&msg, 0, sizeof (msg));
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+#ifdef HAVE_CMSGCRED
+ memset (cmsgmem, 0, sizeof (cmsgmem));
+ msg.msg_control = cmsgmem;
+ msg.msg_controllen = sizeof (cmsgmem);
+#endif
+
+ again:
+ if (recvmsg (client_fd, &msg, 0) < 0)
{
+ if (errno == EINTR)
+ goto again;
+
+ dbus_set_result (result, _dbus_result_from_errno (errno));
+ _dbus_verbose ("Failed to read credentials byte: %s\n",
+ _dbus_strerror (errno));
+ return FALSE;
+ }
+
+ if (buf != '\0')
+ {
+ dbus_set_result (result, DBUS_RESULT_FAILED);
+ _dbus_verbose ("Credentials byte was not nul\n");
+ return FALSE;
+ }
+
+#ifdef HAVE_CMSGCRED
+ if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS)
+ {
+ dbus_set_result (result, DBUS_RESULT_FAILED);
+ _dbus_verbose ("Message from recvmsg() was not SCM_CREDS\n");
+ return FALSE;
+ }
+#endif
+
+ _dbus_verbose ("read credentials byte\n");
+
+ {
#ifdef SO_PEERCRED
- struct ucred cr;
- int cr_len = sizeof (cr);
+ struct ucred cr;
+ int cr_len = sizeof (cr);
- if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
- cr_len == sizeof (cr))
- {
- credentials->pid = cr.pid;
- credentials->uid = cr.uid;
- credentials->gid = cr.gid;
- _dbus_verbose ("Got credentials pid %d uid %d gid %d\n",
- credentials->pid,
- credentials->uid,
- credentials->gid);
- }
- else
- {
- _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
- cr_len, (int) sizeof (cr), _dbus_strerror (errno));
- }
-#else /* !SO_PEERCRED */
- _dbus_verbose ("Socket credentials not supported on this OS\n");
+ if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
+ cr_len == sizeof (cr))
+ {
+ credentials->pid = cr.pid;
+ credentials->uid = cr.uid;
+ credentials->gid = cr.gid;
+ }
+ else
+ {
+ _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
+ cr_len, (int) sizeof (cr), _dbus_strerror (errno));
+ }
+#elif defined(HAVE_CMSGCRED)
+ struct cmsgcred *cred;
+
+ cred = (struct cmsgcred *) CMSG_DATA (cmsg);
+
+ credentials->pid = cred->cmcred_pid;
+ credentials->uid = cred->cmcred_euid;
+ credentials->gid = cred->cmcred_groups[0];
+#else /* !SO_PEERCRED && !HAVE_CMSGCRED */
+ _dbus_verbose ("Socket credentials not supported on this OS\n");
#endif
+ }
- return TRUE;
- }
- else
- return FALSE;
+ _dbus_verbose ("Credentials: pid %d uid %d gid %d\n",
+ credentials->pid,
+ credentials->uid,
+ credentials->gid);
+
+ return TRUE;
}
/**