]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-bus: port to split_user_at_host()
authorLennart Poettering <lennart@poettering.net>
Thu, 5 Jun 2025 09:52:47 +0000 (11:52 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 5 Jun 2025 10:49:35 +0000 (12:49 +0200)
src/libsystemd/sd-bus/sd-bus.c

index 07bf7003a2e153ff8d3a65d54f2abc29af3b44ee..e8c208cb82ebc5c6ec593280d9dd53bee6b9dd13 100644 (file)
@@ -1561,14 +1561,18 @@ _public_ int sd_bus_open_system_remote(sd_bus **ret, const char *host) {
 
 int bus_set_address_machine(sd_bus *b, RuntimeScope runtime_scope, const char *machine) {
         _cleanup_free_ char *a = NULL;
-        const char *rhs;
 
         assert(b);
         assert(machine);
 
-        rhs = strchr(machine, '@');
-        if (rhs || runtime_scope == RUNTIME_SCOPE_USER) {
-                _cleanup_free_ char *u = NULL, *eu = NULL, *erhs = NULL;
+        _cleanup_free_ char *u = NULL, *h = NULL;
+        int with_at;
+        with_at = split_user_at_host(machine, &u, &h);
+        if (with_at < 0)
+                return with_at;
+
+        if (with_at || runtime_scope == RUNTIME_SCOPE_USER) {
+                _cleanup_free_ char *eu = NULL, *eh = NULL;
 
                 /* If there's an "@" in the container specification, we'll connect as a user specified at its
                  * left hand side, which is useful in combination with user=true. This isn't as trivial as it
@@ -1578,43 +1582,38 @@ int bus_set_address_machine(sd_bus *b, RuntimeScope runtime_scope, const char *m
                  * into the container and acquire a PAM session there, and then invoke systemd-stdio-bridge
                  * in it, which propagates the bus transport to us. */
 
-                if (rhs) {
-                        if (rhs > machine)
-                                u = strndup(machine, rhs - machine);
-                        else
+                if (with_at) {
+                        if (!u) {
                                 u = getusername_malloc(); /* Empty user name, let's use the local one */
-                        if (!u)
-                                return -ENOMEM;
+                                if (!u)
+                                        return -ENOMEM;
+                        }
 
                         eu = bus_address_escape(u);
                         if (!eu)
                                 return -ENOMEM;
-
-                        rhs++;
-                } else {
-                        /* No "@" specified but we shall connect to the user instance? Then assume root (and
-                         * not a user named identically to the calling one). This means:
-                         *
-                         *     --machine=foobar --user    → connect to user bus of root user in container "foobar"
-                         *     --machine=@foobar --user   → connect to user bus of user named like the calling user in container "foobar"
-                         *
-                         * Why? so that behaviour for "--machine=foobar --system" is roughly similar to
-                         * "--machine=foobar --user": both times we unconditionally connect as root user
-                         * regardless what the calling user is. */
-
-                        rhs = machine;
                 }
 
-                if (!isempty(rhs)) {
-                        erhs = bus_address_escape(rhs);
-                        if (!erhs)
+                /* No "@" specified but we shall connect to the user instance? Then assume root (and
+                 * not a user named identically to the calling one). This means:
+                 *
+                 *     --machine=foobar --user    → connect to user bus of root user in container "foobar"
+                 *     --machine=@foobar --user   → connect to user bus of user named like the calling user in container "foobar"
+                 *
+                 * Why? so that behaviour for "--machine=foobar --system" is roughly similar to
+                 * "--machine=foobar --user": both times we unconditionally connect as root user
+                 * regardless what the calling user is. */
+
+                if (h) {
+                        eh = bus_address_escape(h);
+                        if (!eh)
                                 return -ENOMEM;
                 }
 
                 /* systemd-run -M… -PGq --wait -pUser=… -pPAMName=login systemd-stdio-bridge */
 
                 a = strjoin("unixexec:path=systemd-run,"
-                            "argv1=-M", erhs ?: ".host", ","
+                            "argv1=-M", eh ?: ".host", ","
                             "argv2=-PGq,"
                             "argv3=--wait,"
                             "argv4=-pUser%3d", eu ?: "root", ",",
@@ -1637,7 +1636,7 @@ int bus_set_address_machine(sd_bus *b, RuntimeScope runtime_scope, const char *m
                 /* Just a container name, we can go the simple way, and just join the container, and connect
                  * to the well-known path of the system bus there. */
 
-                e = bus_address_escape(machine);
+                e = bus_address_escape(h ?: ".host");
                 if (!e)
                         return -ENOMEM;