STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_token_uri, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_fido2_device, strv_freep);
+static const BusLocator *bus_mgr;
+
static bool identity_properties_specified(void) {
return
arg_identity ||
if (r < 0)
return r;
- r = bus_call_method(bus, bus_home_mgr, "ListHomes", &error, &reply, NULL);
+ r = bus_call_method(bus, bus_mgr, "ListHomes", &error, &reply, NULL);
if (r < 0)
return log_error_errno(r, "Failed to list homes: %s", bus_error_message(&error, r));
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- r = bus_message_new_method_call(bus, &m, bus_home_mgr, "ActivateHome");
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "ActivateHome");
if (r < 0)
return bus_log_create_error(r);
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- r = bus_message_new_method_call(bus, &m, bus_home_mgr, "DeactivateHome");
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "DeactivateHome");
if (r < 0)
return bus_log_create_error(r);
continue;
}
- r = bus_call_method(bus, bus_home_mgr, "GetUserRecordByName", &error, &reply, "s", *i);
+ r = bus_call_method(bus, bus_mgr, "GetUserRecordByName", &error, &reply, "s", *i);
} else
- r = bus_call_method(bus, bus_home_mgr, "GetUserRecordByUID", &error, &reply, "u", (uint32_t) uid);
+ r = bus_call_method(bus, bus_mgr, "GetUserRecordByUID", &error, &reply, "u", (uint32_t) uid);
if (r < 0) {
log_error_errno(r, "Failed to inspect home: %s", bus_error_message(&error, r));
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- r = bus_message_new_method_call(bus, &m, bus_home_mgr, "AuthenticateHome");
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "AuthenticateHome");
if (r < 0)
return bus_log_create_error(r);
if (r < 0)
return log_error_errno(r, "Failed to format user record: %m");
- r = bus_message_new_method_call(bus, &m, bus_home_mgr, "CreateHome");
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "CreateHome");
if (r < 0)
return bus_log_create_error(r);
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- r = bus_message_new_method_call(bus, &m, bus_home_mgr, "RemoveHome");
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "RemoveHome");
if (r < 0)
return bus_log_create_error(r);
if (!identity_properties_specified())
return log_error_errno(SYNTHETIC_ERRNO(EALREADY), "No field to change specified.");
- r = bus_call_method(bus, bus_home_mgr, "GetUserRecordByName", &error, &reply, "s", username);
+ r = bus_call_method(bus, bus_mgr, "GetUserRecordByName", &error, &reply, "s", username);
if (r < 0)
return log_error_errno(r, "Failed to acquire user home record: %s", bus_error_message(&error, r));
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *formatted = NULL;
- r = bus_message_new_method_call(bus, &m, bus_home_mgr, "UpdateHome");
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "UpdateHome");
if (r < 0)
return bus_log_create_error(r);
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- r = bus_message_new_method_call(bus, &m, bus_home_mgr, "ResizeHome");
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "ResizeHome");
if (r < 0)
return bus_log_create_error(r);
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- r = bus_message_new_method_call(bus, &m, bus_home_mgr, "ChangePasswordHome");
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "ChangePasswordHome");
if (r < 0)
return bus_log_create_error(r);
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- r = bus_message_new_method_call(bus, &m, bus_home_mgr, "ChangePasswordHome");
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "ChangePasswordHome");
if (r < 0)
return bus_log_create_error(r);
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- r = bus_message_new_method_call(bus, &m, bus_home_mgr, "ResizeHome");
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "ResizeHome");
if (r < 0)
return bus_log_create_error(r);
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- r = bus_message_new_method_call(bus, &m, bus_home_mgr, "LockHome");
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "LockHome");
if (r < 0)
return bus_log_create_error(r);
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- r = bus_message_new_method_call(bus, &m, bus_home_mgr, "UnlockHome");
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "UnlockHome");
if (r < 0)
return bus_log_create_error(r);
return log_oom();
for (;;) {
- r = bus_message_new_method_call(bus, &m, bus_home_mgr, "AcquireHome");
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "AcquireHome");
if (r < 0)
return bus_log_create_error(r);
}
}
- r = bus_call_method(bus, bus_home_mgr, "GetHomeByName", &error, &reply, "s", argv[1]);
+ r = bus_call_method(bus, bus_mgr, "GetHomeByName", &error, &reply, "s", argv[1]);
if (r < 0)
return log_error_errno(r, "Failed to inspect home: %s", bus_error_message(&error, r));
/* Close the fd that pings the home now. */
acquired_fd = safe_close(acquired_fd);
- r = bus_message_new_method_call(bus, &m, bus_home_mgr, "ReleaseHome");
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "ReleaseHome");
if (r < 0)
return bus_log_create_error(r);
if (r < 0)
return r;
- r = bus_message_new_method_call(bus, &m, bus_home_mgr, "LockAllHomes");
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "LockAllHomes");
if (r < 0)
return bus_log_create_error(r);
return 1;
}
+static int redirect_bus_mgr(void) {
+ const char *suffix;
+
+ /* Talk to a different service if that's requested. (The same env var is also understood by homed, so
+ * that it is relatively easily possible to invoke a second instance of homed for debug purposes and
+ * have homectl talk to it, without colliding with the host version. This is handy when operating
+ * from a homed-managed account.) */
+
+ suffix = getenv("SYSTEMD_HOME_DEBUG_SUFFIX");
+ if (suffix) {
+ static BusLocator locator = {
+ .path = "/org/freedesktop/home1",
+ .interface = "org.freedesktop.home1.Manager",
+ };
+
+ /* Yes, we leak this memory, but there's little point to collect this, given that we only do
+ * this in a debug environment, do it only once, and the string shall live for out entire
+ * process runtime. */
+
+ locator.destination = strjoin("org.freedesktop.home1.", suffix);
+ if (!locator.destination)
+ return log_oom();
+
+ bus_mgr = &locator;
+ } else
+ bus_mgr = bus_home_mgr;
+
+ return 0;
+}
+
static int run(int argc, char *argv[]) {
static const Verb verbs[] = {
{ "help", VERB_ANY, VERB_ANY, 0, help },
log_setup_cli();
+ r = redirect_bus_mgr();
+ if (r < 0)
+ return r;
+
r = parse_argv(argc, argv);
if (r <= 0)
return r;
hashmap_free(m->public_keys);
varlink_server_unref(m->varlink_server);
+ free(m->userdb_service);
free(m->default_file_system_type);
}
static int manager_connect_bus(Manager *m) {
+ const char *suffix, *busname;
int r;
assert(m);
if (r < 0)
return r;
- r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.home1", 0, NULL, NULL);
+ suffix = getenv("SYSTEMD_HOME_DEBUG_SUFFIX");
+ if (suffix)
+ busname = strjoina("org.freedesktop.home1.", suffix);
+ else
+ busname = "org.freedesktop.home1";
+
+ r = sd_bus_request_name_async(m->bus, NULL, busname, 0, NULL, NULL);
if (r < 0)
return log_error_errno(r, "Failed to request name: %m");
}
static int manager_bind_varlink(Manager *m) {
+ const char *suffix, *socket_path;
int r;
assert(m);
(void) mkdir_p("/run/systemd/userdb", 0755);
- r = varlink_server_listen_address(m->varlink_server, "/run/systemd/userdb/io.systemd.Home", 0666);
+ /* To make things easier to debug, when working from a homed managed home directory, let's optionally
+ * use a different varlink socket name */
+ suffix = getenv("SYSTEMD_HOME_DEBUG_SUFFIX");
+ if (suffix)
+ socket_path = strjoina("/run/systemd/userdb/io.systemd.Home.", suffix);
+ else
+ socket_path = "/run/systemd/userdb/io.systemd.Home";
+
+ r = varlink_server_listen_address(m->varlink_server, socket_path, 0666);
if (r < 0)
return log_error_errno(r, "Failed to bind to varlink socket: %m");
if (r < 0)
return log_error_errno(r, "Failed to attach varlink connection to event loop: %m");
+ assert(!m->userdb_service);
+ m->userdb_service = strdup(basename(socket_path));
+ if (!m->userdb_service)
+ return log_oom();
+
+ /* Avoid recursion */
+ if (setenv("SYSTEMD_BYPASS_USERDB", m->userdb_service, 1) < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set $SYSTEMD_BYPASS_USERDB: %m");
+
return 0;
}
.un.sun_family = AF_UNIX,
.un.sun_path = "/run/systemd/home/notify",
};
+ const char *suffix;
int r;
assert(m);
assert(!m->notify_socket_event_source);
+ suffix = getenv("SYSTEMD_HOME_DEBUG_SUFFIX");
+ if (suffix) {
+ const char *unix_path;
+
+ unix_path = strjoina("/run/systemd/home/notify.", suffix);
+ r = sockaddr_un_set_path(&sa.un, unix_path);
+ if (r < 0)
+ return log_error_errno(r, "Socket path %s does not fit in sockaddr_un: %m", unix_path);
+ }
+
fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (fd < 0)
return log_error_errno(errno, "Failed to create listening socket: %m");