summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Welche <prlw1@cam.ac.uk>2014-07-29 14:08:20 +0100
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2014-11-06 14:29:50 +0000
commitf26ade306c1d583897610c767a560e972d680f35 (patch)
tree42806a07a916e82b528fc8669689acd320bc2aea
parentfc2fa25a3f729a704ff4ae8e3c733b81eb7c0c75 (diff)
downloaddbus-f26ade306c1d583897610c767a560e972d680f35.tar.gz
Implement NetBSD credentials-passing with LOCAL_PEEREID
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=69702 Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> Reviewed-by: Alban Crequy <alban.crequy@collabora.co.uk> Tested-by: Patrick Welche <prlw1@cam.ac.uk>
-rw-r--r--bus/dispatch.c5
-rw-r--r--configure.ac5
-rw-r--r--dbus/dbus-sysdeps-unix.c37
-rw-r--r--test/dbus-daemon.c55
4 files changed, 96 insertions, 6 deletions
diff --git a/bus/dispatch.c b/bus/dispatch.c
index fa2cc968..8f322f8c 100644
--- a/bus/dispatch.c
+++ b/bus/dispatch.c
@@ -1312,6 +1312,11 @@ check_get_connection_unix_process_id (BusContext *context,
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
defined(__linux__) || \
defined(__OpenBSD__)
+ /* In principle NetBSD should also be in that list, but
+ * its implementation of PID-passing doesn't work
+ * over a socketpair() as used in the debug-pipe transport.
+ * We test this functionality in a more realistic situation
+ * in test/dbus-daemon.c. */
warn_unexpected (connection, message, "not this error");
goto out;
diff --git a/configure.ac b/configure.ac
index de34d3e2..ae2c01ca 100644
--- a/configure.ac
+++ b/configure.ac
@@ -818,6 +818,11 @@ if test x$dbus_have_struct_cmsgcred = xyes; then
AC_DEFINE(HAVE_CMSGCRED,1,[Have cmsgcred structure])
fi
+AC_CHECK_MEMBER([struct unpcbid.unp_pid],
+ [AC_DEFINE([HAVE_UNPCBID], 1, [Have unpcbid structure])],
+ [],
+ [[#include <sys/un.h>]])
+
AC_CHECK_FUNCS(getpeerucred getpeereid)
AC_CHECK_FUNCS(pipe2 accept4)
diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
index b89c6958..f4a42d89 100644
--- a/dbus/dbus-sysdeps-unix.c
+++ b/dbus/dbus-sysdeps-unix.c
@@ -1797,16 +1797,41 @@ _dbus_read_credentials_socket (int client_fd,
#endif
int cr_len = sizeof (cr);
- if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
- cr_len == sizeof (cr))
+ if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0)
{
- pid_read = cr.pid;
- uid_read = cr.uid;
+ _dbus_verbose ("Failed to getsockopt(SO_PEERCRED): %s\n",
+ _dbus_strerror (errno));
+ }
+ else if (cr_len != sizeof (cr))
+ {
+ _dbus_verbose ("Failed to getsockopt(SO_PEERCRED), returned %d bytes, expected %d\n",
+ cr_len, (int) sizeof (cr));
+ }
+ else
+ {
+ pid_read = cr.pid;
+ uid_read = cr.uid;
+ }
+#elif defined(HAVE_UNPCBID) && defined(LOCAL_PEEREID)
+ /* Another variant of the above - used on NetBSD
+ */
+ struct unpcbid cr;
+ socklen_t cr_len = sizeof (cr);
+
+ if (getsockopt (client_fd, 0, LOCAL_PEEREID, &cr, &cr_len) != 0)
+ {
+ _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID): %s\n",
+ _dbus_strerror (errno));
+ }
+ else if (cr_len != sizeof (cr))
+ {
+ _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID), returned %d bytes, expected %d\n",
+ cr_len, (int) sizeof (cr));
}
else
{
- _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
- cr_len, (int) sizeof (cr), _dbus_strerror (errno));
+ pid_read = cr.unp_pid;
+ uid_read = cr.unp_euid;
}
#elif defined(HAVE_CMSGCRED)
/* We only check for HAVE_CMSGCRED, but we're really assuming that the
diff --git a/test/dbus-daemon.c b/test/dbus-daemon.c
index 43f3445c..3b8e1348 100644
--- a/test/dbus-daemon.c
+++ b/test/dbus-daemon.c
@@ -568,6 +568,60 @@ test_creds (Fixture *f,
}
static void
+test_processid (Fixture *f,
+ gconstpointer context)
+{
+ const char *unique = dbus_bus_get_unique_name (f->left_conn);
+ DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "GetConnectionUnixProcessID");
+ DBusPendingCall *pc;
+ DBusError error = DBUS_ERROR_INIT;
+ guint32 pid;
+
+ if (m == NULL)
+ g_error ("OOM");
+
+ if (!dbus_message_append_args (m,
+ DBUS_TYPE_STRING, &unique,
+ DBUS_TYPE_INVALID))
+ g_error ("OOM");
+
+ if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_message_unref (m);
+ m = NULL;
+
+ if (dbus_pending_call_get_completed (pc))
+ pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ g_assert_cmpstr (dbus_message_get_signature (m), ==, "u");
+
+ g_assert_true (dbus_message_get_args (m, &error,
+ DBUS_TYPE_UINT32, &pid,
+ DBUS_TYPE_INVALID));
+// g_assert_no_error (&error);
+
+ g_message ("GetConnectionUnixProcessID returned %u", pid);
+
+#ifdef G_OS_UNIX
+ g_assert_cmpuint (pid, ==, getpid ());
+#elif defined(G_OS_WIN32)
+ g_assert_cmpuint (pid, ==, GetCurrentProcessId ());
+#else
+ g_assert_not_reached ();
+#endif
+}
+
+static void
teardown (Fixture *f,
gconstpointer context G_GNUC_UNUSED)
{
@@ -632,6 +686,7 @@ main (int argc,
g_test_add ("/no-reply/timeout", Fixture, &finite_timeout_config,
setup, test_no_reply, teardown);
g_test_add ("/creds", Fixture, NULL, setup, test_creds, teardown);
+ g_test_add ("/processid", Fixture, NULL, setup, test_processid, teardown);
return g_test_run ();
}