|
|
4cad4c |
From ccdb8883c6ff0e72d5e221768af0718e25cbf177 Mon Sep 17 00:00:00 2001
|
|
|
4cad4c |
From: David Rheinsberg <david.rheinsberg@gmail.com>
|
|
|
4cad4c |
Date: Thu, 14 Mar 2019 13:34:13 +0100
|
|
|
4cad4c |
Subject: [PATCH] sd-bus: skip sending formatted UIDs via SASL
|
|
|
4cad4c |
|
|
|
4cad4c |
The dbus external authentication takes as optional argument the UID the
|
|
|
4cad4c |
sender wants to authenticate as. This uid is purely optional. The
|
|
|
4cad4c |
AF_UNIX socket already conveys the same information through the
|
|
|
4cad4c |
auxiliary socket data, so we really don't have to provide that
|
|
|
4cad4c |
information.
|
|
|
4cad4c |
|
|
|
4cad4c |
Unfortunately, there is no way to send empty arguments, since they are
|
|
|
4cad4c |
interpreted as "missing argument", which has a different meaning. The
|
|
|
4cad4c |
SASL negotiation thus changes from:
|
|
|
4cad4c |
|
|
|
4cad4c |
AUTH EXTERNAL <uid>
|
|
|
4cad4c |
NEGOTIATE_UNIX_FD (optional)
|
|
|
4cad4c |
BEGIN
|
|
|
4cad4c |
|
|
|
4cad4c |
to:
|
|
|
4cad4c |
|
|
|
4cad4c |
AUTH EXTERNAL
|
|
|
4cad4c |
DATA
|
|
|
4cad4c |
NEGOTIATE_UNIX_FD (optional)
|
|
|
4cad4c |
BEGIN
|
|
|
4cad4c |
|
|
|
4cad4c |
And thus the replies we expect as a client change from:
|
|
|
4cad4c |
|
|
|
4cad4c |
OK <server-id>
|
|
|
4cad4c |
AGREE_UNIX_FD (optional)
|
|
|
4cad4c |
|
|
|
4cad4c |
to:
|
|
|
4cad4c |
|
|
|
4cad4c |
DATA
|
|
|
4cad4c |
OK <server-id>
|
|
|
4cad4c |
AGREE_UNIX_FD (optional)
|
|
|
4cad4c |
|
|
|
4cad4c |
Since the old sd-bus server implementation used the wrong reply for
|
|
|
4cad4c |
"AUTH" requests that do not carry the arguments inlined, we decided to
|
|
|
4cad4c |
make sd-bus clients accept this as well. Hence, sd-bus now allows
|
|
|
4cad4c |
"OK <server-id>\r\n" replies instead of "DATA\r\n" replies.
|
|
|
4cad4c |
|
|
|
4cad4c |
Signed-off-by: David Rheinsberg <david.rheinsberg@gmail.com>
|
|
|
4cad4c |
(cherry picked from commit 1ed4723d38cd0d1423c8fe650f90fa86007ddf55)
|
|
|
4cad4c |
|
|
|
4cad4c |
Resolves: #1838081
|
|
|
4cad4c |
---
|
|
|
4cad4c |
src/libsystemd/sd-bus/bus-socket.c | 106 +++++++++++++++++------------
|
|
|
4cad4c |
1 file changed, 64 insertions(+), 42 deletions(-)
|
|
|
4cad4c |
|
|
|
4cad4c |
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
|
|
|
4cad4c |
index e505d43c6b..8813dd5efd 100644
|
|
|
4cad4c |
--- a/src/libsystemd/sd-bus/bus-socket.c
|
|
|
4cad4c |
+++ b/src/libsystemd/sd-bus/bus-socket.c
|
|
|
4cad4c |
@@ -162,17 +162,25 @@ static int bus_socket_write_auth(sd_bus *b) {
|
|
|
4cad4c |
}
|
|
|
4cad4c |
|
|
|
4cad4c |
static int bus_socket_auth_verify_client(sd_bus *b) {
|
|
|
4cad4c |
- char *e, *f, *start;
|
|
|
4cad4c |
+ char *d, *e, *f, *start;
|
|
|
4cad4c |
sd_id128_t peer;
|
|
|
4cad4c |
unsigned i;
|
|
|
4cad4c |
int r;
|
|
|
4cad4c |
|
|
|
4cad4c |
assert(b);
|
|
|
4cad4c |
|
|
|
4cad4c |
- /* We expect two response lines: "OK" and possibly
|
|
|
4cad4c |
- * "AGREE_UNIX_FD" */
|
|
|
4cad4c |
+ /*
|
|
|
4cad4c |
+ * We expect three response lines:
|
|
|
4cad4c |
+ * "DATA\r\n"
|
|
|
4cad4c |
+ * "OK <server-id>\r\n"
|
|
|
4cad4c |
+ * "AGREE_UNIX_FD\r\n" (optional)
|
|
|
4cad4c |
+ */
|
|
|
4cad4c |
|
|
|
4cad4c |
- e = memmem_safe(b->rbuffer, b->rbuffer_size, "\r\n", 2);
|
|
|
4cad4c |
+ d = memmem_safe(b->rbuffer, b->rbuffer_size, "\r\n", 2);
|
|
|
4cad4c |
+ if (!d)
|
|
|
4cad4c |
+ return 0;
|
|
|
4cad4c |
+
|
|
|
4cad4c |
+ e = memmem(d + 2, b->rbuffer_size - (d - (char*) b->rbuffer) - 2, "\r\n", 2);
|
|
|
4cad4c |
if (!e)
|
|
|
4cad4c |
return 0;
|
|
|
4cad4c |
|
|
|
4cad4c |
@@ -187,13 +195,30 @@ static int bus_socket_auth_verify_client(sd_bus *b) {
|
|
|
4cad4c |
start = e + 2;
|
|
|
4cad4c |
}
|
|
|
4cad4c |
|
|
|
4cad4c |
- /* Nice! We got all the lines we need. First check the OK
|
|
|
4cad4c |
- * line */
|
|
|
4cad4c |
+ /* Nice! We got all the lines we need. First check the DATA line. */
|
|
|
4cad4c |
+
|
|
|
4cad4c |
+ if (d - (char*) b->rbuffer == 4) {
|
|
|
4cad4c |
+ if (memcmp(b->rbuffer, "DATA", 4))
|
|
|
4cad4c |
+ return -EPERM;
|
|
|
4cad4c |
+ } else if (d - (char*) b->rbuffer == 3 + 32) {
|
|
|
4cad4c |
+ /*
|
|
|
4cad4c |
+ * Old versions of the server-side implementation of `sd-bus` replied with "OK <id>" to
|
|
|
4cad4c |
+ * "AUTH" requests from a client, even if the "AUTH" line did not contain inlined
|
|
|
4cad4c |
+ * arguments. Therefore, we also accept "OK <id>" here, even though it is technically the
|
|
|
4cad4c |
+ * wrong reply. We ignore the "<id>" parameter, though, since it has no real value.
|
|
|
4cad4c |
+ */
|
|
|
4cad4c |
+ if (memcmp(b->rbuffer, "OK ", 3))
|
|
|
4cad4c |
+ return -EPERM;
|
|
|
4cad4c |
+ } else {
|
|
|
4cad4c |
+ return -EPERM;
|
|
|
4cad4c |
+ }
|
|
|
4cad4c |
+
|
|
|
4cad4c |
+ /* Now check the OK line. */
|
|
|
4cad4c |
|
|
|
4cad4c |
- if (e - (char*) b->rbuffer != 3 + 32)
|
|
|
4cad4c |
+ if (e - d != 2 + 3 + 32)
|
|
|
4cad4c |
return -EPERM;
|
|
|
4cad4c |
|
|
|
4cad4c |
- if (memcmp(b->rbuffer, "OK ", 3))
|
|
|
4cad4c |
+ if (memcmp(d + 2, "OK ", 3))
|
|
|
4cad4c |
return -EPERM;
|
|
|
4cad4c |
|
|
|
4cad4c |
b->auth = b->anonymous_auth ? BUS_AUTH_ANONYMOUS : BUS_AUTH_EXTERNAL;
|
|
|
4cad4c |
@@ -201,8 +226,8 @@ static int bus_socket_auth_verify_client(sd_bus *b) {
|
|
|
4cad4c |
for (i = 0; i < 32; i += 2) {
|
|
|
4cad4c |
int x, y;
|
|
|
4cad4c |
|
|
|
4cad4c |
- x = unhexchar(((char*) b->rbuffer)[3 + i]);
|
|
|
4cad4c |
- y = unhexchar(((char*) b->rbuffer)[3 + i + 1]);
|
|
|
4cad4c |
+ x = unhexchar(d[2 + 3 + i]);
|
|
|
4cad4c |
+ y = unhexchar(d[2 + 3 + i + 1]);
|
|
|
4cad4c |
|
|
|
4cad4c |
if (x < 0 || y < 0)
|
|
|
4cad4c |
return -EINVAL;
|
|
|
4cad4c |
@@ -216,7 +241,7 @@ static int bus_socket_auth_verify_client(sd_bus *b) {
|
|
|
4cad4c |
|
|
|
4cad4c |
b->server_id = peer;
|
|
|
4cad4c |
|
|
|
4cad4c |
- /* And possibly check the second line, too */
|
|
|
4cad4c |
+ /* And possibly check the third line, too */
|
|
|
4cad4c |
|
|
|
4cad4c |
if (f)
|
|
|
4cad4c |
b->can_fds =
|
|
|
4cad4c |
@@ -616,42 +641,39 @@ static void bus_get_peercred(sd_bus *b) {
|
|
|
4cad4c |
}
|
|
|
4cad4c |
|
|
|
4cad4c |
static int bus_socket_start_auth_client(sd_bus *b) {
|
|
|
4cad4c |
- size_t l;
|
|
|
4cad4c |
- const char *auth_suffix, *auth_prefix;
|
|
|
4cad4c |
+ static const char sasl_auth_anonymous[] = {
|
|
|
4cad4c |
+ /*
|
|
|
4cad4c |
+ * We use an arbitrary trace-string for the ANONYMOUS authentication. It can be used by the
|
|
|
4cad4c |
+ * message broker to aid debugging of clients. We fully anonymize the connection and use a
|
|
|
4cad4c |
+ * static default.
|
|
|
4cad4c |
+ */
|
|
|
4cad4c |
+ "\0AUTH ANONYMOUS\r\n"
|
|
|
4cad4c |
+ /* HEX a n o n y m o u s */
|
|
|
4cad4c |
+ "DATA 616e6f6e796d6f7573\r\n"
|
|
|
4cad4c |
+ };
|
|
|
4cad4c |
+ static const char sasl_auth_external[] = {
|
|
|
4cad4c |
+ "\0AUTH EXTERNAL\r\n"
|
|
|
4cad4c |
+ "DATA\r\n"
|
|
|
4cad4c |
+ };
|
|
|
4cad4c |
+ static const char sasl_negotiate_unix_fd[] = {
|
|
|
4cad4c |
+ "NEGOTIATE_UNIX_FD\r\n"
|
|
|
4cad4c |
+ };
|
|
|
4cad4c |
+ static const char sasl_begin[] = {
|
|
|
4cad4c |
+ "BEGIN\r\n"
|
|
|
4cad4c |
+ };
|
|
|
4cad4c |
+ size_t i = 0;
|
|
|
4cad4c |
|
|
|
4cad4c |
assert(b);
|
|
|
4cad4c |
|
|
|
4cad4c |
- if (b->anonymous_auth) {
|
|
|
4cad4c |
- auth_prefix = "\0AUTH ANONYMOUS ";
|
|
|
4cad4c |
-
|
|
|
4cad4c |
- /* For ANONYMOUS auth we send some arbitrary "trace" string */
|
|
|
4cad4c |
- l = 9;
|
|
|
4cad4c |
- b->auth_buffer = hexmem("anonymous", l);
|
|
|
4cad4c |
- } else {
|
|
|
4cad4c |
- char text[DECIMAL_STR_MAX(uid_t) + 1];
|
|
|
4cad4c |
-
|
|
|
4cad4c |
- auth_prefix = "\0AUTH EXTERNAL ";
|
|
|
4cad4c |
-
|
|
|
4cad4c |
- xsprintf(text, UID_FMT, geteuid());
|
|
|
4cad4c |
-
|
|
|
4cad4c |
- l = strlen(text);
|
|
|
4cad4c |
- b->auth_buffer = hexmem(text, l);
|
|
|
4cad4c |
- }
|
|
|
4cad4c |
-
|
|
|
4cad4c |
- if (!b->auth_buffer)
|
|
|
4cad4c |
- return -ENOMEM;
|
|
|
4cad4c |
+ if (b->anonymous_auth)
|
|
|
4cad4c |
+ b->auth_iovec[i++] = IOVEC_MAKE((char*) sasl_auth_anonymous, sizeof(sasl_auth_anonymous) - 1);
|
|
|
4cad4c |
+ else
|
|
|
4cad4c |
+ b->auth_iovec[i++] = IOVEC_MAKE((char*) sasl_auth_external, sizeof(sasl_auth_external) - 1);
|
|
|
4cad4c |
|
|
|
4cad4c |
if (b->accept_fd)
|
|
|
4cad4c |
- auth_suffix = "\r\nNEGOTIATE_UNIX_FD\r\nBEGIN\r\n";
|
|
|
4cad4c |
- else
|
|
|
4cad4c |
- auth_suffix = "\r\nBEGIN\r\n";
|
|
|
4cad4c |
-
|
|
|
4cad4c |
- b->auth_iovec[0].iov_base = (void*) auth_prefix;
|
|
|
4cad4c |
- b->auth_iovec[0].iov_len = 1 + strlen(auth_prefix + 1);
|
|
|
4cad4c |
- b->auth_iovec[1].iov_base = (void*) b->auth_buffer;
|
|
|
4cad4c |
- b->auth_iovec[1].iov_len = l * 2;
|
|
|
4cad4c |
- b->auth_iovec[2].iov_base = (void*) auth_suffix;
|
|
|
4cad4c |
- b->auth_iovec[2].iov_len = strlen(auth_suffix);
|
|
|
4cad4c |
+ b->auth_iovec[i++] = IOVEC_MAKE_STRING(sasl_negotiate_unix_fd);
|
|
|
4cad4c |
+
|
|
|
4cad4c |
+ b->auth_iovec[i++] = IOVEC_MAKE_STRING(sasl_begin);
|
|
|
4cad4c |
|
|
|
4cad4c |
return bus_socket_write_auth(b);
|
|
|
4cad4c |
}
|