diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.ac | 29 | ||||
-rw-r--r-- | libck-connector/Makefile.am | 22 | ||||
-rw-r--r-- | libck-connector/ck-connector.c | 381 | ||||
-rw-r--r-- | libck-connector/ck-connector.h | 122 | ||||
-rw-r--r-- | libck-connector/ck-connector.pc.in | 9 | ||||
-rw-r--r-- | pam-ck-connector/Makefile.am | 17 | ||||
-rw-r--r-- | pam-ck-connector/pam-ck-connector.c | 228 | ||||
-rw-r--r-- | pam-ck-connector/pam_ck_connector.8 | 80 |
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>. |