diff options
author | Michael Chapman <mike@very.puzzling.org> | 2015-09-06 00:07:17 +1000 |
---|---|---|
committer | Michael Chapman <mike@very.puzzling.org> | 2015-09-06 00:07:17 +1000 |
commit | 88ced61bf9673407f4b15bf51b1b408fd78c149d (patch) | |
tree | b6cf57f054c3e65497b01100446a6667b3ef474d /src | |
parent | 403ed0e5c914f2a0a683403d8ba7eaf96e3ffcdf (diff) |
core: pass details to polkit for some unit actions
The following details are passed:
- unit: the primary name of the unit upon which the action was
invoked (i.e. after resolving any aliases);
- verb: one of 'start', 'stop', 'reload', 'restart', 'try-restart',
'reload-or-restart', 'reload-or-try-restart', 'kill',
'reset-failed', or 'set-property', corresponding to the
systemctl verb used to invoke the action.
Typical use of these details in a polkit policy rule might be:
// Allow alice to manage example.service;
// fall back to implicit authorization otherwise.
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.systemd1.manage-units" &&
action.lookup("unit") == "example.service" &&
subject.user == "alice") {
return polkit.Result.YES;
}
});
We also supply a custom polkit message that includes the unit's name and
the requested operation.
Diffstat (limited to 'src')
-rw-r--r-- | src/basic/util.h | 1 | ||||
-rw-r--r-- | src/core/dbus-unit.c | 70 | ||||
-rw-r--r-- | src/core/dbus.c | 5 | ||||
-rw-r--r-- | src/core/dbus.h | 1 |
4 files changed, 67 insertions, 10 deletions
diff --git a/src/basic/util.h b/src/basic/util.h index f8e32360f0..0fafebd52d 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -567,6 +567,7 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, void *arg); #define _(String) gettext (String) +#define N_(String) String void init_gettext(void); bool is_locale_utf8(void); diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 31016b6c4a..f9275ed935 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -391,6 +391,29 @@ static int property_get_load_error( return sd_bus_message_append(reply, "(ss)", e.name, e.message); } +static int bus_verify_manage_units_async_full( + Unit *u, + const char *verb, + int capability, + const char *polkit_message, + sd_bus_message *call, + sd_bus_error *error) { + + const char *details[9] = { + "unit", u->id, + "verb", verb, + }; + + if (polkit_message) { + details[4] = "polkit.message"; + details[5] = polkit_message; + details[6] = "polkit.gettext_domain"; + details[7] = GETTEXT_PACKAGE; + } + + return bus_verify_polkit_async(call, capability, "org.freedesktop.systemd1.manage-units", details, false, UID_INVALID, &u->manager->polkit_registry, error); +} + int bus_unit_method_start_generic( sd_bus_message *message, Unit *u, @@ -400,6 +423,14 @@ int bus_unit_method_start_generic( const char *smode; JobMode mode; + _cleanup_free_ char *verb = NULL; + static const char *const polkit_message_for_job[_JOB_TYPE_MAX] = { + [JOB_START] = N_("Authentication is required to start '$(unit)'."), + [JOB_STOP] = N_("Authentication is required to stop '$(unit)'."), + [JOB_RELOAD] = N_("Authentication is required to reload '$(unit)'."), + [JOB_RESTART] = N_("Authentication is required to restart '$(unit)'."), + [JOB_TRY_RESTART] = N_("Authentication is required to restart '$(unit)'."), + }; int r; assert(message); @@ -418,7 +449,20 @@ int bus_unit_method_start_generic( if (mode < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode); - r = bus_verify_manage_units_async(u->manager, message, error); + if (reload_if_possible) + verb = strjoin("reload-or-", job_type_to_string(job_type), NULL); + else + verb = strdup(job_type_to_string(job_type)); + if (!verb) + return -ENOMEM; + + r = bus_verify_manage_units_async_full( + u, + verb, + CAP_SYS_ADMIN, + job_type < _JOB_TYPE_MAX ? polkit_message_for_job[job_type] : NULL, + message, + error); if (r < 0) return r; if (r == 0) @@ -484,7 +528,13 @@ int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error * if (signo <= 0 || signo >= _NSIG) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range."); - r = bus_verify_manage_units_async_for_kill(u->manager, message, error); + r = bus_verify_manage_units_async_full( + u, + "kill", + CAP_KILL, + N_("Authentication is required to kill '$(unit)'."), + message, + error); if (r < 0) return r; if (r == 0) @@ -508,7 +558,13 @@ int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus if (r < 0) return r; - r = bus_verify_manage_units_async(u->manager, message, error); + r = bus_verify_manage_units_async_full( + u, + "reset-failed", + CAP_SYS_ADMIN, + N_("Authentication is required to reset the \"failed\" state of '$(unit)'."), + message, + error); if (r < 0) return r; if (r == 0) @@ -534,7 +590,13 @@ int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_b if (r < 0) return r; - r = bus_verify_manage_units_async(u->manager, message, error); + r = bus_verify_manage_units_async_full( + u, + "set-property", + CAP_SYS_ADMIN, + N_("Authentication is required to set properties on '$(unit)'."), + message, + error); if (r < 0) return r; if (r == 0) diff --git a/src/core/dbus.c b/src/core/dbus.c index a2ce880115..0a2180c6a7 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -1201,11 +1201,6 @@ int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", NULL, false, UID_INVALID, &m->polkit_registry, error); } -/* Same as bus_verify_manage_unit_async(), but checks for CAP_KILL instead of CAP_SYS_ADMIN */ -int bus_verify_manage_units_async_for_kill(Manager *m, sd_bus_message *call, sd_bus_error *error) { - return bus_verify_polkit_async(call, CAP_KILL, "org.freedesktop.systemd1.manage-units", NULL, false, UID_INVALID, &m->polkit_registry, error); -} - int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) { return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", NULL, false, UID_INVALID, &m->polkit_registry, error); } diff --git a/src/core/dbus.h b/src/core/dbus.h index 4832722069..4f06ad11c4 100644 --- a/src/core/dbus.h +++ b/src/core/dbus.h @@ -37,7 +37,6 @@ int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l); int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata); int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error); -int bus_verify_manage_units_async_for_kill(Manager *m, sd_bus_message *call, sd_bus_error *error); int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error); int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error); int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error); |