summaryrefslogtreecommitdiffstats
path: root/pam-ck-connector/pam-ck-connector.c
diff options
context:
space:
mode:
Diffstat (limited to 'pam-ck-connector/pam-ck-connector.c')
-rw-r--r--pam-ck-connector/pam-ck-connector.c228
1 files changed, 228 insertions, 0 deletions
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 */