diff options
author | Lennart Poettering <lennart@poettering.net> | 2011-07-15 01:52:52 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2011-07-15 01:53:11 +0200 |
commit | 55af3897854263eddc0818d5cc4614ccbdae7f32 (patch) | |
tree | 19c6c69cdf911073847b5a131ebb96002a80ab64 | |
parent | e5fcb8528668a93404d0106770e5baaa54f58365 (diff) |
logind: enable PowerOff/Reboot calls
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | src/logind-dbus.c | 93 | ||||
-rw-r--r-- | src/org.freedesktop.login1.policy.in | 42 |
3 files changed, 134 insertions, 3 deletions
@@ -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 \ " <interface name=\"org.freedesktop.login1.Manager\">\n" \ @@ -112,6 +113,12 @@ " <method name=\"FlushDevices\">\n" \ " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \ " </method>\n" \ + " <method name=\"PowerOff\">\n" \ + " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \ + " </method>\n" \ + " <method name=\"Reboot\">\n" \ + " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \ + " </method>\n" \ " <signal name=\"SessionNew\">\n" \ " <arg name=\"id\" type=\"s\"/>\n" \ " <arg name=\"path\" type=\"o\"/>\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 @@ <action id="org.freedesktop.login1.flush-devices"> <_description>Flush device to seat attachments</_description> - <_message>Authentication is required to allow reseting how devices are attached to seats</_message> + <_message>Authentication is required to allow resetting how devices are attached to seats</_message> + <defaults> + <allow_any>auth_admin_keep</allow_any> + <allow_inactive>auth_admin_keep</allow_inactive> + <allow_active>auth_admin_keep</allow_active> + </defaults> + </action> + + <action id="org.freedesktop.login1.power-off"> + <_description>Power off the system</_description> + <_message>Authentication is required to allow powering off the system</_message> + <defaults> + <allow_any>auth_admin_keep</allow_any> + <allow_inactive>auth_admin_keep</allow_inactive> + <allow_active>yes</allow_active> + </defaults> + </action> + + <action id="org.freedesktop.login1.power-off-multiple-sessions"> + <_description>Power off the system when other users are logged in</_description> + <_message>Authentication is required to allow powering off the system while other users are logged in</_message> + <defaults> + <allow_any>auth_admin_keep</allow_any> + <allow_inactive>auth_admin_keep</allow_inactive> + <allow_active>auth_admin_keep</allow_active> + </defaults> + </action> + + <action id="org.freedesktop.login1.reboot"> + <_description>Reboot the system</_description> + <_message>Authentication is required to allow rebooting the system</_message> + <defaults> + <allow_any>auth_admin_keep</allow_any> + <allow_inactive>auth_admin_keep</allow_inactive> + <allow_active>yes</allow_active> + </defaults> + </action> + + <action id="org.freedesktop.login1.reboot-multiple-sessions"> + <_description>Reboot the system when other users are logged in</_description> + <_message>Authentication is required to allow rebooting the system while other users are logged in</_message> <defaults> <allow_any>auth_admin_keep</allow_any> <allow_inactive>auth_admin_keep</allow_inactive> |