chiark / gitweb /
logind: close FIFO before ending sessions cleanly
[elogind.git] / src / login / pam-module.c
index 46509245fb4a801361a460e63bfa70acec18b992..4106d2ba4b65986f7f8db0982a3f1b26e09c9e44 100644 (file)
@@ -321,7 +321,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
 
         struct passwd *pw;
         bool kill_processes = false, debug = false;
-        const char *username, *id, *object_path, *runtime_path, *service = NULL, *tty = NULL, *display = NULL, *remote_user = NULL, *remote_host = NULL, *seat = NULL, *type, *cvtnr = NULL;
+        const char *username, *id, *object_path, *runtime_path, *service = NULL, *tty = NULL, *display = NULL, *remote_user = NULL, *remote_host = NULL, *seat = NULL, *type, *class, *cvtnr = NULL;
         char **controllers = NULL, **reset_controllers = NULL, **kill_only_users = NULL, **kill_exclude_users = NULL;
         DBusError error;
         uint32_t uid, pid;
@@ -414,7 +414,6 @@ _public_ PAM_EXTERN int pam_sm_open_session(
                         "/org/freedesktop/login1",
                         "org.freedesktop.login1.Manager",
                         "CreateSession");
-
         if (!m) {
                 pam_syslog(handle, LOG_ERR, "Could not allocate create session message.");
                 r = PAM_BUF_ERR;
@@ -465,13 +464,20 @@ _public_ PAM_EXTERN int pam_sm_open_session(
         type = !isempty(display) ? "x11" :
                    !isempty(tty) ? "tty" : "unspecified";
 
-        remote = !isempty(remote_host) && !streq(remote_host, "localhost") && !streq(remote_host, "localhost.localdomain");
+        class = pam_getenv(handle, "XDG_SESSION_CLASS");
+        if (isempty(class))
+                class = "user";
+
+        remote = !isempty(remote_host) &&
+                !streq(remote_host, "localhost") &&
+                !streq(remote_host, "localhost.localdomain");
 
         if (!dbus_message_append_args(m,
                                       DBUS_TYPE_UINT32, &uid,
                                       DBUS_TYPE_UINT32, &pid,
                                       DBUS_TYPE_STRING, &service,
                                       DBUS_TYPE_STRING, &type,
+                                      DBUS_TYPE_STRING, &class,
                                       DBUS_TYPE_STRING, &seat,
                                       DBUS_TYPE_UINT32, &vtnr,
                                       DBUS_TYPE_STRING, &tty,
@@ -613,11 +619,77 @@ _public_ PAM_EXTERN int pam_sm_close_session(
                 int argc, const char **argv) {
 
         const void *p = NULL;
+        const char *id;
+        DBusConnection *bus = NULL;
+        DBusMessage *m = NULL, *reply = NULL;
+        DBusError error;
+        int r;
 
-        pam_get_data(handle, "systemd.session-fd", &p);
+        assert(handle);
+
+        dbus_error_init(&error);
+
+        id = pam_getenv(handle, "XDG_SESSION_ID");
+        if (id) {
+
+                /* Before we go and close the FIFO we need to tell
+                 * logind that this is a clean session shutdown, so
+                 * that it doesn't just go and slaughter us
+                 * immediately after closing the fd */
+
+                bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
+                if (!bus) {
+                        pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", bus_error_message(&error));
+                        r = PAM_SESSION_ERR;
+                        goto finish;
+                }
+
+                m = dbus_message_new_method_call(
+                                "org.freedesktop.login1",
+                                "/org/freedesktop/login1",
+                                "org.freedesktop.login1.Manager",
+                                "ReleaseSession");
+                if (!m) {
+                        pam_syslog(handle, LOG_ERR, "Could not allocate release session message.");
+                        r = PAM_BUF_ERR;
+                        goto finish;
+                }
+
+                if (!dbus_message_append_args(m,
+                                              DBUS_TYPE_STRING, &id,
+                                              DBUS_TYPE_INVALID)) {
+                        pam_syslog(handle, LOG_ERR, "Could not attach parameters to message.");
+                        r = PAM_BUF_ERR;
+                        goto finish;
+                }
 
+                reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+                if (!reply) {
+                        pam_syslog(handle, LOG_ERR, "Failed to release session: %s", bus_error_message(&error));
+                        r = PAM_SESSION_ERR;
+                        goto finish;
+                }
+        }
+
+        r = PAM_SUCCESS;
+
+finish:
+        pam_get_data(handle, "systemd.session-fd", &p);
         if (p)
                 close_nointr(PTR_TO_INT(p) - 1);
 
-        return PAM_SUCCESS;
+        dbus_error_free(&error);
+
+        if (bus) {
+                dbus_connection_close(bus);
+                dbus_connection_unref(bus);
+        }
+
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        return r;
 }