PolicyKit/polkitd PolicyKit.in, 1.2, 1.3 main.c, 1.2, 1.3 policy.c, 1.1, 1.2 policy.h, 1.1, 1.2 polkit-manager.c, 1.2, 1.3 polkit-manager.h, 1.3, 1.4 polkit-session.c, 1.4, 1.5 polkit-session.h, 1.1, 1.2

David Zeuthen david at kemper.freedesktop.org
Mon Jun 5 16:39:03 PDT 2006


Update of /cvs/hal/PolicyKit/polkitd
In directory kemper:/tmp/cvs-serv24124/polkitd

Modified Files:
	PolicyKit.in main.c policy.c policy.h polkit-manager.c 
	polkit-manager.h polkit-session.c polkit-session.h 
Log Message:
2006-06-05  David Zeuthen  <davidz at redhat.com>

	Lots of changes! Almost ready for 0.2 release.

	* Makefile.am:
	* README:
	* configure.in:
	* doc/TODO:
	* doc/api/polkit-docs.xml:
	* doc/spec/Makefile.am:
	* doc/spec/polkit-spec.html:
	* doc/spec/polkit-spec.xml.in:
	* libpolkit/Makefile.am:
	* libpolkit/libpolkit-grant.c: (have_questions_handler),
	(libpolkit_grant_provide_answers), (auth_done_handler),
	(libpolkit_grant_new_context),
	(libpolkit_grant_get_libpolkit_context),
	(libpolkit_grant_set_questions_handler),
	(libpolkit_grant_set_grant_complete_handler),
	(libpolkit_grant_initiate_temporary_grant),
	(libpolkit_grant_get_user_for_auth),
	(libpolkit_grant_get_pam_service_for_auth),
	(libpolkit_grant_close), (libpolkit_grant_free_context),
	(libpolkit_grant_get_user), (libpolkit_grant_get_privilege),
	(libpolkit_grant_get_resource):
	* libpolkit/libpolkit-grant.h:
	* libpolkit/libpolkit.c:
	(libpolkit_get_allowed_resources_for_privilege_for_uid),
	(libpolkit_is_uid_allowed_for_privilege):
	* libpolkit/libpolkit.h:
	* pam-polkit-console/Makefile.am:
	* pam-polkit-console/pam-polkit-console.c: (_pam_log),
	(_parse_module_args), (_is_local_xconsole), (_poke_polkitd),
	(pam_sm_authenticate), (pam_sm_setcred), (pam_sm_open_session),
	(pam_sm_close_session):
	* polkit-interface-manager.xml:
	* polkit-interface-session.xml:
	* polkit.pc.in:
	* polkitd/PolicyKit.in:
	* polkitd/main.c: (handle_sigusr1), (sigusr1_iochn_data), (main):
	* polkitd/policy.c: (txt_backend_read_policy),
	(txt_backend_read_list), (txt_backend_read_word),
	(policy_get_sufficient_privileges),
	(policy_get_required_privileges),
	(policy_get_auth_details_for_policy),
	(_policy_is_uid_gid_allowed_for_policy),
	(policy_is_uid_gid_allowed_for_policy),
	(policy_is_uid_allowed_for_policy):
	* polkitd/policy.h:
	* polkitd/polkit-manager.c: (_granting_temp_priv),
	(_revoking_temp_priv), (polkit_manager_error_get_type),
	(bus_name_owner_changed), (polkit_manager_get_caller_info),
	(_check_for_temp_privilege),
	(polkit_manager_initiate_temporary_privilege_grant),
	(polkit_manager_is_user_privileged),
	(polkit_manager_get_allowed_resources_for_privilege),
	(polkit_manager_revoke_temporary_privilege),
	(polkit_manager_add_temporary_privilege),
	(polkit_manager_remove_temporary_privilege),
	(polkit_manager_update_desktop_console_privileges):
	* polkitd/polkit-manager.h:
	* polkitd/polkit-session.c: (polkit_session_close),
	(polkit_session_grant_privilege_temporarily), (polkit_session_new),
	(polkit_session_initiator_disconnected):
	* polkitd/polkit-session.h:
	* privileges/desktop-console.privilege:
	* tools/Makefile.am:
	* tools/polkit-grant-privilege.c: (questions_cb),
	(grant_complete_cb), (main):
	* tools/polkit-is-privileged.c: (usage), (main):
	* tools/polkit-list-privileges.c: (main):
	* tools/polkit-revoke-privilege.c: (main):



Index: PolicyKit.in
===================================================================
RCS file: /cvs/hal/PolicyKit/polkitd/PolicyKit.in,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- PolicyKit.in	15 Mar 2006 00:33:35 -0000	1.2
+++ PolicyKit.in	5 Jun 2006 23:39:00 -0000	1.3
@@ -23,6 +23,13 @@
 
 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 @@
 # See how we were called.
 case "$1" in
     start)
+	cleanup_state_dir
         start
         ;;
     stop)
@@ -57,13 +65,11 @@
         ;;
     restart)
         stop
-	sleep 3
         start
         ;;
     condrestart)
         if [ -f @LOCALSTATEDIR@/lock/subsys/$servicename ]; then
             stop
-	    sleep 3
             start
         fi
         ;;

Index: main.c
===================================================================
RCS file: /cvs/hal/PolicyKit/polkitd/main.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- main.c	16 Mar 2006 23:28:47 -0000	1.2
+++ main.c	5 Jun 2006 23:39:00 -0000	1.3
@@ -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 @@
 	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 @@
 	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 @@
 
 		/* 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 @@
 
 	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 @@
 	
 
 	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;

Index: policy.c
===================================================================
RCS file: /cvs/hal/PolicyKit/polkitd/policy.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- policy.c	14 Mar 2006 06:14:33 -0000	1.1
+++ policy.c	5 Jun 2006 23:39:00 -0000	1.2
@@ -171,7 +171,7 @@
 		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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 		}
 	}
 
-	*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 @@
 	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 @@
 }
 
 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 @@
 						  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);

Index: policy.h
===================================================================
RCS file: /cvs/hal/PolicyKit/polkitd/policy.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- policy.h	14 Mar 2006 06:14:33 -0000	1.1
+++ policy.h	5 Jun 2006 23:39:00 -0000	1.2
@@ -35,41 +35,68 @@
 	POLICY_RESULT_NO_SUCH_POLICY
 } PolicyResult;
 
-PolicyResult policy_get_policies                                  (GList       **result);
+typedef gboolean (*HaveTempPrivCB) (uid_t        user,
+				    const char  *privilege,
+				    const char  *resource,
+				    gboolean     ignore_resource,
+				    gpointer     userdata);
 
-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_policies                                  (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_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_is_uid_gid_allowed_for_policy                 (uid_t         uid, 
-								   guint         num_gids,
-								   gid_t        *gid_list,
-								   const char   *policy, 
-								   const char   *resource,
-								   gboolean     *result);
+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);
 
-char        *policy_util_uid_to_name                              (uid_t         uid, 
-								   gid_t        *default_gid);
 
-char        *policy_util_gid_to_name                              (gid_t         gid);
+PolicyResult policy_get_allowed_resources_for_policy_for_uid      (uid_t           uid, 
+								   const char     *policy, 
+								   GList         **result);
 
-uid_t        policy_util_name_to_uid                              (const char   *username, 
-								   gid_t        *default_gid);
+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);
 
-gid_t        policy_util_name_to_gid                              (const char   *groupname);
+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);
 
-void         policy_util_set_policy_directory                     (const char   *directory);
+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 */
 

Index: polkit-manager.c
===================================================================
RCS file: /cvs/hal/PolicyKit/polkitd/polkit-manager.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- polkit-manager.c	22 Apr 2006 23:27:14 -0000	1.2
+++ polkit-manager.c	5 Jun 2006 23:39:00 -0000	1.3
@@ -38,7 +38,7 @@
 	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 @@
 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 @@
 			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 @@
 	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 @@
 
 			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 @@
 	gboolean res;
 	CallerInfo *caller_info;
 	GError *error = NULL;
+	GArray *calling_selinux_context;
 
 	res = FALSE;
 
@@ -307,6 +354,22 @@
 		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 @@
 	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 @@
 		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 @@
 
 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 @@
 	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 @@
 		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 @@
 		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 @@
 	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 @@
 
 	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 @@
 	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 @@
 							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 @@
 
 /* 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 @@
 		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 @@
 	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 @@
 					   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 @@
 		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 @@
 
 	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:
+	;
+}

Index: polkit-manager.h
===================================================================
RCS file: /cvs/hal/PolicyKit/polkitd/polkit-manager.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- polkit-manager.h	22 Apr 2006 23:27:14 -0000	1.3
+++ polkit-manager.h	5 Jun 2006 23:39:00 -0000	1.4
@@ -40,6 +40,7 @@
 	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 @@
 								      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 @@
 								      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 */

Index: polkit-session.c
===================================================================
RCS file: /cvs/hal/PolicyKit/polkitd/polkit-session.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- polkit-session.c	29 Mar 2006 16:15:28 -0000	1.4
+++ polkit-session.c	5 Jun 2006 23:39:00 -0000	1.5
@@ -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 @@
 	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 @@
 
 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 @@
 	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 @@
 
 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 @@
 		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 @@
 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 @@
 	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 @@
 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);
 		}
 	}
 }

Index: polkit-session.h
===================================================================
RCS file: /cvs/hal/PolicyKit/polkitd/polkit-session.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- polkit-session.h	14 Mar 2006 06:14:33 -0000	1.1
+++ polkit-session.h	5 Jun 2006 23:39:00 -0000	1.2
@@ -80,11 +80,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);
 
 /* remote methods */
 
@@ -102,7 +102,6 @@
 							      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 @@
 							      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 */




More information about the hal-commit mailing list