summaryrefslogtreecommitdiff
path: root/src/libsystemd/sd-bus
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2019-03-14 15:42:03 +0100
committerGitHub <noreply@github.com>2019-03-14 15:42:03 +0100
commitbeb6196982148a7403cf56db7399909a0da049ee (patch)
treedce3026ac5181a2b83007a36698e28f8eefbf9db /src/libsystemd/sd-bus
parent9e9213cd08ca82d6cc3565f753f343b1739cb263 (diff)
parent1ed4723d38cd0d1423c8fe650f90fa86007ddf55 (diff)
downloadsystemd-beb6196982148a7403cf56db7399909a0da049ee.tar.gz
Merge pull request #11785 from dvdhrm/implicit-sasl
sd-bus: allow cross-uid-namespace connections
Diffstat (limited to 'src/libsystemd/sd-bus')
-rw-r--r--src/libsystemd/sd-bus/bus-socket.c119
1 files changed, 77 insertions, 42 deletions
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index 89ac503ab8..790b64010a 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -158,17 +158,25 @@ static int bus_socket_write_auth(sd_bus *b) {
}
static int bus_socket_auth_verify_client(sd_bus *b) {
- char *e, *f, *start;
+ char *d, *e, *f, *start;
sd_id128_t peer;
unsigned i;
int r;
assert(b);
- /* We expect two response lines: "OK" and possibly
- * "AGREE_UNIX_FD" */
+ /*
+ * We expect three response lines:
+ * "DATA\r\n"
+ * "OK <server-id>\r\n"
+ * "AGREE_UNIX_FD\r\n" (optional)
+ */
- e = memmem_safe(b->rbuffer, b->rbuffer_size, "\r\n", 2);
+ d = memmem_safe(b->rbuffer, b->rbuffer_size, "\r\n", 2);
+ if (!d)
+ return 0;
+
+ e = memmem(d + 2, b->rbuffer_size - (d - (char*) b->rbuffer) - 2, "\r\n", 2);
if (!e)
return 0;
@@ -183,13 +191,30 @@ static int bus_socket_auth_verify_client(sd_bus *b) {
start = e + 2;
}
- /* Nice! We got all the lines we need. First check the OK
- * line */
+ /* Nice! We got all the lines we need. First check the DATA line. */
+
+ if (d - (char*) b->rbuffer == 4) {
+ if (memcmp(b->rbuffer, "DATA", 4))
+ return -EPERM;
+ } else if (d - (char*) b->rbuffer == 3 + 32) {
+ /*
+ * Old versions of the server-side implementation of `sd-bus` replied with "OK <id>" to
+ * "AUTH" requests from a client, even if the "AUTH" line did not contain inlined
+ * arguments. Therefore, we also accept "OK <id>" here, even though it is technically the
+ * wrong reply. We ignore the "<id>" parameter, though, since it has no real value.
+ */
+ if (memcmp(b->rbuffer, "OK ", 3))
+ return -EPERM;
+ } else {
+ return -EPERM;
+ }
+
+ /* Now check the OK line. */
- if (e - (char*) b->rbuffer != 3 + 32)
+ if (e - d != 2 + 3 + 32)
return -EPERM;
- if (memcmp(b->rbuffer, "OK ", 3))
+ if (memcmp(d + 2, "OK ", 3))
return -EPERM;
b->auth = b->anonymous_auth ? BUS_AUTH_ANONYMOUS : BUS_AUTH_EXTERNAL;
@@ -197,8 +222,8 @@ static int bus_socket_auth_verify_client(sd_bus *b) {
for (i = 0; i < 32; i += 2) {
int x, y;
- x = unhexchar(((char*) b->rbuffer)[3 + i]);
- y = unhexchar(((char*) b->rbuffer)[3 + i + 1]);
+ x = unhexchar(d[2 + 3 + i]);
+ y = unhexchar(d[2 + 3 + i + 1]);
if (x < 0 || y < 0)
return -EINVAL;
@@ -212,7 +237,7 @@ static int bus_socket_auth_verify_client(sd_bus *b) {
b->server_id = peer;
- /* And possibly check the second line, too */
+ /* And possibly check the third line, too */
if (f)
b->can_fds =
@@ -386,26 +411,36 @@ static int bus_socket_auth_verify_server(sd_bus *b) {
if (line_begins(line, l, "AUTH ANONYMOUS")) {
- r = verify_anonymous_token(b, line + 14, l - 14);
+ r = verify_anonymous_token(b,
+ line + strlen("AUTH ANONYMOUS"),
+ l - strlen("AUTH ANONYMOUS"));
if (r < 0)
return r;
if (r == 0)
r = bus_socket_auth_write(b, "REJECTED\r\n");
else {
b->auth = BUS_AUTH_ANONYMOUS;
- r = bus_socket_auth_write_ok(b);
+ if (l <= strlen("AUTH ANONYMOUS"))
+ r = bus_socket_auth_write(b, "DATA\r\n");
+ else
+ r = bus_socket_auth_write_ok(b);
}
} else if (line_begins(line, l, "AUTH EXTERNAL")) {
- r = verify_external_token(b, line + 13, l - 13);
+ r = verify_external_token(b,
+ line + strlen("AUTH EXTERNAL"),
+ l - strlen("AUTH EXTERNAL"));
if (r < 0)
return r;
if (r == 0)
r = bus_socket_auth_write(b, "REJECTED\r\n");
else {
b->auth = BUS_AUTH_EXTERNAL;
- r = bus_socket_auth_write_ok(b);
+ if (l <= strlen("AUTH EXTERNAL"))
+ r = bus_socket_auth_write(b, "DATA\r\n");
+ else
+ r = bus_socket_auth_write_ok(b);
}
} else if (line_begins(line, l, "AUTH"))
@@ -601,39 +636,39 @@ static void bus_get_peercred(sd_bus *b) {
}
static int bus_socket_start_auth_client(sd_bus *b) {
- size_t l;
- const char *auth_suffix, *auth_prefix;
+ static const char sasl_auth_anonymous[] = {
+ /*
+ * We use an arbitrary trace-string for the ANONYMOUS authentication. It can be used by the
+ * message broker to aid debugging of clients. We fully anonymize the connection and use a
+ * static default.
+ */
+ "\0AUTH ANONYMOUS\r\n"
+ /* HEX a n o n y m o u s */
+ "DATA 616e6f6e796d6f7573\r\n"
+ };
+ static const char sasl_auth_external[] = {
+ "\0AUTH EXTERNAL\r\n"
+ "DATA\r\n"
+ };
+ static const char sasl_negotiate_unix_fd[] = {
+ "NEGOTIATE_UNIX_FD\r\n"
+ };
+ static const char sasl_begin[] = {
+ "BEGIN\r\n"
+ };
+ size_t i = 0;
assert(b);
- if (b->anonymous_auth) {
- auth_prefix = "\0AUTH ANONYMOUS ";
-
- /* For ANONYMOUS auth we send some arbitrary "trace" string */
- l = 9;
- b->auth_buffer = hexmem("anonymous", l);
- } else {
- char text[DECIMAL_STR_MAX(uid_t) + 1];
-
- auth_prefix = "\0AUTH EXTERNAL ";
-
- xsprintf(text, UID_FMT, geteuid());
-
- l = strlen(text);
- b->auth_buffer = hexmem(text, l);
- }
-
- if (!b->auth_buffer)
- return -ENOMEM;
+ if (b->anonymous_auth)
+ b->auth_iovec[i++] = IOVEC_MAKE((char*) sasl_auth_anonymous, sizeof(sasl_auth_anonymous) - 1);
+ else
+ b->auth_iovec[i++] = IOVEC_MAKE((char*) sasl_auth_external, sizeof(sasl_auth_external) - 1);
if (b->accept_fd)
- auth_suffix = "\r\nNEGOTIATE_UNIX_FD\r\nBEGIN\r\n";
- else
- auth_suffix = "\r\nBEGIN\r\n";
+ b->auth_iovec[i++] = IOVEC_MAKE_STRING(sasl_negotiate_unix_fd);
- b->auth_iovec[0] = IOVEC_MAKE((void*) auth_prefix, 1 + strlen(auth_prefix + 1));
- b->auth_iovec[1] = IOVEC_MAKE(b->auth_buffer, l * 2);
- b->auth_iovec[2] = IOVEC_MAKE_STRING(auth_suffix);
+ b->auth_iovec[i++] = IOVEC_MAKE_STRING(sasl_begin);
return bus_socket_write_auth(b);
}