Since ConsoleKit 0.4.2, the sessions created by ck-launch-session are no
longer marked as local and active. This means that distributions can't simply
call ck-launch-session in Xsession.d anymore to get an active local ConsoleKit
session. Instead, XDM must create the session directly, providing info such as
the UID of the user and the tty used to log in (like GDM does).

It's important that locally logged in users get active local ConsoleKit
sessions because that's used by PolicyKit to determine whether certain actions
are allowed or not (according to a set of policies, of course). As an example
of how this can be used, UDisks can automount devices for locally logged in
users without a password prompt with their default PolicyKit policy.

This patch allows XDM to create a ConsoleKit session. This is disabled at
build time by default, you need to enable it with --with-consolekit. It relies
on a very lightweight library called libck-connector (which is distributed
with ConsoleKit) to do the DBus magic required for the creation of the active
local session.

openSUSE bug #528829 <http://bugzilla.novell.com/show_bug.cgi?id=528829>
X.Org bug #17325 <http://bugs.freedesktop.org/show_bug.cgi?id=17325>

Signed-off-by: Takashi Iwai <ti...@suse.de>
Tested-by: Cyril Brulebois <k...@debian.org>
Signed-off-by: Cyril Brulebois <k...@debian.org>
---
 configure.ac   |   12 ++++++
 include/dm.h   |    3 ++
 man/xdm.man    |    6 +++
 xdm/resource.c |   13 ++++++-
 xdm/session.c  |  102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 135 insertions(+), 1 deletions(-)


To recap, Takashi Iwai seems to be the author, and also agreed to have the patch
pushed upstream (https://bugzilla.novell.com/show_bug.cgi?id=528829#c3);
Fernando and Stefan “only” passed it on (but feel free to correct that, I can
add your S-o-b). Thanks for passing on the patch anyway! And finally I
made some modifications and tested it, hence the tags.

From v1, mostly:
 - configure.ac: redone to follow Dan's excellent comments.

Tests I performed:
 - even with ck-connector's devel files available, ./configure defaults to no ck
   support; same result with an explicit --without-consolekit
 - without ck-connector's devel files, ./configure --with-consolekit bails out
   since it doesn't find ck through pkg-config.
 - with ck-connector's devel files, ./configure --with-consolekit builds xdm
   with ck support, and the xdm binary gets an extra NEEDED entry:
   libck-connector.so.0

Consequently:
 - distros enabling ck support will have an extra dependency on the
   libck-connector library;
 - they also might want to add a dependency on the consolekit daemon; if it
   can't be contacted while starting the session, that session dies
   right away and one gets back the xdm prompt. It's still possible to
   start xdm with -noconsolekit though, in which case sessions can be
   started without consolekit.

[ At least that last point should be in the commit message, I think. ]

Run-time tests performed with xfce4: Without active, local ck support,
one can't shut down, restart, suspend or hibernate. With ck support, all
that becomes possible (again…).


diff --git a/configure.ac b/configure.ac
index 0c79999..4fc0531 100644
--- a/configure.ac
+++ b/configure.ac
@@ -358,6 +358,18 @@ PKG_CHECK_MODULES(DMCP, xdmcp)
 PKG_CHECK_MODULES(XLIB, x11)
 PKG_CHECK_MODULES(AUTH, xau)
 
+# ConsoleKit support
+AC_ARG_WITH(consolekit,
+       AS_HELP_STRING([--with-consolekit], [Use ConsoleKit]),
+       [USE_CONSOLEKIT=$withval],
+       [USE_CONSOLEKIT=no])
+if test x"$USE_CONSOLEKIT" != xno; then
+       PKG_CHECK_MODULES(CK_CONNECTOR, ck-connector)
+       AC_DEFINE([USE_CONSOLEKIT], 1, [Define to 1 to use ConsoleKit])
+       XDM_CFLAGS="$XDM_CFLAGS $CK_CONNECTOR_CFLAGS"
+       XDM_LIBS="$XDM_LIBS $CK_CONNECTOR_LIBS"
+fi
+
 #
 # Greeter
 #
diff --git a/include/dm.h b/include/dm.h
index 316dd46..b81d735 100644
--- a/include/dm.h
+++ b/include/dm.h
@@ -325,6 +325,9 @@ extern char *randomFile;
 extern char    *prngdSocket;
 extern int     prngdPort;
 # endif
+# ifdef USE_CONSOLEKIT
+extern int     use_consolekit;
+# endif
 
 extern char    *greeterLib;
 extern char    *willing;
diff --git a/man/xdm.man b/man/xdm.man
index 9590c1a..fb50349 100644
--- a/man/xdm.man
+++ b/man/xdm.man
@@ -48,6 +48,8 @@ xdm \- X Display Manager with support for XDMCP, host chooser
 ] [
 .B \-session
 .I session_program
+] [
+.B \-noconsolekit
 ]
 .SH DESCRIPTION
 .I Xdm
@@ -215,6 +217,10 @@ indicates the program to run as the session after the user 
has logged in.
 .IP "\fB\-xrm\fP \fIresource_specification\fP"
 Allows an arbitrary resource to be specified, as in most
 X Toolkit applications.
+.IP "\fB\-noconsolekit\fP"
+Specifies ``false'' as the value for the \fBDisplayManager.consoleKit\fP
+resource.
+This suppresses the session management using ConsoleKit.
 .SH RESOURCES
 At many stages the actions of
 .I xdm
diff --git a/xdm/resource.c b/xdm/resource.c
index ece4de3..ebcbeaa 100644
--- a/xdm/resource.c
+++ b/xdm/resource.c
@@ -65,6 +65,9 @@ char  *randomDevice;
 char   *prngdSocket;
 int    prngdPort;
 #endif
+#ifdef USE_CONSOLEKIT
+int    use_consolekit;
+#endif
 
 char   *greeterLib;
 char   *willing;
@@ -196,6 +199,10 @@ struct dmResources {
                                "false"} ,
 { "willing",   "Willing",      DM_STRING,      &willing,
                                ""} ,
+#ifdef USE_CONSOLEKIT
+{ "consoleKit",        "ConsoleKit",   DM_BOOL,        (char **) 
&use_consolekit,
+                               "true"} ,
+#endif
 };
 
 #define NUM_DM_RESOURCES       (sizeof DmResources / sizeof DmResources[0])
@@ -380,7 +387,11 @@ XrmOptionDescRec optionTable [] = {
 {"-debug",     "*debugLevel",          XrmoptionSepArg,        (caddr_t) NULL 
},
 {"-xrm",       NULL,                   XrmoptionResArg,        (caddr_t) NULL 
},
 {"-daemon",    ".daemonMode",          XrmoptionNoArg,         "true"         
},
-{"-nodaemon",  ".daemonMode",          XrmoptionNoArg,         "false"        }
+{"-nodaemon",  ".daemonMode",          XrmoptionNoArg,         "false"        
},
+#ifdef USE_CONSOLEKIT
+{"-consolekit",        ".consoleKit",          XrmoptionNoArg,         "true"  
},
+{"-noconsolekit", ".consoleKit",       XrmoptionNoArg,         "false" }
+#endif
 };
 
 static int     originalArgc;
diff --git a/xdm/session.c b/xdm/session.c
index 5fd47f0..b2bf3a3 100644
--- a/xdm/session.c
+++ b/xdm/session.c
@@ -67,6 +67,11 @@ extern int key_setnet(struct key_netstarg *arg);
 # endif
 #endif /* USE_PAM */
 
+#ifdef USE_CONSOLEKIT
+#include <ck-connector.h>
+#include <dbus/dbus.h>
+#endif
+
 #ifdef __SCO__
 # include <prot.h>
 #endif
@@ -504,6 +509,97 @@ UnsecureDisplay (struct display *d, Display *dpy)
     }
 }
 
+#ifdef USE_CONSOLEKIT
+
+static CkConnector *connector;
+
+static int openCKSession(struct verify_info *verify, struct display *d)
+{
+    int ret;
+    DBusError error;
+    char *remote_host_name = "";
+    dbus_bool_t is_local;
+    char *display_name = "";
+    char *display_device = "";
+    char devtmp[16];
+
+    if (!use_consolekit)
+       return 1;
+
+    is_local = d->displayType.location == Local;
+    if (d->peerlen > 0 && d->peer)
+       remote_host_name = d->peer;
+    if (d->name)
+       display_name = d->name;
+    /* how can we get the corresponding tty at best...? */
+    if (d->windowPath) {
+       display_device = strchr(d->windowPath, ':');
+       if (display_device && display_device[1])
+           display_device++;
+       else
+           display_device = d->windowPath;
+       snprintf(devtmp, sizeof(devtmp), "/dev/tty%s", display_device);
+       display_device = devtmp;
+    }
+
+    connector = ck_connector_new();
+    if (!connector) {
+       LogOutOfMem("ck_connector");
+       return 0;
+    }
+
+    dbus_error_init(&error);
+    ret = ck_connector_open_session_with_parameters(
+               connector, &error,
+               "unix-user", &verify->uid,
+               "x11-display", &display_name,
+               "x11-display-device", &display_device,
+               "remote-host-name", &remote_host_name,
+               "is-local", &is_local,
+               NULL);
+    if (!ret) {
+       if (dbus_error_is_set(&error)) {
+           LogError("Dbus error: %s\n", error.message);
+           dbus_error_free(&error);
+       } else {
+           LogError("ConsoleKit error\n");
+       }
+       LogError("console-kit-daemon not running?\n");
+       ck_connector_unref(connector);
+       connector = NULL;
+       return 0;
+    }
+
+    verify->userEnviron = setEnv(verify->userEnviron,
+               "XDG_SESSION_COOKIE", (char 
*)ck_connector_get_cookie(connector));
+    return 1;
+}
+
+static void closeCKSession(void)
+{
+    DBusError error;
+
+    if (!connector)
+       return;
+
+    dbus_error_init(&error);
+    if (!ck_connector_close_session(connector, &error)) {
+       if (dbus_error_is_set(&error)) {
+           LogError("Dbus error: %s\n", error.message);
+           dbus_error_free(&error);
+       } else {
+           LogError("ConsoleKit close error\n");
+       }
+       LogError("console-kit-daemon not running?\n");
+    }
+    ck_connector_unref(connector);
+    connector = NULL;
+}
+#else
+#define openCKSession(v,d)     1
+#define closeCKSession()
+#endif
+
 void
 SessionExit (struct display *d, int status, int removeAuth)
 {
@@ -518,6 +614,8 @@ SessionExit (struct display *d, int status, int removeAuth)
     }
 #endif
 
+    closeCKSession();
+
     /* make sure the server gets reset after the session is over */
     if (d->serverPid >= 2 && d->resetSignal)
        kill (d->serverPid, d->resetSignal);
@@ -600,6 +698,10 @@ StartClient (
 #ifdef USE_PAM
     if (pamh) pam_open_session(pamh, 0);
 #endif
+
+    if (!openCKSession(verify, d))
+       return 0;
+
     switch (pid = fork ()) {
     case 0:
        CleanUpChild ();
-- 
1.7.5.4

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to