gnome-session-24-rbac.diff revision 21861
20127N/A--- gnome-session-2.30.2/egg/eggdesktopfile.c-orig 2011-03-14 16:05:27.567087180 -0500
20127N/A+++ gnome-session-2.30.2/egg/eggdesktopfile.c 2011-03-14 16:07:41.020838521 -0500
20127N/A@@ -29,6 +29,17 @@
20127N/A
20127N/A #include <string.h>
20127N/A #include <unistd.h>
20127N/A+#include <user_attr.h>
20127N/A+#include <exec_attr.h>
20127N/A+#include <stdlib.h>
20127N/A+#include <secdb.h>
20127N/A+#include <dlfcn.h>
20127N/A+#include <pwd.h>
20127N/A+
20127N/A+#include <tsol/label.h>
20127N/A+#include <sys/tsol/label_macro.h>
20127N/A+#include <X11/Xlib.h>
20127N/A+#include <X11/extensions/Xtsol.h>
20127N/A
20127N/A #include <glib/gi18n.h>
20127N/A #include <gdk/gdkx.h>
21861N/A@@ -1066,6 +1077,451 @@ array_putenv (GPtrArray *env, char *vari
20127N/A return env;
20127N/A }
20127N/A
20127N/A+/*
20127N/A+ * Note that the following code is in three patches:
20127N/A+ * - gnome-panel-XX-rbac.diff (filter_with_rbac)
20127N/A+ * - gnome-menus-XX-rbac.diff (filter_with_rbac)
20127N/A+ * - glib-XX-gio-rbac.diff (get_gksu_role)
20127N/A+ * - gnome-session-XX-rbac.diff (get_gksu_role)
20127N/A+ *
20127N/A+ * So if there is a need to fix this code, it is probably necessary to fix the
20127N/A+ * code in these other two places as well. Though the functions are a bit
20127N/A+ * different.
20127N/A+ */
20127N/A+static
20127N/A+void * dlopen_tsol (void)
20127N/A+{
20127N/A+ void *handle = NULL;
20127N/A+
20127N/A+ /*
20127N/A+ * No 64-bit version of libwnck so we can get away with hardcoding
20127N/A+ * to a single path on this occasion
20127N/A+ */
20127N/A+ if ((handle = dlopen ("/usr/lib/libtsol.so.2", RTLD_LAZY)) != NULL)
20127N/A+ return handle;
20127N/A+
20127N/A+ return handle;
20127N/A+}
20127N/A+
20127N/A+static
20127N/A+void * dlopen_xtsol (void)
20127N/A+{
20127N/A+ void *handle = NULL;
20127N/A+
20127N/A+ if ((handle = dlopen ("/usr/lib/libXtsol.so.1", RTLD_LAZY)) != NULL)
20127N/A+ return handle;
20127N/A+ if ((handle = dlopen ("/usr/openwin/lib/libXtsol.so.1", RTLD_LAZY)) != NULL)
20127N/A+ return handle;
20127N/A+
20127N/A+ return handle;
20127N/A+}
20127N/A+
20127N/A+static
20127N/A+void * dlopen_gnometsol (void)
20127N/A+{
20127N/A+ void *handle = NULL;
20127N/A+
20127N/A+ if ((handle = dlopen ("/usr/lib/libgnometsol.so", RTLD_LAZY)) != NULL)
20127N/A+ return handle;
20127N/A+
20127N/A+ return handle;
20127N/A+}
20127N/A+
20127N/A+/* Libtsol functions */
20127N/A+
20127N/A+typedef int (*tsol_blequal) (const m_label_t *label1, const m_label_t *label2);
20127N/A+typedef int (*tsol_label_to_str) (const m_label_t *label, char **string,
20127N/A+ const m_label_str_t conversion_type,
20127N/A+ uint_t flags);
20127N/A+typedef int (*tsol_str_to_label) (const char *string, m_label_t **label,
20127N/A+ const m_label_type_t label_type, uint_t flags,
20127N/A+ int *error);
20127N/A+typedef void (*tsol_m_label_dup) (m_label_t **dst, const m_label_t *src);
20127N/A+typedef void (*tsol_m_label_free) (m_label_t *label);
20127N/A+
20127N/A+/* Other misc. libtsol functions that seem to be stable */
20127N/A+typedef blrange_t* (*tsol_getuserrange) (const char *username);
20127N/A+typedef int (*tsol_blinrange) (const m_label_t *label,
20127N/A+ const blrange_t *range);
20127N/A+typedef void (*tsol_blminimum) (m_label_t *minimum_label,
20127N/A+ const m_label_t *bounding_label);
20127N/A+typedef void (*tsol_blmaximum) (m_label_t *maximum_label,
20127N/A+ const m_label_t *bounding_label);
20127N/A+typedef m_label_t* (*tsol_blabel_alloc) (void);
20127N/A+typedef void (*tsol_blabel_free) (m_label_t *label_p);
20127N/A+typedef void (*tsol_bsllow) (m_label_t *label);
20127N/A+typedef void (*tsol_bslhigh) (m_label_t *label);
20127N/A+
20127N/A+/* libXtsol functions */
20127N/A+typedef Status (*xtsol_XTSOLgetClientLabel) (Display *dpy, XID xid,
20127N/A+ bslabel_t *sl);
20127N/A+typedef Bool (*xtsol_XTSOLIsWindowTrusted) (Display *dpy, Window win);
20127N/A+
20127N/A+/* libgnometsol functions */
20127N/A+typedef gpointer (*gnometsol_gnome_label_builder_new) (char *msg,
20127N/A+ blevel_t *upper, blevel_t *lower, int mode);
20127N/A+typedef GType (*gnometsol_gnome_label_builder_get_type) (void);
20127N/A+
20127N/A+/* libtsol functions */
20127N/A+tsol_blequal libtsol_blequal;
20127N/A+tsol_label_to_str libtsol_label_to_str;
20127N/A+tsol_str_to_label libtsol_str_to_label;
20127N/A+tsol_m_label_dup libtsol_m_label_dup;
20127N/A+tsol_m_label_free libtsol_m_label_free;
20127N/A+/* Other misc. libtsol functions */
20127N/A+tsol_blminimum libtsol_blminimum;
20127N/A+tsol_blmaximum libtsol_blmaximum;
20127N/A+tsol_blinrange libtsol_blinrange;
20127N/A+tsol_getuserrange libtsol_getuserrange;
20127N/A+tsol_blabel_alloc libtsol_blabel_alloc;
20127N/A+tsol_blabel_free libtsol_blabel_free;
20127N/A+tsol_bsllow libtsol_bsllow;
20127N/A+tsol_bslhigh libtsol_bslhigh;
20127N/A+
20127N/A+xtsol_XTSOLgetClientLabel libxtsol_XTSOLgetClientLabel;
20127N/A+xtsol_XTSOLIsWindowTrusted libxtsol_XTSOLIsWindowTrusted;
20127N/A+
20127N/A+gnometsol_gnome_label_builder_new libgnometsol_gnome_label_builder_new;
20127N/A+gnometsol_gnome_label_builder_get_type libgnometsol_gnome_label_builder_get_type;
20127N/A+
20127N/A+gboolean
20127N/A+use_trusted_extensions (void)
20127N/A+{
20127N/A+ static int trusted = -1;
20127N/A+
20127N/A+ /*
20127N/A+ * Sun Trusted Extensions (tm) for Solaris (tm) support. (Damn I should be a lawyer).
20127N/A+ *
20127N/A+ * It is necessary to use dlopen because the label aware extensions to libwnck work
20127N/A+ * only on systems with the trusted extensions installed and with the SUN_TSOL
20127N/A+ * xserver extension present
20127N/A+ */
20127N/A+
20127N/A+ if (trusted < 0) {
20127N/A+ static gpointer tsol_handle = NULL;
20127N/A+ static gpointer xtsol_handle = NULL;
20127N/A+ static gpointer gnometsol_handle = NULL;
20127N/A+
20127N/A+ if (getenv ("TRUSTED_SESSION") == NULL) {
20127N/A+ trusted = 0;
20127N/A+ return 0;
20127N/A+ }
20127N/A+
20127N/A+ tsol_handle = dlopen_tsol ();
20127N/A+ if (tsol_handle != NULL)
20127N/A+ xtsol_handle = dlopen_xtsol ();
20127N/A+ if (tsol_handle && xtsol_handle) {
20127N/A+
20127N/A+ /* libtsol functions */
20127N/A+ libtsol_blequal = (tsol_blequal) dlsym (tsol_handle, "blequal");
20127N/A+ libtsol_label_to_str = (tsol_label_to_str) dlsym (tsol_handle, "label_to_str");
20127N/A+ libtsol_str_to_label = (tsol_str_to_label) dlsym (tsol_handle, "str_to_label");
20127N/A+ libtsol_m_label_dup = (tsol_m_label_dup) dlsym (tsol_handle, "m_label_dup");
20127N/A+ libtsol_m_label_free = (tsol_m_label_free) dlsym (tsol_handle, "m_label_free");
20127N/A+
20127N/A+
20127N/A+ /* Other misc. libtsol functions */
20127N/A+ libtsol_blminimum = (tsol_blminimum) dlsym (tsol_handle, "blminimum");
20127N/A+ libtsol_blmaximum = (tsol_blmaximum) dlsym (tsol_handle, "blmaximum");
20127N/A+ libtsol_blinrange = (tsol_blinrange) dlsym (tsol_handle, "blinrange");
20127N/A+ libtsol_getuserrange = (tsol_getuserrange) dlsym (tsol_handle, "getuserrange");
20127N/A+ libtsol_blabel_alloc = (tsol_blabel_alloc) dlsym (tsol_handle, "blabel_alloc");
20127N/A+ libtsol_blabel_free = (tsol_blabel_free) dlsym (tsol_handle, "blabel_free");
20127N/A+ libtsol_bsllow = (tsol_bsllow) dlsym (tsol_handle, "bsllow");
20127N/A+ libtsol_bslhigh = (tsol_bslhigh) dlsym (tsol_handle, "bslhigh");
20127N/A+
20127N/A+ /* libXtsol functions */
20127N/A+ libxtsol_XTSOLgetClientLabel = (xtsol_XTSOLgetClientLabel) dlsym (xtsol_handle,
20127N/A+ "XTSOLgetClientLabel");
20127N/A+ libxtsol_XTSOLIsWindowTrusted = (xtsol_XTSOLIsWindowTrusted) dlsym (xtsol_handle,
20127N/A+ "XTSOLIsWindowTrusted");
20127N/A+
20127N/A+ if (libtsol_label_to_str == NULL ||
20127N/A+ libtsol_str_to_label == NULL ||
20127N/A+ libtsol_m_label_dup == NULL ||
20127N/A+ libtsol_m_label_free == NULL ||
20127N/A+ libtsol_blminimum == NULL ||
20127N/A+ libtsol_blmaximum == NULL ||
20127N/A+ libtsol_blinrange == NULL ||
20127N/A+ libtsol_getuserrange == NULL ||
20127N/A+ libtsol_blabel_alloc == NULL ||
20127N/A+ libtsol_blabel_free == NULL ||
20127N/A+ libtsol_bsllow == NULL ||
20127N/A+ libtsol_bslhigh == NULL ||
20127N/A+ libxtsol_XTSOLgetClientLabel == NULL ||
20127N/A+ libxtsol_XTSOLIsWindowTrusted == NULL) {
20127N/A+ dlclose (tsol_handle);
20127N/A+ dlclose (xtsol_handle);
20127N/A+ tsol_handle = NULL;
20127N/A+ xtsol_handle = NULL;
20127N/A+ }
20127N/A+ }
20127N/A+
20127N/A+ gnometsol_handle = dlopen_gnometsol ();
20127N/A+ if (gnometsol_handle != NULL) {
20127N/A+ libgnometsol_gnome_label_builder_new =
20127N/A+ (gnometsol_gnome_label_builder_new) dlsym (gnometsol_handle,
20127N/A+ "gnome_label_builder_new");
20127N/A+ libgnometsol_gnome_label_builder_get_type =
20127N/A+ (gnometsol_gnome_label_builder_get_type) dlsym (gnometsol_handle,
20127N/A+ "gnome_label_builder_get_type");
20127N/A+ if (libgnometsol_gnome_label_builder_new == NULL ||
20127N/A+ libgnometsol_gnome_label_builder_get_type == NULL)
20127N/A+ gnometsol_handle = NULL;
20127N/A+
20127N/A+ }
20127N/A+ trusted = ((tsol_handle != NULL) && (xtsol_handle != NULL) && (gnometsol_handle != NULL)) ? 1 : 0;
20127N/A+ }
20127N/A+ return trusted ? TRUE : FALSE;
20127N/A+}
20127N/A+
20127N/A+static gchar *
20127N/A+get_stripped_exec (const gchar *full_exec)
20127N/A+{
20127N/A+ gchar *str1, *str2, *retval, *p;
20127N/A+
20127N/A+ str1 = g_strdup (full_exec);
20127N/A+ p = strtok (str1, " ");
20127N/A+
20127N/A+ if (p != NULL)
20127N/A+ str2 = g_strdup (p);
20127N/A+ else
20127N/A+ str2 = g_strdup (full_exec);
20127N/A+
20127N/A+ g_free (str1);
20127N/A+
20127N/A+ if (g_path_is_absolute (str2)) {
20127N/A+ retval = g_strdup (str2);
20127N/A+ } else {
20127N/A+ retval = g_strdup (g_find_program_in_path ((const gchar *)str2));
20127N/A+ }
20127N/A+ g_free (str2);
20127N/A+
20127N/A+ return retval;
20127N/A+}
20127N/A+
20127N/A+static
20127N/A+char * get_validated_stripped_exec (const char *command)
20127N/A+{
20127N/A+ const char *username = NULL;
20127N/A+ char *stripped_cmd;
20127N/A+ char *path;
20127N/A+
20127N/A+ username = g_get_user_name ();
20127N/A+
20127N/A+ /* Do not use pfexec for root */
20127N/A+ if (strcmp (username, "root") == 0) {
20127N/A+ return NULL;
20127N/A+ }
20127N/A+
20127N/A+ stripped_cmd = get_stripped_exec (command);
20127N/A+ if (stripped_cmd == NULL) {
20127N/A+ return NULL;
20127N/A+ }
20127N/A+
20127N/A+ path = g_find_program_in_path (g_strstrip (stripped_cmd));
20127N/A+ if (path == NULL)
20127N/A+ return NULL;
20127N/A+
20127N/A+ return stripped_cmd;
20127N/A+}
20127N/A+
20127N/A+static gboolean
20127N/A+command_has_profile (const char *command)
20127N/A+{
20127N/A+ execattr_t *exec = NULL;
20127N/A+ gboolean rc = FALSE;
20127N/A+
20127N/A+ /* Check if the program is in any profile. */
20229N/A+ exec = getexecprof (NULL, KV_COMMAND, command, GET_ONE);
20127N/A+ if (exec == NULL) {
20127N/A+ return rc;
20127N/A+ }
20127N/A+
20127N/A+ while (exec != NULL) {
20900N/A+ if (exec->attr != NULL) {
20127N/A+ rc = TRUE;
20127N/A+ break;
20127N/A+ }
20127N/A+ exec = exec->next;
20127N/A+ }
20127N/A+
20127N/A+ free_execattr (exec);
20127N/A+
20127N/A+ return rc;
20127N/A+}
20127N/A+
20127N/A+static gboolean
20127N/A+use_pfexec (char *command)
20127N/A+{
20127N/A+ execattr_t *exec = NULL;
20127N/A+ const char *username = NULL;
20127N/A+ char *stripped_cmd;
20127N/A+ gboolean trusted;
20127N/A+ gboolean has_profile;
20127N/A+ gboolean rc;
20127N/A+
20127N/A+ rc = FALSE;
20127N/A+
20127N/A+ /* Never use pfexec in Trusted mode */
20127N/A+ trusted = use_trusted_extensions ();
20127N/A+ if (trusted) {
20127N/A+ goto out;
20127N/A+ }
20127N/A+
20127N/A+ stripped_cmd = get_validated_stripped_exec (command);
20127N/A+ if (stripped_cmd == NULL) {
20127N/A+ goto out;
20127N/A+ }
20127N/A+
20127N/A+ has_profile = command_has_profile (stripped_cmd);
20127N/A+
20127N/A+ username = g_get_user_name ();
20127N/A+
20127N/A+ /* Check if the user can run the command. */
20229N/A+ exec = getexecuser (username, KV_COMMAND, stripped_cmd, GET_ONE);
20127N/A+
20127N/A+ /*
20127N/A+ * If the program is not associated with any profile, then do not
20127N/A+ * use pfexec.
20127N/A+ */
20127N/A+ if (exec == NULL)
20127N/A+ goto out;
20127N/A+
20127N/A+ /*
20127N/A+ * If getexecuser does not return NULL and the program is not
20127N/A+ * associated with any profile, then pfexec is not needed.
20127N/A+ */
20127N/A+ if (has_profile == FALSE) {
20127N/A+ goto out;
20127N/A+ }
20127N/A+
20127N/A+ /*
20127N/A+ * Does the user have a profile that can run the command?
20127N/A+ */
20127N/A+ while (exec != NULL) {
20900N/A+ if (exec->attr != NULL) {
20127N/A+ rc = TRUE;
20127N/A+ break;
20127N/A+ }
20127N/A+ exec = exec->next;
20127N/A+ }
20127N/A+out:
20127N/A+ if (exec != NULL)
20127N/A+ free_execattr (exec);
20127N/A+
20127N/A+ if (stripped_cmd)
20127N/A+ g_free (stripped_cmd);
20127N/A+
20127N/A+ return rc;
20127N/A+}
20127N/A+
20127N/A+/*
20127N/A+ * Checks RBAC and if the user can run the command with gksu, the role is
20127N/A+ * passed back, otherwise NULL.
20127N/A+ */
20127N/A+gchar *
20127N/A+get_gksu_role (char *command)
20127N/A+{
20127N/A+ execattr_t *exec;
20127N/A+ userattr_t *user;
20127N/A+ const char *username = NULL;
20127N/A+ char *rc = NULL;
20127N/A+ char *stripped_cmd;
20127N/A+ char *path;
20127N/A+ int i;
20127N/A+ gboolean has_profile;
20127N/A+ gboolean trusted;
20127N/A+
20127N/A+ /* Never use gksu in Trusted mode */
20127N/A+ trusted = use_trusted_extensions ();
20127N/A+ if (trusted) {
20127N/A+ goto out;
20127N/A+ }
20127N/A+
20127N/A+ stripped_cmd = get_validated_stripped_exec (command);
20127N/A+ if (stripped_cmd == NULL) {
20127N/A+ goto out;
20127N/A+ }
20127N/A+
20127N/A+ /* If pfexec should be used, then do not use gksu. */
20127N/A+ if (use_pfexec (command) == TRUE) {
20127N/A+ goto out;
20127N/A+ }
20127N/A+
20127N/A+ has_profile = command_has_profile (stripped_cmd);
20127N/A+ username = g_get_user_name ();
20127N/A+
20127N/A+ /* Check if the user can run the command. */
20229N/A+ exec = getexecuser (username, KV_COMMAND, stripped_cmd, GET_ONE);
20127N/A+
20127N/A+ /*
20127N/A+ * If the program is not associated with any profile, then do not
20127N/A+ * use gksu.
20127N/A+ */
20127N/A+ if (exec == NULL)
20127N/A+ goto out;
20127N/A+
21861N/A+ free_execattr (exec);
21861N/A+
20127N/A+ /*
20127N/A+ * If getexecuser does not return NULL and the program is not
20127N/A+ * associated with any profile, then gksu is not needed.
20127N/A+ */
20127N/A+ if (has_profile == FALSE) {
20127N/A+ goto out;
20127N/A+ }
20127N/A+
20127N/A+ /* If no gksu is available, then do not try to use it */
21861N/A+ path = g_find_program_in_path ("/usr/bin/gksu");
20127N/A+ if (path == NULL)
20127N/A+ goto out;
20127N/A+
20127N/A+ /* Check if the user is in a role that can run the command. */
20127N/A+ /* If so, use gksu with that role */
20127N/A+ if ((user = getusernam (username)) != NULL) {
20127N/A+ const char *rolelist = NULL;
20127N/A+ char **v = NULL;
20127N/A+ char *role = NULL;
20127N/A+
20127N/A+ /* Use roles associated with the user. */
20127N/A+ rolelist = kva_match (user->attr, USERATTR_ROLES_KW);
20127N/A+
20127N/A+ if (rolelist != NULL)
20127N/A+ v = g_strsplit (rolelist, ",", -1);
20127N/A+
20127N/A+ for (i=0; v != NULL && v[i] != NULL; i++) {
20127N/A+ role = g_strdup (v[i]);
20127N/A+ g_strstrip (role);
20127N/A+
20229N/A+ exec = getexecuser (role, KV_COMMAND, stripped_cmd, GET_ONE);
20127N/A+ while (exec != NULL) {
20127N/A+ if ((strcmp (role, "root") == 0) ||
20900N/A+ (exec->attr != NULL)) {
20127N/A+ rc = g_strdup (role);
20127N/A+ break;
20127N/A+ }
20127N/A+ exec = exec->next;
20127N/A+ }
20127N/A+
20127N/A+ g_free (role);
20127N/A+ free_execattr (exec);
20127N/A+
20127N/A+ if (rc != NULL) {
20127N/A+ break;
20127N/A+ }
20127N/A+ }
20127N/A+ if (v != NULL)
20127N/A+ g_strfreev (v);
20127N/A+ }
20127N/A+
20127N/A+out:
20127N/A+ if (stripped_cmd)
20127N/A+ g_free (stripped_cmd);
20127N/A+
20127N/A+ return (rc);
20127N/A+}
20127N/A+
20127N/A static gboolean
20127N/A egg_desktop_file_launchv (EggDesktopFile *desktop_file,
20127N/A GSList *documents, va_list args,
20127N/A@@ -1078,6 +1532,9 @@ egg_desktop_file_launchv (EggDesktopFile
20127N/A gboolean success, current_success;
20127N/A GdkDisplay *display;
20127N/A char *startup_id;
20127N/A+ char *gksu_role, *final_cmd;
20127N/A+ struct passwd *pw;
20127N/A+ uid_t uid;
20127N/A
20127N/A GPtrArray *env = NULL;
20127N/A char **variables = NULL;
20127N/A@@ -1200,11 +1657,42 @@ egg_desktop_file_launchv (EggDesktopFile
20127N/A if (!command)
20127N/A goto out;
20127N/A
20127N/A- if (!g_shell_parse_argv (command, &argc, &argv, error))
20127N/A- {
20127N/A+ /* Only use a prefix if not in Trusted mode */
20127N/A+ gksu_role = NULL;
20127N/A+ if (!use_trusted_extensions ())
20127N/A+ gksu_role = get_gksu_role (command);
20127N/A+
20127N/A+ final_cmd = NULL;
20127N/A+ if (command != NULL)
20127N/A+ {
20127N/A+ /* Only use a prefix if not in Trusted mode */
20127N/A+ gksu_role = NULL;
20127N/A+ if (!use_trusted_extensions ())
20127N/A+ gksu_role = get_gksu_role (command);
20127N/A+
20127N/A+ uid = getuid ();
20127N/A+ pw = getpwuid (uid);
20127N/A+
20127N/A+ if (gksu_role)
20127N/A+ final_cmd = g_strdup_printf ("/usr/bin/gksu -u %s %s", gksu_role, command);
20127N/A+ else if (use_pfexec (command) == TRUE ||
20127N/A+ (pw != NULL && pw->pw_shell != NULL &&
20127N/A+ strncmp (pw->pw_shell, "/usr/bin/pf", strlen ("/usr/bin/pf")) == 0))
20127N/A+ final_cmd = g_strdup_printf ("/usr/bin/pfexec %s", command);
20127N/A+ else
20127N/A+ final_cmd = g_strdup_printf ("%s", command);
20127N/A+ }
20127N/A+
20127N/A+ if (gksu_role)
20127N/A+ g_free (gksu_role);
20127N/A+
20127N/A+ if (!g_shell_parse_argv (final_cmd, &argc, &argv, error))
20127N/A+ {
20127N/A+ g_free (final_cmd);
20127N/A g_free (command);
20127N/A goto out;
20127N/A }
20127N/A+ g_free (final_cmd);
20127N/A g_free (command);
20127N/A
20127N/A #if GTK_CHECK_VERSION (2, 12, 0)