Blame SOURCES/0027-systemd-login-check-for-LockedHint-property.patch

ad7ee3
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
ad7ee3
From: Victor Toso <victortoso@redhat.com>
ad7ee3
Date: Fri, 27 May 2016 11:42:29 +0200
ad7ee3
Subject: [PATCH] systemd-login: check for LockedHint property
ad7ee3
ad7ee3
Property introduced in v230 of systemd.
ad7ee3
ad7ee3
Systems that don't have up to date systemd-login will get the
ad7ee3
following log message:
ad7ee3
ad7ee3
"Properties.Get failed (locked-hint) due Unknown property or interface."
ad7ee3
ad7ee3
Resolves: rhbz#1323623
ad7ee3
Acked-by: Pavel Grunt <pgrunt@redhat.com>
ad7ee3
(cherry picked from commit ec843a21b29d7fa21ba3393b84368bc2e39d3ce7)
ad7ee3
---
ad7ee3
 src/systemd-login.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++-----
ad7ee3
 1 file changed, 98 insertions(+), 10 deletions(-)
ad7ee3
ad7ee3
diff --git a/src/systemd-login.c b/src/systemd-login.c
ad7ee3
index ff9a3be..1b0b6f1 100644
ad7ee3
--- a/src/systemd-login.c
ad7ee3
+++ b/src/systemd-login.c
ad7ee3
@@ -36,14 +36,21 @@ struct session_info {
ad7ee3
         char *match_session_signals;
ad7ee3
     } dbus;
ad7ee3
     gboolean session_is_locked;
ad7ee3
+    gboolean session_locked_hint;
ad7ee3
 };
ad7ee3
 
ad7ee3
+#define LOGIND_INTERFACE            "org.freedesktop.login1"
ad7ee3
+
ad7ee3
 #define LOGIND_SESSION_INTERFACE    "org.freedesktop.login1.Session"
ad7ee3
-#define LOGIND_SESSION_OBJ_TEMPLATE "'/org/freedesktop/login1/session/_3%s'"
ad7ee3
+#define LOGIND_SESSION_OBJ_TEMPLATE "/org/freedesktop/login1/session/_3%s"
ad7ee3
+
ad7ee3
+#define DBUS_PROPERTIES_INTERFACE   "org.freedesktop.DBus.Properties"
ad7ee3
 
ad7ee3
 #define SESSION_SIGNAL_LOCK         "Lock"
ad7ee3
 #define SESSION_SIGNAL_UNLOCK       "Unlock"
ad7ee3
 
ad7ee3
+#define SESSION_PROP_LOCKED_HINT    "LockedHint"
ad7ee3
+
ad7ee3
 /* dbus related */
ad7ee3
 static DBusConnection *si_dbus_get_system_bus(void)
ad7ee3
 {
ad7ee3
@@ -91,8 +98,8 @@ static void si_dbus_match_rule_update(struct session_info *si)
ad7ee3
     si_dbus_match_remove(si);
ad7ee3
 
ad7ee3
     si->dbus.match_session_signals =
ad7ee3
-        g_strdup_printf ("type='signal',interface='%s',path="
ad7ee3
-                         LOGIND_SESSION_OBJ_TEMPLATE,
ad7ee3
+        g_strdup_printf ("type='signal',interface='%s',path='"
ad7ee3
+                         LOGIND_SESSION_OBJ_TEMPLATE"'",
ad7ee3
                          LOGIND_SESSION_INTERFACE,
ad7ee3
                          si->session);
ad7ee3
     if (si->verbose)
ad7ee3
@@ -112,6 +119,84 @@ static void si_dbus_match_rule_update(struct session_info *si)
ad7ee3
 }
ad7ee3
 
ad7ee3
 static void
ad7ee3
+si_dbus_read_properties(struct session_info *si)
ad7ee3
+{
ad7ee3
+    dbus_bool_t locked_hint, ret;
ad7ee3
+    DBusMessageIter iter, iter_variant;
ad7ee3
+    gint type;
ad7ee3
+    DBusError error;
ad7ee3
+    DBusMessage *message = NULL;
ad7ee3
+    DBusMessage *reply = NULL;
ad7ee3
+    gchar *session_object;
ad7ee3
+    const gchar *interface, *property;
ad7ee3
+
ad7ee3
+    if (si->session == NULL)
ad7ee3
+        return;
ad7ee3
+
ad7ee3
+    session_object = g_strdup_printf(LOGIND_SESSION_OBJ_TEMPLATE, si->session);
ad7ee3
+    message = dbus_message_new_method_call(LOGIND_INTERFACE,
ad7ee3
+                                           session_object,
ad7ee3
+                                           DBUS_PROPERTIES_INTERFACE,
ad7ee3
+                                           "Get");
ad7ee3
+    g_free (session_object);
ad7ee3
+    if (message == NULL) {
ad7ee3
+        syslog(LOG_ERR, "Unable to create dbus message");
ad7ee3
+        goto exit;
ad7ee3
+    }
ad7ee3
+
ad7ee3
+    interface = LOGIND_SESSION_INTERFACE;
ad7ee3
+    property = SESSION_PROP_LOCKED_HINT;
ad7ee3
+    ret = dbus_message_append_args(message,
ad7ee3
+                                   DBUS_TYPE_STRING, &interface,
ad7ee3
+                                   DBUS_TYPE_STRING, &property,
ad7ee3
+                                   DBUS_TYPE_INVALID);
ad7ee3
+    if (!ret) {
ad7ee3
+        syslog(LOG_ERR, "Unable to request locked-hint");
ad7ee3
+        goto exit;
ad7ee3
+    }
ad7ee3
+
ad7ee3
+    dbus_error_init(&error);
ad7ee3
+    reply = dbus_connection_send_with_reply_and_block(si->dbus.system_connection,
ad7ee3
+                                                      message,
ad7ee3
+                                                      -1,
ad7ee3
+                                                      &error);
ad7ee3
+    if (reply == NULL) {
ad7ee3
+        if (dbus_error_is_set(&error)) {
ad7ee3
+            syslog(LOG_ERR, "Properties.Get failed (locked-hint) due %s", error.message);
ad7ee3
+            dbus_error_free(&error);
ad7ee3
+        } else {
ad7ee3
+            syslog(LOG_ERR, "Properties.Get failed (locked-hint)");
ad7ee3
+        }
ad7ee3
+        goto exit;
ad7ee3
+    }
ad7ee3
+
ad7ee3
+    dbus_message_iter_init(reply, &iter);
ad7ee3
+    type = dbus_message_iter_get_arg_type(&iter);
ad7ee3
+    if (type != DBUS_TYPE_VARIANT) {
ad7ee3
+        syslog(LOG_ERR, "expected a variant, got a '%c' instead", type);
ad7ee3
+        goto exit;
ad7ee3
+    }
ad7ee3
+
ad7ee3
+    dbus_message_iter_recurse(&iter, &iter_variant);
ad7ee3
+    type = dbus_message_iter_get_arg_type(&iter_variant);
ad7ee3
+    if (type != DBUS_TYPE_BOOLEAN) {
ad7ee3
+        syslog(LOG_ERR, "expected a boolean, got a '%c' instead", type);
ad7ee3
+        goto exit;
ad7ee3
+    }
ad7ee3
+    dbus_message_iter_get_basic(&iter_variant, &locked_hint);
ad7ee3
+
ad7ee3
+    si->session_locked_hint = (locked_hint) ? TRUE : FALSE;
ad7ee3
+exit:
ad7ee3
+    if (reply != NULL) {
ad7ee3
+        dbus_message_unref(reply);
ad7ee3
+    }
ad7ee3
+
ad7ee3
+    if (message != NULL) {
ad7ee3
+        dbus_message_unref(message);
ad7ee3
+    }
ad7ee3
+}
ad7ee3
+
ad7ee3
+static void
ad7ee3
 si_dbus_read_signals(struct session_info *si)
ad7ee3
 {
ad7ee3
     DBusMessage *message = NULL;
ad7ee3
@@ -220,16 +305,19 @@ char *session_info_session_for_pid(struct session_info *si, uint32_t pid)
ad7ee3
 
ad7ee3
 gboolean session_info_session_is_locked(struct session_info *si)
ad7ee3
 {
ad7ee3
-    g_return_val_if_fail (si != NULL, FALSE);
ad7ee3
+    gboolean locked;
ad7ee3
 
ad7ee3
-    /* We could also rely on IdleHint property from Session which seems to work
ad7ee3
-     * well in rhel7 but it wasn't working well in my own system (F23). I'm
ad7ee3
-     * convinced for now that Lock/Unlock signals should be enough but that
ad7ee3
-     * means Lock/Unlock being done by logind. That might take a while.
ad7ee3
-     * Check: https://bugzilla.gnome.org/show_bug.cgi?id=764773 */
ad7ee3
+    g_return_val_if_fail (si != NULL, FALSE);
ad7ee3
 
ad7ee3
     si_dbus_read_signals(si);
ad7ee3
-    return si->session_is_locked;
ad7ee3
+    si_dbus_read_properties(si);
ad7ee3
+
ad7ee3
+    locked = (si->session_is_locked || si->session_locked_hint);
ad7ee3
+    if (si->verbose) {
ad7ee3
+        syslog(LOG_DEBUG, "(systemd-login) session is locked: %s",
ad7ee3
+               locked ? "yes" : "no");
ad7ee3
+    }
ad7ee3
+    return locked;
ad7ee3
 }
ad7ee3
 
ad7ee3
 /* This function should only be called after session_info_get_active_session