aboutsummaryrefslogtreecommitdiff
path: root/modules/pam_keyinit/pam_keyinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_keyinit/pam_keyinit.c')
-rw-r--r--modules/pam_keyinit/pam_keyinit.c269
1 files changed, 0 insertions, 269 deletions
diff --git a/modules/pam_keyinit/pam_keyinit.c b/modules/pam_keyinit/pam_keyinit.c
deleted file mode 100644
index 378a7723..00000000
--- a/modules/pam_keyinit/pam_keyinit.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/* pam_keyinit.c: Initialise the session keyring on login through a PAM module
- *
- * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include "config.h"
-#include <stdarg.h>
-#include <string.h>
-#include <syslog.h>
-#include <pwd.h>
-#include <unistd.h>
-#include <errno.h>
-#include <security/pam_modules.h>
-#include <security/pam_modutil.h>
-#include <security/pam_ext.h>
-#include <sys/syscall.h>
-
-#define KEY_SPEC_SESSION_KEYRING -3 /* ID for session keyring */
-#define KEY_SPEC_USER_KEYRING -4 /* ID for UID-specific keyring */
-#define KEY_SPEC_USER_SESSION_KEYRING -5 /* - key ID for UID-session keyring */
-
-#define KEYCTL_GET_KEYRING_ID 0 /* ask for a keyring's ID */
-#define KEYCTL_JOIN_SESSION_KEYRING 1 /* start named session keyring */
-#define KEYCTL_REVOKE 3 /* revoke a key */
-#define KEYCTL_LINK 8 /* link a key into a keyring */
-
-static int my_session_keyring;
-static int session_counter;
-static int do_revoke;
-static int revoke_as_uid;
-static int revoke_as_gid;
-static int xdebug = 0;
-
-static void debug(pam_handle_t *pamh, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
-
-static void debug(pam_handle_t *pamh, const char *fmt, ...)
-{
- va_list va;
-
- if (xdebug) {
- va_start(va, fmt);
- pam_vsyslog(pamh, LOG_DEBUG, fmt, va);
- va_end(va);
- }
-}
-
-static int error(pam_handle_t *pamh, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
-
-static int error(pam_handle_t *pamh, const char *fmt, ...)
-{
- va_list va;
-
- va_start(va, fmt);
- pam_vsyslog(pamh, LOG_ERR, fmt, va);
- va_end(va);
-
- return PAM_SESSION_ERR;
-}
-
-/*
- * initialise the session keyring for this process
- */
-static int init_keyrings(pam_handle_t *pamh, int force)
-{
- int session, usession, ret;
-
- if (!force) {
- /* get the IDs of the session keyring and the user session
- * keyring */
- session = syscall(__NR_keyctl,
- KEYCTL_GET_KEYRING_ID,
- KEY_SPEC_SESSION_KEYRING,
- 0);
- debug(pamh, "GET SESSION = %d", session);
- if (session < 0) {
- /* don't worry about keyrings if facility not
- * installed */
- if (errno == ENOSYS)
- return PAM_SUCCESS;
- return PAM_SESSION_ERR;
- }
-
- usession = syscall(__NR_keyctl,
- KEYCTL_GET_KEYRING_ID,
- KEY_SPEC_USER_SESSION_KEYRING,
- 0);
- debug(pamh, "GET SESSION = %d", usession);
- if (usession < 0)
- return PAM_SESSION_ERR;
-
- /* if the user session keyring is our keyring, then we don't
- * need to do anything if we're not forcing */
- if (session != usession)
- return PAM_SUCCESS;
- }
-
- /* create a session keyring, discarding the old one */
- ret = syscall(__NR_keyctl,
- KEYCTL_JOIN_SESSION_KEYRING,
- NULL);
- debug(pamh, "JOIN = %d", ret);
- if (ret < 0)
- return PAM_SESSION_ERR;
-
- my_session_keyring = ret;
-
- /* make a link from the session keyring to the user keyring */
- ret = syscall(__NR_keyctl,
- KEYCTL_LINK,
- KEY_SPEC_USER_KEYRING,
- KEY_SPEC_SESSION_KEYRING);
-
- return ret < 0 ? PAM_SESSION_ERR : PAM_SUCCESS;
-}
-
-/*
- * revoke the session keyring for this process
- */
-static void kill_keyrings(pam_handle_t *pamh)
-{
- int old_uid, old_gid;
-
- /* revoke the session keyring we created earlier */
- if (my_session_keyring > 0) {
- debug(pamh, "REVOKE %d", my_session_keyring);
-
- old_uid = geteuid();
- old_gid = getegid();
- debug(pamh, "UID:%d [%d] GID:%d [%d]",
- revoke_as_uid, old_uid, revoke_as_gid, old_gid);
-
- /* switch to the real UID and GID so that we have permission to
- * revoke the key */
- if (revoke_as_gid != old_gid && setregid(-1, revoke_as_gid) < 0)
- error(pamh, "Unable to change GID to %d temporarily\n",
- revoke_as_gid);
-
- if (revoke_as_uid != old_uid && setreuid(-1, revoke_as_uid) < 0)
- error(pamh, "Unable to change UID to %d temporarily\n",
- revoke_as_uid);
-
- syscall(__NR_keyctl,
- KEYCTL_REVOKE,
- my_session_keyring);
-
- /* return to the orignal UID and GID (probably root) */
- if (revoke_as_uid != old_uid && setreuid(-1, old_uid) < 0)
- error(pamh, "Unable to change UID back to %d\n", old_uid);
-
- if (revoke_as_gid != old_gid && setregid(-1, old_gid) < 0)
- error(pamh, "Unable to change GID back to %d\n", old_gid);
-
- my_session_keyring = 0;
- }
-}
-
-/*
- * open a PAM session by making sure there's a session keyring
- */
-PAM_EXTERN
-int pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED,
- int argc, const char **argv)
-{
- struct passwd *pw;
- const char *username;
- int ret, old_uid, uid, old_gid, gid, loop, force = 0;
-
- for (loop = 0; loop < argc; loop++) {
- if (strcmp(argv[loop], "force") == 0)
- force = 1;
- else if (strcmp(argv[loop], "debug") == 0)
- xdebug = 1;
- else if (strcmp(argv[loop], "revoke") == 0)
- do_revoke = 1;
- }
-
- /* don't do anything if already created a keyring (will be called
- * multiple times if mentioned more than once in a pam script)
- */
- session_counter++;
-
- debug(pamh, "OPEN %d", session_counter);
-
- if (my_session_keyring > 0)
- return PAM_SUCCESS;
-
- /* look up the target UID */
- ret = pam_get_user(pamh, &username, "key user");
- if (ret != PAM_SUCCESS)
- return ret;
-
- pw = pam_modutil_getpwnam(pamh, username);
- if (!pw) {
- error(pamh, "Unable to look up user \"%s\"\n", username);
- return PAM_USER_UNKNOWN;
- }
-
- revoke_as_uid = uid = pw->pw_uid;
- old_uid = getuid();
- revoke_as_gid = gid = pw->pw_gid;
- old_gid = getgid();
- debug(pamh, "UID:%d [%d] GID:%d [%d]", uid, old_uid, gid, old_gid);
-
- /* switch to the real UID and GID so that the keyring ends up owned by
- * the right user */
- if (gid != old_gid && setregid(gid, -1) < 0) {
- error(pamh, "Unable to change GID to %d temporarily\n", gid);
- return PAM_SESSION_ERR;
- }
-
- if (uid != old_uid && setreuid(uid, -1) < 0) {
- error(pamh, "Unable to change UID to %d temporarily\n", uid);
- setregid(old_gid, -1);
- return PAM_SESSION_ERR;
- }
-
- ret = init_keyrings(pamh, force);
-
- /* return to the orignal UID and GID (probably root) */
- if (uid != old_uid && setreuid(old_uid, -1) < 0)
- ret = error(pamh, "Unable to change UID back to %d\n", old_uid);
-
- if (gid != old_gid && setregid(old_gid, -1) < 0)
- ret = error(pamh, "Unable to change GID back to %d\n", old_gid);
-
- return ret;
-}
-
-/*
- * close a PAM session by revoking the session keyring if requested
- */
-PAM_EXTERN
-int pam_sm_close_session(pam_handle_t *pamh, int flags UNUSED,
- int argc UNUSED, const char **argv UNUSED)
-{
- debug(pamh, "CLOSE %d,%d,%d",
- session_counter, my_session_keyring, do_revoke);
-
- session_counter--;
-
- if (session_counter == 0 && my_session_keyring > 0 && do_revoke)
- kill_keyrings(pamh);
-
- return PAM_SUCCESS;
-}
-
-#ifdef PAM_STATIC
-
-/* static module data */
-
-struct pam_module _pam_keyinit_modstruct = {
- "pam_keyinit",
- NULL,
- NULL,
- NULL,
- pam_sm_open_session,
- pam_sm_close_session,
- NULL
-};
-#endif
-