diff --git a/TODO b/TODO index 60ca96fe92..d8af5b15ea 100644 --- a/TODO +++ b/TODO @@ -30,8 +30,6 @@ Features: * logind: spawn user@..service on login -* logind: implement shutdown service - * logind: non-local X11 server handling * logind: use sysfs path in device hash table instead of syname, as soon as fb driver is fixed diff --git a/src/logind-dbus.c b/src/logind-dbus.c index 4321ffd900..f39941c9d2 100644 --- a/src/logind-dbus.c +++ b/src/logind-dbus.c @@ -28,6 +28,7 @@ #include "dbus-common.h" #include "strv.h" #include "polkit.h" +#include "special.h" #define BUS_MANAGER_INTERFACE \ " \n" \ @@ -112,6 +113,12 @@ " \n" \ " \n" \ " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ " \n" \ " \n" \ " \n" \ @@ -1255,6 +1262,92 @@ static DBusHandlerResult manager_message_handler( if (!reply) goto oom; + } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "PowerOff") || + dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Reboot")) { + dbus_bool_t interactive; + bool multiple_sessions; + DBusMessage *forward, *freply; + const char *name; + const char *mode = "replace"; + const char *action; + + if (!dbus_message_get_args( + message, + &error, + DBUS_TYPE_BOOLEAN, &interactive, + DBUS_TYPE_INVALID)) + return bus_send_error_reply(connection, message, &error, -EINVAL); + + multiple_sessions = hashmap_size(m->sessions) > 1; + + if (!multiple_sessions) { + Session *s; + + /* Hmm, there's only one session, but let's + * make sure it actually belongs to the user + * who is asking. If not, better be safe than + * sorry. */ + + s = hashmap_first(m->sessions); + if (s) { + unsigned long ul; + + ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), &error); + if (ul == (unsigned long) -1) + return bus_send_error_reply(connection, message, &error, -EIO); + + multiple_sessions = s->user->uid != ul; + } + } + + if (streq(dbus_message_get_member(message), "PowerOff")) { + if (multiple_sessions) + action = "org.freedesktop.login1.power-off-multiple-sessions"; + else + action = "org.freedesktop.login1.power-off"; + + name = SPECIAL_POWEROFF_TARGET; + } else { + if (multiple_sessions) + action = "org.freedesktop.login1.reboot-multiple-sessions"; + else + action = "org.freedesktop.login1.reboot"; + + name = SPECIAL_REBOOT_TARGET; + } + + r = verify_polkit(connection, message, action, interactive, &error); + if (r < 0) + return bus_send_error_reply(connection, message, &error, r); + + forward = dbus_message_new_method_call( + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartUnit"); + if (!forward) + return bus_send_error_reply(connection, message, NULL, -ENOMEM); + + if (!dbus_message_append_args(forward, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &mode, + DBUS_TYPE_INVALID)) { + dbus_message_unref(forward); + return bus_send_error_reply(connection, message, NULL, -ENOMEM); + } + + freply = dbus_connection_send_with_reply_and_block(connection, forward, -1, &error); + dbus_message_unref(forward); + + if (!freply) + return bus_send_error_reply(connection, message, &error, -EIO); + + dbus_message_unref(freply); + + reply = dbus_message_new_method_return(message); + if (!reply) + goto oom; + } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) { char *introspection = NULL; FILE *f; diff --git a/src/org.freedesktop.login1.policy.in b/src/org.freedesktop.login1.policy.in index 9482c87f1f..adc904886d 100644 --- a/src/org.freedesktop.login1.policy.in +++ b/src/org.freedesktop.login1.policy.in @@ -38,7 +38,47 @@ <_description>Flush device to seat attachments - <_message>Authentication is required to allow reseting how devices are attached to seats + <_message>Authentication is required to allow resetting how devices are attached to seats + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + <_description>Power off the system + <_message>Authentication is required to allow powering off the system + + auth_admin_keep + auth_admin_keep + yes + + + + + <_description>Power off the system when other users are logged in + <_message>Authentication is required to allow powering off the system while other users are logged in + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + <_description>Reboot the system + <_message>Authentication is required to allow rebooting the system + + auth_admin_keep + auth_admin_keep + yes + + + + + <_description>Reboot the system when other users are logged in + <_message>Authentication is required to allow rebooting the system while other users are logged in auth_admin_keep auth_admin_keep