source: trunk/debathena/debathena/libpam-krb524/pam_krb524.c @ 23623

Revision 23623, 5.9 KB checked in by tabbott, 16 years ago (diff)
In libpam-krb524: * Change the log level for "No krb5 cache available" to DEBUG.
Line 
1/*
2 * pam_krb524.c
3 * PAM session management functions for pam_krb524.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#include <stdio.h>      /* snprintf */
30#include <string.h>     /* strcmp */
31#include <unistd.h>     /* unlink, syslog */
32#include <security/pam_appl.h>
33#include <security/pam_modules.h>
34#include <sys/types.h>
35#include <sys/wait.h>
36#include <pwd.h>
37#include <stdlib.h>
38#include <errno.h>
39#include <syslog.h>
40
41#define MAXBUF 256
42
43
44/*
45 * Make up a deterministic name for the Kerberos 4 ticket cache from
46 * KRB5CCNAME.
47 */
48static int
49get_krb4_name(pam_handle_t *pamh, const char **cache_name, char *cache_name4, size_t len, int debug)
50{
51    int n;
52    *cache_name = pam_getenv(pamh, "KRB5CCNAME");
53    if (*cache_name == NULL) {
54        if (debug)
55            syslog(LOG_DEBUG, "pam_krb524: No krb5 cache found");
56        return PAM_SESSION_ERR;
57    }
58
59    if (strncmp(*cache_name, "FILE:/tmp/krb5cc_", 17) == 0)
60        n = snprintf(cache_name4, len, "/tmp/tkt_%s", *cache_name + 17);
61    else if (strncmp(*cache_name, "/tmp/krb5cc_", 12) == 0)
62        n = snprintf(cache_name4, len, "/tmp/tkt_%s", *cache_name + 12);
63    else {
64        syslog(LOG_ERR, "pam_krb524: Could not get krb4 name from krb5 name: %s", *cache_name);
65        return PAM_SESSION_ERR;
66    }
67    if (n < 0 || n >= len) {
68        syslog(LOG_ERR, "pam_krb524: snprintf failed");
69        return PAM_BUF_ERR;
70    }
71    return PAM_SUCCESS;
72}
73
74/*
75 * Do the Kerberos 4 ticket getting work, using a name based on the
76 * name of the Kerberos 5 ticket cache.  The flags are ignored.
77 */
78int
79pam_sm_open_session(pam_handle_t *pamh, int flags, int argc,
80                    const char **argv)
81{
82    int i;
83    int pamret;
84    struct passwd *pw = NULL;
85    uid_t uid;
86    gid_t gid;
87    int debug = 0;
88    int pid;
89    const char *user = NULL;
90    int n;
91    char cache_name4[MAXBUF];
92    char cache_env_name4[MAXBUF];
93    const char *cache_name;
94    int status;
95
96    for (i = 0; i < argc; i++) {
97        if (strcmp(argv[i], "debug") == 0)
98            debug = 1;
99    }
100
101    /* Get username */
102    if ((pamret = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) {
103        return PAM_SERVICE_ERR;
104    }
105
106    pw = getpwnam(user);
107    if (pw == NULL) {
108        return PAM_USER_UNKNOWN;
109    }
110    uid = pw->pw_uid;
111    gid = pw->pw_gid;
112
113    if ((pamret = get_krb4_name(pamh, &cache_name, cache_name4, MAXBUF, debug))
114        != PAM_SUCCESS)
115        return pamret;
116
117    if (debug)
118        syslog(LOG_DEBUG, "pam_krb524: Got krb4 name: %s", cache_name4);
119
120    n = snprintf(cache_env_name4, MAXBUF, "KRBTKFILE=%s", cache_name4);
121    if (n < 0 || n >= MAXBUF) {
122        syslog(LOG_ERR, "pam_krb524: snprintf failed");
123        return PAM_BUF_ERR;
124    }
125
126    if ((pamret = pam_putenv(pamh, cache_env_name4)) != PAM_SUCCESS) {
127        syslog(LOG_ERR, "pam_krb524: pam_putenv(): %s", pam_strerror(pamh, pamret));
128        return PAM_SESSION_ERR;
129    }
130
131    if ((pid = fork()) == -1) {
132        syslog(LOG_ERR, "pam_krb524: fork(): %s", strerror(errno));
133        return PAM_SESSION_ERR;
134    }
135    if (pid == 0) {
136        /* setup the environment */
137        char buf[MAXBUF], buf4[MAXBUF];
138        char *envi[3] = {buf, buf4, NULL};
139        n = snprintf(buf, MAXBUF, "KRB5CCNAME=%s", cache_name);
140        if (n < 0 || n >= MAXBUF) {
141            syslog(LOG_ERR, "pam_krb524: snprintf failed");
142            _exit(-1);
143        }
144        n = snprintf(buf4, MAXBUF, "KRBTKFILE=%s", cache_name4);
145        if (n < 0 || n >= MAXBUF) {
146            syslog(LOG_ERR, "pam_krb524: snprintf failed");
147            _exit(-1);
148        }
149
150        /* make the forked process have the right real UID for krb524init
151           which is very unhappy with uid != euid. */
152        if (setregid(gid, gid) != 0 ||
153            setreuid(uid, uid) != 0) {
154            syslog(LOG_ERR, "pam_krb524: could not set egid and euid");
155            _exit(-1);
156        }
157
158        execle("/usr/bin/krb524init", "krb524init", NULL, envi);
159        syslog(LOG_ERR, "pam_krb524: execle(): %s", strerror(errno));
160        _exit(-1);
161    }
162    if (waitpid(pid, &status, 0) == -1) {
163        syslog(LOG_ERR, "pam_krb524: waitpid(): %s", strerror(errno));
164        return PAM_SESSION_ERR;
165    }
166    if (!WIFEXITED(status)) {
167        syslog(LOG_ERR, "pam_krb524: krb524init failed");
168        return PAM_SESSION_ERR;
169    }
170    if (debug)
171        syslog(LOG_DEBUG, "pam_krb524: Success: %s", cache_name4);
172
173    return PAM_SUCCESS;
174}
175
176
177/* Terminate session management. */
178int
179pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
180{
181    int i;
182    int pamret;
183    const char *cache_name;
184    char cache_name4[MAXBUF];
185    int debug = 0;
186
187    for (i = 0; i < argc; i++) {
188        if (strcmp(argv[i], "debug") == 0)
189            debug = 1;
190    }
191
192    if ((pamret = get_krb4_name(pamh, &cache_name, cache_name4, MAXBUF, debug))
193        != PAM_SUCCESS)
194        return pamret;
195
196    if (debug)
197        syslog(LOG_DEBUG, "pam_krb524: Unlinking %s", cache_name4);
198    unlink(cache_name4);
199    return PAM_SUCCESS;
200}
201
202
203int
204pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
205{
206    if (flags == PAM_ESTABLISH_CRED)
207        return pam_sm_open_session(pamh, flags, argc, argv);
208    return PAM_SUCCESS;
209}
210
211int
212pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
213{
214    return PAM_SUCCESS;
215}
Note: See TracBrowser for help on using the repository browser.