source: trunk/debathena/debathena/libpam-athena-locker/pam_athena_locker.c @ 22686

Revision 22686, 4.8 KB checked in by ghudson, 17 years ago (diff)
* debathena/debathena: Snapshot debathena package sources from /mit/debathena/packages/debathena.
Line 
1/*
2 * pam_athena-locker.c
3 * PAM session management functions for pam_athena_locker.so
4 *
5 * Copyright © 2007 Tim Abbott <tabbott@mit.edu> and Anders Kaseorg
6 * <andersk@mit.edu>
7 *
8 * Permission is hereby granted, free of charge, to any person
9 * obtaining a copy of this software and associated documentation
10 * files (the "Software"), to deal in the Software without
11 * restriction, including without limitation the rights to use, copy,
12 * modify, merge, publish, distribute, sublicense, and/or sell copies
13 * of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
23 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
24 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
29#define _GNU_SOURCE
30#include <sys/types.h>
31#include <sys/wait.h>
32#include <unistd.h>
33#include <syslog.h>
34#include <pwd.h>
35#include <grp.h>
36#include <stdio.h>
37#include <string.h>
38#include <stdlib.h>
39#include <signal.h>
40#include <stdarg.h>
41#include <errno.h>
42#include <security/pam_appl.h>
43#include <security/pam_modules.h>
44#include <security/pam_misc.h>
45#include <afs/afssyscalls.h>
46
47/* Initiate session management by attaching locker. */
48int
49pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
50{
51    int i;
52    int debug = 0;
53    int pamret;
54    const char *user;
55    struct passwd *pw;
56    const char *filecache;
57    pid_t pid;
58    int status;
59    struct sigaction act, oldact;
60
61    for (i = 0; i < argc; i++) {
62        if (strcmp(argv[i], "debug") == 0)
63            debug = 1;
64    }
65
66    if ((pamret = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) {
67        syslog(LOG_ERR, "pam_athena_locker: pam_get_user: %s:%d", pam_strerror(pamh, pamret), pamret);
68        return PAM_SESSION_ERR;
69    }
70
71    errno = 0;
72    pw = getpwnam(user);
73    if (pw == NULL) {
74        if (errno != 0)
75            syslog(LOG_ERR, "pam_athena_locker: getpwnam: %s", strerror(errno));
76        else
77            syslog(LOG_ERR, "pam_athena_locker: no such user: %s", user);
78        return PAM_SESSION_ERR;
79    }
80
81    if (lsetpag() != 0) {
82        syslog(LOG_ERR, "pam_athena_locker: Could not create a PAG");
83        return PAM_SESSION_ERR;
84    }
85
86    if ((filecache = pam_getenv(pamh, "KRB5CCNAME")) == NULL) {
87        syslog(LOG_ERR, "pam_athena_locker: No Kerberos ticket cache; not attaching locker");
88        return PAM_SESSION_ERR;
89    }
90
91    /* Override gdm's SIGCHLD handler that makes waitpid() return -1.
92       Maybe this leads to some race condition if gdm used that at the time? */
93    memset(&act, 0, sizeof(act));
94    act.sa_handler = SIG_DFL;
95    sigaction(SIGCHLD, &act, &oldact);
96
97    pid = fork();
98    if (pid == -1) {
99        syslog(LOG_ERR, "pam_athena_locker: fork(): %s", strerror(errno));
100        return PAM_SESSION_ERR;
101    }
102    if (pid == 0) {
103        if (setenv("KRB5CCNAME", filecache, 1) != 0) {
104            syslog(LOG_ERR, "pam_athena_locker: setenv(): %s", strerror(errno));
105            _exit(1);
106        }
107        if (debug)
108            syslog(LOG_DEBUG, "pam_athena_locker: uid=%d euid=%d", getuid(), geteuid());
109        if (setuid(pw->pw_uid) != 0) {
110            syslog(LOG_ERR, "pam_athena_locker: setuid(): %s", strerror(errno));
111            return PAM_SESSION_ERR;
112        }
113        if (debug)
114            syslog(LOG_DEBUG, "pam_athena_locker: uid=%d euid=%d", getuid(), geteuid());
115        if (close(1) < 0) {
116            syslog(LOG_ERR, "pam_debathena_home_type: close(): %s",
117                   strerror(errno));
118            _exit(-1);
119        }
120        if (close(2) < 0) {
121            syslog(LOG_ERR, "pam_debathena_home_type: close(): %s",
122                   strerror(errno));
123            _exit(-1);
124        }
125        execl("/bin/attach", "attach", "--quiet", "--nozephyr", user, NULL);
126        syslog(LOG_ERR, "pam_athena_locker: execl(): %s", strerror(errno));
127        _exit(1);
128    }
129    if (TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)) == -1 ||
130        !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
131        syslog(LOG_ERR, "pam_athena_locker: locker attachment failed: %s", user);
132        return PAM_SESSION_ERR;
133    }
134    if (debug)
135        syslog(LOG_DEBUG, "pam_athena_locker: attached locker %s", user);
136    sigaction(SIGCHLD, &oldact, NULL);
137    return PAM_SUCCESS;
138}
139
140/* Terminate session management. */
141int
142pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
143{
144    return PAM_SUCCESS;
145}
146
147int
148pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
149{
150    if (flags == PAM_ESTABLISH_CRED)
151        return pam_sm_open_session(pamh, flags, argc, argv);
152    return PAM_SUCCESS;
153}
154
155int
156pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
157{
158    return PAM_SUCCESS;
159}
160
Note: See TracBrowser for help on using the repository browser.