]>
Commit | Line | Data |
---|---|---|
6cf77d05 SS |
1 | Modify ksu so that it performs account and session management on behalf of |
2 | the target user account, mimicking the action of regular su. The default | |
3 | service name is "ksu", because on Fedora at least the configuration used | |
4 | is determined by whether or not a login shell is being opened, and so | |
5 | this may need to vary, too. At run-time, ksu's behavior can be reset to | |
6 | the earlier, non-PAM behavior by setting "use_pam" to false in the [ksu] | |
7 | section of /etc/krb5.conf. | |
8 | ||
9 | When enabled, ksu gains a dependency on libpam. | |
10 | ||
11 | Originally RT#5939, though it's changed since then to perform the account | |
12 | and session management before dropping privileges. | |
13 | ||
14 | diff -up krb5-1.8/src/aclocal.m4.pam krb5-1.8/src/aclocal.m4 | |
15 | --- krb5-1.8/src/aclocal.m4.pam 2009-11-22 12:00:45.000000000 -0500 | |
16 | +++ krb5-1.8/src/aclocal.m4 2010-03-05 10:48:08.000000000 -0500 | |
17 | @@ -1703,3 +1703,70 @@ AC_DEFUN(KRB5_AC_KEYRING_CCACHE,[ | |
18 | ])) | |
19 | ])dnl | |
20 | dnl | |
21 | +dnl | |
22 | +dnl Use PAM instead of local crypt() compare for checking local passwords, | |
23 | +dnl and perform PAM account, session management, and password-changing where | |
24 | +dnl appropriate. | |
25 | +dnl | |
26 | +AC_DEFUN(KRB5_WITH_PAM,[ | |
27 | +AC_ARG_WITH(pam,[AC_HELP_STRING(--with-pam,[compile with PAM support])], | |
28 | + withpam="$withval",withpam=auto) | |
29 | +AC_ARG_WITH(pam-ksu-service,[AC_HELP_STRING(--with-ksu-service,[PAM service name for ksu ["ksu"]])], | |
30 | + withksupamservice="$withval",withksupamservice=ksu) | |
31 | +old_LIBS="$LIBS" | |
32 | +if test "$withpam" != no ; then | |
33 | + AC_MSG_RESULT([checking for PAM...]) | |
34 | + PAM_LIBS= | |
35 | + | |
36 | + AC_CHECK_HEADERS(security/pam_appl.h) | |
37 | + if test "x$ac_cv_header_security_pam_appl_h" != xyes ; then | |
38 | + if test "$withpam" = auto ; then | |
39 | + AC_MSG_RESULT([Unable to locate security/pam_appl.h.]) | |
40 | + withpam=no | |
41 | + else | |
42 | + AC_MSG_ERROR([Unable to locate security/pam_appl.h.]) | |
43 | + fi | |
44 | + fi | |
45 | + | |
46 | + LIBS= | |
47 | + unset ac_cv_func_pam_start | |
48 | + AC_CHECK_FUNCS(putenv pam_start) | |
49 | + if test "x$ac_cv_func_pam_start" = xno ; then | |
50 | + unset ac_cv_func_pam_start | |
51 | + AC_CHECK_LIB(dl,dlopen) | |
52 | + AC_CHECK_FUNCS(pam_start) | |
53 | + if test "x$ac_cv_func_pam_start" = xno ; then | |
54 | + AC_CHECK_LIB(pam,pam_start) | |
55 | + unset ac_cv_func_pam_start | |
56 | + unset ac_cv_func_pam_getenvlist | |
57 | + AC_CHECK_FUNCS(pam_start pam_getenvlist) | |
58 | + if test "x$ac_cv_func_pam_start" = xyes ; then | |
59 | + PAM_LIBS="$LIBS" | |
60 | + else | |
61 | + if test "$withpam" = auto ; then | |
62 | + AC_MSG_RESULT([Unable to locate libpam.]) | |
63 | + withpam=no | |
64 | + else | |
65 | + AC_MSG_ERROR([Unable to locate libpam.]) | |
66 | + fi | |
67 | + fi | |
68 | + fi | |
69 | + fi | |
70 | + if test "$withpam" != no ; then | |
71 | + AC_MSG_NOTICE([building with PAM support]) | |
72 | + AC_DEFINE(USE_PAM,1,[Define if Kerberos-aware tools should support PAM]) | |
73 | + AC_DEFINE_UNQUOTED(KSU_PAM_SERVICE,"$withksupamservice", | |
74 | + [Define to the name of the PAM service name to be used by ksu.]) | |
75 | + PAM_LIBS="$LIBS" | |
76 | + NON_PAM_MAN=".\\\" " | |
77 | + PAM_MAN= | |
78 | + else | |
79 | + PAM_MAN=".\\\" " | |
80 | + NON_PAM_MAN= | |
81 | + fi | |
82 | +fi | |
83 | +LIBS="$old_LIBS" | |
84 | +AC_SUBST(PAM_LIBS) | |
85 | +AC_SUBST(PAM_MAN) | |
86 | +AC_SUBST(NON_PAM_MAN) | |
87 | +])dnl | |
88 | diff -up krb5-1.8/src/clients/ksu/main.c.pam krb5-1.8/src/clients/ksu/main.c | |
89 | --- krb5-1.8/src/clients/ksu/main.c.pam 2009-11-02 22:27:56.000000000 -0500 | |
90 | +++ krb5-1.8/src/clients/ksu/main.c 2010-03-05 10:48:08.000000000 -0500 | |
91 | @@ -26,6 +26,7 @@ | |
92 | * KSU was writen by: Ari Medvinsky, ari@isi.edu | |
93 | */ | |
94 | ||
95 | +#include "autoconf.h" | |
96 | #include "ksu.h" | |
97 | #include "adm_proto.h" | |
98 | #include <sys/types.h> | |
99 | @@ -33,6 +34,10 @@ | |
100 | #include <signal.h> | |
101 | #include <grp.h> | |
102 | ||
103 | +#ifdef USE_PAM | |
104 | +#include "pam.h" | |
105 | +#endif | |
106 | + | |
107 | /* globals */ | |
108 | char * prog_name; | |
109 | int auth_debug =0; | |
110 | @@ -40,6 +45,7 @@ char k5login_path[MAXPATHLEN]; | |
111 | char k5users_path[MAXPATHLEN]; | |
112 | char * gb_err = NULL; | |
113 | int quiet = 0; | |
114 | +int force_fork = 0; | |
115 | /***********/ | |
116 | ||
117 | #define _DEF_CSH "/bin/csh" | |
118 | @@ -586,6 +592,25 @@ main (argc, argv) | |
119 | prog_name,target_user,client_name, | |
120 | source_user,ontty()); | |
121 | ||
122 | +#ifdef USE_PAM | |
123 | + if (appl_pam_enabled(ksu_context, "ksu")) { | |
124 | + if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL, | |
125 | + NULL, source_user, | |
126 | + ttyname(STDERR_FILENO)) != 0) { | |
127 | + fprintf(stderr, "Access denied for %s.\n", target_user); | |
128 | + sweep_up(ksu_context, cc_target); | |
129 | + exit(1); | |
130 | + } | |
131 | + if (appl_pam_requires_chauthtok()) { | |
132 | + fprintf(stderr, "Password change required for %s.\n", | |
133 | + target_user); | |
134 | + sweep_up(ksu_context, cc_target); | |
135 | + exit(1); | |
136 | + } | |
137 | + force_fork++; | |
138 | + } | |
139 | +#endif | |
140 | + | |
141 | /* Run authorization as target.*/ | |
142 | if (krb5_seteuid(target_uid)) { | |
143 | com_err(prog_name, errno, _("while switching to target for " | |
144 | @@ -651,6 +676,26 @@ | |
145 | sweep_up(ksu_context, cc_target); | |
146 | exit(1); | |
147 | } | |
148 | +#ifdef USE_PAM | |
149 | + } else { | |
150 | + /* we always do PAM account management, even for root */ | |
151 | + if (appl_pam_enabled(ksu_context, "ksu")) { | |
152 | + if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL, | |
153 | + NULL, source_user, | |
154 | + ttyname(STDERR_FILENO)) != 0) { | |
155 | + fprintf(stderr, "Access denied for %s.\n", target_user); | |
156 | + sweep_up(ksu_context, cc_target); | |
157 | + exit(1); | |
158 | + } | |
159 | + if (appl_pam_requires_chauthtok()) { | |
160 | + fprintf(stderr, "Password change required for %s.\n", | |
161 | + target_user); | |
162 | + sweep_up(ksu_context, cc_target); | |
163 | + exit(1); | |
164 | + } | |
165 | + force_fork++; | |
166 | + } | |
167 | +#endif | |
168 | } | |
169 | ||
170 | if( some_rest_copy){ | |
171 | @@ -720,6 +745,32 @@ | |
172 | exit(1); | |
173 | } | |
174 | ||
175 | +#ifdef USE_PAM | |
176 | + if (appl_pam_enabled(ksu_context, "ksu")) { | |
177 | + if (appl_pam_session_open() != 0) { | |
178 | + fprintf(stderr, "Error opening session for %s.\n", target_user); | |
179 | + sweep_up(ksu_context, cc_target); | |
180 | + exit(1); | |
181 | + } | |
182 | +#ifdef DEBUG | |
183 | + if (auth_debug){ | |
184 | + printf(" Opened PAM session.\n"); | |
185 | + } | |
186 | +#endif | |
187 | + if (appl_pam_cred_init()) { | |
188 | + fprintf(stderr, "Error initializing credentials for %s.\n", | |
189 | + target_user); | |
190 | + sweep_up(ksu_context, cc_target); | |
191 | + exit(1); | |
192 | + } | |
193 | +#ifdef DEBUG | |
194 | + if (auth_debug){ | |
195 | + printf(" Initialized PAM credentials.\n"); | |
196 | + } | |
197 | +#endif | |
198 | + } | |
199 | +#endif | |
200 | + | |
201 | /* set permissions */ | |
202 | if (setgid(target_pwd->pw_gid) < 0) { | |
203 | perror("ksu: setgid"); | |
204 | @@ -792,7 +817,7 @@ main (argc, argv) | |
205 | fprintf(stderr, "program to be execed %s\n",params[0]); | |
206 | } | |
207 | ||
208 | - if( keep_target_cache ) { | |
209 | + if( keep_target_cache && !force_fork ) { | |
210 | execv(params[0], params); | |
211 | com_err(prog_name, errno, _("while trying to execv %s"), params[0]); | |
212 | sweep_up(ksu_context, cc_target); | |
213 | @@ -823,16 +875,35 @@ main (argc, argv) | |
214 | if (ret_pid == -1) { | |
215 | com_err(prog_name, errno, _("while calling waitpid")); | |
216 | } | |
217 | - sweep_up(ksu_context, cc_target); | |
218 | + if( !keep_target_cache ) { | |
219 | + sweep_up(ksu_context, cc_target); | |
220 | + } | |
221 | exit (statusp); | |
222 | case -1: | |
223 | com_err(prog_name, errno, _("while trying to fork.")); | |
224 | sweep_up(ksu_context, cc_target); | |
225 | exit (1); | |
226 | case 0: | |
227 | +#ifdef USE_PAM | |
228 | + if (appl_pam_enabled(ksu_context, "ksu")) { | |
229 | + if (appl_pam_setenv() != 0) { | |
230 | + fprintf(stderr, "Error setting up environment for %s.\n", | |
231 | + target_user); | |
232 | + exit (1); | |
233 | + } | |
234 | +#ifdef DEBUG | |
235 | + if (auth_debug){ | |
236 | + printf(" Set up PAM environment.\n"); | |
237 | + } | |
238 | +#endif | |
239 | + } | |
240 | +#endif | |
241 | execv(params[0], params); | |
242 | com_err(prog_name, errno, _("while trying to execv %s"), | |
243 | params[0]); | |
244 | + if( keep_target_cache ) { | |
245 | + sweep_up(ksu_context, cc_target); | |
246 | + } | |
247 | exit (1); | |
248 | } | |
249 | } | |
250 | diff -up krb5-1.8/src/clients/ksu/Makefile.in.pam krb5-1.8/src/clients/ksu/Makefile.in | |
251 | --- krb5-1.8/src/clients/ksu/Makefile.in.pam 2009-11-22 13:13:29.000000000 -0500 | |
252 | +++ krb5-1.8/src/clients/ksu/Makefile.in 2010-03-05 11:55:14.000000000 -0500 | |
253 | @@ -7,12 +7,14 @@ | |
254 | PROG_RPATH=$(KRB5_LIBDIR) | |
255 | ||
256 | KSU_LIBS=@KSU_LIBS@ | |
257 | +PAM_LIBS=@PAM_LIBS@ | |
258 | ||
259 | SRCS = \ | |
260 | $(srcdir)/krb_auth_su.c \ | |
261 | $(srcdir)/ccache.c \ | |
262 | $(srcdir)/authorization.c \ | |
263 | $(srcdir)/main.c \ | |
264 | + $(srcdir)/pam.c \ | |
265 | $(srcdir)/heuristic.c \ | |
266 | $(srcdir)/xmalloc.c \ | |
267 | $(srcdir)/setenv.c | |
268 | @@ -21,13 +23,17 @@ OBJS = \ | |
269 | ccache.o \ | |
270 | authorization.o \ | |
271 | main.o \ | |
272 | + pam.o \ | |
273 | heuristic.o \ | |
274 | xmalloc.o @SETENVOBJ@ | |
275 | ||
276 | all:: ksu | |
277 | ||
278 | ksu: $(OBJS) $(KRB5_BASE_DEPLIBS) | |
279 | - $(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS) | |
280 | + $(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS) $(PAM_LIBS) | |
281 | + | |
282 | +pam.o: pam.c | |
283 | + $(CC) $(ALL_CFLAGS) -c $< | |
284 | ||
285 | clean:: | |
286 | $(RM) ksu | |
287 | diff -up krb5-1.8/src/clients/ksu/pam.c.pam krb5-1.8/src/clients/ksu/pam.c | |
288 | --- krb5-1.8/src/clients/ksu/pam.c.pam 2010-03-05 10:48:08.000000000 -0500 | |
289 | +++ krb5-1.8/src/clients/ksu/pam.c 2010-03-05 10:48:08.000000000 -0500 | |
290 | @@ -0,0 +1,389 @@ | |
291 | +/* | |
292 | + * src/clients/ksu/pam.c | |
293 | + * | |
294 | + * Copyright 2007,2009,2010 Red Hat, Inc. | |
295 | + * | |
296 | + * All Rights Reserved. | |
297 | + * | |
298 | + * Redistribution and use in source and binary forms, with or without | |
299 | + * modification, are permitted provided that the following conditions are met: | |
300 | + * | |
301 | + * Redistributions of source code must retain the above copyright notice, this | |
302 | + * list of conditions and the following disclaimer. | |
303 | + * | |
304 | + * Redistributions in binary form must reproduce the above copyright notice, | |
305 | + * this list of conditions and the following disclaimer in the documentation | |
306 | + * and/or other materials provided with the distribution. | |
307 | + * | |
308 | + * Neither the name of Red Hat, Inc. nor the names of its contributors may be | |
309 | + * used to endorse or promote products derived from this software without | |
310 | + * specific prior written permission. | |
311 | + * | |
312 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
313 | + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
314 | + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
315 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
316 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
317 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
318 | + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
319 | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
320 | + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
321 | + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
322 | + * POSSIBILITY OF SUCH DAMAGE. | |
323 | + * | |
324 | + * Convenience wrappers for using PAM. | |
325 | + */ | |
326 | + | |
327 | +#include "autoconf.h" | |
328 | +#ifdef USE_PAM | |
329 | +#include <sys/types.h> | |
330 | +#include <stdio.h> | |
331 | +#include <stdlib.h> | |
332 | +#include <string.h> | |
333 | +#include <unistd.h> | |
334 | +#include "k5-int.h" | |
335 | +#include "pam.h" | |
336 | + | |
337 | +#ifndef MAXPWSIZE | |
338 | +#define MAXPWSIZE 128 | |
339 | +#endif | |
340 | + | |
341 | +static int appl_pam_started; | |
342 | +static pid_t appl_pam_starter = -1; | |
343 | +static int appl_pam_session_opened; | |
344 | +static int appl_pam_creds_initialized; | |
345 | +static int appl_pam_pwchange_required; | |
346 | +static pam_handle_t *appl_pamh; | |
347 | +static struct pam_conv appl_pam_conv; | |
348 | +static char *appl_pam_user; | |
349 | +struct appl_pam_non_interactive_args { | |
350 | + const char *user; | |
351 | + const char *password; | |
352 | +}; | |
353 | + | |
354 | +int | |
355 | +appl_pam_enabled(krb5_context context, const char *section) | |
356 | +{ | |
357 | + int enabled = 1; | |
358 | + if ((context != NULL) && (context->profile != NULL)) { | |
359 | + if (profile_get_boolean(context->profile, | |
360 | + section, | |
361 | + USE_PAM_CONFIGURATION_KEYWORD, | |
362 | + NULL, | |
363 | + enabled, &enabled) != 0) { | |
364 | + enabled = 1; | |
365 | + } | |
366 | + } | |
367 | + return enabled; | |
368 | +} | |
369 | + | |
370 | +void | |
371 | +appl_pam_cleanup(void) | |
372 | +{ | |
373 | + if (getpid() != appl_pam_starter) { | |
374 | + return; | |
375 | + } | |
376 | +#ifdef DEBUG | |
377 | + printf("Called to clean up PAM.\n"); | |
378 | +#endif | |
379 | + if (appl_pam_creds_initialized) { | |
380 | +#ifdef DEBUG | |
381 | + printf("Deleting PAM credentials.\n"); | |
382 | +#endif | |
383 | + pam_setcred(appl_pamh, PAM_DELETE_CRED); | |
384 | + appl_pam_creds_initialized = 0; | |
385 | + } | |
386 | + if (appl_pam_session_opened) { | |
387 | +#ifdef DEBUG | |
388 | + printf("Closing PAM session.\n"); | |
389 | +#endif | |
390 | + pam_close_session(appl_pamh, 0); | |
391 | + appl_pam_session_opened = 0; | |
392 | + } | |
393 | + appl_pam_pwchange_required = 0; | |
394 | + if (appl_pam_started) { | |
395 | +#ifdef DEBUG | |
396 | + printf("Shutting down PAM.\n"); | |
397 | +#endif | |
398 | + pam_end(appl_pamh, 0); | |
399 | + appl_pam_started = 0; | |
400 | + appl_pam_starter = -1; | |
401 | + free(appl_pam_user); | |
402 | + appl_pam_user = NULL; | |
403 | + } | |
404 | +} | |
405 | +static int | |
406 | +appl_pam_interactive_converse(int num_msg, const struct pam_message **msg, | |
407 | + struct pam_response **presp, void *appdata_ptr) | |
408 | +{ | |
409 | + const struct pam_message *message; | |
410 | + struct pam_response *resp; | |
411 | + int i, code; | |
412 | + char *pwstring, pwbuf[MAXPWSIZE]; | |
413 | + unsigned int pwsize; | |
414 | + resp = malloc(sizeof(struct pam_response) * num_msg); | |
415 | + if (resp == NULL) { | |
416 | + return PAM_BUF_ERR; | |
417 | + } | |
418 | + memset(resp, 0, sizeof(struct pam_response) * num_msg); | |
419 | + code = PAM_SUCCESS; | |
420 | + for (i = 0; i < num_msg; i++) { | |
421 | + message = &(msg[0][i]); /* XXX */ | |
422 | + message = msg[i]; /* XXX */ | |
423 | + pwstring = NULL; | |
424 | + switch (message->msg_style) { | |
425 | + case PAM_TEXT_INFO: | |
426 | + case PAM_ERROR_MSG: | |
427 | + printf("[%s]\n", message->msg ? message->msg : ""); | |
428 | + fflush(stdout); | |
429 | + resp[i].resp = NULL; | |
430 | + resp[i].resp_retcode = PAM_SUCCESS; | |
431 | + break; | |
432 | + case PAM_PROMPT_ECHO_ON: | |
433 | + case PAM_PROMPT_ECHO_OFF: | |
434 | + if (message->msg_style == PAM_PROMPT_ECHO_ON) { | |
435 | + if (fgets(pwbuf, sizeof(pwbuf), | |
436 | + stdin) != NULL) { | |
437 | + pwbuf[strcspn(pwbuf, "\r\n")] = '\0'; | |
438 | + pwstring = pwbuf; | |
439 | + } | |
440 | + } else { | |
441 | + pwstring = getpass(message->msg ? | |
442 | + message->msg : | |
443 | + ""); | |
444 | + } | |
445 | + if ((pwstring != NULL) && (pwstring[0] != '\0')) { | |
446 | + pwsize = strlen(pwstring); | |
447 | + resp[i].resp = malloc(pwsize + 1); | |
448 | + if (resp[i].resp == NULL) { | |
449 | + resp[i].resp_retcode = PAM_BUF_ERR; | |
450 | + } else { | |
451 | + memcpy(resp[i].resp, pwstring, pwsize); | |
452 | + resp[i].resp[pwsize] = '\0'; | |
453 | + resp[i].resp_retcode = PAM_SUCCESS; | |
454 | + } | |
455 | + } else { | |
456 | + resp[i].resp_retcode = PAM_CONV_ERR; | |
457 | + code = PAM_CONV_ERR; | |
458 | + } | |
459 | + break; | |
460 | + default: | |
461 | + break; | |
462 | + } | |
463 | + } | |
464 | + *presp = resp; | |
465 | + return code; | |
466 | +} | |
467 | +static int | |
468 | +appl_pam_non_interactive_converse(int num_msg, | |
469 | + const struct pam_message **msg, | |
470 | + struct pam_response **presp, | |
471 | + void *appdata_ptr) | |
472 | +{ | |
473 | + const struct pam_message *message; | |
474 | + struct pam_response *resp; | |
475 | + int i, code; | |
476 | + unsigned int pwsize; | |
477 | + struct appl_pam_non_interactive_args *args; | |
478 | + const char *pwstring; | |
479 | + resp = malloc(sizeof(struct pam_response) * num_msg); | |
480 | + if (resp == NULL) { | |
481 | + return PAM_BUF_ERR; | |
482 | + } | |
483 | + args = appdata_ptr; | |
484 | + memset(resp, 0, sizeof(struct pam_response) * num_msg); | |
485 | + code = PAM_SUCCESS; | |
486 | + for (i = 0; i < num_msg; i++) { | |
487 | + message = &((*msg)[i]); | |
488 | + message = msg[i]; | |
489 | + pwstring = NULL; | |
490 | + switch (message->msg_style) { | |
491 | + case PAM_TEXT_INFO: | |
492 | + case PAM_ERROR_MSG: | |
493 | + break; | |
494 | + case PAM_PROMPT_ECHO_ON: | |
495 | + case PAM_PROMPT_ECHO_OFF: | |
496 | + if (message->msg_style == PAM_PROMPT_ECHO_ON) { | |
497 | + /* assume "user" */ | |
498 | + pwstring = args->user; | |
499 | + } else { | |
500 | + /* assume "password" */ | |
501 | + pwstring = args->password; | |
502 | + } | |
503 | + if ((pwstring != NULL) && (pwstring[0] != '\0')) { | |
504 | + pwsize = strlen(pwstring); | |
505 | + resp[i].resp = malloc(pwsize + 1); | |
506 | + if (resp[i].resp == NULL) { | |
507 | + resp[i].resp_retcode = PAM_BUF_ERR; | |
508 | + } else { | |
509 | + memcpy(resp[i].resp, pwstring, pwsize); | |
510 | + resp[i].resp[pwsize] = '\0'; | |
511 | + resp[i].resp_retcode = PAM_SUCCESS; | |
512 | + } | |
513 | + } else { | |
514 | + resp[i].resp_retcode = PAM_CONV_ERR; | |
515 | + code = PAM_CONV_ERR; | |
516 | + } | |
517 | + break; | |
518 | + default: | |
519 | + break; | |
520 | + } | |
521 | + } | |
522 | + *presp = resp; | |
523 | + return code; | |
524 | +} | |
525 | +static int | |
526 | +appl_pam_start(const char *service, int interactive, | |
527 | + const char *login_username, | |
528 | + const char *non_interactive_password, | |
529 | + const char *hostname, | |
530 | + const char *ruser, | |
531 | + const char *tty) | |
532 | +{ | |
533 | + static int exit_handler_registered; | |
534 | + static struct appl_pam_non_interactive_args args; | |
535 | + int ret = 0; | |
536 | + if (appl_pam_started && | |
537 | + (strcmp(login_username, appl_pam_user) != 0)) { | |
538 | + appl_pam_cleanup(); | |
539 | + appl_pam_user = NULL; | |
540 | + } | |
541 | + if (!appl_pam_started) { | |
542 | +#ifdef DEBUG | |
543 | + printf("Starting PAM up (service=\"%s\",user=\"%s\").\n", | |
544 | + service, login_username); | |
545 | +#endif | |
546 | + memset(&appl_pam_conv, 0, sizeof(appl_pam_conv)); | |
547 | + appl_pam_conv.conv = interactive ? | |
548 | + &appl_pam_interactive_converse : | |
549 | + &appl_pam_non_interactive_converse; | |
550 | + memset(&args, 0, sizeof(args)); | |
551 | + args.user = strdup(login_username); | |
552 | + args.password = non_interactive_password ? | |
553 | + strdup(non_interactive_password) : | |
554 | + NULL; | |
555 | + appl_pam_conv.appdata_ptr = &args; | |
556 | + ret = pam_start(service, login_username, | |
557 | + &appl_pam_conv, &appl_pamh); | |
558 | + if (ret == 0) { | |
559 | + if (hostname != NULL) { | |
560 | +#ifdef DEBUG | |
561 | + printf("Setting PAM_RHOST to \"%s\".\n", hostname); | |
562 | +#endif | |
563 | + pam_set_item(appl_pamh, PAM_RHOST, hostname); | |
564 | + } | |
565 | + if (ruser != NULL) { | |
566 | +#ifdef DEBUG | |
567 | + printf("Setting PAM_RUSER to \"%s\".\n", ruser); | |
568 | +#endif | |
569 | + pam_set_item(appl_pamh, PAM_RUSER, ruser); | |
570 | + } | |
571 | + if (tty != NULL) { | |
572 | +#ifdef DEBUG | |
573 | + printf("Setting PAM_TTY to \"%s\".\n", tty); | |
574 | +#endif | |
575 | + pam_set_item(appl_pamh, PAM_TTY, tty); | |
576 | + } | |
577 | + if (!exit_handler_registered && | |
578 | + (atexit(appl_pam_cleanup) != 0)) { | |
579 | + pam_end(appl_pamh, 0); | |
580 | + appl_pamh = NULL; | |
581 | + ret = -1; | |
582 | + } else { | |
583 | + appl_pam_started = 1; | |
584 | + appl_pam_starter = getpid(); | |
585 | + appl_pam_user = strdup(login_username); | |
586 | + exit_handler_registered = 1; | |
587 | + } | |
588 | + } | |
589 | + } | |
590 | + return ret; | |
591 | +} | |
592 | +int | |
593 | +appl_pam_acct_mgmt(const char *service, int interactive, | |
594 | + const char *login_username, | |
595 | + const char *non_interactive_password, | |
596 | + const char *hostname, | |
597 | + const char *ruser, | |
598 | + const char *tty) | |
599 | +{ | |
600 | + int ret; | |
601 | + appl_pam_pwchange_required = 0; | |
602 | + ret = appl_pam_start(service, interactive, login_username, | |
603 | + non_interactive_password, hostname, ruser, tty); | |
604 | + if (ret == 0) { | |
605 | +#ifdef DEBUG | |
606 | + printf("Calling pam_acct_mgmt().\n"); | |
607 | +#endif | |
608 | + ret = pam_acct_mgmt(appl_pamh, 0); | |
609 | + switch (ret) { | |
610 | + case PAM_IGNORE: | |
611 | + ret = 0; | |
612 | + break; | |
613 | + case PAM_NEW_AUTHTOK_REQD: | |
614 | + appl_pam_pwchange_required = 1; | |
615 | + ret = 0; | |
616 | + break; | |
617 | + default: | |
618 | + break; | |
619 | + } | |
620 | + } | |
621 | + return ret; | |
622 | +} | |
623 | +int | |
624 | +appl_pam_requires_chauthtok(void) | |
625 | +{ | |
626 | + return appl_pam_pwchange_required; | |
627 | +} | |
628 | +int | |
629 | +appl_pam_session_open(void) | |
630 | +{ | |
631 | + int ret = 0; | |
632 | + if (appl_pam_started) { | |
633 | +#ifdef DEBUG | |
634 | + printf("Opening PAM session.\n"); | |
635 | +#endif | |
636 | + ret = pam_open_session(appl_pamh, 0); | |
637 | + if (ret == 0) { | |
638 | + appl_pam_session_opened = 1; | |
639 | + } | |
640 | + } | |
641 | + return ret; | |
642 | +} | |
643 | +int | |
644 | +appl_pam_setenv(void) | |
645 | +{ | |
646 | + int ret = 0; | |
647 | +#ifdef HAVE_PAM_GETENVLIST | |
648 | +#ifdef HAVE_PUTENV | |
649 | + int i; | |
650 | + char **list; | |
651 | + if (appl_pam_started) { | |
652 | + list = pam_getenvlist(appl_pamh); | |
653 | + for (i = 0; ((list != NULL) && (list[i] != NULL)); i++) { | |
654 | +#ifdef DEBUG | |
655 | + printf("Setting \"%s\" in environment.\n", list[i]); | |
656 | +#endif | |
657 | + putenv(list[i]); | |
658 | + } | |
659 | + } | |
660 | +#endif | |
661 | +#endif | |
662 | + return ret; | |
663 | +} | |
664 | +int | |
665 | +appl_pam_cred_init(void) | |
666 | +{ | |
667 | + int ret = 0; | |
668 | + if (appl_pam_started) { | |
669 | +#ifdef DEBUG | |
670 | + printf("Initializing PAM credentials.\n"); | |
671 | +#endif | |
672 | + ret = pam_setcred(appl_pamh, PAM_ESTABLISH_CRED); | |
673 | + if (ret == 0) { | |
674 | + appl_pam_creds_initialized = 1; | |
675 | + } | |
676 | + } | |
677 | + return ret; | |
678 | +} | |
679 | +#endif | |
680 | diff -up krb5-1.8/src/clients/ksu/pam.h.pam krb5-1.8/src/clients/ksu/pam.h | |
681 | --- krb5-1.8/src/clients/ksu/pam.h.pam 2010-03-05 10:48:08.000000000 -0500 | |
682 | +++ krb5-1.8/src/clients/ksu/pam.h 2010-03-05 10:48:08.000000000 -0500 | |
683 | @@ -0,0 +1,57 @@ | |
684 | +/* | |
685 | + * src/clients/ksu/pam.h | |
686 | + * | |
687 | + * Copyright 2007,2009,2010 Red Hat, Inc. | |
688 | + * | |
689 | + * All Rights Reserved. | |
690 | + * | |
691 | + * Redistribution and use in source and binary forms, with or without | |
692 | + * modification, are permitted provided that the following conditions are met: | |
693 | + * | |
694 | + * Redistributions of source code must retain the above copyright notice, this | |
695 | + * list of conditions and the following disclaimer. | |
696 | + * | |
697 | + * Redistributions in binary form must reproduce the above copyright notice, | |
698 | + * this list of conditions and the following disclaimer in the documentation | |
699 | + * and/or other materials provided with the distribution. | |
700 | + * | |
701 | + * Neither the name of Red Hat, Inc. nor the names of its contributors may be | |
702 | + * used to endorse or promote products derived from this software without | |
703 | + * specific prior written permission. | |
704 | + * | |
705 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
706 | + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
707 | + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
708 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
709 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
710 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
711 | + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
712 | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
713 | + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
714 | + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
715 | + * POSSIBILITY OF SUCH DAMAGE. | |
716 | + * | |
717 | + * Convenience wrappers for using PAM. | |
718 | + */ | |
719 | + | |
720 | +#include <krb5.h> | |
721 | +#ifdef HAVE_SECURITY_PAM_APPL_H | |
722 | +#include <security/pam_appl.h> | |
723 | +#endif | |
724 | + | |
725 | +#define USE_PAM_CONFIGURATION_KEYWORD "use_pam" | |
726 | + | |
727 | +#ifdef USE_PAM | |
728 | +int appl_pam_enabled(krb5_context context, const char *section); | |
729 | +int appl_pam_acct_mgmt(const char *service, int interactive, | |
730 | + const char *local_username, | |
731 | + const char *non_interactive_password, | |
732 | + const char *hostname, | |
733 | + const char *ruser, | |
734 | + const char *tty); | |
735 | +int appl_pam_requires_chauthtok(void); | |
736 | +int appl_pam_session_open(void); | |
737 | +int appl_pam_setenv(void); | |
738 | +int appl_pam_cred_init(void); | |
739 | +void appl_pam_cleanup(void); | |
740 | +#endif | |
741 | diff -up krb5-1.8/src/configure.in.pam krb5-1.8/src/configure.in | |
742 | --- krb5-1.8/src/configure.in.pam 2009-12-31 18:13:56.000000000 -0500 | |
743 | +++ krb5-1.8/src/configure.in 2010-03-05 10:48:08.000000000 -0500 | |
744 | @@ -1051,6 +1051,8 @@ if test "$ac_cv_lib_socket" = "yes" -a " | |
745 | AC_SUBST([VERTO_LIBS]) | |
746 | AC_SUBST([VERTO_VERSION]) | |
747 | ||
748 | +KRB5_WITH_PAM | |
749 | + | |
750 | # Make localedir work in autoconf 2.5x. | |
751 | if test "${localedir+set}" != set; then | |
752 | localedir='$(datadir)/locale' |