diff options
author | James Meyer <james.meyer@operamail.com> | 2012-08-07 20:44:06 (GMT) |
---|---|---|
committer | James Meyer <james.meyer@operamail.com> | 2012-08-07 20:44:06 (GMT) |
commit | 1286c7f751a1a20d08b1a85445b4757c712b203b (patch) | |
tree | 1c50311f7d4963a7836745293de29ae0fa0c4447 | |
parent | 6073f35662d91dad364bd03a1760eca93860d0c3 (diff) | |
download | linhes_pkgbuild-1286c7f751a1a20d08b1a85445b4757c712b203b.zip linhes_pkgbuild-1286c7f751a1a20d08b1a85445b4757c712b203b.tar.gz linhes_pkgbuild-1286c7f751a1a20d08b1a85445b4757c712b203b.tar.bz2 |
polkit .105
-rw-r--r-- | abs/extra/polkit/CVE-2011-1485.patch | 908 | ||||
-rw-r--r-- | abs/extra/polkit/PKGBUILD | 23 | ||||
-rw-r--r-- | abs/extra/polkit/systemd-fallback.patch | 1571 |
3 files changed, 1583 insertions, 919 deletions
diff --git a/abs/extra/polkit/CVE-2011-1485.patch b/abs/extra/polkit/CVE-2011-1485.patch deleted file mode 100644 index f7054a6..0000000 --- a/abs/extra/polkit/CVE-2011-1485.patch +++ /dev/null @@ -1,908 +0,0 @@ -From dd848a42a64a3b22a0cc60f6657b56ce9b6010ae Mon Sep 17 00:00:00 2001 -From: David Zeuthen <davidz@redhat.com> -Date: Thu, 31 Mar 2011 16:59:09 +0000 -Subject: PolkitUnixProcess: Clarify that the real uid is returned, not the effective one - -On Linux, also switch to parsing /proc/<pid>/status instead of relying -on the st_uid returned by stat(2) to be the uid we want. - -This was pointed out by Neel Mehta <nmehta@google.com>. Thanks! - -Signed-off-by: David Zeuthen <davidz@redhat.com> ---- -diff --git a/src/polkit/polkitunixprocess.c b/src/polkit/polkitunixprocess.c -index d95a1d4..876da69 100644 ---- a/src/polkit/polkitunixprocess.c -+++ b/src/polkit/polkitunixprocess.c -@@ -24,9 +24,7 @@ - #endif - - #include <sys/types.h> --#ifndef HAVE_FREEBSD --#include <sys/stat.h> --#else -+#ifdef HAVE_FREEBSD - #include <sys/param.h> - #include <sys/sysctl.h> - #include <sys/user.h> -@@ -34,6 +32,7 @@ - #include <stdlib.h> - #include <string.h> - #include <errno.h> -+#include <stdio.h> - - #include "polkitunixprocess.h" - #include "polkitsubject.h" -@@ -208,6 +207,8 @@ polkit_unix_process_get_pid (PolkitUnixProcess *process) - * - * Gets the uid of the owner of @process. - * -+ * Note that this returns the real user-id (not the effective user-id) of @process. -+ * - * Returns: The UNIX user id of the owner for @process or 0 if @error is set. - **/ - gint -@@ -215,17 +216,21 @@ polkit_unix_process_get_owner (PolkitUnixProcess *process, - GError **error) - { - gint result; -+ gchar *contents; -+ gchar **lines; - #ifdef HAVE_FREEBSD - struct kinfo_proc p; - #else -- struct stat statbuf; -- char procbuf[32]; -+ gchar filename[64]; -+ guint n; - #endif - - g_return_val_if_fail (POLKIT_IS_UNIX_PROCESS (process), 0); - g_return_val_if_fail (error == NULL || *error == NULL, 0); - - result = 0; -+ lines = NULL; -+ contents = NULL; - - #ifdef HAVE_FREEBSD - if (get_kinfo_proc (process->pid, &p) == 0) -@@ -241,23 +246,52 @@ polkit_unix_process_get_owner (PolkitUnixProcess *process, - - result = p.ki_uid; - #else -- g_snprintf (procbuf, sizeof procbuf, "/proc/%d", process->pid); -- if (stat (procbuf, &statbuf) != 0) -+ -+ /* see 'man proc' for layout of the status file -+ * -+ * Uid, Gid: Real, effective, saved set, and file system UIDs (GIDs). -+ */ -+ g_snprintf (filename, sizeof filename, "/proc/%d/status", process->pid); -+ if (!g_file_get_contents (filename, -+ &contents, -+ NULL, -+ error)) - { -- g_set_error (error, -- POLKIT_ERROR, -- POLKIT_ERROR_FAILED, -- "stat() failed for /proc/%d: %s", -- process->pid, -- g_strerror (errno)); - goto out; - } -+ lines = g_strsplit (contents, "\n", -1); -+ for (n = 0; lines != NULL && lines[n] != NULL; n++) -+ { -+ gint real_uid, effective_uid; -+ if (!g_str_has_prefix (lines[n], "Uid:")) -+ continue; -+ if (sscanf (lines[n] + 4, "%d %d", &real_uid, &effective_uid) != 2) -+ { -+ g_set_error (error, -+ POLKIT_ERROR, -+ POLKIT_ERROR_FAILED, -+ "Unexpected line `%s' in file %s", -+ lines[n], -+ filename); -+ goto out; -+ } -+ else -+ { -+ result = real_uid; -+ goto out; -+ } -+ } - -- result = statbuf.st_uid; -+ g_set_error (error, -+ POLKIT_ERROR, -+ POLKIT_ERROR_FAILED, -+ "Didn't find any line starting with `Uid:' in file %s", -+ filename); - #endif - -- out: -- -+out: -+ g_strfreev (lines); -+ g_free (contents); - return result; - } - --- -cgit v0.8.3-6-g21f6 -From 129b6223a19e7fb2753f8cad7957ac5402394076 Mon Sep 17 00:00:00 2001 -From: David Zeuthen <davidz@redhat.com> -Date: Fri, 01 Apr 2011 16:09:45 +0000 -Subject: Make PolkitUnixProcess also record the uid of the process - -This is needed to avoid possible TOCTTOU issues since a process can -change both its real uid and effective uid. - -Signed-off-by: David Zeuthen <davidz@redhat.com> ---- -diff --git a/docs/polkit/polkit-1-sections.txt b/docs/polkit/polkit-1-sections.txt -index 12141e3..9f4fcf8 100644 ---- a/docs/polkit/polkit-1-sections.txt -+++ b/docs/polkit/polkit-1-sections.txt -@@ -145,10 +145,13 @@ POLKIT_UNIX_SESSION_GET_CLASS - PolkitUnixProcess - polkit_unix_process_new - polkit_unix_process_new_full -+polkit_unix_process_new_for_owner -+polkit_unix_process_set_pid - polkit_unix_process_get_pid -+polkit_unix_process_set_start_time - polkit_unix_process_get_start_time --polkit_unix_process_set_pid --polkit_unix_process_get_owner -+polkit_unix_process_set_uid -+polkit_unix_process_get_uid - <SUBSECTION Standard> - PolkitUnixProcessClass - POLKIT_UNIX_PROCESS -diff --git a/src/polkit/polkitsubject.c b/src/polkit/polkitsubject.c -index 577afec..d2c4c20 100644 ---- a/src/polkit/polkitsubject.c -+++ b/src/polkit/polkitsubject.c -@@ -238,13 +238,18 @@ polkit_subject_from_string (const gchar *str, - { - gint scanned_pid; - guint64 scanned_starttime; -- if (sscanf (str, "unix-process:%d:%" G_GUINT64_FORMAT, &scanned_pid, &scanned_starttime) == 2) -+ gint scanned_uid; -+ if (sscanf (str, "unix-process:%d:%" G_GUINT64_FORMAT ":%d", &scanned_pid, &scanned_starttime, &scanned_uid) == 3) -+ { -+ subject = polkit_unix_process_new_for_owner (scanned_pid, scanned_starttime, scanned_uid); -+ } -+ else if (sscanf (str, "unix-process:%d:%" G_GUINT64_FORMAT, &scanned_pid, &scanned_starttime) == 2) - { - subject = polkit_unix_process_new_full (scanned_pid, scanned_starttime); - } - else if (sscanf (str, "unix-process:%d", &scanned_pid) == 1) - { -- subject = polkit_unix_process_new_full (scanned_pid, 0); -+ subject = polkit_unix_process_new (scanned_pid); - if (polkit_unix_process_get_start_time (POLKIT_UNIX_PROCESS (subject)) == 0) - { - g_object_unref (subject); -@@ -297,6 +302,8 @@ polkit_subject_to_gvariant (PolkitSubject *subject) - g_variant_new_uint32 (polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject)))); - g_variant_builder_add (&builder, "{sv}", "start-time", - g_variant_new_uint64 (polkit_unix_process_get_start_time (POLKIT_UNIX_PROCESS (subject)))); -+ g_variant_builder_add (&builder, "{sv}", "uid", -+ g_variant_new_int32 (polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)))); - } - else if (POLKIT_IS_UNIX_SESSION (subject)) - { -@@ -395,6 +402,7 @@ polkit_subject_new_for_gvariant (GVariant *variant, - GVariant *v; - guint32 pid; - guint64 start_time; -+ gint32 uid; - - v = lookup_asv (details_gvariant, "pid", G_VARIANT_TYPE_UINT32, error); - if (v == NULL) -@@ -414,7 +422,18 @@ polkit_subject_new_for_gvariant (GVariant *variant, - start_time = g_variant_get_uint64 (v); - g_variant_unref (v); - -- ret = polkit_unix_process_new_full (pid, start_time); -+ v = lookup_asv (details_gvariant, "uid", G_VARIANT_TYPE_INT32, error); -+ if (v != NULL) -+ { -+ uid = g_variant_get_int32 (v); -+ g_variant_unref (v); -+ } -+ else -+ { -+ uid = -1; -+ } -+ -+ ret = polkit_unix_process_new_for_owner (pid, start_time, uid); - } - else if (g_strcmp0 (kind, "unix-session") == 0) - { -diff --git a/src/polkit/polkitunixprocess.c b/src/polkit/polkitunixprocess.c -index 876da69..913be3a 100644 ---- a/src/polkit/polkitunixprocess.c -+++ b/src/polkit/polkitunixprocess.c -@@ -62,6 +62,7 @@ struct _PolkitUnixProcess - - gint pid; - guint64 start_time; -+ gint uid; - }; - - struct _PolkitUnixProcessClass -@@ -74,6 +75,7 @@ enum - PROP_0, - PROP_PID, - PROP_START_TIME, -+ PROP_UID - }; - - static void subject_iface_init (PolkitSubjectIface *subject_iface); -@@ -81,6 +83,9 @@ static void subject_iface_init (PolkitSubjectIface *subject_iface); - static guint64 get_start_time_for_pid (gint pid, - GError **error); - -+static gint _polkit_unix_process_get_owner (PolkitUnixProcess *process, -+ GError **error); -+ - #ifdef HAVE_FREEBSD - static gboolean get_kinfo_proc (gint pid, struct kinfo_proc *p); - #endif -@@ -92,6 +97,7 @@ G_DEFINE_TYPE_WITH_CODE (PolkitUnixProcess, polkit_unix_process, G_TYPE_OBJECT, - static void - polkit_unix_process_init (PolkitUnixProcess *unix_process) - { -+ unix_process->uid = -1; - } - - static void -@@ -108,6 +114,10 @@ polkit_unix_process_get_property (GObject *object, - g_value_set_int (value, unix_process->pid); - break; - -+ case PROP_UID: -+ g_value_set_int (value, unix_process->uid); -+ break; -+ - case PROP_START_TIME: - g_value_set_uint64 (value, unix_process->start_time); - break; -@@ -132,6 +142,14 @@ polkit_unix_process_set_property (GObject *object, - polkit_unix_process_set_pid (unix_process, g_value_get_int (value)); - break; - -+ case PROP_UID: -+ polkit_unix_process_set_uid (unix_process, g_value_get_int (value)); -+ break; -+ -+ case PROP_START_TIME: -+ polkit_unix_process_set_start_time (unix_process, g_value_get_uint64 (value)); -+ break; -+ - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; -@@ -139,12 +157,39 @@ polkit_unix_process_set_property (GObject *object, - } - - static void -+polkit_unix_process_constructed (GObject *object) -+{ -+ PolkitUnixProcess *process = POLKIT_UNIX_PROCESS (object); -+ -+ /* sets start_time and uid in case they are unset */ -+ -+ if (process->start_time == 0) -+ process->start_time = get_start_time_for_pid (process->pid, NULL); -+ -+ if (process->uid == -1) -+ { -+ GError *error; -+ error = NULL; -+ process->uid = _polkit_unix_process_get_owner (process, &error); -+ if (error != NULL) -+ { -+ process->uid = -1; -+ g_error_free (error); -+ } -+ } -+ -+ if (G_OBJECT_CLASS (polkit_unix_process_parent_class)->constructed != NULL) -+ G_OBJECT_CLASS (polkit_unix_process_parent_class)->constructed (object); -+} -+ -+static void - polkit_unix_process_class_init (PolkitUnixProcessClass *klass) - { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->get_property = polkit_unix_process_get_property; - gobject_class->set_property = polkit_unix_process_set_property; -+ gobject_class->constructed = polkit_unix_process_constructed; - - /** - * PolkitUnixProcess:pid: -@@ -156,7 +201,7 @@ polkit_unix_process_class_init (PolkitUnixProcessClass *klass) - g_param_spec_int ("pid", - "Process ID", - "The UNIX process ID", -- -1, -+ 0, - G_MAXINT, - 0, - G_PARAM_CONSTRUCT | -@@ -166,6 +211,27 @@ polkit_unix_process_class_init (PolkitUnixProcessClass *klass) - G_PARAM_STATIC_NICK)); - - /** -+ * PolkitUnixProcess:uid: -+ * -+ * The UNIX user id of the process or -1 if unknown. -+ * -+ * Note that this is the real user-id, not the effective user-id. -+ */ -+ g_object_class_install_property (gobject_class, -+ PROP_UID, -+ g_param_spec_int ("uid", -+ "User ID", -+ "The UNIX user ID", -+ -1, -+ G_MAXINT, -+ -1, -+ G_PARAM_CONSTRUCT | -+ G_PARAM_READWRITE | -+ G_PARAM_STATIC_NAME | -+ G_PARAM_STATIC_BLURB | -+ G_PARAM_STATIC_NICK)); -+ -+ /** - * PolkitUnixProcess:start-time: - * - * The start time of the process. -@@ -178,7 +244,8 @@ polkit_unix_process_class_init (PolkitUnixProcessClass *klass) - 0, - G_MAXUINT64, - 0, -- G_PARAM_READABLE | -+ G_PARAM_CONSTRUCT | -+ G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_BLURB | - G_PARAM_STATIC_NICK)); -@@ -186,113 +253,50 @@ polkit_unix_process_class_init (PolkitUnixProcessClass *klass) - } - - /** -- * polkit_unix_process_get_pid: -+ * polkit_unix_process_get_uid: - * @process: A #PolkitUnixProcess. - * -- * Gets the process id for @process. -+ * Gets the user id for @process. Note that this is the real user-id, -+ * not the effective user-id. - * -- * Returns: The process id for @process. -+ * Returns: The user id for @process or -1 if unknown. - */ - gint --polkit_unix_process_get_pid (PolkitUnixProcess *process) -+polkit_unix_process_get_uid (PolkitUnixProcess *process) - { -- g_return_val_if_fail (POLKIT_IS_UNIX_PROCESS (process), 0); -- return process->pid; -+ g_return_val_if_fail (POLKIT_IS_UNIX_PROCESS (process), -1); -+ return process->uid; - } - - /** -- * polkit_unix_process_get_owner: -+ * polkit_unix_process_set_uid: - * @process: A #PolkitUnixProcess. -- * @error: (allow-none): Return location for error or %NULL. -+ * @uid: The user id to set for @process or -1 to unset it. - * -- * Gets the uid of the owner of @process. -+ * Sets the (real, not effective) user id for @process. -+ */ -+void -+polkit_unix_process_set_uid (PolkitUnixProcess *process, -+ gint uid) -+{ -+ g_return_if_fail (POLKIT_IS_UNIX_PROCESS (process)); -+ g_return_if_fail (uid >= -1); -+ process->uid = uid; -+} -+ -+/** -+ * polkit_unix_process_get_pid: -+ * @process: A #PolkitUnixProcess. - * -- * Note that this returns the real user-id (not the effective user-id) of @process. -+ * Gets the process id for @process. - * -- * Returns: The UNIX user id of the owner for @process or 0 if @error is set. -- **/ -+ * Returns: The process id for @process. -+ */ - gint --polkit_unix_process_get_owner (PolkitUnixProcess *process, -- GError **error) -+polkit_unix_process_get_pid (PolkitUnixProcess *process) - { -- gint result; -- gchar *contents; -- gchar **lines; --#ifdef HAVE_FREEBSD -- struct kinfo_proc p; --#else -- gchar filename[64]; -- guint n; --#endif -- - g_return_val_if_fail (POLKIT_IS_UNIX_PROCESS (process), 0); -- g_return_val_if_fail (error == NULL || *error == NULL, 0); -- -- result = 0; -- lines = NULL; -- contents = NULL; -- --#ifdef HAVE_FREEBSD -- if (get_kinfo_proc (process->pid, &p) == 0) -- { -- g_set_error (error, -- POLKIT_ERROR, -- POLKIT_ERROR_FAILED, -- "get_kinfo_proc() failed for pid %d: %s", -- process->pid, -- g_strerror (errno)); -- goto out; -- } -- -- result = p.ki_uid; --#else -- -- /* see 'man proc' for layout of the status file -- * -- * Uid, Gid: Real, effective, saved set, and file system UIDs (GIDs). -- */ -- g_snprintf (filename, sizeof filename, "/proc/%d/status", process->pid); -- if (!g_file_get_contents (filename, -- &contents, -- NULL, -- error)) -- { -- goto out; -- } -- lines = g_strsplit (contents, "\n", -1); -- for (n = 0; lines != NULL && lines[n] != NULL; n++) -- { -- gint real_uid, effective_uid; -- if (!g_str_has_prefix (lines[n], "Uid:")) -- continue; -- if (sscanf (lines[n] + 4, "%d %d", &real_uid, &effective_uid) != 2) -- { -- g_set_error (error, -- POLKIT_ERROR, -- POLKIT_ERROR_FAILED, -- "Unexpected line `%s' in file %s", -- lines[n], -- filename); -- goto out; -- } -- else -- { -- result = real_uid; -- goto out; -- } -- } -- -- g_set_error (error, -- POLKIT_ERROR, -- POLKIT_ERROR_FAILED, -- "Didn't find any line starting with `Uid:' in file %s", -- filename); --#endif -- --out: -- g_strfreev (lines); -- g_free (contents); -- return result; -+ return process->pid; - } - - /** -@@ -311,6 +315,21 @@ polkit_unix_process_get_start_time (PolkitUnixProcess *process) - } - - /** -+ * polkit_unix_process_set_start_time: -+ * @process: A #PolkitUnixProcess. -+ * @start_time: The start time for @pid. -+ * -+ * Set the start time of @process. -+ */ -+void -+polkit_unix_process_set_start_time (PolkitUnixProcess *process, -+ guint64 start_time) -+{ -+ g_return_if_fail (POLKIT_IS_UNIX_PROCESS (process)); -+ process->start_time = start_time; -+} -+ -+/** - * polkit_unix_process_set_pid: - * @process: A #PolkitUnixProcess. - * @pid: A process id. -@@ -323,18 +342,17 @@ polkit_unix_process_set_pid (PolkitUnixProcess *process, - { - g_return_if_fail (POLKIT_IS_UNIX_PROCESS (process)); - process->pid = pid; -- if (pid != (gint) -1) -- process->start_time = get_start_time_for_pid (pid, NULL); - } - - /** - * polkit_unix_process_new: - * @pid: The process id. - * -- * Creates a new #PolkitUnixProcess for @pid. The start time of the -- * process will be looked up in using e.g. the -- * <filename>/proc</filename> filesystem depending on the platform in -- * use. -+ * Creates a new #PolkitUnixProcess for @pid. -+ * -+ * The uid and start time of the process will be looked up in using -+ * e.g. the <filename>/proc</filename> filesystem depending on the -+ * platform in use. - * - * Returns: (transfer full): A #PolkitSubject. Free with g_object_unref(). - */ -@@ -353,22 +371,42 @@ polkit_unix_process_new (gint pid) - * - * Creates a new #PolkitUnixProcess object for @pid and @start_time. - * -+ * The uid of the process will be looked up in using e.g. the -+ * <filename>/proc</filename> filesystem depending on the platform in -+ * use. -+ * - * Returns: (transfer full): A #PolkitSubject. Free with g_object_unref(). - */ - PolkitSubject * - polkit_unix_process_new_full (gint pid, - guint64 start_time) - { -- PolkitUnixProcess *process; -- -- process = POLKIT_UNIX_PROCESS (polkit_unix_process_new ((gint) -1)); -- process->pid = pid; -- if (start_time != 0) -- process->start_time = start_time; -- else -- process->start_time = get_start_time_for_pid (pid, NULL); -+ return POLKIT_SUBJECT (g_object_new (POLKIT_TYPE_UNIX_PROCESS, -+ "pid", pid, -+ "start_time", start_time, -+ NULL)); -+} - -- return POLKIT_SUBJECT (process); -+/** -+ * polkit_unix_process_new_for_owner: -+ * @pid: The process id. -+ * @start_time: The start time for @pid or 0 to look it up in e.g. <filename>/proc</filename>. -+ * @uid: The (real, not effective) uid of the owner of @pid or -1 to look it up in e.g. <filename>/proc</filename>. -+ * -+ * Creates a new #PolkitUnixProcess object for @pid, @start_time and @uid. -+ * -+ * Returns: (transfer full): A #PolkitSubject. Free with g_object_unref(). -+ */ -+PolkitSubject * -+polkit_unix_process_new_for_owner (gint pid, -+ guint64 start_time, -+ gint uid) -+{ -+ return POLKIT_SUBJECT (g_object_new (POLKIT_TYPE_UNIX_PROCESS, -+ "pid", pid, -+ "start_time", start_time, -+ "uid", uid, -+ NULL)); - } - - static guint -@@ -616,3 +654,95 @@ out: - - return start_time; - } -+ -+static gint -+_polkit_unix_process_get_owner (PolkitUnixProcess *process, -+ GError **error) -+{ -+ gint result; -+ gchar *contents; -+ gchar **lines; -+#ifdef HAVE_FREEBSD -+ struct kinfo_proc p; -+#else -+ gchar filename[64]; -+ guint n; -+#endif -+ -+ g_return_val_if_fail (POLKIT_IS_UNIX_PROCESS (process), 0); -+ g_return_val_if_fail (error == NULL || *error == NULL, 0); -+ -+ result = 0; -+ lines = NULL; -+ contents = NULL; -+ -+#ifdef HAVE_FREEBSD -+ if (get_kinfo_proc (process->pid, &p) == 0) -+ { -+ g_set_error (error, -+ POLKIT_ERROR, -+ POLKIT_ERROR_FAILED, -+ "get_kinfo_proc() failed for pid %d: %s", -+ process->pid, -+ g_strerror (errno)); -+ goto out; -+ } -+ -+ result = p.ki_uid; -+#else -+ -+ /* see 'man proc' for layout of the status file -+ * -+ * Uid, Gid: Real, effective, saved set, and file system UIDs (GIDs). -+ */ -+ g_snprintf (filename, sizeof filename, "/proc/%d/status", process->pid); -+ if (!g_file_get_contents (filename, -+ &contents, -+ NULL, -+ error)) -+ { -+ goto out; -+ } -+ lines = g_strsplit (contents, "\n", -1); -+ for (n = 0; lines != NULL && lines[n] != NULL; n++) -+ { -+ gint real_uid, effective_uid; -+ if (!g_str_has_prefix (lines[n], "Uid:")) -+ continue; -+ if (sscanf (lines[n] + 4, "%d %d", &real_uid, &effective_uid) != 2) -+ { -+ g_set_error (error, -+ POLKIT_ERROR, -+ POLKIT_ERROR_FAILED, -+ "Unexpected line `%s' in file %s", -+ lines[n], -+ filename); -+ goto out; -+ } -+ else -+ { -+ result = real_uid; -+ goto out; -+ } -+ } -+ -+ g_set_error (error, -+ POLKIT_ERROR, -+ POLKIT_ERROR_FAILED, -+ "Didn't find any line starting with `Uid:' in file %s", -+ filename); -+#endif -+ -+out: -+ g_strfreev (lines); -+ g_free (contents); -+ return result; -+} -+ -+/* deprecated public method */ -+gint -+polkit_unix_process_get_owner (PolkitUnixProcess *process, -+ GError **error) -+{ -+ return _polkit_unix_process_get_owner (process, error); -+} -diff --git a/src/polkit/polkitunixprocess.h b/src/polkit/polkitunixprocess.h -index b88cd03..531a57d 100644 ---- a/src/polkit/polkitunixprocess.h -+++ b/src/polkit/polkitunixprocess.h -@@ -47,16 +47,24 @@ typedef struct _PolkitUnixProcess PolkitUnixProcess; - typedef struct _PolkitUnixProcessClass PolkitUnixProcessClass; - - GType polkit_unix_process_get_type (void) G_GNUC_CONST; --PolkitSubject *polkit_unix_process_new (gint pid); --PolkitSubject *polkit_unix_process_new_full (gint pid, -- guint64 start_time); -- -+PolkitSubject *polkit_unix_process_new (gint pid); -+PolkitSubject *polkit_unix_process_new_full (gint pid, -+ guint64 start_time); -+PolkitSubject *polkit_unix_process_new_for_owner (gint pid, -+ guint64 start_time, -+ gint uid); - gint polkit_unix_process_get_pid (PolkitUnixProcess *process); - guint64 polkit_unix_process_get_start_time (PolkitUnixProcess *process); -+gint polkit_unix_process_get_uid (PolkitUnixProcess *process); - void polkit_unix_process_set_pid (PolkitUnixProcess *process, - gint pid); -+void polkit_unix_process_set_uid (PolkitUnixProcess *process, -+ gint uid); -+void polkit_unix_process_set_start_time (PolkitUnixProcess *process, -+ guint64 start_time); -+ - gint polkit_unix_process_get_owner (PolkitUnixProcess *process, -- GError **error); -+ GError **error) G_GNUC_DEPRECATED_FOR (polkit_unix_process_get_uid); - - G_END_DECLS - --- -cgit v0.8.3-6-g21f6 -From c23d74447c7615dc74dae259f0fc3688ec988867 Mon Sep 17 00:00:00 2001 -From: David Zeuthen <davidz@redhat.com> -Date: Fri, 01 Apr 2011 16:12:27 +0000 -Subject: Use polkit_unix_process_get_uid() to get the owner of a process - -This avoids a TOCTTOU problem. - -Signed-off-by: David Zeuthen <davidz@redhat.com> ---- -diff --git a/src/polkitbackend/polkitbackendsessionmonitor.c b/src/polkitbackend/polkitbackendsessionmonitor.c -index 495f752..9c331b6 100644 ---- a/src/polkitbackend/polkitbackendsessionmonitor.c -+++ b/src/polkitbackend/polkitbackendsessionmonitor.c -@@ -293,14 +293,15 @@ polkit_backend_session_monitor_get_user_for_subject (PolkitBackendSessionMonitor - - if (POLKIT_IS_UNIX_PROCESS (subject)) - { -- local_error = NULL; -- uid = polkit_unix_process_get_owner (POLKIT_UNIX_PROCESS (subject), &local_error); -- if (local_error != NULL) -+ uid = polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)); -+ if ((gint) uid == -1) - { -- g_propagate_prefixed_error (error, local_error, "Error getting user for process: "); -+ g_set_error (error, -+ POLKIT_ERROR, -+ POLKIT_ERROR_FAILED, -+ "Unix process subject does not have uid set"); - goto out; - } -- - ret = polkit_unix_user_new (uid); - } - else if (POLKIT_IS_SYSTEM_BUS_NAME (subject)) --- -cgit v0.8.3-6-g21f6 -From 3b12cfac29dddd27f1f166a7574d8374cc1dccf2 Mon Sep 17 00:00:00 2001 -From: David Zeuthen <davidz@redhat.com> -Date: Fri, 01 Apr 2011 16:13:15 +0000 -Subject: pkexec: Avoid TOCTTOU problems with parent process - -In a nutshell, the parent process may change its uid (either real- or -effective uid) after launching pkexec. It can do this by exec()'ing -e.g. a setuid root program. - -To avoid this problem, just use the uid the parent process had when it -executed pkexec. This happens to be the same uid of the pkexec process -itself. - -Additionally, remove some dubious code that allowed pkexec to continue -when the parent process died as there is no reason to support -something like that. Also ensure that the pkexec process is killed if -the parent process dies. - -This problem was pointed out by Neel Mehta <nmehta@google.com>. - -Signed-off-by: David Zeuthen <davidz@redhat.com> ---- -diff --git a/src/programs/pkexec.c b/src/programs/pkexec.c -index 9217954..3e656be 100644 ---- a/src/programs/pkexec.c -+++ b/src/programs/pkexec.c -@@ -35,6 +35,10 @@ - #include <pwd.h> - #include <errno.h> - -+#ifdef __linux__ -+#include <sys/prctl.h> -+#endif -+ - #include <glib/gi18n.h> - - #ifdef POLKIT_AUTHFW_PAM -@@ -423,7 +427,6 @@ main (int argc, char *argv[]) - GPtrArray *saved_env; - gchar *opt_user; - pid_t pid_of_caller; -- uid_t uid_of_caller; - gpointer local_agent_handle; - - ret = 127; -@@ -598,40 +601,49 @@ main (int argc, char *argv[]) - */ - g_type_init (); - -- /* now check if the program that invoked us is authorized */ -+ /* make sure we are nuked if the parent process dies */ -+#ifdef __linux__ -+ if (prctl (PR_SET_PDEATHSIG, SIGTERM) != 0) -+ { -+ g_printerr ("prctl(PR_SET_PDEATHSIG, SIGTERM) failed: %s\n", g_strerror (errno)); -+ goto out; -+ } -+#else -+#warning "Please add OS specific code to catch when the parent dies" -+#endif -+ -+ /* Figure out the parent process */ - pid_of_caller = getppid (); - if (pid_of_caller == 1) - { - /* getppid() can return 1 if the parent died (meaning that we are reaped -- * by /sbin/init); get process group leader instead - for example, this -- * happens when launching via gnome-panel (alt+f2, then 'pkexec gedit'). -+ * by /sbin/init); In that case we simpy bail. - */ -- pid_of_caller = getpgrp (); -- } -- -- subject = polkit_unix_process_new (pid_of_caller); -- if (subject == NULL) -- { -- g_printerr ("No such process for pid %d: %s\n", (gint) pid_of_caller, error->message); -- g_error_free (error); -+ g_printerr ("Refusing to render service to dead parents.\n"); - goto out; - } - -- /* paranoia: check that the uid of pid_of_caller matches getuid() */ -- error = NULL; -- uid_of_caller = polkit_unix_process_get_owner (POLKIT_UNIX_PROCESS (subject), -- &error); -- if (error != NULL) -- { -- g_printerr ("Error determing pid of caller (pid %d): %s\n", (gint) pid_of_caller, error->message); -- g_error_free (error); -- goto out; -- } -- if (uid_of_caller != getuid ()) -- { -- g_printerr ("User of caller (%d) does not match our uid (%d)\n", uid_of_caller, getuid ()); -- goto out; -- } -+ /* This process we want to check an authorization for is the process -+ * that launched us - our parent process. -+ * -+ * At the time the parent process fork()'ed and exec()'ed us, the -+ * process had the same real-uid that we have now. So we use this -+ * real-uid instead of of looking it up to avoid TOCTTOU issues -+ * (consider the parent process exec()'ing a setuid helper). -+ * -+ * On the other hand, the monotonic process start-time is guaranteed -+ * to never change so it's safe to look that up given only the PID -+ * since we are guaranteed to be nuked if the parent goes away -+ * (cf. the prctl(2) call above). -+ */ -+ subject = polkit_unix_process_new_for_owner (pid_of_caller, -+ 0, /* 0 means "look up start-time in /proc" */ -+ getuid ()); -+ /* really double-check the invariants guaranteed by the PolkitUnixProcess class */ -+ g_assert (subject != NULL); -+ g_assert (polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject)) == pid_of_caller); -+ g_assert (polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)) >= 0); -+ g_assert (polkit_unix_process_get_start_time (POLKIT_UNIX_PROCESS (subject)) > 0); - - error = NULL; - authority = polkit_authority_get_sync (NULL /* GCancellable* */, &error); --- -cgit v0.8.3-6-g21f6 diff --git a/abs/extra/polkit/PKGBUILD b/abs/extra/polkit/PKGBUILD index 3a55ddc..e86dbbc 100644 --- a/abs/extra/polkit/PKGBUILD +++ b/abs/extra/polkit/PKGBUILD @@ -1,9 +1,9 @@ -# $Id$ +# $Id: PKGBUILD 158972 2012-05-13 21:06:37Z jgc $ # Maintainer: Jan de Groot <jgc@archlinux.org> pkgname=polkit -pkgver=0.101 -pkgrel=2 +pkgver=0.105 +pkgrel=1 pkgdesc="Application development toolkit for controlling system-wide privileges" arch=(i686 x86_64) license=('LGPL') @@ -12,21 +12,22 @@ depends=('glib2' 'pam' 'expat') makedepends=('intltool' 'gtk-doc' 'gobject-introspection') replaces=('policykit') options=('!libtool') -source=(http://hal.freedesktop.org/releases/${pkgname}-${pkgver}.tar.gz - CVE-2011-1485.patch +source=(http://www.freedesktop.org/software/polkit/releases/$pkgname-$pkgver.tar.gz polkit.pam) -md5sums=('f925ac93aba3c072977370c1e27feb7f' - '4d858b8ab602614d7db2bc8574f6fd29' +md5sums=('9c29e1b6c214f0bd6f1d4ee303dfaed9' '6564f95878297b954f0572bc1610dd15') build() { - cd "${srcdir}/${pkgname}-${pkgver}" - patch -Np1 -i "${srcdir}/CVE-2011-1485.patch" + cd $pkgname-$pkgver ./configure --prefix=/usr --sysconfdir=/etc \ --localstatedir=/var --libexecdir=/usr/lib/polkit-1 \ --disable-static --enable-gtk-doc make - make DESTDIR="${pkgdir}" install +} + +package() { + cd $pkgname-$pkgver + make DESTDIR="$pkgdir" install - install -m644 "${srcdir}/polkit.pam" "${pkgdir}/etc/pam.d/polkit-1" + install -m644 "$srcdir/polkit.pam" "$pkgdir/etc/pam.d/polkit-1" } diff --git a/abs/extra/polkit/systemd-fallback.patch b/abs/extra/polkit/systemd-fallback.patch new file mode 100644 index 0000000..f89ce10 --- /dev/null +++ b/abs/extra/polkit/systemd-fallback.patch @@ -0,0 +1,1571 @@ +diff -u -rN polkit-0.104/configure.ac polkit-0.104-systemd-fallback/configure.ac +--- polkit-0.104/configure.ac 2012-01-03 17:25:49.000000000 +0100 ++++ polkit-0.104-systemd-fallback/configure.ac 2012-03-06 15:45:55.275860194 +0100 +@@ -160,14 +160,14 @@ + [enable_systemd=auto]) + if test "$enable_systemd" != "no"; then + PKG_CHECK_MODULES(SYSTEMD, +- [libsystemd-login], ++ [libsystemd-login libsystemd-daemon], + have_systemd=yes, + have_systemd=no) + if test "$have_systemd" = "yes"; then + SESSION_TRACKING=systemd + else + if test "$enable_systemd" = "yes"; then +- AC_MSG_ERROR([systemd support requested but libsystemd-login1 library not found]) ++ AC_MSG_ERROR([systemd support requested but systemd libraries not found]) + fi + fi + fi +diff -u -rN polkit-0.104/src/polkit/Makefile.am polkit-0.104-systemd-fallback/src/polkit/Makefile.am +--- polkit-0.104/src/polkit/Makefile.am 2012-01-03 16:03:47.000000000 +0100 ++++ polkit-0.104-systemd-fallback/src/polkit/Makefile.am 2012-03-06 15:19:25.108853325 +0100 +@@ -79,15 +79,8 @@ + polkitimplicitauthorization.c polkitimplicitauthorization.h \ + polkittemporaryauthorization.c polkittemporaryauthorization.h \ + polkitpermission.c polkitpermission.h \ +- $(NULL) +- +-if HAVE_SYSTEMD +-libpolkit_gobject_1_la_SOURCES += \ +- polkitunixsession-systemd.c polkitunixsession.h +-else +-libpolkit_gobject_1_la_SOURCES += \ + polkitunixsession.c polkitunixsession.h +-endif ++ $(NULL) + + libpolkit_gobject_1_la_CFLAGS = \ + -D_POLKIT_COMPILATION \ +diff -u -rN polkit-0.104/src/polkit/polkitunixsession.c polkit-0.104-systemd-fallback/src/polkit/polkitunixsession.c +--- polkit-0.104/src/polkit/polkitunixsession.c 2011-10-18 19:02:27.000000000 +0200 ++++ polkit-0.104-systemd-fallback/src/polkit/polkitunixsession.c 2012-03-06 15:17:29.829788021 +0100 +@@ -23,12 +23,18 @@ + # include "config.h" + #endif + ++#include <stdlib.h> + #include <string.h> + #include "polkitunixsession.h" + #include "polkitsubject.h" + #include "polkiterror.h" + #include "polkitprivate.h" + ++#ifdef HAVE_SYSTEMD ++# include <systemd/sd-daemon.h> ++# include <systemd/sd-login.h> ++#endif ++ + /** + * SECTION:polkitunixsession + * @title: PolkitUnixSession +@@ -364,34 +370,44 @@ + PolkitUnixSession *session = POLKIT_UNIX_SESSION (subject); + GDBusConnection *connection; + GVariant *result; +- gboolean ret; +- +- ret = FALSE; ++ gboolean ret = FALSE; + +- connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error); +- if (connection == NULL) +- goto out; +- +- result = g_dbus_connection_call_sync (connection, +- "org.freedesktop.ConsoleKit", /* name */ +- session->session_id, /* object path */ +- "org.freedesktop.ConsoleKit.Session", /* interface name */ +- "GetUser", /* method */ +- NULL, /* parameters */ +- G_VARIANT_TYPE ("(u)"), +- G_DBUS_CALL_FLAGS_NONE, +- -1, +- cancellable, +- error); +- if (result == NULL) +- goto out; ++#ifdef HAVE_SYSTEMD ++ uid_t uid; ++ ++ if (sd_booted () > 0) ++ { ++ if (sd_session_get_uid (session->session_id, &uid) == 0) ++ ret = TRUE; ++ } ++ else ++#endif ++ { ++ connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error); ++ if (connection == NULL) ++ goto out; ++ ++ result = g_dbus_connection_call_sync (connection, ++ "org.freedesktop.ConsoleKit", /* name */ ++ session->session_id, /* object path */ ++ "org.freedesktop.ConsoleKit.Session", /* interface name */ ++ "GetUser", /* method */ ++ NULL, /* parameters */ ++ G_VARIANT_TYPE ("(u)"), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, ++ cancellable, ++ error); ++ if (result == NULL) ++ goto out; + +- ret = TRUE; +- g_variant_unref (result); ++ ret = TRUE; ++ g_variant_unref (result); + +- out: +- if (connection != NULL) +- g_object_unref (connection); ++ out: ++ if (connection != NULL) ++ g_object_unref (connection); ++ } + return ret; + } + +@@ -470,12 +486,9 @@ + GError **error) + { + PolkitUnixSession *session = POLKIT_UNIX_SESSION (initable); +- GDBusConnection *connection; ++ GDBusConnection *connection = NULL; + GVariant *result; +- gboolean ret; +- +- connection = NULL; +- ret = FALSE; ++ gboolean ret = FALSE; + + if (session->session_id != NULL) + { +@@ -484,33 +497,56 @@ + goto out; + } + +- connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error); +- if (connection == NULL) +- goto out; ++#ifdef HAVE_SYSTEMD ++ char *s; ++ ++ if (sd_booted () > 0) ++ { ++ if (sd_pid_get_session (session->pid, &s) == 0) ++ { ++ session->session_id = g_strdup (s); ++ free (s); ++ ret = TRUE; ++ goto out; ++ } ++ ++ g_set_error (error, ++ POLKIT_ERROR, ++ POLKIT_ERROR_FAILED, ++ "No session for pid %d", ++ (gint) session->pid); ++ } ++ else ++#endif ++ { ++ connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error); ++ if (connection == NULL) ++ goto out; ++ ++ result = g_dbus_connection_call_sync (connection, ++ "org.freedesktop.ConsoleKit", /* name */ ++ "/org/freedesktop/ConsoleKit/Manager", /* object path */ ++ "org.freedesktop.ConsoleKit.Manager", /* interface name */ ++ "GetSessionForUnixProcess", /* method */ ++ g_variant_new ("(u)", session->pid), /* parameters */ ++ G_VARIANT_TYPE ("(o)"), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, ++ cancellable, ++ error); ++ if (result == NULL) ++ goto out; + +- result = g_dbus_connection_call_sync (connection, +- "org.freedesktop.ConsoleKit", /* name */ +- "/org/freedesktop/ConsoleKit/Manager", /* object path */ +- "org.freedesktop.ConsoleKit.Manager", /* interface name */ +- "GetSessionForUnixProcess", /* method */ +- g_variant_new ("(u)", session->pid), /* parameters */ +- G_VARIANT_TYPE ("(o)"), +- G_DBUS_CALL_FLAGS_NONE, +- -1, +- cancellable, +- error); +- if (result == NULL) +- goto out; ++ g_variant_get (result, "(o)", &session->session_id); ++ g_variant_unref (result); + +- g_variant_get (result, "(o)", &session->session_id); +- g_variant_unref (result); ++ ret = TRUE; ++ } + +- ret = TRUE; + + out: + if (connection != NULL) + g_object_unref (connection); +- + return ret; + } + +diff -u -rN polkit-0.104/src/polkit/polkitunixsession-systemd.c polkit-0.104-systemd-fallback/src/polkit/polkitunixsession-systemd.c +--- polkit-0.104/src/polkit/polkitunixsession-systemd.c 2012-01-03 16:03:47.000000000 +0100 ++++ polkit-0.104-systemd-fallback/src/polkit/polkitunixsession-systemd.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,481 +0,0 @@ +-/* +- * Copyright (C) 2011 Red Hat, Inc. +- * +- * This library is free software; you can redistribute it and/or +- * modify it under the terms of the GNU Lesser General Public +- * License as published by the Free Software Foundation; either +- * version 2 of the License, or (at your option) any later version. +- * +- * This library is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- * Lesser General Public License for more details. +- * +- * You should have received a copy of the GNU Lesser General +- * Public License along with this library; if not, write to the +- * Free Software Foundation, Inc., 59 Temple Place, Suite 330, +- * Boston, MA 02111-1307, USA. +- * +- * Author: Matthias Clasen +- */ +- +-#ifdef HAVE_CONFIG_H +-# include "config.h" +-#endif +- +-#include <string.h> +-#include "polkitunixsession.h" +-#include "polkitsubject.h" +-#include "polkiterror.h" +-#include "polkitprivate.h" +- +-#include <systemd/sd-login.h> +- +-/** +- * SECTION:polkitunixsession +- * @title: PolkitUnixSession +- * @short_description: Unix sessions +- * +- * An object that represents an user session. +- * +- * The session id is an opaque string obtained from ConsoleKit. +- */ +- +-/** +- * PolkitUnixSession: +- * +- * The #PolkitUnixSession struct should not be accessed directly. +- */ +-struct _PolkitUnixSession +-{ +- GObject parent_instance; +- +- gchar *session_id; +- +- gint pid; +-}; +- +-struct _PolkitUnixSessionClass +-{ +- GObjectClass parent_class; +-}; +- +-enum +-{ +- PROP_0, +- PROP_SESSION_ID, +- PROP_PID, +-}; +- +-static void subject_iface_init (PolkitSubjectIface *subject_iface); +-static void initable_iface_init (GInitableIface *initable_iface); +-static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface); +- +-G_DEFINE_TYPE_WITH_CODE (PolkitUnixSession, polkit_unix_session, G_TYPE_OBJECT, +- G_IMPLEMENT_INTERFACE (POLKIT_TYPE_SUBJECT, subject_iface_init) +- G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init) +- G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init) +- ); +- +-static void +-polkit_unix_session_init (PolkitUnixSession *session) +-{ +-} +- +-static void +-polkit_unix_session_finalize (GObject *object) +-{ +- PolkitUnixSession *session = POLKIT_UNIX_SESSION (object); +- +- g_free (session->session_id); +- +- if (G_OBJECT_CLASS (polkit_unix_session_parent_class)->finalize != NULL) +- G_OBJECT_CLASS (polkit_unix_session_parent_class)->finalize (object); +-} +- +-static void +-polkit_unix_session_get_property (GObject *object, +- guint prop_id, +- GValue *value, +- GParamSpec *pspec) +-{ +- PolkitUnixSession *session = POLKIT_UNIX_SESSION (object); +- +- switch (prop_id) +- { +- case PROP_SESSION_ID: +- g_value_set_string (value, session->session_id); +- break; +- +- default: +- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); +- break; +- } +-} +- +-static void +-polkit_unix_session_set_property (GObject *object, +- guint prop_id, +- const GValue *value, +- GParamSpec *pspec) +-{ +- PolkitUnixSession *session = POLKIT_UNIX_SESSION (object); +- +- switch (prop_id) +- { +- case PROP_SESSION_ID: +- polkit_unix_session_set_session_id (session, g_value_get_string (value)); +- break; +- +- case PROP_PID: +- session->pid = g_value_get_int (value); +- break; +- +- default: +- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); +- break; +- } +-} +- +-static void +-polkit_unix_session_class_init (PolkitUnixSessionClass *klass) +-{ +- GObjectClass *gobject_class = G_OBJECT_CLASS (klass); +- +- gobject_class->finalize = polkit_unix_session_finalize; +- gobject_class->get_property = polkit_unix_session_get_property; +- gobject_class->set_property = polkit_unix_session_set_property; +- +- /** +- * PolkitUnixSession:session-id: +- * +- * The UNIX session id. +- */ +- g_object_class_install_property (gobject_class, +- PROP_SESSION_ID, +- g_param_spec_string ("session-id", +- "Session ID", +- "The UNIX session ID", +- NULL, +- G_PARAM_CONSTRUCT | +- G_PARAM_READWRITE | +- G_PARAM_STATIC_NAME | +- G_PARAM_STATIC_BLURB | +- G_PARAM_STATIC_NICK)); +- +- +- /** +- * PolkitUnixSession:pid: +- * +- * The UNIX process id to look up the session. +- */ +- g_object_class_install_property (gobject_class, +- PROP_PID, +- g_param_spec_int ("pid", +- "Process ID", +- "Process ID to use for looking up the session", +- 0, +- G_MAXINT, +- 0, +- G_PARAM_CONSTRUCT_ONLY | +- G_PARAM_WRITABLE | +- G_PARAM_STATIC_NAME | +- G_PARAM_STATIC_BLURB | +- G_PARAM_STATIC_NICK)); +- +-} +- +-/** +- * polkit_unix_session_get_session_id: +- * @session: A #PolkitUnixSession. +- * +- * Gets the session id for @session. +- * +- * Returns: The session id for @session. Do not free this string, it +- * is owned by @session. +- **/ +-const gchar * +-polkit_unix_session_get_session_id (PolkitUnixSession *session) +-{ +- g_return_val_if_fail (POLKIT_IS_UNIX_SESSION (session), NULL); +- return session->session_id; +-} +- +-/** +- * polkit_unix_session_set_session_id: +- * @session: A #PolkitUnixSession. +- * @session_id: The session id. +- * +- * Sets the session id for @session to @session_id. +- **/ +-void +-polkit_unix_session_set_session_id (PolkitUnixSession *session, +- const gchar *session_id) +-{ +- g_return_if_fail (POLKIT_IS_UNIX_SESSION (session)); +- /*g_return_if_fail (session_id != NULL);*/ +- g_free (session->session_id); +- session->session_id = g_strdup (session_id); +-} +- +-/** +- * polkit_unix_session_new: +- * @session_id: The session id. +- * +- * Creates a new #PolkitUnixSession for @session_id. +- * +- * Returns: (transfer full): A #PolkitUnixSession. Free with g_object_unref(). +- **/ +-PolkitSubject * +-polkit_unix_session_new (const gchar *session_id) +-{ +- return POLKIT_SUBJECT (g_object_new (POLKIT_TYPE_UNIX_SESSION, +- "session-id", session_id, +- NULL)); +-} +- +-/** +- * polkit_unix_session_new_for_process: +- * @pid: The process id of the process to get the session for. +- * @cancellable: (allow-none): A #GCancellable or %NULL. +- * @callback: A #GAsyncReadyCallback to call when the request is satisfied +- * @user_data: The data to pass to @callback. +- * +- * Asynchronously creates a new #PolkitUnixSession object for the +- * process with process id @pid. +- * +- * When the operation is finished, @callback will be invoked in the +- * <link linkend="g-main-context-push-thread-default">thread-default +- * main loop</link> of the thread you are calling this method +- * from. You can then call +- * polkit_unix_session_new_for_process_finish() to get the result of +- * the operation. +- * +- * This method constructs the object asynchronously, for the synchronous and blocking version +- * use polkit_unix_session_new_for_process_sync(). +- **/ +-void +-polkit_unix_session_new_for_process (gint pid, +- GCancellable *cancellable, +- GAsyncReadyCallback callback, +- gpointer user_data) +-{ +- g_async_initable_new_async (POLKIT_TYPE_UNIX_SESSION, +- G_PRIORITY_DEFAULT, +- cancellable, +- callback, +- user_data, +- "pid", pid, +- NULL); +-} +- +-/** +- * polkit_unix_session_new_for_process_finish: +- * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to polkit_unix_session_new_for_process(). +- * @error: (allow-none): Return location for error. +- * +- * Finishes constructing a #PolkitSubject for a process id. +- * +- * Returns: (transfer full) (allow-none): A #PolkitUnixSession for the @pid passed to +- * polkit_unix_session_new_for_process() or %NULL if @error is +- * set. Free with g_object_unref(). +- **/ +-PolkitSubject * +-polkit_unix_session_new_for_process_finish (GAsyncResult *res, +- GError **error) +-{ +- GObject *object; +- GObject *source_object; +- +- source_object = g_async_result_get_source_object (res); +- g_assert (source_object != NULL); +- +- object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), +- res, +- error); +- g_object_unref (source_object); +- +- if (object != NULL) +- return POLKIT_SUBJECT (object); +- else +- return NULL; +-} +- +- +-/** +- * polkit_unix_session_new_for_process_sync: +- * @pid: The process id of the process to get the session for. +- * @cancellable: (allow-none): A #GCancellable or %NULL. +- * @error: (allow-none): Return location for error. +- * +- * Creates a new #PolkitUnixSession for the process with process id @pid. +- * +- * This is a synchronous call - the calling thread is blocked until a +- * reply is received. For the asynchronous version, see +- * polkit_unix_session_new_for_process(). +- * +- * Returns: (allow-none) (transfer full): A #PolkitUnixSession for +- * @pid or %NULL if @error is set. Free with g_object_unref(). +- **/ +-PolkitSubject * +-polkit_unix_session_new_for_process_sync (gint pid, +- GCancellable *cancellable, +- GError **error) +-{ +- return POLKIT_SUBJECT (g_initable_new (POLKIT_TYPE_UNIX_SESSION, +- cancellable, +- error, +- "pid", pid, +- NULL)); +-} +- +-static guint +-polkit_unix_session_hash (PolkitSubject *subject) +-{ +- PolkitUnixSession *session = POLKIT_UNIX_SESSION (subject); +- +- return g_str_hash (session->session_id); +-} +- +-static gboolean +-polkit_unix_session_equal (PolkitSubject *a, +- PolkitSubject *b) +-{ +- PolkitUnixSession *session_a; +- PolkitUnixSession *session_b; +- +- session_a = POLKIT_UNIX_SESSION (a); +- session_b = POLKIT_UNIX_SESSION (b); +- +- return g_strcmp0 (session_a->session_id, session_b->session_id) == 0; +-} +- +-static gchar * +-polkit_unix_session_to_string (PolkitSubject *subject) +-{ +- PolkitUnixSession *session = POLKIT_UNIX_SESSION (subject); +- +- return g_strdup_printf ("unix-session:%s", session->session_id); +-} +- +-static gboolean +-polkit_unix_session_exists_sync (PolkitSubject *subject, +- GCancellable *cancellable, +- GError **error) +-{ +- PolkitUnixSession *session = POLKIT_UNIX_SESSION (subject); +- gboolean ret; +- uid_t uid; +- +- ret = FALSE; +- +- if (!sd_session_get_uid (session->session_id, &uid)) +- ret = FALSE; +- +- return ret; +-} +- +-static void +-exists_in_thread_func (GSimpleAsyncResult *res, +- GObject *object, +- GCancellable *cancellable) +-{ +- GError *error; +- error = NULL; +- if (!polkit_unix_session_exists_sync (POLKIT_SUBJECT (object), +- cancellable, +- &error)) +- { +- g_simple_async_result_set_from_error (res, error); +- g_error_free (error); +- } +-} +- +-static void +-polkit_unix_session_exists (PolkitSubject *subject, +- GCancellable *cancellable, +- GAsyncReadyCallback callback, +- gpointer user_data) +-{ +- GSimpleAsyncResult *simple; +- +- g_return_if_fail (POLKIT_IS_UNIX_SESSION (subject)); +- +- simple = g_simple_async_result_new (G_OBJECT (subject), +- callback, +- user_data, +- polkit_unix_session_exists); +- g_simple_async_result_run_in_thread (simple, +- exists_in_thread_func, +- G_PRIORITY_DEFAULT, +- cancellable); +- g_object_unref (simple); +-} +- +-static gboolean +-polkit_unix_session_exists_finish (PolkitSubject *subject, +- GAsyncResult *res, +- GError **error) +-{ +- GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); +- gboolean ret; +- +- g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_unix_session_exists); +- +- ret = FALSE; +- +- if (g_simple_async_result_propagate_error (simple, error)) +- goto out; +- +- ret = g_simple_async_result_get_op_res_gboolean (simple); +- +- out: +- return ret; +-} +- +-static void +-subject_iface_init (PolkitSubjectIface *subject_iface) +-{ +- subject_iface->hash = polkit_unix_session_hash; +- subject_iface->equal = polkit_unix_session_equal; +- subject_iface->to_string = polkit_unix_session_to_string; +- subject_iface->exists = polkit_unix_session_exists; +- subject_iface->exists_finish = polkit_unix_session_exists_finish; +- subject_iface->exists_sync = polkit_unix_session_exists_sync; +-} +- +-static gboolean +-polkit_unix_session_initable_init (GInitable *initable, +- GCancellable *cancellable, +- GError **error) +-{ +- PolkitUnixSession *session = POLKIT_UNIX_SESSION (initable); +- gboolean ret; +- +- ret = FALSE; +- +- if (session->session_id != NULL) +- { +- /* already set, nothing to do */ +- ret = TRUE; +- goto out; +- } +- +- if (!sd_pid_get_session (session->pid, &session->session_id)) +- ret = TRUE; +- +-out: +- return ret; +-} +- +-static void +-initable_iface_init (GInitableIface *initable_iface) +-{ +- initable_iface->init = polkit_unix_session_initable_init; +-} +- +-static void +-async_initable_iface_init (GAsyncInitableIface *async_initable_iface) +-{ +- /* use default implementation to run GInitable code in a thread */ +-} +diff -u -rN polkit-0.104/src/polkitbackend/Makefile.am polkit-0.104-systemd-fallback/src/polkitbackend/Makefile.am +--- polkit-0.104/src/polkitbackend/Makefile.am 2012-01-03 16:03:47.000000000 +0100 ++++ polkit-0.104-systemd-fallback/src/polkitbackend/Makefile.am 2012-03-06 15:44:15.380014886 +0100 +@@ -41,15 +41,8 @@ + polkitbackendconfigsource.h polkitbackendconfigsource.c \ + polkitbackendactionlookup.h polkitbackendactionlookup.c \ + polkitbackendlocalauthorizationstore.h polkitbackendlocalauthorizationstore.c \ +- $(NULL) +- +-if HAVE_SYSTEMD +-libpolkit_backend_1_la_SOURCES += \ +- polkitbackendsessionmonitor.h polkitbackendsessionmonitor-systemd.c +-else +-libpolkit_backend_1_la_SOURCES += \ + polkitbackendsessionmonitor.h polkitbackendsessionmonitor.c +-endif ++ $(NULL) + + libpolkit_backend_1_la_CFLAGS = \ + -D_POLKIT_COMPILATION \ +diff -u -rN polkit-0.104/src/polkitbackend/polkitbackendsessionmonitor.c polkit-0.104-systemd-fallback/src/polkitbackend/polkitbackendsessionmonitor.c +--- polkit-0.104/src/polkitbackend/polkitbackendsessionmonitor.c 2011-10-18 19:02:27.000000000 +0200 ++++ polkit-0.104-systemd-fallback/src/polkitbackend/polkitbackendsessionmonitor.c 2012-03-06 15:43:49.353562242 +0100 +@@ -26,6 +26,12 @@ + #include <string.h> + #include <glib/gstdio.h> + ++#ifdef HAVE_SYSTEMD ++# include <systemd/sd-daemon.h> ++# include <systemd/sd-login.h> ++# include <stdlib.h> ++#endif ++ + #include <polkit/polkit.h> + #include "polkitbackendsessionmonitor.h" + +@@ -39,6 +45,88 @@ + * The #PolkitBackendSessionMonitor class is a utility class to track and monitor sessions. + */ + ++#ifdef HAVE_SYSTEMD ++typedef struct ++{ ++ GSource source; ++ GPollFD pollfd; ++ sd_login_monitor *monitor; ++} SdSource; ++ ++static gboolean ++sd_source_prepare (GSource *source, ++ gint *timeout) ++{ ++ *timeout = -1; ++ return FALSE; ++} ++ ++static gboolean ++sd_source_check (GSource *source) ++{ ++ SdSource *sd_source = (SdSource *)source; ++ ++ return sd_source->pollfd.revents != 0; ++} ++ ++static gboolean ++sd_source_dispatch (GSource *source, ++ GSourceFunc callback, ++ gpointer user_data) ++ ++{ ++ SdSource *sd_source = (SdSource *)source; ++ gboolean ret; ++ ++ g_warn_if_fail (callback != NULL); ++ ++ ret = (*callback) (user_data); ++ ++ sd_login_monitor_flush (sd_source->monitor); ++ ++ return ret; ++} ++ ++static void ++sd_source_finalize (GSource *source) ++{ ++ SdSource *sd_source = (SdSource*)source; ++ ++ sd_login_monitor_unref (sd_source->monitor); ++} ++ ++static GSourceFuncs sd_source_funcs = { ++ sd_source_prepare, ++ sd_source_check, ++ sd_source_dispatch, ++ sd_source_finalize ++}; ++ ++static GSource * ++sd_source_new (void) ++{ ++ GSource *source; ++ SdSource *sd_source; ++ int ret; ++ ++ source = g_source_new (&sd_source_funcs, sizeof (SdSource)); ++ sd_source = (SdSource *)source; ++ ++ if ((ret = sd_login_monitor_new (NULL, &sd_source->monitor)) < 0) ++ { ++ g_printerr ("Error getting login monitor: %d", ret); ++ } ++ else ++ { ++ sd_source->pollfd.fd = sd_login_monitor_get_fd (sd_source->monitor); ++ sd_source->pollfd.events = G_IO_IN; ++ g_source_add_poll (source, &sd_source->pollfd); ++ } ++ ++ return source; ++} ++#endif /* HAVE_SYSTEMD */ ++ + struct _PolkitBackendSessionMonitor + { + GObject parent_instance; +@@ -48,6 +136,10 @@ + GKeyFile *database; + GFileMonitor *database_monitor; + time_t database_mtime; ++ ++#ifdef HAVE_SYSTEMD ++ GSource *sd_source; ++#endif + }; + + struct _PolkitBackendSessionMonitorClass +@@ -162,6 +254,18 @@ + g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0); + } + ++#ifdef HAVE_SYSTEMD ++static gboolean ++sessions_changed (gpointer user_data) ++{ ++ PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data); ++ ++ g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0); ++ ++ return TRUE; ++} ++#endif ++ + static void + polkit_backend_session_monitor_init (PolkitBackendSessionMonitor *monitor) + { +@@ -176,31 +280,47 @@ + g_error_free (error); + } + +- error = NULL; +- if (!ensure_database (monitor, &error)) +- { +- g_printerr ("Error loading " CKDB_PATH ": %s", error->message); +- g_error_free (error); +- } ++#ifdef HAVE_SYSTEMD ++ monitor->sd_source = NULL; ++ ++ if (sd_booted () > 0) ++ { ++ monitor->sd_source = sd_source_new (); ++ g_source_set_callback (monitor->sd_source, sessions_changed, monitor, NULL); ++ g_source_attach (monitor->sd_source, NULL); + +- error = NULL; +- file = g_file_new_for_path (CKDB_PATH); +- monitor->database_monitor = g_file_monitor_file (file, +- G_FILE_MONITOR_NONE, +- NULL, +- &error); +- g_object_unref (file); +- if (monitor->database_monitor == NULL) +- { +- g_printerr ("Error monitoring " CKDB_PATH ": %s", error->message); +- g_error_free (error); ++ monitor->database = NULL; ++ monitor->database_monitor = NULL; + } + else ++#endif + { +- g_signal_connect (monitor->database_monitor, +- "changed", +- G_CALLBACK (on_file_monitor_changed), +- monitor); ++ error = NULL; ++ if (!ensure_database (monitor, &error)) ++ { ++ g_printerr ("Error loading " CKDB_PATH ": %s", error->message); ++ g_error_free (error); ++ } ++ ++ error = NULL; ++ file = g_file_new_for_path (CKDB_PATH); ++ monitor->database_monitor = g_file_monitor_file (file, ++ G_FILE_MONITOR_NONE, ++ NULL, ++ &error); ++ g_object_unref (file); ++ if (monitor->database_monitor == NULL) ++ { ++ g_printerr ("Error monitoring " CKDB_PATH ": %s", error->message); ++ g_error_free (error); ++ } ++ else ++ { ++ g_signal_connect (monitor->database_monitor, ++ "changed", ++ G_CALLBACK (on_file_monitor_changed), ++ monitor); ++ } + } + } + +@@ -212,6 +332,14 @@ + if (monitor->system_bus != NULL) + g_object_unref (monitor->system_bus); + ++#ifdef HAVE_SYSTEMD ++ if (monitor->sd_source != NULL) ++ { ++ g_source_destroy (monitor->sd_source); ++ g_source_unref (monitor->sd_source); ++ } ++#endif ++ + if (monitor->database_monitor != NULL) + g_object_unref (monitor->database_monitor); + +@@ -328,22 +456,38 @@ + } + else if (POLKIT_IS_UNIX_SESSION (subject)) + { +- if (!ensure_database (monitor, error)) ++#ifdef HAVE_SYSTEMD ++ if (monitor->sd_source != NULL) + { +- g_prefix_error (error, "Error getting user for session: Error ensuring CK database at " CKDB_PATH ": "); +- goto out; ++ if (sd_session_get_uid (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (subject)), &uid) < 0) ++ { ++ g_set_error (error, ++ POLKIT_ERROR, ++ POLKIT_ERROR_FAILED, ++ "Error getting uid for session"); ++ goto out; ++ } + } +- +- group = g_strdup_printf ("Session %s", polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (subject))); +- local_error = NULL; +- uid = g_key_file_get_integer (monitor->database, group, "uid", &local_error); +- if (local_error != NULL) ++ else ++#endif + { +- g_propagate_prefixed_error (error, local_error, "Error getting uid using " CKDB_PATH ": "); ++ if (!ensure_database (monitor, error)) ++ { ++ g_prefix_error (error, "Error getting user for session: Error ensuring CK database at " CKDB_PATH ": "); ++ goto out; ++ } ++ ++ group = g_strdup_printf ("Session %s", polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (subject))); ++ local_error = NULL; ++ uid = g_key_file_get_integer (monitor->database, group, "uid", &local_error); ++ if (local_error != NULL) ++ { ++ g_propagate_prefixed_error (error, local_error, "Error getting uid using " CKDB_PATH ": "); ++ g_free (group); ++ goto out; ++ } + g_free (group); +- goto out; + } +- g_free (group); + + ret = polkit_unix_user_new (uid); + } +@@ -373,29 +517,46 @@ + + if (POLKIT_IS_UNIX_PROCESS (subject)) + { +- const gchar *session_id; +- GVariant *result; +- result = g_dbus_connection_call_sync (monitor->system_bus, +- "org.freedesktop.ConsoleKit", +- "/org/freedesktop/ConsoleKit/Manager", +- "org.freedesktop.ConsoleKit.Manager", +- "GetSessionForUnixProcess", +- g_variant_new ("(u)", polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject))), +- G_VARIANT_TYPE ("(o)"), +- G_DBUS_CALL_FLAGS_NONE, +- -1, /* timeout_msec */ +- NULL, /* GCancellable */ +- error); +- if (result == NULL) +- goto out; +- g_variant_get (result, "(&o)", &session_id); +- session = polkit_unix_session_new (session_id); +- g_variant_unref (result); ++#ifdef HAVE_SYSTEMD ++ if (monitor->sd_source != NULL) ++ { ++ gchar *session_id; ++ pid_t pid; ++ ++ pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject)); ++ if (sd_pid_get_session (pid, &session_id) < 0) ++ goto out; ++ ++ session = polkit_unix_session_new (session_id); ++ free (session_id); ++ } ++ else ++#endif ++ { ++ const gchar *session_id; ++ GVariant *result; ++ result = g_dbus_connection_call_sync (monitor->system_bus, ++ "org.freedesktop.ConsoleKit", ++ "/org/freedesktop/ConsoleKit/Manager", ++ "org.freedesktop.ConsoleKit.Manager", ++ "GetSessionForUnixProcess", ++ g_variant_new ("(u)", polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject))), ++ G_VARIANT_TYPE ("(o)"), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, /* timeout_msec */ ++ NULL, /* GCancellable */ ++ error); ++ if (result == NULL) ++ goto out; ++ g_variant_get (result, "(&o)", &session_id); ++ session = polkit_unix_session_new (session_id); ++ g_variant_unref (result); ++ } + } + else if (POLKIT_IS_SYSTEM_BUS_NAME (subject)) + { + guint32 pid; +- const gchar *session_id; ++ gchar *session_id; + GVariant *result; + + result = g_dbus_connection_call_sync (monitor->system_bus, +@@ -414,22 +575,35 @@ + g_variant_get (result, "(u)", &pid); + g_variant_unref (result); + +- result = g_dbus_connection_call_sync (monitor->system_bus, +- "org.freedesktop.ConsoleKit", +- "/org/freedesktop/ConsoleKit/Manager", +- "org.freedesktop.ConsoleKit.Manager", +- "GetSessionForUnixProcess", +- g_variant_new ("(u)", pid), +- G_VARIANT_TYPE ("(o)"), +- G_DBUS_CALL_FLAGS_NONE, +- -1, /* timeout_msec */ +- NULL, /* GCancellable */ +- error); +- if (result == NULL) +- goto out; +- g_variant_get (result, "(&o)", &session_id); +- session = polkit_unix_session_new (session_id); +- g_variant_unref (result); ++#ifdef HAVE_SYSTEMD ++ if (monitor->sd_source != NULL) ++ { ++ if (sd_pid_get_session (pid, &session_id) < 0) ++ goto out; ++ ++ session = polkit_unix_session_new (session_id); ++ free (session_id); ++ } ++ else ++#endif ++ { ++ result = g_dbus_connection_call_sync (monitor->system_bus, ++ "org.freedesktop.ConsoleKit", ++ "/org/freedesktop/ConsoleKit/Manager", ++ "org.freedesktop.ConsoleKit.Manager", ++ "GetSessionForUnixProcess", ++ g_variant_new ("(u)", pid), ++ G_VARIANT_TYPE ("(o)"), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, /* timeout_msec */ ++ NULL, /* GCancellable */ ++ error); ++ if (result == NULL) ++ goto out; ++ g_variant_get (result, "(&o)", &session_id); ++ session = polkit_unix_session_new (session_id); ++ g_variant_unref (result); ++ } + } + else + { +@@ -490,7 +664,22 @@ + polkit_backend_session_monitor_is_session_local (PolkitBackendSessionMonitor *monitor, + PolkitSubject *session) + { +- return get_boolean (monitor, session, "is_local"); ++#ifdef HAVE_SYSTEMD ++ if (monitor->sd_source != NULL) ++ { ++ char *seat; ++ ++ if (!sd_session_get_seat (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session)), &seat)) ++ { ++ free (seat); ++ return TRUE; ++ } ++ ++ return FALSE; ++ } ++ else ++#endif ++ return get_boolean (monitor, session, "is_local"); + } + + +@@ -498,6 +687,11 @@ + polkit_backend_session_monitor_is_session_active (PolkitBackendSessionMonitor *monitor, + PolkitSubject *session) + { +- return get_boolean (monitor, session, "is_active"); ++#ifdef HAVE_SYSTEMD ++ if (monitor->sd_source != NULL) ++ return sd_session_is_active (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session))); ++ else ++#endif ++ return get_boolean (monitor, session, "is_active"); + } + +diff -u -rN polkit-0.104/src/polkitbackend/polkitbackendsessionmonitor-systemd.c polkit-0.104-systemd-fallback/src/polkitbackend/polkitbackendsessionmonitor-systemd.c +--- polkit-0.104/src/polkitbackend/polkitbackendsessionmonitor-systemd.c 2012-01-03 16:03:47.000000000 +0100 ++++ polkit-0.104-systemd-fallback/src/polkitbackend/polkitbackendsessionmonitor-systemd.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,414 +0,0 @@ +-/* +- * Copyright (C) 2011 Red Hat, Inc. +- * +- * This library is free software; you can redistribute it and/or +- * modify it under the terms of the GNU Lesser General Public +- * License as published by the Free Software Foundation; either +- * version 2 of the License, or (at your option) any later version. +- * +- * This library is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- * Lesser General Public License for more details. +- * +- * You should have received a copy of the GNU Lesser General +- * Public License along with this library; if not, write to the +- * Free Software Foundation, Inc., 59 Temple Place, Suite 330, +- * Boston, MA 02111-1307, USA. +- * +- * Author: Matthias Clasen +- */ +- +-#include "config.h" +-#include <errno.h> +-#include <pwd.h> +-#include <grp.h> +-#include <string.h> +-#include <glib/gstdio.h> +-#include <systemd/sd-login.h> +-#include <stdlib.h> +- +-#include <polkit/polkit.h> +-#include "polkitbackendsessionmonitor.h" +- +-/* <internal> +- * SECTION:polkitbackendsessionmonitor +- * @title: PolkitBackendSessionMonitor +- * @short_description: Monitor sessions +- * +- * The #PolkitBackendSessionMonitor class is a utility class to track and monitor sessions. +- */ +- +-typedef struct +-{ +- GSource source; +- GPollFD pollfd; +- sd_login_monitor *monitor; +-} SdSource; +- +-static gboolean +-sd_source_prepare (GSource *source, +- gint *timeout) +-{ +- *timeout = -1; +- return FALSE; +-} +- +-static gboolean +-sd_source_check (GSource *source) +-{ +- SdSource *sd_source = (SdSource *)source; +- +- return sd_source->pollfd.revents != 0; +-} +- +-static gboolean +-sd_source_dispatch (GSource *source, +- GSourceFunc callback, +- gpointer user_data) +- +-{ +- SdSource *sd_source = (SdSource *)source; +- gboolean ret; +- +- g_warn_if_fail (callback != NULL); +- +- ret = (*callback) (user_data); +- +- sd_login_monitor_flush (sd_source->monitor); +- +- return ret; +-} +- +-static void +-sd_source_finalize (GSource *source) +-{ +- SdSource *sd_source = (SdSource*)source; +- +- sd_login_monitor_unref (sd_source->monitor); +-} +- +-static GSourceFuncs sd_source_funcs = { +- sd_source_prepare, +- sd_source_check, +- sd_source_dispatch, +- sd_source_finalize +-}; +- +-static GSource * +-sd_source_new (void) +-{ +- GSource *source; +- SdSource *sd_source; +- int ret; +- +- source = g_source_new (&sd_source_funcs, sizeof (SdSource)); +- sd_source = (SdSource *)source; +- +- if ((ret = sd_login_monitor_new (NULL, &sd_source->monitor)) < 0) +- { +- g_printerr ("Error getting login monitor: %d", ret); +- } +- else +- { +- sd_source->pollfd.fd = sd_login_monitor_get_fd (sd_source->monitor); +- sd_source->pollfd.events = G_IO_IN; +- g_source_add_poll (source, &sd_source->pollfd); +- } +- +- return source; +-} +- +-struct _PolkitBackendSessionMonitor +-{ +- GObject parent_instance; +- +- GDBusConnection *system_bus; +- +- GSource *sd_source; +-}; +- +-struct _PolkitBackendSessionMonitorClass +-{ +- GObjectClass parent_class; +- +- void (*changed) (PolkitBackendSessionMonitor *monitor); +-}; +- +- +-enum +-{ +- CHANGED_SIGNAL, +- LAST_SIGNAL, +-}; +- +-static guint signals[LAST_SIGNAL] = {0}; +- +-G_DEFINE_TYPE (PolkitBackendSessionMonitor, polkit_backend_session_monitor, G_TYPE_OBJECT); +- +-/* ---------------------------------------------------------------------------------------------------- */ +- +-static gboolean +-sessions_changed (gpointer user_data) +-{ +- PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data); +- +- g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0); +- +- return TRUE; +-} +- +- +-static void +-polkit_backend_session_monitor_init (PolkitBackendSessionMonitor *monitor) +-{ +- GError *error; +- +- error = NULL; +- monitor->system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); +- if (monitor->system_bus == NULL) +- { +- g_printerr ("Error getting system bus: %s", error->message); +- g_error_free (error); +- } +- +- monitor->sd_source = sd_source_new (); +- g_source_set_callback (monitor->sd_source, sessions_changed, monitor, NULL); +- g_source_attach (monitor->sd_source, NULL); +-} +- +-static void +-polkit_backend_session_monitor_finalize (GObject *object) +-{ +- PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (object); +- +- if (monitor->system_bus != NULL) +- g_object_unref (monitor->system_bus); +- +- if (monitor->sd_source != NULL) +- { +- g_source_destroy (monitor->sd_source); +- g_source_unref (monitor->sd_source); +- } +- +- if (G_OBJECT_CLASS (polkit_backend_session_monitor_parent_class)->finalize != NULL) +- G_OBJECT_CLASS (polkit_backend_session_monitor_parent_class)->finalize (object); +-} +- +-static void +-polkit_backend_session_monitor_class_init (PolkitBackendSessionMonitorClass *klass) +-{ +- GObjectClass *gobject_class; +- +- gobject_class = G_OBJECT_CLASS (klass); +- +- gobject_class->finalize = polkit_backend_session_monitor_finalize; +- +- /** +- * PolkitBackendSessionMonitor::changed: +- * @monitor: A #PolkitBackendSessionMonitor +- * +- * Emitted when something changes. +- */ +- signals[CHANGED_SIGNAL] = g_signal_new ("changed", +- POLKIT_BACKEND_TYPE_SESSION_MONITOR, +- G_SIGNAL_RUN_LAST, +- G_STRUCT_OFFSET (PolkitBackendSessionMonitorClass, changed), +- NULL, /* accumulator */ +- NULL, /* accumulator data */ +- g_cclosure_marshal_VOID__VOID, +- G_TYPE_NONE, +- 0); +-} +- +-PolkitBackendSessionMonitor * +-polkit_backend_session_monitor_new (void) +-{ +- PolkitBackendSessionMonitor *monitor; +- +- monitor = POLKIT_BACKEND_SESSION_MONITOR (g_object_new (POLKIT_BACKEND_TYPE_SESSION_MONITOR, NULL)); +- +- return monitor; +-} +- +-/* ---------------------------------------------------------------------------------------------------- */ +- +-GList * +-polkit_backend_session_monitor_get_sessions (PolkitBackendSessionMonitor *monitor) +-{ +- /* TODO */ +- return NULL; +-} +- +-/* ---------------------------------------------------------------------------------------------------- */ +- +-/** +- * polkit_backend_session_monitor_get_user: +- * @monitor: A #PolkitBackendSessionMonitor. +- * @subject: A #PolkitSubject. +- * @error: Return location for error. +- * +- * Gets the user corresponding to @subject or %NULL if no user exists. +- * +- * Returns: %NULL if @error is set otherwise a #PolkitUnixUser that should be freed with g_object_unref(). +- */ +-PolkitIdentity * +-polkit_backend_session_monitor_get_user_for_subject (PolkitBackendSessionMonitor *monitor, +- PolkitSubject *subject, +- GError **error) +-{ +- PolkitIdentity *ret; +- guint32 uid; +- +- ret = NULL; +- +- if (POLKIT_IS_UNIX_PROCESS (subject)) +- { +- uid = polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)); +- if ((gint) uid == -1) +- { +- g_set_error (error, +- POLKIT_ERROR, +- POLKIT_ERROR_FAILED, +- "Unix process subject does not have uid set"); +- goto out; +- } +- ret = polkit_unix_user_new (uid); +- } +- else if (POLKIT_IS_SYSTEM_BUS_NAME (subject)) +- { +- GVariant *result; +- +- result = g_dbus_connection_call_sync (monitor->system_bus, +- "org.freedesktop.DBus", +- "/org/freedesktop/DBus", +- "org.freedesktop.DBus", +- "GetConnectionUnixUser", +- g_variant_new ("(s)", polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (subject))), +- G_VARIANT_TYPE ("(u)"), +- G_DBUS_CALL_FLAGS_NONE, +- -1, /* timeout_msec */ +- NULL, /* GCancellable */ +- error); +- if (result == NULL) +- goto out; +- g_variant_get (result, "(u)", &uid); +- g_variant_unref (result); +- +- ret = polkit_unix_user_new (uid); +- } +- else if (POLKIT_IS_UNIX_SESSION (subject)) +- { +- +- if (sd_session_get_uid (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (subject)), &uid) < 0) +- { +- g_set_error (error, +- POLKIT_ERROR, +- POLKIT_ERROR_FAILED, +- "Error getting uid for session"); +- goto out; +- } +- +- ret = polkit_unix_user_new (uid); +- } +- +- out: +- return ret; +-} +- +-/** +- * polkit_backend_session_monitor_get_session_for_subject: +- * @monitor: A #PolkitBackendSessionMonitor. +- * @subject: A #PolkitSubject. +- * @error: Return location for error. +- * +- * Gets the session corresponding to @subject or %NULL if no session exists. +- * +- * Returns: %NULL if @error is set otherwise a #PolkitUnixSession that should be freed with g_object_unref(). +- */ +-PolkitSubject * +-polkit_backend_session_monitor_get_session_for_subject (PolkitBackendSessionMonitor *monitor, +- PolkitSubject *subject, +- GError **error) +-{ +- PolkitSubject *session; +- +- session = NULL; +- +- if (POLKIT_IS_UNIX_PROCESS (subject)) +- { +- gchar *session_id; +- pid_t pid; +- +- pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject)); +- if (sd_pid_get_session (pid, &session_id) < 0) +- goto out; +- +- session = polkit_unix_session_new (session_id); +- free (session_id); +- } +- else if (POLKIT_IS_SYSTEM_BUS_NAME (subject)) +- { +- guint32 pid; +- gchar *session_id; +- GVariant *result; +- +- result = g_dbus_connection_call_sync (monitor->system_bus, +- "org.freedesktop.DBus", +- "/org/freedesktop/DBus", +- "org.freedesktop.DBus", +- "GetConnectionUnixProcessID", +- g_variant_new ("(s)", polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (subject))), +- G_VARIANT_TYPE ("(u)"), +- G_DBUS_CALL_FLAGS_NONE, +- -1, /* timeout_msec */ +- NULL, /* GCancellable */ +- error); +- if (result == NULL) +- goto out; +- g_variant_get (result, "(u)", &pid); +- g_variant_unref (result); +- +- if (sd_pid_get_session (pid, &session_id) < 0) +- goto out; +- +- session = polkit_unix_session_new (session_id); +- free (session_id); +- } +- else +- { +- g_set_error (error, +- POLKIT_ERROR, +- POLKIT_ERROR_NOT_SUPPORTED, +- "Cannot get user for subject of type %s", +- g_type_name (G_TYPE_FROM_INSTANCE (subject))); +- } +- +- out: +- +- return session; +-} +- +-gboolean +-polkit_backend_session_monitor_is_session_local (PolkitBackendSessionMonitor *monitor, +- PolkitSubject *session) +-{ +- char *seat; +- +- if (!sd_session_get_seat (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session)), &seat)) +- { +- free (seat); +- return TRUE; +- } +- +- return FALSE; +-} +- +- +-gboolean +-polkit_backend_session_monitor_is_session_active (PolkitBackendSessionMonitor *monitor, +- PolkitSubject *session) +-{ +- return sd_session_is_active (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session))); +-} +- |