summaryrefslogtreecommitdiff
path: root/polkitd
diff options
context:
space:
mode:
authorDavid Zeuthen <david@fubar.dk>2006-06-05 23:39:00 +0000
committerDavid Zeuthen <david@fubar.dk>2006-06-05 23:39:00 +0000
commit1c3d5691ad444ae2849d079e3745d6b476614623 (patch)
tree0692c2f1eb10b1ea952449d09782cccb826588a6 /polkitd
parent12d20fc8a71b59584f5636ac4dc85c36e45c0157 (diff)
downloadpolkit-1c3d5691ad444ae2849d079e3745d6b476614623.tar.gz
Lots of changes! Almost ready for 0.2 release.
Diffstat (limited to 'polkitd')
-rwxr-xr-xpolkitd/PolicyKit.in10
-rw-r--r--polkitd/main.c102
-rw-r--r--polkitd/policy.c480
-rw-r--r--polkitd/policy.h97
-rw-r--r--polkitd/polkit-manager.c375
-rw-r--r--polkitd/polkit-manager.h11
-rw-r--r--polkitd/polkit-session.c61
-rw-r--r--polkitd/polkit-session.h7
8 files changed, 994 insertions, 149 deletions
diff --git a/polkitd/PolicyKit.in b/polkitd/PolicyKit.in
index 104386b..023fd7f 100755
--- a/polkitd/PolicyKit.in
+++ b/polkitd/PolicyKit.in
@@ -23,6 +23,13 @@ servicename=PolicyKit
RETVAL=0
+cleanup_state_dir()
+{
+ # Clean out all files in
+ rm -f @LOCALSTATEDIR@/run/polkit-console/*
+ mkdir -p @LOCALSTATEDIR@/run/polkit-console
+}
+
start() {
echo -n $"Starting PolicyKit daemon: "
daemon --check $servicename $processname
@@ -46,6 +53,7 @@ stop() {
# See how we were called.
case "$1" in
start)
+ cleanup_state_dir
start
;;
stop)
@@ -57,13 +65,11 @@ case "$1" in
;;
restart)
stop
- sleep 3
start
;;
condrestart)
if [ -f @LOCALSTATEDIR@/lock/subsys/$servicename ]; then
stop
- sleep 3
start
fi
;;
diff --git a/polkitd/main.c b/polkitd/main.c
index f996540..8286670 100644
--- a/polkitd/main.c
+++ b/polkitd/main.c
@@ -33,6 +33,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <signal.h>
#include <dbus/dbus-glib.h>
@@ -69,18 +70,61 @@ delete_pid (void)
unlink (POLKITD_PID_FILE);
}
+static int sigusr1_unix_signal_pipe_fds[2];
+static GIOChannel *sigusr1_iochn = NULL;
+static PolicyKitManager *manager = NULL;
+
+static void
+handle_sigusr1 (int value)
+{
+ ssize_t written;
+ static char marker[1] = {'S'};
+
+ written = write (sigusr1_unix_signal_pipe_fds[1], marker, 1);
+}
+
+static gboolean
+sigusr1_iochn_data (GIOChannel *source,
+ GIOCondition condition,
+ gpointer user_data)
+{
+ GError *err = NULL;
+ gchar data[1];
+ gsize bytes_read;
+
+ /* Empty the pipe */
+ if (G_IO_STATUS_NORMAL !=
+ g_io_channel_read_chars (source, data, 1, &bytes_read, &err)) {
+ g_warning ("Error emptying sigusr1 pipe: %s", err->message);
+ g_error_free (err);
+ goto out;
+ }
+
+ g_debug ("Caught SIGUSR1");
+ if (manager != NULL) {
+ polkit_manager_update_desktop_console_privileges (manager);
+ }
+
+out:
+ return TRUE;
+}
+
+
int
main (int argc, char *argv[])
{
DBusGConnection *bus;
DBusGProxy *bus_proxy;
GError *error = NULL;
- PolicyKitManager *manager;
GMainLoop *mainloop;
guint request_name_result;
int ret;
gboolean no_daemon = FALSE;
gboolean is_verbose = FALSE;
+ int pf;
+ ssize_t written;
+ char pid[9];
+ guint sigusr1_iochn_listener_source_id;
static const struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"no-daemon", no_argument, NULL, 'n'},
@@ -131,10 +175,6 @@ main (int argc, char *argv[])
if (!no_daemon) {
int child_pid;
int dev_null_fd;
- int pf;
- ssize_t written;
- char pid[9];
-
if (chdir ("/") < 0) {
g_warning ("Could not chdir to /: %s", strerror (errno));
@@ -170,21 +210,21 @@ main (int argc, char *argv[])
/* create session */
setsid ();
-
- /* remove old pid file */
- unlink (POLKITD_PID_FILE);
-
- /* make a new pid file */
- if ((pf = open (POLKITD_PID_FILE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644)) > 0) {
- snprintf (pid, sizeof(pid), "%lu\n", (long unsigned) getpid ());
- written = write (pf, pid, strlen(pid));
- close (pf);
- g_atexit (delete_pid);
- }
} else {
g_debug (("not becoming a daemon"));
}
+ /* remove old pid file */
+ unlink (POLKITD_PID_FILE);
+
+ /* make a new pid file */
+ if ((pf = open (POLKITD_PID_FILE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644)) > 0) {
+ snprintf (pid, sizeof(pid), "%lu\n", (long unsigned) getpid ());
+ written = write (pf, pid, strlen(pid));
+ close (pf);
+ g_atexit (delete_pid);
+ }
+
g_type_init ();
dbus_g_object_type_install_info (POLKIT_TYPE_MANAGER, &dbus_glib_polkit_manager_object_info);
@@ -194,6 +234,30 @@ main (int argc, char *argv[])
mainloop = g_main_loop_new (NULL, FALSE);
+ /* Listen for SIGUSR1 - UNIX signal handlers are evil though,
+ * so set up a pipe to transmit the signal.
+ */
+
+ /* create pipe */
+ if (pipe (sigusr1_unix_signal_pipe_fds) != 0) {
+ g_warning ("Could not setup pipe, errno=%d", errno);
+ goto out;
+ }
+
+ /* setup glib handler - 0 is for reading, 1 is for writing */
+ sigusr1_iochn = g_io_channel_unix_new (sigusr1_unix_signal_pipe_fds[0]);
+ if (sigusr1_iochn == NULL) {
+ g_warning ("Could not create GIOChannel");
+ goto out;
+ }
+
+ /* get callback when there is data to read */
+ sigusr1_iochn_listener_source_id = g_io_add_watch (
+ sigusr1_iochn, G_IO_IN, sigusr1_iochn_data, NULL);
+
+ /* setup UNIX signal handler for SIGUSR1 */
+ signal (SIGUSR1, handle_sigusr1);
+
bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
if (bus == NULL) {
g_warning ("Couldn't connect to system bus: %s", error->message);
@@ -222,9 +286,15 @@ main (int argc, char *argv[])
manager = polkit_manager_new (bus, bus_proxy);
+ if (manager == NULL) {
+ g_warning ("Could not construct manager object; bailing out");
+ goto out;
+ }
g_debug ("service running");
+ polkit_manager_update_desktop_console_privileges (manager);
+
g_main_loop_run (mainloop);
ret = 0;
diff --git a/polkitd/policy.c b/polkitd/policy.c
index 95032ec..32c8f78 100644
--- a/polkitd/policy.c
+++ b/polkitd/policy.c
@@ -171,7 +171,7 @@ txt_backend_read_policy (const char *policy,
goto out;
}
- value = g_key_file_get_string (keyfile, "Policy", key, &error);
+ value = g_key_file_get_string (keyfile, "Privilege", key, &error);
if (value == NULL) {
g_warning ("Cannot get key '%s' in group 'Policy' in file '%s': %s", key, path, error->message);
g_error_free (error);
@@ -295,6 +295,115 @@ out:
return rc;
}
+
+static PolicyResult
+txt_backend_read_list (const char *policy,
+ const char *key,
+ GList **result)
+{
+ int i;
+ GKeyFile *keyfile;
+ GError *error;
+ PolicyResult rc;
+ char *path;
+ char *value = NULL;
+ char **tokens = NULL;
+ GList *res;
+ char *token;
+
+ error = NULL;
+ rc = POLICY_RESULT_ERROR;
+ res = NULL;
+ *result = NULL;
+
+ keyfile = g_key_file_new ();
+ path = g_strdup_printf ("%s/%s.privilege", policy_directory, policy);
+ /*g_message ("Loading %s", path);*/
+ if (!g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, &error)) {
+ g_warning ("Couldn't open key-file '%s': %s", path, error->message);
+ g_error_free (error);
+ rc = POLICY_RESULT_NO_SUCH_POLICY;
+ goto out;
+ }
+
+ value = g_key_file_get_string (keyfile, "Privilege", key, &error);
+ if (value == NULL) {
+ g_warning ("Cannot get key '%s' in group 'Policy' in file '%s': %s", key, path, error->message);
+ g_error_free (error);
+ rc = POLICY_RESULT_ERROR;
+ goto out;
+ }
+
+ /*g_message ("value = '%s'", value);*/
+ tokens = g_strsplit (value, " ", 0);
+ for (i = 0; tokens[i] != NULL; i++) {
+ token = tokens[i];
+ /*g_message (" token = '%s'", token);*/
+
+ res = g_list_append (res, g_strdup (token));
+ }
+
+ *result = res;
+ rc = POLICY_RESULT_OK;
+
+out:
+ g_strfreev (tokens);
+ g_free (value);
+
+ g_key_file_free (keyfile);
+ g_free (path);
+
+ return rc;
+}
+
+static PolicyResult
+txt_backend_read_word (const char *policy,
+ const char *key,
+ char **result)
+{
+ GKeyFile *keyfile;
+ GError *error;
+ PolicyResult rc;
+ char *path;
+ char *value = NULL;
+
+ error = NULL;
+ rc = POLICY_RESULT_ERROR;
+ *result = NULL;
+
+ keyfile = g_key_file_new ();
+ path = g_strdup_printf ("%s/%s.privilege", policy_directory, policy);
+ /*g_message ("Loading %s", path);*/
+ if (!g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, &error)) {
+ g_warning ("Couldn't open key-file '%s': %s", path, error->message);
+ g_error_free (error);
+ rc = POLICY_RESULT_NO_SUCH_POLICY;
+ goto out;
+ }
+
+ value = g_key_file_get_string (keyfile, "Privilege", key, &error);
+ if (value == NULL) {
+ g_warning ("Cannot get key '%s' in group 'Policy' in file '%s': %s", key, path, error->message);
+ g_error_free (error);
+ rc = POLICY_RESULT_ERROR;
+ goto out;
+ }
+
+ /*g_message ("value = '%s'", value);*/
+
+ *result = g_strdup (value);
+
+ rc = POLICY_RESULT_OK;
+
+out:
+ g_free (value);
+
+ g_key_file_free (keyfile);
+ g_free (path);
+
+ return rc;
+}
+
static PolicyResult
policy_get_whitelist (const char *policy,
GList **result)
@@ -309,6 +418,20 @@ policy_get_blacklist (const char *policy,
return txt_backend_read_policy (policy, "Deny", result);
}
+static PolicyResult
+policy_get_sufficient_privileges (const char *policy,
+ GList **result)
+{
+ return txt_backend_read_list (policy, "SufficientPrivileges", result);
+}
+
+static PolicyResult
+policy_get_required_privileges (const char *policy,
+ GList **result)
+{
+ return txt_backend_read_list (policy, "RequiredPrivileges", result);
+}
+
/** Return all elements in the white-list for a policy
*
* @param result On success set to a list of dynamically allocated strings.
@@ -352,6 +475,177 @@ error:
return POLICY_RESULT_ERROR;
}
+PolicyResult
+policy_get_auth_details_for_policy (uid_t uid,
+ const char *policy,
+ const char *resource,
+ gboolean *out_auth_can_obtain,
+ gboolean *out_auth_can_obtain_is_temporary,
+ gboolean *out_auth_can_grant,
+ gboolean *out_auth_obtain_requires_root,
+ gpointer have_temp_privilege_userdata,
+ HaveTempPrivCB have_temp_privilege)
+{
+ PolicyResult res;
+ GList *required_privs;
+ GList *l;
+ char *can_obtain_word;
+ char *can_grant_word;
+ char *obtain_requires_root_word;
+
+ required_privs = NULL;
+ can_obtain_word = NULL;
+ can_grant_word = NULL;
+
+ *out_auth_can_obtain = FALSE;
+ *out_auth_can_obtain_is_temporary = FALSE;
+ *out_auth_can_grant = FALSE;
+ *out_auth_obtain_requires_root = TRUE;
+
+ res = POLICY_RESULT_ERROR;
+
+ res = txt_backend_read_word (policy, "CanObtain", &can_obtain_word);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ res = txt_backend_read_word (policy, "CanGrant", &can_grant_word);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ res = txt_backend_read_word (policy, "ObtainRequireRoot", &obtain_requires_root_word);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ if (strcmp (can_obtain_word, "True") == 0) {
+ *out_auth_can_obtain = TRUE;
+ *out_auth_can_obtain_is_temporary = FALSE;
+ } else if (strcmp (can_obtain_word, "False") == 0) {
+ *out_auth_can_obtain = FALSE;
+ *out_auth_can_obtain_is_temporary = FALSE;
+ } else if (strcmp (can_obtain_word, "Temporary") == 0) {
+ *out_auth_can_obtain = TRUE;
+ *out_auth_can_obtain_is_temporary = TRUE;
+ } else {
+ g_critical ("CanObtain has bogus value '%s' in privilege '%s'",
+ can_obtain_word, policy);
+ goto out;
+ }
+
+ if (strcmp (can_grant_word, "True") == 0) {
+ *out_auth_can_grant = TRUE;
+ } else if (strcmp (can_grant_word, "False") == 0) {
+ *out_auth_can_grant = FALSE;
+ } else {
+ g_critical ("CanGrant has bogus value '%s' in privilege '%s'",
+ can_grant_word, policy);
+ goto out;
+ }
+
+ if (strcmp (obtain_requires_root_word, "True") == 0) {
+ *out_auth_obtain_requires_root = TRUE;
+ } else if (strcmp (obtain_requires_root_word, "False") == 0) {
+ *out_auth_obtain_requires_root = FALSE;
+ } else {
+ g_critical ("ObtainRequireRoot has bogus value '%s' in privilege '%s'",
+ obtain_requires_root_word, policy);
+ goto out;
+ }
+
+ /* no need to check RequiredPrivileges if said privilege says we can't obtain it */
+ if ((*out_auth_can_obtain) == FALSE)
+ goto determined;
+
+ /* if privilege already requires super user, no need to check RequiredPrivileges */
+ if ((*out_auth_obtain_requires_root) == TRUE)
+ goto determined;
+
+ /* So now the user can obtain the privilege and doesn't
+ * require root. However, per the spec, if he is lacking any
+ * of the privileges listed and one or more of these have
+ *
+ * - has ObtainRequiresRoot set to TRUE; or
+ *
+ * - has CanObtain set to FALSE
+ *
+ * then effectively ObtainsRequireRoot becomes TRUE.
+ */
+
+ res = policy_get_required_privileges (policy, &required_privs);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ g_message (" * obtain_requires_root = %d", *out_auth_obtain_requires_root);
+
+ for (l = required_privs; l != NULL; l = g_list_next (l)) {
+ gboolean has_required_privilege = FALSE;
+ gboolean has_required_privilege_is_temp = FALSE;
+ char *has_required_privilege_is_restricted = NULL;
+ const char *required_privilege = (const char *) l->data;
+ PolicyResult res2;
+
+ g_message (" checking for required privilege '%s'", required_privilege);
+
+ has_required_privilege = FALSE;
+ res2 = policy_is_uid_allowed_for_policy (uid,
+ required_privilege,
+ NULL,
+ &has_required_privilege,
+ &has_required_privilege_is_temp,
+ &has_required_privilege_is_restricted,
+ have_temp_privilege_userdata,
+ have_temp_privilege);
+ if (res2 != POLICY_RESULT_OK)
+ goto out;
+
+ g_message (" has_required_privilege = %d", has_required_privilege);
+
+ if (!has_required_privilege ||
+ (has_required_privilege && has_required_privilege_is_restricted != NULL)) {
+
+ g_free (can_obtain_word);
+ g_free (can_grant_word);
+ can_obtain_word = NULL;
+ can_grant_word = NULL;
+
+ res = txt_backend_read_word (required_privilege, "CanObtain",
+ &can_obtain_word);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ res = txt_backend_read_word (required_privilege, "ObtainRequireRoot",
+ &obtain_requires_root_word);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ if (strcmp (can_obtain_word, "False") == 0) {
+ *out_auth_obtain_requires_root = TRUE;
+ goto determined;
+ }
+
+ if (strcmp (obtain_requires_root_word, "True") == 0) {
+ *out_auth_obtain_requires_root = TRUE;
+ goto determined;
+ }
+ }
+ }
+
+determined:
+ g_message (" ** obtain_requires_root = %d", *out_auth_obtain_requires_root);
+ res = POLICY_RESULT_OK;
+
+out:
+ if (required_privs != NULL) {
+ g_list_foreach (required_privs, (GFunc) g_free, NULL);
+ g_list_free (required_privs);
+ }
+
+ g_free (can_obtain_word);
+ g_free (can_grant_word);
+
+ return res;
+}
+
+
static void
afp_process_elem(PolicyElement *elem, gboolean *flag, uid_t uid, guint num_gids, gid_t *gid_list)
@@ -467,25 +761,143 @@ out:
return res;
}
-PolicyResult
-policy_is_uid_gid_allowed_for_policy (uid_t uid,
- guint num_gids,
- gid_t *gid_list,
- const char *policy,
- const char *resource,
- gboolean *result)
+static PolicyResult
+_policy_is_uid_gid_allowed_for_policy (uid_t uid,
+ guint num_gids,
+ gid_t *gid_list,
+ const char *policy,
+ const char *resource,
+ gboolean *out_is_privileged,
+ gboolean *out_is_temporary,
+ char **out_is_privileged_but_restricted,
+ gpointer have_temp_privilege_userdata,
+ HaveTempPrivCB have_temp_privilege,
+ int recursion_counter)
{
gboolean is_in_whitelist;
gboolean is_in_blacklist;
GList *l;
GList *whitelist;
GList *blacklist;
+ GList *sufficient_privs;
+ GList *required_privs;
PolicyResult res;
+ PolicyResult res2;
whitelist = NULL;
blacklist = NULL;
+ sufficient_privs = NULL;
+ required_privs = NULL;
res = POLICY_RESULT_ERROR;
+ *out_is_privileged = FALSE;
+ *out_is_temporary = FALSE;
+ *out_is_privileged_but_restricted = NULL;
+
+ if (recursion_counter > 8) {
+ g_critical ("Maximal (8) recursion depth detected checking privilege '%s'", policy);
+ goto out;
+ }
+
+ res = policy_get_sufficient_privileges (policy, &sufficient_privs);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ /* first check SufficientPrivileges.. if we have one of those, then return TRUE */
+ for (l = sufficient_privs; l != NULL; l = g_list_next (l)) {
+ gboolean has_sufficient_privilege = FALSE;
+ gboolean has_sufficient_privilege_is_temp = FALSE;
+ char *has_sufficient_privilege_is_restricted = NULL;
+ const char *sufficient_privilege = (const char *) l->data;
+
+ g_message (" checking for sufficient privilege '%s'", sufficient_privilege);
+
+ has_sufficient_privilege = FALSE;
+ res2 = _policy_is_uid_gid_allowed_for_policy (uid, num_gids, gid_list,
+ sufficient_privilege, NULL,
+ &has_sufficient_privilege,
+ &has_sufficient_privilege_is_temp,
+ &has_sufficient_privilege_is_restricted,
+ have_temp_privilege_userdata,
+ have_temp_privilege, recursion_counter + 1);
+ if (res2 != POLICY_RESULT_OK)
+ goto out;
+
+ if (has_sufficient_privilege && has_sufficient_privilege_is_restricted == NULL) {
+ g_message ("Returned TRUE because we have the sufficient privilege '%s' for privilege '%s'",
+ sufficient_privilege, policy);
+ res = POLICY_RESULT_OK;
+ *out_is_privileged = TRUE;
+ *out_is_temporary = has_sufficient_privilege_is_temp;
+ *out_is_privileged_but_restricted = NULL;
+ goto out;
+ }
+ }
+
+ /* then check temporary privileges as it's OK to have a
+ * privilege temporarily without having the all the
+ * RequiredPrivileges.
+ */
+
+ if ((*out_is_privileged == FALSE) && have_temp_privilege != NULL) {
+ gboolean ignore_resource;
+
+ if (recursion_counter == 0)
+ ignore_resource = FALSE;
+ else
+ ignore_resource = TRUE;
+
+ /* TODO: ask for restriction */
+ if (have_temp_privilege (uid, policy, resource, ignore_resource, have_temp_privilege_userdata)) {
+
+ res = POLICY_RESULT_OK;
+ *out_is_privileged = TRUE;
+ *out_is_temporary = TRUE;
+ *out_is_privileged_but_restricted = NULL;
+ goto out;
+ }
+ }
+
+
+ /* now check RequiredPrivileges.. if we have don't have all of those, then return FALSE */
+
+ res = policy_get_required_privileges (policy, &required_privs);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ for (l = required_privs; l != NULL; l = g_list_next (l)) {
+ gboolean has_required_privilege = FALSE;
+ gboolean has_required_privilege_is_temp = FALSE;
+ char *has_required_privilege_is_restricted = NULL;
+ const char *required_privilege = (const char *) l->data;
+
+ g_message (" checking for required privilege '%s'", required_privilege);
+
+ has_required_privilege = FALSE;
+ res2 = _policy_is_uid_gid_allowed_for_policy (uid, num_gids, gid_list,
+ required_privilege, NULL,
+ &has_required_privilege,
+ &has_required_privilege_is_temp,
+ &has_required_privilege_is_restricted,
+ have_temp_privilege_userdata,
+ have_temp_privilege, recursion_counter + 1);
+ if (res2 != POLICY_RESULT_OK)
+ goto out;
+
+ if (!has_required_privilege ||
+ (has_required_privilege && has_required_privilege_is_restricted != NULL)) {
+ g_message ("Returned FALSE because we don't have the required privilege '%s' for privilege '%s'",
+ required_privilege, policy);
+ res = POLICY_RESULT_OK;
+ *out_is_privileged = FALSE;
+ *out_is_temporary = TRUE;
+ *out_is_privileged_but_restricted = NULL;
+ goto out;
+ }
+ }
+
+ /* Check against whitelist and blacklist */
+
res = policy_get_whitelist (policy, &whitelist);
if (res != POLICY_RESULT_OK)
goto out;
@@ -517,11 +929,21 @@ policy_is_uid_gid_allowed_for_policy (uid_t uid,
}
}
- *result = is_in_whitelist && (!is_in_blacklist);
+ *out_is_privileged = is_in_whitelist && (!is_in_blacklist);
+ *out_is_temporary = FALSE;
+ *out_is_privileged_but_restricted = NULL;
res = POLICY_RESULT_OK;
out:
+ if (required_privs != NULL) {
+ g_list_foreach (required_privs, (GFunc) g_free, NULL);
+ g_list_free (required_privs);
+ }
+ if (sufficient_privs != NULL) {
+ g_list_foreach (sufficient_privs, (GFunc) g_free, NULL);
+ g_list_free (sufficient_privs);
+ }
if (whitelist != NULL)
policy_element_free_list (whitelist);
if (blacklist != NULL)
@@ -530,6 +952,28 @@ out:
return res;
}
+
+PolicyResult
+policy_is_uid_gid_allowed_for_policy (uid_t uid,
+ guint num_gids,
+ gid_t *gid_list,
+ const char *policy,
+ const char *resource,
+ gboolean *out_is_privileged,
+ gboolean *out_is_temporary,
+ char **out_is_privileged_but_restricted,
+ gpointer have_temp_privilege_userdata,
+ HaveTempPrivCB have_temp_privilege)
+{
+ return _policy_is_uid_gid_allowed_for_policy (uid, num_gids, gid_list, policy,
+ resource,
+ out_is_privileged,
+ out_is_temporary,
+ out_is_privileged_but_restricted,
+ have_temp_privilege_userdata,
+ have_temp_privilege, 0);
+}
+
char *
policy_util_uid_to_name (uid_t uid,
gid_t *default_gid)
@@ -686,10 +1130,14 @@ out:
}
PolicyResult
-policy_is_uid_allowed_for_policy (uid_t uid,
- const char *policy,
- const char *resource,
- gboolean *result)
+policy_is_uid_allowed_for_policy (uid_t uid,
+ const char *policy,
+ const char *resource,
+ gboolean *out_is_privileged,
+ gboolean *out_is_temporary,
+ char **out_is_privileged_but_restricted,
+ gpointer have_temp_privilege_userdata,
+ HaveTempPrivCB have_temp_privilege)
{
int num_groups = 0;
gid_t *groups = NULL;
@@ -715,7 +1163,11 @@ policy_is_uid_allowed_for_policy (uid_t uid,
groups,
policy,
resource,
- result);
+ out_is_privileged,
+ out_is_temporary,
+ out_is_privileged_but_restricted,
+ have_temp_privilege_userdata,
+ have_temp_privilege);
out:
g_free (username);
diff --git a/polkitd/policy.h b/polkitd/policy.h
index 11865ea..94a2fd3 100644
--- a/polkitd/policy.h
+++ b/polkitd/policy.h
@@ -35,41 +35,68 @@ typedef enum {
POLICY_RESULT_NO_SUCH_POLICY
} PolicyResult;
-PolicyResult policy_get_policies (GList **result);
-
-PolicyResult policy_is_uid_allowed_for_policy (uid_t uid,
- const char *policy,
- const char *resource,
- gboolean *result);
-
-PolicyResult policy_get_allowed_resources_for_policy_for_uid (uid_t uid,
- const char *policy,
- GList **result);
-
-PolicyResult policy_get_allowed_resources_for_policy_for_uid_gid (uid_t uid,
- guint num_gids,
- gid_t *gid_list,
- const char *policy,
- GList **result);
-
-PolicyResult policy_is_uid_gid_allowed_for_policy (uid_t uid,
- guint num_gids,
- gid_t *gid_list,
- const char *policy,
- const char *resource,
- gboolean *result);
-
-char *policy_util_uid_to_name (uid_t uid,
- gid_t *default_gid);
-
-char *policy_util_gid_to_name (gid_t gid);
-
-uid_t policy_util_name_to_uid (const char *username,
- gid_t *default_gid);
-
-gid_t policy_util_name_to_gid (const char *groupname);
-
-void policy_util_set_policy_directory (const char *directory);
+typedef gboolean (*HaveTempPrivCB) (uid_t user,
+ const char *privilege,
+ const char *resource,
+ gboolean ignore_resource,
+ gpointer userdata);
+
+
+PolicyResult policy_get_policies (GList **result);
+
+PolicyResult policy_is_uid_allowed_for_policy (uid_t uid,
+ const char *policy,
+ const char *resource,
+ gboolean *out_is_privileged,
+ gboolean *out_is_temporary,
+ char **out_is_privileged_but_restricted,
+ gpointer have_temp_privilege_userdata,
+ HaveTempPrivCB have_temp_privilege);
+
+
+PolicyResult policy_get_auth_details_for_policy (uid_t uid,
+ const char *policy,
+ const char *resource,
+ gboolean *out_auth_can_obtain,
+ gboolean *out_auth_can_obtain_is_temporary,
+ gboolean *out_auth_can_grant,
+ gboolean *out_auth_obtain_requires_root,
+ gpointer have_temp_privilege_userdata,
+ HaveTempPrivCB have_temp_privilege);
+
+
+PolicyResult policy_get_allowed_resources_for_policy_for_uid (uid_t uid,
+ const char *policy,
+ GList **result);
+
+PolicyResult policy_get_allowed_resources_for_policy_for_uid_gid (uid_t uid,
+ guint num_gids,
+ gid_t *gid_list,
+ const char *policy,
+ GList **result);
+
+PolicyResult policy_is_uid_gid_allowed_for_policy (uid_t uid,
+ guint num_gids,
+ gid_t *gid_list,
+ const char *policy,
+ const char *resource,
+ gboolean *out_is_privileged,
+ gboolean *out_is_temporary,
+ char **out_is_privileged_but_restricted,
+ gpointer have_temp_privilege_userdata,
+ HaveTempPrivCB have_temp_privilege);
+
+char *policy_util_uid_to_name (uid_t uid,
+ gid_t *default_gid);
+
+char *policy_util_gid_to_name (gid_t gid);
+
+uid_t policy_util_name_to_uid (const char *username,
+ gid_t *default_gid);
+
+gid_t policy_util_name_to_gid (const char *groupname);
+
+void policy_util_set_policy_directory (const char *directory);
#endif /* POLICY_H */
diff --git a/polkitd/polkit-manager.c b/polkitd/polkit-manager.c
index 52c59d9..947d333 100644
--- a/polkitd/polkit-manager.c
+++ b/polkitd/polkit-manager.c
@@ -38,7 +38,7 @@ typedef struct
uid_t user;
char *privilege;
char *resource;
- pid_t pid_restriction;
+ char *system_bus_unique_name; /* whether the tmp priv is restricted to e.g. :1.43 */
} TemporaryPrivilege;
struct PolicyKitManagerPrivate
@@ -58,6 +58,26 @@ G_DEFINE_TYPE(PolicyKitManager, polkit_manager, G_TYPE_OBJECT)
static GObjectClass *parent_class = NULL;
+
+static void
+_granting_temp_priv (PolicyKitManager *manager,
+ TemporaryPrivilege *p)
+{
+ g_debug ("Granting temporary privilege '%s' to uid %d on resource '%s'",
+ p->privilege, p->user, p->resource != NULL ? p->resource : "(none)");
+ /* TODO: send out D-BUS signal */
+}
+
+static void
+_revoking_temp_priv (PolicyKitManager *manager,
+ TemporaryPrivilege *p)
+{
+ g_debug ("Revoking temporary privilege '%s' to uid %d on resource '%s'",
+ p->privilege, p->user, p->resource != NULL ? p->resource : "(none)");
+ /* TODO: send out D-BUS signal */
+}
+
+
typedef struct {
uid_t uid;
pid_t pid;
@@ -130,6 +150,7 @@ polkit_manager_error_get_type (void)
ENUM_ENTRY (POLKIT_MANAGER_ERROR_NO_SUCH_USER, "NoSuchUser"),
ENUM_ENTRY (POLKIT_MANAGER_ERROR_NO_SUCH_PRIVILEGE, "NoSuchPrivilege"),
ENUM_ENTRY (POLKIT_MANAGER_ERROR_NOT_PRIVILEGED, "NotPrivileged"),
+ ENUM_ENTRY (POLKIT_MANAGER_ERROR_CANNOT_OBTAIN_PRIVILEGE, "CannotObtainPrivilege"),
ENUM_ENTRY (POLKIT_MANAGER_ERROR_ERROR, "Error"),
{ 0, 0, 0 }
};
@@ -157,6 +178,8 @@ bus_name_owner_changed (DBusGProxy *bus_proxy,
if (strlen (new_service_name) == 0) {
CallerInfo *caller_info;
PolicyKitSession *session;
+ GList *i;
+ TemporaryPrivilege *p;
/* evict CallerInfo from cache */
caller_info = (CallerInfo *) g_hash_table_lookup (manager->priv->connection_name_to_caller_info,
@@ -177,6 +200,29 @@ bus_name_owner_changed (DBusGProxy *bus_proxy,
g_hash_table_remove (manager->priv->connection_name_to_session_object, old_service_name);
}
+
+ /* revoke any temporary privileges that is restricted to this name */
+ for (i = manager->priv->temporary_privileges; i != NULL; ) {
+ p = (TemporaryPrivilege *) i->data;
+
+ i = g_list_next (i);
+
+ if (p->system_bus_unique_name != NULL &&
+ strcmp (p->system_bus_unique_name, old_service_name) == 0) {
+
+ /* da, revoke this privilege */
+ _revoking_temp_priv (manager, p);
+
+ g_free (p->privilege);
+ g_free (p->resource);
+ g_free (p->system_bus_unique_name);
+ g_free (p);
+
+ manager->priv->temporary_privileges = g_list_remove (
+ manager->priv->temporary_privileges, p);
+ }
+ }
+
}
/*g_message ("NameOwnerChanged: service_name='%s', old_service_name='%s' new_service_name='%s'",
@@ -269,6 +315,7 @@ polkit_manager_get_caller_info (PolicyKitManager *manager,
gboolean res;
CallerInfo *caller_info;
GError *error = NULL;
+ GArray *calling_selinux_context;
res = FALSE;
@@ -307,6 +354,22 @@ polkit_manager_get_caller_info (PolicyKitManager *manager,
goto out;
}
+ if (!dbus_g_proxy_call (manager->priv->bus_proxy, "GetConnectionSELinuxSecurityContext", &error,
+ G_TYPE_STRING, sender,
+ G_TYPE_INVALID,
+ dbus_g_type_get_collection ("GArray", G_TYPE_UCHAR), &calling_selinux_context,
+ G_TYPE_INVALID)) {
+ g_warning ("GetConnectionSELinuxSecurityContext() failed: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ char *selinux_context_string;
+ g_array_append_val (calling_selinux_context, "\0");
+ selinux_context_string = (char *) g_array_free (calling_selinux_context, FALSE);
+ g_message ("selinux context = '%s' for sender '%s'", selinux_context_string, sender);
+ g_free (selinux_context_string);
+
caller_info = g_new0 (CallerInfo, 1);
caller_info->uid = *calling_uid;
caller_info->pid = *calling_pid;
@@ -324,6 +387,68 @@ out:
return res;
}
+
+typedef struct
+{
+ PolicyKitManager *manager;
+ char *system_bus_unique_name;
+ char *privileged_but_restricted_to;
+ gboolean is_temporary;
+} TempPrivCheckUserData;
+
+static gboolean
+_check_for_temp_privilege (uid_t user,
+ const char *privilege,
+ const char *resource,
+ gboolean ignore_resource,
+ gpointer userdata)
+{
+ GList *i;
+ TempPrivCheckUserData *tpcud = (TempPrivCheckUserData *) userdata;
+ gboolean is_privileged;
+
+ is_privileged = FALSE;
+
+ g_message ("in _check_for_temp_privilege for user=%d priv=%s resource=%s sbun=%s",
+ user, privilege, resource, tpcud->system_bus_unique_name);
+
+ for (i = tpcud->manager->priv->temporary_privileges; i != NULL; i = g_list_next (i)) {
+ TemporaryPrivilege *p;
+ gboolean res_match;
+
+ p = (TemporaryPrivilege *) i->data;
+
+ if (ignore_resource) {
+ res_match = TRUE;
+ } else {
+ if (resource == NULL || strlen (resource) == 0)
+ res_match = (p->resource == NULL);
+ else
+ res_match = (safe_strcmp (p->resource, resource) == 0);
+ }
+
+ if ((strcmp (p->privilege, privilege) == 0) &&
+ res_match &&
+ (p->user == user)) {
+
+ if (p->system_bus_unique_name == NULL) {
+ is_privileged = TRUE;
+ tpcud->is_temporary = TRUE;
+ break;
+ } else if (strcmp (p->system_bus_unique_name, tpcud->system_bus_unique_name) == 0) {
+ is_privileged = TRUE;
+ tpcud->is_temporary = TRUE;
+ break;
+ } else {
+ tpcud->privileged_but_restricted_to = p->system_bus_unique_name;
+ }
+
+ }
+ }
+
+ return is_privileged;
+}
+
gboolean
polkit_manager_initiate_temporary_privilege_grant (PolicyKitManager *manager,
char *user,
@@ -365,14 +490,45 @@ polkit_manager_initiate_temporary_privilege_grant (PolicyKitManager *manag
return FALSE;
}
+
+ gboolean auth_can_obtain;
+ gboolean auth_can_obtain_is_temporary;
+ gboolean auth_can_grant;
+ gboolean auth_obtain_requires_root;
+ PolicyResult res;
+ TempPrivCheckUserData tpcud;
+
+ tpcud.manager = manager;
+ tpcud.system_bus_unique_name = NULL;
+ tpcud.privileged_but_restricted_to = "";
+ tpcud.is_temporary = FALSE;
+
+ res = policy_get_auth_details_for_policy (uid,
+ privilege,
+ resource,
+ &auth_can_obtain,
+ &auth_can_obtain_is_temporary,
+ &auth_can_grant,
+ &auth_obtain_requires_root,
+ &tpcud,
+ _check_for_temp_privilege);
+
+ if (!auth_can_obtain) {
+ dbus_g_method_return_error (context,
+ g_error_new (POLKIT_MANAGER_ERROR,
+ POLKIT_MANAGER_ERROR_ERROR,
+ "The privilege %s cannot be obtained.", privilege));
+ return FALSE;
+ }
+
session = polkit_session_new (manager->priv->connection,
manager,
calling_uid,
- calling_pid,
sender,
uid,
privilege,
- strlen (resource) > 0 ? resource : NULL);
+ strlen (resource) > 0 ? resource : NULL,
+ auth_obtain_requires_root);
g_object_weak_ref (G_OBJECT (session),
session_finalized,
@@ -391,7 +547,7 @@ polkit_manager_initiate_temporary_privilege_grant (PolicyKitManager *manag
gboolean
polkit_manager_is_user_privileged (PolicyKitManager *manager,
- int pid,
+ char *system_bus_unique_name,
char *user,
char *privilege,
char *resource,
@@ -403,7 +559,8 @@ polkit_manager_is_user_privileged (PolicyKitManager *manager,
PolicyResult res;
gboolean is_privileged;
gboolean is_temporary;
-
+ char *is_privileged_but_restricted_to = NULL;
+ TempPrivCheckUserData tpcud;
if (!polkit_manager_get_caller_info (manager,
dbus_g_method_get_sender (context),
@@ -438,10 +595,18 @@ polkit_manager_is_user_privileged (PolicyKitManager *manager,
return FALSE;
}
+ tpcud.manager = manager;
+ tpcud.system_bus_unique_name = system_bus_unique_name;
+ tpcud.privileged_but_restricted_to = "";
+ tpcud.is_temporary = FALSE;
res = policy_is_uid_allowed_for_policy (uid,
privilege,
strlen (resource) > 0 ? resource : NULL,
- &is_privileged);
+ &is_privileged,
+ &is_temporary,
+ &is_privileged_but_restricted_to,
+ &tpcud,
+ _check_for_temp_privilege);
switch (res) {
case POLICY_RESULT_OK:
break;
@@ -463,35 +628,16 @@ polkit_manager_is_user_privileged (PolicyKitManager *manager,
return FALSE;
}
- is_temporary = FALSE;
-
- /* check temporary lists */
- if (!is_privileged) {
- GList *i;
- TemporaryPrivilege *p;
-
- for (i = manager->priv->temporary_privileges; i != NULL; i = g_list_next (i)) {
- p = (TemporaryPrivilege *) i->data;
- gboolean res_match;
- if (strlen (resource) == 0)
- res_match = (p->resource == NULL);
- else
- res_match = (safe_strcmp (p->resource, resource) == 0);
-
- if ((strcmp (p->privilege, privilege) == 0) &&
- res_match &&
- (p->user == uid) &&
- ((p->pid_restriction == -1) || (p->pid_restriction == pid))) {
-
- is_privileged = TRUE;
- is_temporary = TRUE;
- break;
- }
- }
+ /* if we ended up being privileged, then don't fill in the _but_restricted_to */
+ if (is_privileged) {
+ g_free (is_privileged_but_restricted_to);
+ is_privileged_but_restricted_to = g_strdup ("");
}
- dbus_g_method_return (context, is_privileged, is_temporary);
+ dbus_g_method_return (context, is_privileged, is_temporary, is_privileged_but_restricted_to);
+
+ g_free (is_privileged_but_restricted_to);
return TRUE;
}
@@ -508,10 +654,12 @@ polkit_manager_get_allowed_resources_for_privilege (PolicyKitManager *manag
int n;
GList *i;
GList *resources;
+ GList *restrictions;
uid_t uid;
PolicyResult res;
TemporaryPrivilege *p;
char **resource_list;
+ char **restriction_list;
int num_non_temporary;
if (!polkit_manager_get_caller_info (manager,
@@ -572,15 +720,19 @@ polkit_manager_get_allowed_resources_for_privilege (PolicyKitManager *manag
num_non_temporary = g_list_length (resources);
+ restrictions = NULL;
+
/* check temporary list */
for (i = manager->priv->temporary_privileges; i != NULL; i = g_list_next (i)) {
p = (TemporaryPrivilege *) i->data;
if ((strcmp (p->privilege, privilege) == 0) &&
(p->resource != NULL) &&
- (p->user == uid) &&
- (p->pid_restriction == -1)) {
+ (p->user == uid)) {
+
resources = g_list_append (resources, g_strdup (p->resource));
+ restrictions = g_list_append (restrictions, p->system_bus_unique_name != NULL ?
+ p->system_bus_unique_name : "");
}
}
@@ -595,7 +747,18 @@ polkit_manager_get_allowed_resources_for_privilege (PolicyKitManager *manag
g_list_foreach (resources, (GFunc) g_free, NULL);
g_list_free (resources);
- dbus_g_method_return (context, resource_list, num_non_temporary);
+ restriction_list = g_new0 (char *, g_list_length (resources) + 1);
+ for (n = 0; n < num_non_temporary; n++) {
+ restriction_list[n] = "";
+ }
+ for (i = restrictions; i != NULL; i = g_list_next (i)) {
+ char *restriction = (char *) i->data;
+ restriction_list[n] = g_strdup (restriction);
+ n++;
+ }
+ restriction_list[n] = NULL;
+
+ dbus_g_method_return (context, resource_list, restriction_list, num_non_temporary);
return TRUE;
}
@@ -713,7 +876,8 @@ polkit_manager_revoke_temporary_privilege (PolicyKitManager *manager,
uid,
privilege,
resource,
- -1)) {
+ NULL,
+ TRUE)) {
dbus_g_method_return_error (context,
g_error_new (POLKIT_MANAGER_ERROR,
POLKIT_MANAGER_ERROR_NO_SUCH_PRIVILEGE,
@@ -730,13 +894,12 @@ polkit_manager_revoke_temporary_privilege (PolicyKitManager *manager,
/* local methods */
-
gboolean
polkit_manager_add_temporary_privilege (PolicyKitManager *manager,
uid_t user,
const char *privilege,
const char *resource,
- pid_t pid_restriction)
+ const char *system_bus_unique_name)
{
GList *i;
TemporaryPrivilege *p;
@@ -747,7 +910,7 @@ polkit_manager_add_temporary_privilege (PolicyKitManager *manager,
if ((strcmp (p->privilege, privilege) == 0) &&
((resource != NULL) && (safe_strcmp (p->resource, resource)) == 0) &&
(p->user == user) &&
- (p->pid_restriction == pid_restriction))
+ (p->system_bus_unique_name == system_bus_unique_name))
return FALSE;
}
@@ -755,8 +918,9 @@ polkit_manager_add_temporary_privilege (PolicyKitManager *manager,
p->user = user;
p->privilege = g_strdup (privilege);
p->resource = g_strdup (resource);
- p->pid_restriction = pid_restriction;
+ p->system_bus_unique_name = g_strdup (system_bus_unique_name);
+ _granting_temp_priv (manager, p);
manager->priv->temporary_privileges = g_list_append (manager->priv->temporary_privileges, p);
return TRUE;
@@ -767,7 +931,8 @@ polkit_manager_remove_temporary_privilege (PolicyKitManager *manager,
uid_t user,
const char *privilege,
const char *resource,
- pid_t pid_restriction)
+ const char *system_bus_unique_name,
+ gboolean remove_even_if_system_bus_unique_name_does_not_match)
{
GList *i;
TemporaryPrivilege *p;
@@ -776,13 +941,25 @@ polkit_manager_remove_temporary_privilege (PolicyKitManager *manager,
p = (TemporaryPrivilege *) i->data;
if ((strcmp (p->privilege, privilege) == 0) &&
+
((resource == NULL) ? (p->resource == NULL)
: ((p->resource != NULL) ? (strcmp (p->resource, resource) == 0) : FALSE)) &&
+
(p->user == user) &&
- (p->pid_restriction == pid_restriction)) {
+
+ (remove_even_if_system_bus_unique_name_does_not_match ||
+ ((system_bus_unique_name == NULL) ? (p->system_bus_unique_name == NULL)
+ : ((p->system_bus_unique_name != NULL) ?
+ (strcmp (p->system_bus_unique_name, system_bus_unique_name) == 0) :
+ FALSE)))
+ ) {
+
+ _revoking_temp_priv (manager, p);
g_free (p->privilege);
g_free (p->resource);
+ g_free (p->system_bus_unique_name);
+ g_free (p);
manager->priv->temporary_privileges = g_list_remove (
manager->priv->temporary_privileges, p);
@@ -793,3 +970,117 @@ polkit_manager_remove_temporary_privilege (PolicyKitManager *manager,
return FALSE;
}
+
+void
+polkit_manager_update_desktop_console_privileges (PolicyKitManager *manager)
+{
+ GDir *dir;
+ GError *err = NULL;
+ const char *f;
+ GSList *list;
+ GSList *j;
+ GList *i;
+ TemporaryPrivilege *p;
+
+ g_debug ("Entering polkit_manager_update_desktop_console_privileges");
+
+ /* Build a list of what /var/run/polkit-console contains;
+ * e.g. {":0", "davidz", ":1", "bateman", ..}
+ *
+ * This is essentially a list of pairs <consoleId, userId>
+ * denoting what users are logged in at the consoles attached
+ * to the system.
+ */
+ list = NULL;
+ if ((dir = g_dir_open (PACKAGE_LOCALSTATEDIR "/run/polkit-console", 0, &err)) == NULL) {
+ g_warning ("Unable to open " PACKAGE_LOCALSTATEDIR "/run/polkit-console : %s", err->message);
+ g_error_free (err);
+ goto out;
+ }
+ while ((f = g_dir_read_name (dir)) != NULL) {
+ char **tokens;
+
+ tokens = g_strsplit (f, "_", 2);
+ if (tokens != NULL && g_strv_length (tokens) == 2) {
+ char *console;
+ char *user;
+
+ console = g_strdup_printf ("console://%s", tokens[0]);
+ user = g_strdup (tokens[1]);
+ list = g_slist_append (list, console);
+ list = g_slist_append (list, user);
+ }
+ g_strfreev (tokens);
+ }
+ g_dir_close (dir);
+
+ /* now revoke the temporary desktop-console privilege for
+ * users no longer at the console; go through all tempoary
+ * desktop-console privileges and check that each one is still
+ * in the list above...
+ */
+ for (i = manager->priv->temporary_privileges; i != NULL; ) {
+ p = (TemporaryPrivilege *) i->data;
+ gboolean found;
+
+ i = g_list_next (i);
+
+ found = FALSE;
+
+ if ((strcmp (p->privilege, "desktop-console") == 0) && p->resource != NULL) {
+
+ for (j = list; j != NULL; j = g_slist_next (j)) {
+ char *console;
+ char *user;
+ uid_t uid;
+
+ console = (char *) j->data;
+ j = g_slist_next (j);
+ user = (char *) j->data;
+ uid = policy_util_name_to_uid (user, NULL);
+ if (uid != (uid_t) -1 && strcmp (p->resource, console) == 0 &&
+ p->user == uid &&
+ p->system_bus_unique_name == NULL) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ /* revoke this privilege */
+ _revoking_temp_priv (manager, p);
+
+ g_free (p->privilege);
+ g_free (p->resource);
+ g_free (p->system_bus_unique_name);
+ g_free (p);
+
+ manager->priv->temporary_privileges = g_list_remove (
+ manager->priv->temporary_privileges, p);
+ }
+ }
+
+ /* finally grant temporary desktop-console privilege for users
+ * now at the console
+ */
+ for (j = list; j != NULL; j = g_slist_next (j)) {
+ char *console;
+ char *user;
+ uid_t uid;
+
+ console = (char *) j->data;
+ j = g_slist_next (j);
+ user = (char *) j->data;
+ uid = policy_util_name_to_uid (user, NULL);
+ if (uid != (uid_t) -1) {
+ polkit_manager_add_temporary_privilege (manager, uid, "desktop-console", console, NULL);
+ }
+ }
+
+ g_slist_foreach (list, (GFunc) g_free, NULL);
+ g_slist_free (list);
+
+out:
+ ;
+}
diff --git a/polkitd/polkit-manager.h b/polkitd/polkit-manager.h
index f59e2dd..9d7b802 100644
--- a/polkitd/polkit-manager.h
+++ b/polkitd/polkit-manager.h
@@ -40,6 +40,7 @@ typedef enum
POLKIT_MANAGER_ERROR_NO_SUCH_PRIVILEGE = 1,
POLKIT_MANAGER_ERROR_NOT_PRIVILEGED = 2,
POLKIT_MANAGER_ERROR_ERROR = 3,
+ POLKIT_MANAGER_ERROR_CANNOT_OBTAIN_PRIVILEGE = 4,
POLKIT_MANAGER_NUM_ERRORS
} PolkitManagerError;
@@ -90,7 +91,7 @@ gboolean polkit_manager_revoke_temporary_privilege (PolicyKitM
DBusGMethodInvocation *context);
gboolean polkit_manager_is_user_privileged (PolicyKitManager *manager,
- int pid,
+ char *system_bus_unique_name,
char *user,
char *privilege,
char *resource,
@@ -116,12 +117,16 @@ gboolean polkit_manager_add_temporary_privilege (PolicyKitM
uid_t user,
const char *privilege,
const char *resource,
- pid_t pid_restriction);
+ const char *system_bus_unique_name);
gboolean polkit_manager_remove_temporary_privilege (PolicyKitManager *manager,
uid_t user,
const char *privilege,
const char *resource,
- pid_t pid_restriction);
+ const char *system_bus_unique_name,
+ gboolean remove_even_if_system_bus_unique_name_does_not_match);
+
+void polkit_manager_update_desktop_console_privileges (PolicyKitManager *manager);
+
#endif /* _POLKIT_MANAGER_H */
diff --git a/polkitd/polkit-session.c b/polkitd/polkit-session.c
index 458e854..cbc2fb5 100644
--- a/polkitd/polkit-session.c
+++ b/polkitd/polkit-session.c
@@ -36,6 +36,7 @@
#include <dbus/dbus-glib-lowlevel.h>
#include <security/pam_appl.h>
+#include "policy.h"
#include "polkit-session.h"
enum
@@ -58,13 +59,12 @@ struct PolicyKitSessionPrivate
char *auth_with_pam_service;
uid_t calling_uid;
- pid_t calling_pid;
char *calling_dbus_name;
uid_t grant_to_uid;
char *grant_privilege;
char *grant_resource;
- pid_t grant_pid_restriction;
+ char *grant_system_bus_name_unique_name_restriction;
gboolean have_granted_temp_privileges;
@@ -879,10 +879,9 @@ polkit_session_provide_answers (PolicyKitSession *session,
gboolean
polkit_session_close (PolicyKitSession *session,
- gboolean do_not_revoke_privilege,
DBusGMethodInvocation *context)
{
- /*g_debug ("in %s", __FUNCTION__);*/
+ g_debug ("In polkit_session_close for session %d", session->priv->session_number);
if (!polkit_session_check_caller (session, context))
return FALSE;
@@ -891,21 +890,6 @@ polkit_session_close (PolicyKitSession *session,
if (session->priv->child_pid != 0)
kill (session->priv->child_pid, SIGTERM);
- if (!do_not_revoke_privilege && session->priv->have_granted_temp_privileges) {
-
- if (!polkit_manager_remove_temporary_privilege (session->priv->manager,
- session->priv->grant_to_uid,
- session->priv->grant_privilege,
- session->priv->grant_resource,
- session->priv->grant_pid_restriction)) {
- g_warning ("Could not remove tmp priv '%s' to uid %d for resource '%s' on pid %d",
- session->priv->grant_privilege,
- session->priv->grant_to_uid,
- session->priv->grant_resource,
- session->priv->grant_pid_restriction);
- }
- }
-
g_object_unref (session);
dbus_g_method_return (context);
@@ -914,7 +898,7 @@ polkit_session_close (PolicyKitSession *session,
gboolean
polkit_session_grant_privilege_temporarily (PolicyKitSession *session,
- gboolean restrict_to_callers_pid,
+ gboolean restrict_to_callers_system_bus_unique_name,
DBusGMethodInvocation *context)
{
if (!polkit_session_check_caller (session, context))
@@ -936,17 +920,18 @@ polkit_session_grant_privilege_temporarily (PolicyKitSession *session,
return FALSE;
}
- session->priv->grant_pid_restriction = restrict_to_callers_pid ? session->priv->calling_pid : (pid_t) -1;
+ session->priv->grant_system_bus_name_unique_name_restriction = restrict_to_callers_system_bus_unique_name ?
+ g_strdup (session->priv->calling_dbus_name) : NULL;
if (!polkit_manager_add_temporary_privilege (session->priv->manager,
session->priv->grant_to_uid,
session->priv->grant_privilege,
session->priv->grant_resource,
- session->priv->grant_pid_restriction)) {
- g_warning ("Could not add tmp priv '%s' to uid %d for resource '%s' on pid %d",
+ session->priv->grant_system_bus_name_unique_name_restriction)) {
+ g_warning ("Could not add tmp priv '%s' to uid %d for resource '%s' on connection '%s'",
session->priv->grant_privilege,
session->priv->grant_to_uid,
session->priv->grant_resource,
- session->priv->grant_pid_restriction);
+ session->priv->grant_system_bus_name_unique_name_restriction);
}
session->priv->have_granted_temp_privileges = TRUE;
@@ -959,11 +944,11 @@ PolicyKitSession *
polkit_session_new (DBusGConnection *connection,
PolicyKitManager *manager,
uid_t calling_uid,
- pid_t calling_pid,
const char *calling_dbus_name,
uid_t uid,
const char *privilege,
- const char *resource)
+ const char *resource,
+ gboolean auth_as_root)
{
char *objpath;
PolicyKitSession *session;
@@ -978,17 +963,21 @@ polkit_session_new (DBusGConnection *connection,
g_free (objpath);
session->priv->calling_uid = calling_uid;
- session->priv->calling_pid = calling_pid;
session->priv->calling_dbus_name = g_strdup (calling_dbus_name);
session->priv->grant_to_uid = uid;
session->priv->grant_privilege = g_strdup (privilege);
session->priv->grant_resource = g_strdup (resource);
- /* TODO: look up auth_as_user, auth_with_pam_service from privilege configuration files */
- session->priv->auth_as_user = g_strdup ("root");
+ /* TODO: look up auth_as_user from privilege configuration files */
+ if (auth_as_root)
+ session->priv->auth_as_user = g_strdup ("root");
+ else
+ session->priv->auth_as_user = policy_util_uid_to_name (uid, NULL);
session->priv->auth_with_pam_service = g_strdup ("policy-kit");
+ g_debug ("In polkit_session_new ; established session %d", session->priv->session_number);
+
return session;
}
@@ -996,23 +985,29 @@ polkit_session_new (DBusGConnection *connection,
void
polkit_session_initiator_disconnected (PolicyKitSession *session)
{
- /*g_debug ("initiator disconnected");*/
+ g_debug ("Initiator for session %d disconnected", session->priv->session_number);
/* if we have a child... kill it */
if (session->priv->child_pid != 0)
kill (session->priv->child_pid, SIGTERM);
if (session->priv->have_granted_temp_privileges) {
+ g_debug (" Revoking temporary privilege %s on %s for uid %d on connection %s",
+ session->priv->grant_privilege,
+ session->priv->grant_resource,
+ session->priv->grant_to_uid,
+ session->priv->grant_system_bus_name_unique_name_restriction);
if (!polkit_manager_remove_temporary_privilege (session->priv->manager,
session->priv->grant_to_uid,
session->priv->grant_privilege,
session->priv->grant_resource,
- session->priv->grant_pid_restriction)) {
- g_warning ("Could not remove tmp priv '%s' to uid %d for resource '%s' on pid %d",
+ session->priv->grant_system_bus_name_unique_name_restriction,
+ FALSE)) {
+ g_warning ("Could not remove tmp priv '%s' to uid %d for resource '%s' on connection '%s'",
session->priv->grant_privilege,
session->priv->grant_to_uid,
session->priv->grant_resource,
- session->priv->grant_pid_restriction);
+ session->priv->grant_system_bus_name_unique_name_restriction);
}
}
}
diff --git a/polkitd/polkit-session.h b/polkitd/polkit-session.h
index c02bd22..19fac2f 100644
--- a/polkitd/polkit-session.h
+++ b/polkitd/polkit-session.h
@@ -80,11 +80,11 @@ struct PolicyKitSessionClass
PolicyKitSession *polkit_session_new (DBusGConnection *connection,
PolicyKitManager *manager,
uid_t calling_uid,
- pid_t calling_pid,
const char *calling_dbus_name,
uid_t uid,
const char *privilege,
- const char *resource);
+ const char *resource,
+ gboolean auth_as_root);
/* remote methods */
@@ -102,7 +102,6 @@ gboolean polkit_session_provide_answers (PolicyKitSession
DBusGMethodInvocation *context);
gboolean polkit_session_close (PolicyKitSession *session,
- gboolean do_not_revoke_privilege,
DBusGMethodInvocation *context);
gboolean polkit_session_get_auth_details (PolicyKitSession *session,
@@ -112,7 +111,7 @@ gboolean polkit_session_get_auth_denied_reason (PolicyKitSession
DBusGMethodInvocation *context);
gboolean polkit_session_grant_privilege_temporarily (PolicyKitSession *session,
- gboolean restrict_to_callers_pid,
+ gboolean restrict_to_callers_system_bus_unique_name,
DBusGMethodInvocation *context);
/* local methods */