summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac29
-rw-r--r--libck-connector/Makefile.am22
-rw-r--r--libck-connector/ck-connector.c381
-rw-r--r--libck-connector/ck-connector.h122
-rw-r--r--libck-connector/ck-connector.pc.in9
-rw-r--r--pam-ck-connector/Makefile.am17
-rw-r--r--pam-ck-connector/pam-ck-connector.c228
-rw-r--r--pam-ck-connector/pam_ck_connector.880
9 files changed, 890 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index 5cae098..55f71b8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,6 +8,8 @@ SUBDIRS = \
src \
tools \
data \
+ libck-connector \
+ pam-ck-connector \
$(NULL)
EXTRA_DIST = \
diff --git a/configure.ac b/configure.ac
index 2da5655..1e2c1aa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -44,6 +44,9 @@ PKG_CHECK_MODULES(CONSOLE_KIT,
gobject-2.0 >= $GLIB_REQUIRED_VERSION
gthread-2.0 >= $GLIB_REQUIRED_VERSION
)
+PKG_CHECK_MODULES(LIBDBUS,
+ dbus-1 >= $DBUS_REQUIRED_VERSION
+)
AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal)
EXTRA_COMPILE_WARNINGS(yes)
@@ -198,6 +201,28 @@ else
fi
#
+# Check for pam
+#
+have_pam=no
+AC_CHECK_LIB(pam, pam_getenv, have_pam=yes)
+AM_CONDITIONAL(HAVE_PAM, test x$have_pam = xyes)
+AC_SUBST(HAVE_PAM)
+
+#
+# Check if we should build the PAM module
+#
+msg_pam_module=no
+AC_ARG_ENABLE(pam-module, [AC_HELP_STRING([--enable-pam-module], [build PAM module])],, enable_pam_module=no)
+if test "x$enable_pam_module" = "xyes"; then
+ if test "x$have_pam" = "xno"; then
+ AC_MSG_ERROR([--enable-pam-module requires PAM but PAM was not found])
+ fi
+ AC_DEFINE(ENABLE_PAM_MODULE, [], [Set if we build PAM module])
+ msg_pam_module=yes
+fi
+AM_CONDITIONAL(ENABLE_PAM_MODULE, test "x$enable_pam_module" = "xyes")
+
+#
# Enable Debug
#
AC_ARG_ENABLE(debug, [AC_HELP_STRING([--enable-debug=[no/yes]], [turn on debugging])],, enable_debug=yes)
@@ -230,6 +255,9 @@ tools/Makefile
tools/linux/Makefile
data/Makefile
data/ConsoleKit
+libck-connector/Makefile
+libck-connector/ck-connector.pc
+pam-ck-connector/Makefile
])
echo "
@@ -253,5 +281,6 @@ echo "
Backend: ${CK_BACKEND}
dbus-1 system.d dir: ${DBUS_SYS_DIR}
+ build PAM module: ${msg_pam_module}
"
diff --git a/libck-connector/Makefile.am b/libck-connector/Makefile.am
new file mode 100644
index 0000000..80a4e2b
--- /dev/null
+++ b/libck-connector/Makefile.am
@@ -0,0 +1,22 @@
+
+INCLUDES = $(LIBDBUS_CFLAGS)
+
+slib_LTLIBRARIES=libck-connector.la
+slibdir=/lib
+libck_connectorincludedir=$(includedir)/ConsoleKit/ck-connector
+libck_connectorinclude_HEADERS = ck-connector.h
+libck_connector_la_SOURCES = ck-connector.c ck-connector.h
+
+# soname management for libck-connector
+LIBCKCON_LT_CURRENT=0
+LIBCKCON_LT_REVISION=0
+LIBCKCON_LT_AGE=0
+
+libck_connector_la_LIBADD = $(LIBDBUS_LIBS)
+libck_connector_la_LDFLAGS = -version-info $(LIBCKCON_LT_CURRENT):$(LIBCKCON_LT_REVISION):$(LIBCKCON_LT_AGE)
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = ck-connector.pc
+
+clean-local :
+ rm -f *~
diff --git a/libck-connector/ck-connector.c b/libck-connector/ck-connector.c
new file mode 100644
index 0000000..b22f76c
--- /dev/null
+++ b/libck-connector/ck-connector.c
@@ -0,0 +1,381 @@
+/*
+ * ck-connector.c : Code for login managers to register with ConsoleKit.
+ *
+ * Copyright (c) 2007 David Zeuthen <davidz@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dbus/dbus.h>
+
+#include "ck-connector.h"
+
+static dbus_bool_t
+add_param_int32 (DBusMessageIter *iter_array, const char *key, dbus_int32_t value)
+{
+ DBusMessageIter iter_struct;
+ DBusMessageIter iter_variant;
+
+ if (!dbus_message_iter_open_container (iter_array,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &iter_struct))
+ goto oom;
+ if (!dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &key))
+ goto oom;
+ if (!dbus_message_iter_open_container (&iter_struct,
+ DBUS_TYPE_VARIANT,
+ DBUS_TYPE_INT32_AS_STRING,
+ &iter_variant))
+ goto oom;
+ if (!dbus_message_iter_append_basic (&iter_variant, DBUS_TYPE_INT32, &value))
+ goto oom;
+ if (!dbus_message_iter_close_container (&iter_struct, &iter_variant))
+ goto oom;
+ if (!dbus_message_iter_close_container (iter_array, &iter_struct))
+ goto oom;
+
+ return TRUE;
+oom:
+ return FALSE;
+}
+
+static dbus_bool_t
+add_param_string (DBusMessageIter *iter_array, const char *key, const char *value)
+{
+ DBusMessageIter iter_struct;
+ DBusMessageIter iter_variant;
+
+ if (!dbus_message_iter_open_container (iter_array,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &iter_struct))
+ goto oom;
+ if (!dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &key))
+ goto oom;
+ if (!dbus_message_iter_open_container (&iter_struct,
+ DBUS_TYPE_VARIANT,
+ DBUS_TYPE_STRING_AS_STRING,
+ &iter_variant))
+ goto oom;
+ if (!dbus_message_iter_append_basic (&iter_variant, DBUS_TYPE_STRING, &value))
+ goto oom;
+ if (!dbus_message_iter_close_container (&iter_struct, &iter_variant))
+ goto oom;
+ if (!dbus_message_iter_close_container (iter_array, &iter_struct))
+ goto oom;
+
+ return TRUE;
+oom:
+ return FALSE;
+}
+
+static dbus_bool_t
+add_param_bool (DBusMessageIter *iter_array, const char *key, dbus_bool_t value)
+{
+ DBusMessageIter iter_struct;
+ DBusMessageIter iter_variant;
+
+ if (!dbus_message_iter_open_container (iter_array,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &iter_struct))
+ goto oom;
+ if (!dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &key))
+ goto oom;
+ if (!dbus_message_iter_open_container (&iter_struct,
+ DBUS_TYPE_VARIANT,
+ DBUS_TYPE_BOOLEAN_AS_STRING,
+ &iter_variant))
+ goto oom;
+ if (!dbus_message_iter_append_basic (&iter_variant, DBUS_TYPE_BOOLEAN, &value))
+ goto oom;
+ if (!dbus_message_iter_close_container (&iter_struct, &iter_variant))
+ goto oom;
+ if (!dbus_message_iter_close_container (iter_array, &iter_struct))
+ goto oom;
+
+ return TRUE;
+oom:
+ return FALSE;
+}
+
+
+struct CKConnector_s
+{
+ char *cookie;
+ dbus_bool_t session_created;
+ DBusConnection *con;
+};
+
+CKConnector*
+ckc_new (void)
+{
+ CKConnector *ckc;
+
+ ckc = calloc (1, sizeof (CKConnector));
+ if (ckc == NULL)
+ goto oom;
+ ckc->con = NULL;
+ ckc->cookie = NULL;
+ ckc->session_created = FALSE;
+oom:
+ return ckc;
+};
+
+dbus_bool_t
+ckc_create_local_session2 (CKConnector *ckc)
+{
+ DBusError error;
+ DBusMessage *message;
+ DBusMessage *reply;
+ dbus_bool_t ret;
+ char *cookie;
+
+ reply = NULL;
+ message = NULL;
+ ret = FALSE;
+
+ dbus_error_init (&error);
+ ckc->con = dbus_bus_get_private (DBUS_BUS_SYSTEM, &error);
+ if (ckc->con == NULL) {
+ goto out;
+ }
+ dbus_connection_set_exit_on_disconnect (ckc->con, FALSE);
+
+ message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit",
+ "/org/freedesktop/ConsoleKit/Manager",
+ "org.freedesktop.ConsoleKit.Manager",
+ "OpenSession");
+ if (message == NULL)
+ goto out;
+
+ reply = dbus_connection_send_with_reply_and_block (ckc->con, message, -1, &error);
+ if (reply == NULL) {
+ if (dbus_error_is_set (&error)) {
+ dbus_error_free (&error);
+ goto out;
+ }
+ }
+
+ if (!dbus_message_get_args (reply,
+ &error,
+ DBUS_TYPE_STRING, &cookie,
+ DBUS_TYPE_INVALID)) {
+ if (dbus_error_is_set (&error)) {
+ dbus_error_free (&error);
+ goto out;
+ }
+ }
+
+ ckc->cookie = strdup (cookie);
+ if (ckc->cookie == NULL)
+ goto out;
+
+ ckc->session_created = TRUE;
+ ret = TRUE;
+
+out:
+ if (reply != NULL)
+ dbus_message_unref (reply);
+
+ if (message != NULL)
+ dbus_message_unref (message);
+
+ return ret;
+}
+
+dbus_bool_t
+ckc_create_local_session (CKConnector *ckc, uid_t user, const char *tty, const char *x11_display)
+{
+ DBusError error;
+ DBusMessage *message;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ DBusMessageIter iter_array;
+ dbus_bool_t ret;
+ char *cookie;
+
+ reply = NULL;
+ message = NULL;
+ ret = FALSE;
+
+ dbus_error_init (&error);
+ ckc->con = dbus_bus_get_private (DBUS_BUS_SYSTEM, &error);
+ if (ckc->con == NULL) {
+ goto out;
+ }
+ dbus_connection_set_exit_on_disconnect (ckc->con, FALSE);
+
+ message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit",
+ "/org/freedesktop/ConsoleKit/Manager",
+ "org.freedesktop.ConsoleKit.Manager",
+ "OpenSessionWithParameters");
+ if (message == NULL)
+ goto out;
+
+ dbus_message_iter_init_append (message, &iter);
+ if (!dbus_message_iter_open_container (&iter,
+ DBUS_TYPE_ARRAY,
+ "(sv)",
+ &iter_array))
+ goto out;
+
+ if (!add_param_string (&iter_array, "host-name", "localhost"))
+ goto out;
+ if (!add_param_string (&iter_array, "display-device", tty))
+ goto out;
+ if (x11_display != NULL)
+ if (!add_param_string (&iter_array, "x11-display", x11_display))
+ goto out;
+ if (!add_param_int32 (&iter_array, "user", user))
+ goto out;
+ if (!add_param_bool (&iter_array, "is-local", TRUE))
+ goto out;
+
+ if (!dbus_message_iter_close_container (&iter, &iter_array))
+ goto out;
+
+ reply = dbus_connection_send_with_reply_and_block (ckc->con, message, -1, &error);
+ if (reply == NULL) {
+ if (dbus_error_is_set (&error)) {
+ dbus_error_free (&error);
+ goto out;
+ }
+ }
+
+ if (!dbus_message_get_args (reply,
+ &error,
+ DBUS_TYPE_STRING, &cookie,
+ DBUS_TYPE_INVALID)) {
+ if (dbus_error_is_set (&error)) {
+ dbus_error_free (&error);
+ goto out;
+ }
+ }
+
+ ckc->cookie = strdup (cookie);
+ if (ckc->cookie == NULL)
+ goto out;
+
+ ckc->session_created = TRUE;
+ ret = TRUE;
+
+out:
+ if (reply != NULL)
+ dbus_message_unref (reply);
+
+ if (message != NULL)
+ dbus_message_unref (message);
+
+ return ret;
+}
+
+char *
+ckc_get_cookie (CKConnector *ckc)
+{
+ if (!ckc->session_created)
+ return NULL;
+ else
+ return ckc->cookie;
+}
+
+dbus_bool_t
+ckc_close_session (CKConnector *ckc)
+{
+ DBusError error;
+ DBusMessage *message;
+ DBusMessage *reply;
+ dbus_bool_t ret;
+ dbus_bool_t session_closed;
+
+ reply = NULL;
+ message = NULL;
+ ret = FALSE;
+ if (!ckc->session_created || ckc->cookie == NULL)
+ goto out;
+
+ dbus_error_init (&error);
+ message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit",
+ "/org/freedesktop/ConsoleKit/Manager",
+ "org.freedesktop.ConsoleKit.Manager",
+ "CloseSession");
+ if (message == NULL)
+ goto out;
+
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &(ckc->cookie),
+ DBUS_TYPE_INVALID))
+ goto out;
+
+ reply = dbus_connection_send_with_reply_and_block (ckc->con, message, -1, &error);
+ if (reply == NULL) {
+ if (dbus_error_is_set (&error)) {
+ dbus_error_free (&error);
+ goto out;
+ }
+ }
+
+ if (!dbus_message_get_args (reply,
+ &error,
+ DBUS_TYPE_BOOLEAN, &session_closed,
+ DBUS_TYPE_INVALID)) {
+ if (dbus_error_is_set (&error)) {
+ dbus_error_free (&error);
+ goto out;
+ }
+ }
+
+ if (!session_closed)
+ goto out;
+
+ ckc->session_created = FALSE;
+ ret = TRUE;
+
+out:
+ if (reply != NULL)
+ dbus_message_unref (reply);
+
+ if (message != NULL)
+ dbus_message_unref (message);
+
+ return ret;
+
+}
+
+void
+ckc_free (CKConnector *ckc)
+{
+ if (ckc->con != NULL) {
+ /* it's a private connection so it's all good */
+ dbus_connection_close (ckc->con);
+ }
+ if (ckc->cookie != NULL) {
+ free (ckc->cookie);
+ }
+ free (ckc);
+}
diff --git a/libck-connector/ck-connector.h b/libck-connector/ck-connector.h
new file mode 100644
index 0000000..e92712d
--- /dev/null
+++ b/libck-connector/ck-connector.h
@@ -0,0 +1,122 @@
+/*
+ * ck-connector.h : Code for login managers to register with ConsoleKit.
+ *
+ * Copyright (c) 2007 David Zeuthen <davidz@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef CK_CONNECTOR_H
+#define CK_CONNECTOR_H
+
+#include <sys/types.h>
+#include <dbus/dbus.h>
+
+struct CKConnecter_s;
+typedef struct CKConnector_s CKConnector;
+
+/* Allocates a new CKConnector instance.
+ *
+ * Returns NULL on OOM */
+CKConnector *ckc_new (void);
+
+/* Connects to the D-Bus system bus daemon and issues the method call
+ * OpenSessionWithParameters on the ConsoleKit manager interface. The
+ * connection to the bus is private.
+ *
+ * The only parameter that is optional is x11_display - it may be set
+ * to NULL if there is no X11 server associated with the session.
+ *
+ * Returns FALSE on OOM, if the system bus daemon is not running, if
+ * the ConsoleKit daemon is not running or if the caller doesn't have
+ * sufficient privileges.
+ */
+dbus_bool_t ckc_create_local_session (CKConnector *ckc, uid_t user, const char *tty, const char *x11_display);
+
+dbus_bool_t ckc_create_local_session2 (CKConnector *ckc);
+
+/* Gets the cookie that should be set as XDG_SESSION_COOKIE in the
+ * users environment.
+ *
+ * Returns NULL unless ckc_create_local_session() succeeded
+ */
+char *ckc_get_cookie (CKConnector *ckc);
+
+/* Issues the CloseSession method call on the ConsoleKit manager
+ * interface.
+ *
+ * Returns FALSE on OOM, if the system bus daemon is not running, if
+ * the ConsoleKit daemon is not running, if the caller doesn't have
+ * sufficient privilege or if ckc_create_local_session() wasn't
+ * successfully invoked.
+ */
+dbus_bool_t ckc_close_session (CKConnector *ckc);
+
+/* Frees all resources allocated and disconnects from the system
+ * message bus.
+ */
+void ckc_free (CKConnector *ckc);
+
+/* example code:
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "ck-connector.h"
+
+int
+main (int argc, char *argv[])
+{
+ CKConnector *ckc;
+
+ ckc = ckc_new ();
+ if (ckc == NULL) {
+ printf ("OOM creating CKConnector\n");
+ goto out;
+ }
+
+ if (!ckc_create_local_session (ckc, 500, "/dev/tty2", ":1")) {
+ printf ("cannot create CK session: OOM, D-Bus system bus not available,\n"
+ "ConsoleKit not available or insufficient privileges.\n");
+ goto out;
+ }
+
+ printf ("Session cookie is '%s'\n", ckc_get_cookie (ckc));
+ sleep (20);
+
+ if (!ckc_close_session (ckc)) {
+ printf ("Cannot close CK session: OOM, D-Bus system bus not available,\n"
+ "ConsoleKit not available or insufficient privileges.\n");
+ goto out;
+ }
+
+out:
+ if (ckc != NULL) {
+ ckc_free (ckc);
+ }
+}
+
+*/
+
+#endif /* CK_CONNECTOR_H */
+
+
+
diff --git a/libck-connector/ck-connector.pc.in b/libck-connector/ck-connector.pc.in
new file mode 100644
index 0000000..e3f00cd
--- /dev/null
+++ b/libck-connector/ck-connector.pc.in
@@ -0,0 +1,9 @@
+libdir=/lib
+includedir=@prefix@/include
+
+Name: ck-connector
+Description: Library for connecting new sessions to ConsoleKit
+Version: @VERSION@
+Requires: dbus-1
+Libs: -L${libdir} -lck-connector
+Cflags: -I${includedir}/ConsoleKit/ck-connector
diff --git a/pam-ck-connector/Makefile.am b/pam-ck-connector/Makefile.am
new file mode 100644
index 0000000..e03923b
--- /dev/null
+++ b/pam-ck-connector/Makefile.am
@@ -0,0 +1,17 @@
+
+if ENABLE_PAM_MODULE
+
+INCLUDES = $(LIBDBUS_CFLAGS) -I$(top_builddir)/libck-connector
+
+pamlib_LTLIBRARIES=pam_ck_connector.la
+pamlibdir=/lib/security
+pam_ck_connector_la_SOURCES = pam-ck-connector.c
+pam_ck_connector_la_LDFLAGS = -no-undefined -module -avoid-version
+pam_ck_connector_la_LIBADD = -lpam $(LIBDBUS_LIBS) $(top_builddir)/libck-connector/libck-connector.la
+
+man_MANS = pam_ck_connector.8
+
+endif
+
+clean-local :
+ rm -f *~
diff --git a/pam-ck-connector/pam-ck-connector.c b/pam-ck-connector/pam-ck-connector.c
new file mode 100644
index 0000000..835be0c
--- /dev/null
+++ b/pam-ck-connector/pam-ck-connector.c
@@ -0,0 +1,228 @@
+/*
+ * pam-ck-connector.c : PAM module for registering with CK
+ *
+ * Copyright (c) 2007 David Zeuthen <davidz@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <ctype.h>
+#include <pwd.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+
+#define PAM_SM_SESSION
+
+#include <security/pam_modules.h>
+#include <security/_pam_macros.h>
+#include <security/pam_modutil.h>
+#include <security/pam_ext.h>
+
+#include "ck-connector.h"
+
+static int opt_debug = FALSE;
+
+static void
+_parse_pam_args (const pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ int i;
+
+ opt_debug = FALSE;
+ for (i = 0; i < argc && argv[i] != NULL; i++) {
+ if (strcmp (argv[i] ,"debug") == 0) {
+ opt_debug = TRUE;
+ } else {
+ pam_syslog (pamh, LOG_ERR, "unknown option: %s", argv[i]);
+ }
+ }
+}
+
+
+PAM_EXTERN int
+pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return PAM_IGNORE;
+}
+
+PAM_EXTERN int
+pam_sm_setcred (pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return PAM_IGNORE;
+}
+
+static uid_t
+_util_name_to_uid (const char *username, gid_t *default_gid)
+{
+ int rc;
+ uid_t res;
+ char *buf = NULL;
+ unsigned int bufsize;
+ struct passwd pwd;
+ struct passwd *pwdp;
+
+ res = (uid_t) -1;
+
+ bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
+ buf = calloc (sizeof (char), bufsize);
+ rc = getpwnam_r (username, &pwd, buf, bufsize, &pwdp);
+ if (rc != 0 || pwdp == NULL) {
+ goto out;
+ }
+
+ res = pwdp->pw_uid;
+ if (default_gid != NULL)
+ *default_gid = pwdp->pw_gid;
+
+out:
+ free (buf);
+ return res;
+}
+
+/* our singleton */
+static CKConnector *ckc = NULL;
+
+PAM_EXTERN int
+pam_sm_close_session (pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ if (ckc != NULL) {
+ ckc_free (ckc);
+ ckc = NULL;
+ }
+ return PAM_SUCCESS;
+}
+
+PAM_EXTERN int
+pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ int ret;
+ const char *user;
+ const char *tty;
+ const char *x11_display;
+ const char *s;
+ uid_t uid;
+ char buf[256];
+
+ ret = PAM_IGNORE;
+
+ _parse_pam_args (pamh, flags, argc, argv);
+
+ /* Register with ConsoleKit as part of the session management */
+ if (ckc != NULL) {
+ pam_syslog (pamh, LOG_ERR, "process already registered with ConsoleKit");
+ goto out;
+ }
+
+ ckc = ckc_new ();
+ if (ckc == NULL) {
+ pam_syslog (pamh, LOG_ERR, "oom creating ConsoleKit connector object");
+ goto out;
+ }
+
+ if (pam_get_user (pamh, &user, NULL) != PAM_SUCCESS || user == NULL) {
+ pam_syslog (pamh, LOG_ERR, "cannot determine username");
+ goto out;
+ }
+
+ if (pam_get_item (pamh, PAM_TTY, (const void **) &tty) != PAM_SUCCESS || tty == NULL) {
+ pam_syslog (pamh, LOG_ERR, "cannot determine tty");
+ goto out;
+ }
+
+ if ((s = pam_getenv (pamh, "CKCON_TTY")) != NULL) {
+ tty = s;
+ if (opt_debug)
+ pam_syslog (pamh, LOG_INFO, "using '%s' as tty (from CKCON_TTY)", tty);
+ }
+
+ x11_display = NULL;
+ if ((s = pam_getenv (pamh, "CKCON_X11_DISPLAY")) != NULL) {
+ x11_display = s;
+ if (opt_debug)
+ pam_syslog (pamh, LOG_INFO, "using '%s' as X11 display (from CKCON_X11_DISPLAY)", x11_display);
+ }
+
+ uid = _util_name_to_uid (user, NULL);
+ if (uid == (uid_t) -1) {
+ pam_syslog (pamh, LOG_ERR, "cannot determine uid for user '%s'", user);
+ goto out;
+ }
+
+ if (!ckc_create_local_session (ckc, uid, tty, x11_display)) {
+ /* this might not be a bug for servers that don't have
+ * the message bus or ConsoleKit daemon running - so
+ * only log a message in debugging mode.
+ */
+ if (opt_debug)
+ pam_syslog (pamh, LOG_DEBUG, "insufficient privileges or D-Bus / ConsoleKit not available");
+ goto out;
+ }
+
+ /* now set the cookie */
+ buf[sizeof (buf) - 1] = '\0';
+ snprintf (buf, sizeof (buf) - 1, "XDG_SESSION_COOKIE=%s", ckc_get_cookie (ckc));
+ if (pam_putenv (pamh, buf) != PAM_SUCCESS) {
+ pam_syslog (pamh, LOG_ERR, "unable to set XDG_SESSION_COOKIE vairable");
+ /* tear down session the hard way */
+ ckc_free (ckc);
+ ckc = NULL;
+ goto out;
+ }
+
+ if (opt_debug) {
+ pam_syslog (pamh, LOG_DEBUG, "registered uid=%d on tty='%s' with ConsoleKit", uid, tty);
+ }
+
+ /* note that we're leaking our CKConnector instance ckc - this
+ * is *by design* such that when the login manager (that uses
+ * us) exits / crashes / etc. ConsoleKit will notice, via D-Bus
+ * connection tracking, that the login session ended.
+ */
+
+ ret = PAM_SUCCESS;
+
+out:
+ return ret;
+}
+
+#ifdef PAM_STATIC
+
+struct pam_module _pam_ckconnector_modstruct = {
+ "pam_ck_connector",
+ pam_sm_authenticate,
+ pam_sm_setcred,
+ NULL,
+ pam_sm_open_session,
+ pam_sm_close_session,
+ NULL,
+};
+
+#endif
+
+/* end of module definition */
diff --git a/pam-ck-connector/pam_ck_connector.8 b/pam-ck-connector/pam_ck_connector.8
new file mode 100644
index 0000000..43241a0
--- /dev/null
+++ b/pam-ck-connector/pam_ck_connector.8
@@ -0,0 +1,80 @@
+.\" Title: pam_ck_connector
+.\" Author: David Zeuthen <davidz@redhat.com>
+.\" Date: 02/27/2007
+.\"
+.TH "PAM_CK_CONNECTOR" "8" "02/27/2007" "ConsoleKit Manual" "ConsoleKit Manual"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+pam_ck_connector \- Register sessin with ConsoleKit
+.SH "SYNOPSIS"
+.HP 12
+\fBpam_ck_connector.so\fR [debug]
+.SH "DESCRIPTION"
+.PP
+The pam_ck_connector PAM module registers a login session with
+the system-wide
+.I ConsoleKit
+daemon. This PAM module should be used with
+caution; only local login managers such as
+.B login(1)
+should use this. Since the
+.I ConsoleKit
+daemon can accept both an
+.B tty
+and an X11 display the normal parameters set by PAM are not always
+useful.
+
+An application can therefore override these with the PAM environment
+variables
+.B CKCON_TTY
+and
+.B CHCON_X11_DISPLAY
+(the application should remember to unset these before starting the
+login session).
+
+Also note that the
+.I ConsoleKit
+daemon may reject registration attempts if the given set of data are
+inconsistent with each other. More more information, see the
+.I ConsoleKit
+documentation on the
+.B OpenSessionWithParameters()
+method call on the
+.B org.freedesktop.ConsoleKit.Manager
+D-Bus interface.
+
+If registration with the
+.I ConsoleKit
+daemon succeeds, this PAM module will set the environment variable
+.B XDG_SESSION_COOKIE
+which is used to defined membership of a login session.
+
+This PAM module has the side effect that it creates a connection to
+the system message bus that is kept open until the session ends. This
+is used by the
+.I ConsoleKit
+daemon to track the life-cycle of the
+session and, as such, should the login manager crash, the session will
+be properly unregistered.
+
+.SH "OPTIONS"
+.PP
+.TP 3n
+\fBdebug\fR
+Print debug information.
+.fi
+.RE
+.sp
+.SH "SEE ALSO"
+.PP
+
+\fBpam.conf\fR(5),
+\fBpam.d\fR(8),
+\fBpam\fR(8),
+\fBdbus-daemon\fR(1)
+.SH "AUTHOR"
+.PP
+pam_ck_connector was written by David Zeuthen <davidz@redhat.com>.