33695f3
Modify krshd so that it performs PAM account and session management.  It
33695f3
must now always fork so that it can always clean up the session.  The
33695f3
PAM session is opened and credentials initialized after any forwarded
33695f3
credentials are stored to disk and before access to the user's home
33695f3
directory is attempted.  The default service name is "kshell" or
33695f3
"ekshell", depending on whether or not encryption is in use, to avoid a
33695f3
dependency or conflict on the plain rsh server's configuration file.  At
33695f3
run-time, krshd's behavior can be reset to the earlier, non-PAM behavior
33695f3
by setting "use_pam" to false in the [rshd] section of /etc/krb5.conf.
33695f3
33695f3
Modify ftpd so that authentication with a plaintext password goes
33695f3
through PAM, and it performs PAM account and session management.  The
33695f3
PAM session is opened and credentials initialized after any forwarded
33695f3
credentials are stored to disk.  The default service name is "gssftp",
33695f3
mainly to avoid conflicts with other FTP servers' configuration files.
33695f3
At run-time, krshd's behavior can be reset to the earlier, non-PAM
33695f3
behavior by setting "use_pam" to false in the [ftpd] section of
33695f3
/etc/krb5.conf.
33695f3
33695f3
Modify login so that instead of directly obtaining v5 or v4 credentials
33695f3
or running aklog, it calls PAM for authentication if strong
33695f3
authentication hasn't already been performed, so that it performs
33695f3
account management using PAM (prompting for a password change if need
33695f3
be), and that it performs session management.  The PAM session is opened
33695f3
and credentials initialized after any forwarded credentials are stored
33695f3
to disk.  The default service name is "login", because its configuration
33695f3
is pretty much always going to be there.  At run-time, login's behavior
33695f3
can be reset to the earlier, non-PAM behavior by setting "use_pam" to
33695f3
false in the [login] section of /etc/krb5.conf.
33695f3
02e9ad1
Modify ksu so that it performs account and session management on behalf of
02e9ad1
the target user account, mimicking the action of regular su.  The default
33695f3
service name is "ksu", because on Fedora at least the configuration used
33695f3
is determined by whether or not a login shell is being opened, and so
33695f3
this may need to vary, too.  At run-time, ksu's behavior can be reset to
33695f3
the earlier, non-PAM behavior by setting "use_pam" to false in the [ksu]
33695f3
section of /etc/krb5.conf.
33695f3
33695f3
When enabled, ftpd, krshd, login.krb5, and ksu gain dependence on libpam.
9b20bca
RT#5939.
33695f3
33695f3
diff -up krb5-1.7/src/aclocal.m4 krb5-1.7/src/aclocal.m4
33695f3
--- krb5-1.7/src/aclocal.m4	2009-02-18 19:38:17.000000000 -0500
33695f3
+++ krb5-1.7/src/aclocal.m4	2009-06-04 13:45:57.000000000 -0400
33695f3
@@ -1771,3 +1771,86 @@ AC_DEFUN(KRB5_AC_KEYRING_CCACHE,[
33695f3
       ]))
33695f3
 ])dnl
33695f3
 dnl
33695f3
+dnl
33695f3
+dnl Use PAM instead of local crypt() compare for checking local passwords,
33695f3
+dnl and perform PAM account, session management, and password-changing where
33695f3
+dnl appropriate.
33695f3
+dnl 
33695f3
+AC_DEFUN(KRB5_WITH_PAM,[
33695f3
+AC_ARG_WITH(pam,[AC_HELP_STRING(--with-pam,[compile with PAM support])],
33695f3
+	    withpam="$withval",withpam=auto)
33695f3
+AC_ARG_WITH(pam-login-service,[AC_HELP_STRING(--with-login-service,[PAM service name for login ["login"]])],
33695f3
+	    withloginpamservice="$withval",withloginpamservice=login)
33695f3
+AC_ARG_WITH(pam-kshell-service,[AC_HELP_STRING(--with-kshell-service,[PAM service name for unencrypted rsh ["kshell"]])],
33695f3
+	    withkshellpamservice="$withval",withkshellpamservice=kshell)
33695f3
+AC_ARG_WITH(pam-ekshell-service,[AC_HELP_STRING(--with-ekshell-service,[PAM service name for encrypted rsh ["ekshell"]])],
33695f3
+	    withekshellpamservice="$withval",withekshellpamservice=ekshell)
33695f3
+AC_ARG_WITH(pam-ftp-service,[AC_HELP_STRING(--with-ftp-service,[PAM service name for ftpd ["gssftp"]])],
33695f3
+	    withftppamservice="$withval",withftppamservice=gssftp)
33695f3
+AC_ARG_WITH(pam-ksu-service,[AC_HELP_STRING(--with-ksu-service,[PAM service name for ksu ["ksu"]])],
33695f3
+	    withksupamservice="$withval",withksupamservice=ksu)
33695f3
+old_LIBS="$LIBS"
33695f3
+if test "$withpam" != no ; then
33695f3
+	AC_MSG_RESULT([checking for PAM...])
33695f3
+	PAM_LIBS=
33695f3
+
33695f3
+	AC_CHECK_HEADERS(security/pam_appl.h)
33695f3
+	if test "x$ac_cv_header_security_pam_appl_h" != xyes ; then
33695f3
+		if test "$withpam" = auto ; then
33695f3
+			AC_MSG_RESULT([Unable to locate security/pam_appl.h.])
33695f3
+			withpam=no
33695f3
+		else
33695f3
+			AC_MSG_ERROR([Unable to locate security/pam_appl.h.])
33695f3
+		fi
33695f3
+	fi
33695f3
+
33695f3
+	LIBS=
33695f3
+	unset ac_cv_func_pam_start
33695f3
+	AC_CHECK_FUNCS(putenv pam_start)
33695f3
+	if test "x$ac_cv_func_pam_start" = xno ; then
33695f3
+		unset ac_cv_func_pam_start
33695f3
+		AC_CHECK_LIB(dl,dlopen)
33695f3
+		AC_CHECK_FUNCS(pam_start)
33695f3
+		if test "x$ac_cv_func_pam_start" = xno ; then
33695f3
+			AC_CHECK_LIB(pam,pam_start)
33695f3
+			unset ac_cv_func_pam_start
33695f3
+			unset ac_cv_func_pam_getenvlist
33695f3
+			AC_CHECK_FUNCS(pam_start pam_getenvlist)
33695f3
+			if test "x$ac_cv_func_pam_start" = xyes ; then
33695f3
+				PAM_LIBS="$LIBS"
33695f3
+			else
33695f3
+				if test "$withpam" = auto ; then
33695f3
+					AC_MSG_RESULT([Unable to locate libpam.])
33695f3
+					withpam=no
33695f3
+				else
33695f3
+					AC_MSG_ERROR([Unable to locate libpam.])
33695f3
+				fi
33695f3
+			fi
33695f3
+		fi
33695f3
+	fi
33695f3
+	if test "$withpam" != no ; then
7b79d36
+		AC_MSG_NOTICE([building with PAM support])
33695f3
+		AC_DEFINE(USE_PAM,1,[Define if Kerberos-aware tools should support PAM])
33695f3
+		AC_DEFINE_UNQUOTED(LOGIN_PAM_SERVICE,"$withloginpamservice",
33695f3
+				   [Define to the name of the PAM service name to be used by login.])
33695f3
+		AC_DEFINE_UNQUOTED(KSHELL_PAM_SERVICE,"$withkshellpamservice",
33695f3
+				   [Define to the name of the PAM service name to be used by rshd for unencrypted sessions.])
33695f3
+		AC_DEFINE_UNQUOTED(EKSHELL_PAM_SERVICE,"$withekshellpamservice",
33695f3
+				   [Define to the name of the PAM service name to be used by rshd for encrypted sessions.])
33695f3
+		AC_DEFINE_UNQUOTED(FTP_PAM_SERVICE,"$withftppamservice",
33695f3
+				   [Define to the name of the PAM service name to be used by ftpd.])
33695f3
+		AC_DEFINE_UNQUOTED(KSU_PAM_SERVICE,"$withksupamservice",
33695f3
+				   [Define to the name of the PAM service name to be used by ksu.])
33695f3
+		PAM_LIBS="$LIBS"
33695f3
+		NON_PAM_MAN=".\\\" "
33695f3
+		PAM_MAN=
33695f3
+	else
33695f3
+		PAM_MAN=".\\\" "
33695f3
+		NON_PAM_MAN=
33695f3
+	fi
33695f3
+fi
33695f3
+LIBS="$old_LIBS"
33695f3
+AC_SUBST(PAM_LIBS)
33695f3
+AC_SUBST(PAM_MAN)
33695f3
+AC_SUBST(NON_PAM_MAN)
33695f3
+])dnl
33695f3
diff -up krb5-1.7/src/appl/bsd/configure.in krb5-1.7/src/appl/bsd/configure.in
33695f3
--- krb5-1.7/src/appl/bsd/configure.in	2008-12-15 15:29:01.000000000 -0500
33695f3
+++ krb5-1.7/src/appl/bsd/configure.in	2009-06-04 13:45:57.000000000 -0400
33695f3
@@ -24,6 +24,7 @@ AC_CHECK_LIB(odm,main,
33695f3
     AC_CHECK_LIB(cfg,main, 
33695f3
       LOGINLIBS="$LOGINLIBS -lodm -ls -lcfg" 
33695f3
       )))
33695f3
+KRB5_WITH_PAM
33695f3
 dnl
33695f3
 dnl Make our operating system-specific security checks and definitions for
33695f3
 dnl login.
33695f3
diff -up krb5-1.7/src/appl/bsd/krshd.c krb5-1.7/src/appl/bsd/krshd.c
33695f3
--- krb5-1.7/src/appl/bsd/krshd.c	2009-04-15 16:07:15.000000000 -0400
33695f3
+++ krb5-1.7/src/appl/bsd/krshd.c	2009-06-04 13:45:57.000000000 -0400
33695f3
@@ -161,6 +161,10 @@ char copyright[] =
33695f3
 #include <arpa/nameser.h>
33695f3
 #endif
33695f3
 
33695f3
+#ifdef USE_PAM
33695f3
+#include "pam.h"
33695f3
+#endif
33695f3
+
33695f3
 #ifndef MAXDNAME
33695f3
 #define MAXDNAME 256 /*per the rfc*/
33695f3
 #endif
33695f3
@@ -181,6 +185,7 @@ void fatal(int, const char *);
33695f3
 
33695f3
 int require_encrypt = 0;
33695f3
 int do_encrypt = 0;
33695f3
+int force_fork = 0;
33695f3
 int anyport = 0;
33695f3
 char *kprogdir = KPROGDIR;
33695f3
 int netf;
33695f3
@@ -1030,14 +1035,6 @@ void doit(f, fromp)
33695f3
     }
33695f3
 #endif /*CRAY*/
33695f3
     
33695f3
-    if (chdir(pwd->pw_dir) < 0) {
33695f3
-      if(chdir("/") < 0) {
33695f3
-      	error("No remote directory.\n");
33695f3
-	goto signout_please;
33695f3
-      }
33695f3
-	   pwd->pw_dir = "/";
33695f3
-    }
33695f3
-
33695f3
 #ifdef KERBEROS
33695f3
     /* krb5_kuserok returns 1 if OK */
33695f3
     if (!krb5_kuserok(bsd_context, client, locuser)){
33695f3
@@ -1067,11 +1064,51 @@ void doit(f, fromp)
33695f3
 	goto signout_please;
33695f3
     }
33695f3
     
33695f3
+#ifdef USE_PAM
33695f3
+    if (appl_pam_enabled(bsd_context, "rshd")) {
33695f3
+        if (appl_pam_acct_mgmt(do_encrypt ?
33695f3
+			       EKSHELL_PAM_SERVICE :
33695f3
+			       KSHELL_PAM_SERVICE,
33695f3
+			       0,
33695f3
+			       locuser,
33695f3
+			       "",
33695f3
+			       hostname,
33695f3
+			       NULL,
33695f3
+			       do_encrypt ?
33695f3
+			       EKSHELL_PAM_SERVICE :
33695f3
+			       KSHELL_PAM_SERVICE) != 0) {
33695f3
+	    error("Login denied.\n");
33695f3
+	    goto signout_please;
33695f3
+        }
33695f3
+        if (appl_pam_requires_chauthtok()) {
33695f3
+	    error("Password change required, but not possible over rsh.\n");
33695f3
+	    goto signout_please;
33695f3
+        }
33695f3
+        force_fork = 1;
33695f3
+        appl_pam_set_forwarded_ccname(getenv("KRB5CCNAME"));
33695f3
+        if (appl_pam_session_open() != 0) {
33695f3
+	    error("Login failure.\n");
33695f3
+	    goto signout_please;
33695f3
+        }
33695f3
+        if (appl_pam_cred_init()) {
33695f3
+	    error("Login failure.\n");
33695f3
+	    goto signout_please;
33695f3
+        }
33695f3
+    } else
33695f3
+#endif
33695f3
     if (pwd->pw_uid && !access(NOLOGIN, F_OK)) {
33695f3
 	error("Logins currently disabled.\n");
33695f3
 	goto signout_please;
33695f3
     }
33695f3
     
33695f3
+    if (chdir(pwd->pw_dir) < 0) {
33695f3
+	if (chdir("/") < 0) {
33695f3
+	    error("No remote directory.\n");
33695f3
+	    goto signout_please;
33695f3
+	}
33695f3
+	pwd->pw_dir = "/";
33695f3
+    }
33695f3
+
33695f3
     /* Log access to account */
33695f3
     pwd = (struct passwd *) getpwnam(locuser);
33695f3
     if (pwd && (pwd->pw_uid == 0)) {
33695f3
@@ -1111,7 +1148,7 @@ void doit(f, fromp)
33695f3
     
33695f3
     (void) write(2, "", 1);
33695f3
     
33695f3
-    if (port||do_encrypt) {
33695f3
+    if (port||do_encrypt||force_fork) {
33695f3
 	if (port&&(pipe(pv) < 0)) {
33695f3
 	    error("Can't make pipe.\n");
33695f3
 	    goto signout_please;
33695f3
@@ -1416,6 +1453,15 @@ void doit(f, fromp)
33695f3
 
33695f3
     environ = envinit;
33695f3
     
33695f3
+#ifdef USE_PAM
33695f3
+    if (appl_pam_enabled(bsd_context, "rshd")) {
33695f3
+        if (appl_pam_setenv() != 0) {
33695f3
+	    error("Login failure.\n");
33695f3
+	    goto signout_please;
33695f3
+        }
33695f3
+    }
33695f3
+#endif
33695f3
+
33695f3
 #ifdef KERBEROS
33695f3
     /* To make Kerberos rcp work correctly, we must ensure that we
33695f3
        invoke Kerberos rcp on this end, not normal rcp, even if the
33695f3
diff -up krb5-1.7/src/appl/bsd/login.c krb5-1.7/src/appl/bsd/login.c
33695f3
--- krb5-1.7/src/appl/bsd/login.c	2008-12-15 15:29:01.000000000 -0500
33695f3
+++ krb5-1.7/src/appl/bsd/login.c	2009-06-04 13:45:57.000000000 -0400
33695f3
@@ -145,6 +145,11 @@ typedef sigtype (*handler)();
33695f3
 #include "osconf.h"
33695f3
 #endif /* KRB5_GET_TICKETS */
33695f3
 
33695f3
+#ifdef USE_PAM
33695f3
+#include "pam.h"
33695f3
+int login_use_pam = 1;
33695f3
+#endif
33695f3
+
33695f3
 #ifndef __STDC__
33695f3
 #ifndef volatile
33695f3
 #define volatile
33695f3
@@ -294,6 +299,9 @@ static struct login_confs {
33695f3
     char *flagname;
33695f3
     int *flag;
33695f3
 } login_conf_set[] = {
33695f3
+#ifdef USE_PAM
33695f3
+    {USE_PAM_CONFIGURATION_KEYWORD, &login_use_pam},
33695f3
+#endif
33695f3
 #ifdef KRB5_GET_TICKETS
33695f3
     {"krb5_get_tickets", &login_krb5_get_tickets},
33695f3
     {"krb_run_aklog", &login_krb_run_aklog},
33695f3
@@ -933,6 +941,21 @@ int main(argc, argv)
33695f3
 	if (!unix_needs_passwd())
33695f3
 	    break;
33695f3
 
33695f3
+#ifdef USE_PAM
33695f3
+	if (login_use_pam) {
33695f3
+	    if (appl_pam_authenticate(LOGIN_PAM_SERVICE, 1, username, "",
33695f3
+				      hostname,
33695f3
+				      NULL,
33695f3
+				      ttyname(STDIN_FILENO)) == PAM_SUCCESS) {
33695f3
+		break;
33695f3
+	    } else {
33695f3
+		/* the goto target label is in a different nesting scope, but
33695f3
+		 * it's roughly where we want to land */
33695f3
+		goto bad_login;
33695f3
+	    }
33695f3
+	}
33695f3
+#endif
33695f3
+
33695f3
 #ifdef KRB5_GET_TICKETS
33695f3
 	if (login_krb5_get_tickets) {
33695f3
 	    /* rename these to something more verbose */
33695f3
@@ -1020,6 +1043,24 @@ int main(argc, argv)
33695f3
     /* committed to login -- turn off timeout */
33695f3
     (void) alarm((u_int) 0);
33695f3
 
33695f3
+#ifdef USE_PAM
33695f3
+    if (login_use_pam) {
33695f3
+	if (appl_pam_acct_mgmt(LOGIN_PAM_SERVICE, 1, username, "",
33695f3
+			       hostname, NULL, ttyname(STDIN_FILENO)) != 0) {
33695f3
+	    printf("Login incorrect\n");
33695f3
+	    sleepexit(1);
33695f3
+	}
33695f3
+	if (appl_pam_requires_chauthtok()) {
33695f3
+	    if (appl_pam_chauthtok() != 0) {
33695f3
+		printf("Failed to change password.\n");
33695f3
+		sleepexit(1);
33695f3
+	    }
33695f3
+	}
33695f3
+    } else {
33695f3
+	/* the "else" here is the non-PAM behavior which continues until the
33695f3
+	 * next ifdef USE_PAM block, as of this writing more or less
33695f3
+	 * duplicating the work of pam_securetty and an OQUOTA check */
33695f3
+#endif
33695f3
     /*
33695f3
      * If valid so far and root is logging in, see if root logins on
33695f3
      * this terminal are permitted.
33695f3
@@ -1060,6 +1101,21 @@ int main(argc, argv)
33695f3
 	sleepexit(0);
33695f3
     }
33695f3
 #endif
33695f3
+#ifdef USE_PAM
33695f3
+    }
33695f3
+#endif /* USE_PAM */
33695f3
+
33695f3
+#ifdef USE_PAM
33695f3
+    if (login_use_pam) {
33695f3
+	appl_pam_set_forwarded_ccname(getenv("KRB5CCNAME"));
33695f3
+	if (appl_pam_session_open() != 0) {
33695f3
+	    sleepexit(1);
33695f3
+	}
33695f3
+	if (appl_pam_cred_init() != 0) {
33695f3
+	    sleepexit(1);
33695f3
+	}
33695f3
+    }
33695f3
+#endif /* USE_PAM */
33695f3
 
33695f3
     if (chdir(pwd->pw_dir) < 0) {
33695f3
 	printf("No directory %s!\n", pwd->pw_dir);
33695f3
@@ -1347,6 +1403,11 @@ int main(argc, argv)
33695f3
     }
33695f3
 #endif /* KRB5_GET_TICKETS */
33695f3
 
33695f3
+#ifdef USE_PAM
33695f3
+    if (login_use_pam)
33695f3
+	appl_pam_setenv();
33695f3
+#endif
33695f3
+
33695f3
     if (tty[sizeof("tty")-1] == 'd')
33695f3
 	syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
33695f3
     if (pwd->pw_uid == 0)
33695f3
diff -up krb5-1.7/src/appl/bsd/Makefile.in krb5-1.7/src/appl/bsd/Makefile.in
33695f3
--- krb5-1.7/src/appl/bsd/Makefile.in	2009-01-05 15:27:53.000000000 -0500
33695f3
+++ krb5-1.7/src/appl/bsd/Makefile.in	2009-06-04 13:45:57.000000000 -0400
33695f3
@@ -11,12 +11,13 @@ SETENVOBJ=@SETENVOBJ@
33695f3
 LOGINLIBS=@LOGINLIBS@
33695f3
 LIBOBJS=@LIBOBJS@
33695f3
 KRSHDLIBS=@KRSHDLIBS@
33695f3
+PAMOBJS=pam.o
33695f3
 
33695f3
 SRCS= $(srcdir)/krcp.c $(srcdir)/krlogin.c $(srcdir)/krsh.c $(srcdir)/kcmd.c \
33695f3
 	$(srcdir)/forward.c $(srcdir)/login.c $(srcdir)/krshd.c \
33695f3
 	$(srcdir)/krlogind.c
33695f3
 OBJS= krcp.o krlogin.o krsh.o kcmd.o forward.o $(SETENVOBJ) login.o krshd.o \
33695f3
-	krlogind.o $(LIBOBJS)
33695f3
+	krlogind.o $(LIBOBJS) $(PAMOBJS)
33695f3
 
33695f3
 UCB_RLOGIN = @UCB_RLOGIN@
33695f3
 UCB_RSH = @UCB_RSH@
33695f3
@@ -53,8 +54,8 @@ install::
33695f3
 	  ) || exit 1; \
33695f3
 	done
33695f3
 
33695f3
-kshd: krshd.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(PTY_DEPLIB) $(KRB5_BASE_DEPLIBS) $(APPUTILS_DEPLIB)
33695f3
-	$(CC_LINK) -o kshd krshd.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRSHDLIBS) $(PTY_LIB) $(UTIL_LIB) $(KRB5_BASE_LIBS) $(APPUTILS_LIB)
33695f3
+kshd: krshd.o kcmd.o forward.o $(PAMOBJS) $(SETENVOBJ) $(LIBOBJS) $(PTY_DEPLIB) $(KRB5_BASE_DEPLIBS) $(APPUTILS_DEPLIB)
33695f3
+	$(CC_LINK) -o kshd krshd.o kcmd.o forward.o $(PAMOBJS) $(SETENVOBJ) $(LIBOBJS) $(KRSHDLIBS) $(PTY_LIB) $(UTIL_LIB) $(KRB5_BASE_LIBS) $(PAM_LIBS) $(APPUTILS_LIB)
33695f3
 
33695f3
 klogind: krlogind.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(PTY_DEPLIB) $(KRB5_BASE_DEPLIBS) $(APPUTILS_DEPLIB)
33695f3
 	$(CC_LINK) -o klogind krlogind.o  kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(PTY_LIB) $(UTIL_LIB) $(KRB5_BASE_LIBS) $(APPUTILS_LIB)
33695f3
@@ -71,8 +72,8 @@ install::
33695f3
 # No program name transformation is done with login.krb5 since it is directly
33695f3
 # referenced by klogind.
33695f3
 #
33695f3
-login.krb5: login.o  $(SETENVOBJ) $(LIBOBJS) $(PTY_DEPLIB) $(KRB5_BASE_DEPLIBS)
33695f3
-	$(CC_LINK) -o login.krb5 login.o $(SETENVOBJ) $(LIBOBJS) $(LOGINLIBS) $(PTY_LIB) $(KRB5_BASE_LIBS)
33695f3
+login.krb5: login.o  $(SETENVOBJ) $(PAMOBJS) $(LIBOBJS) $(PTY_DEPLIB) $(KRB5_BASE_DEPLIBS)
33695f3
+	$(CC_LINK) -o login.krb5 login.o $(SETENVOBJ) $(PAMOBJS) $(LIBOBJS) $(LOGINLIBS) $(PTY_LIB) $(KRB5_BASE_LIBS) $(PAM_LIBS)
33695f3
 
33695f3
 install::
33695f3
 	$(INSTALL_PROGRAM) login.krb5 $(DESTDIR)$(SERVER_BINDIR)/login.krb5
33695f3
diff -up /dev/null krb5-1.7/src/appl/bsd/pam.c
33695f3
--- /dev/null	2009-06-04 10:34:55.169007373 -0400
33695f3
+++ krb5-1.7/src/appl/bsd/pam.c	2009-06-04 13:45:57.000000000 -0400
33695f3
@@ -0,0 +1,433 @@
33695f3
+/*
33695f3
+ * src/appl/bsd/pam.c
33695f3
+ *
33695f3
+ * Copyright 2007,2009 Red Hat, Inc.
33695f3
+ *
33695f3
+ * All Rights Reserved.
33695f3
+ *
33695f3
+ * Redistribution and use in source and binary forms, with or without
33695f3
+ * modification, are permitted provided that the following conditions are met:
33695f3
+ *
33695f3
+ *  Redistributions of source code must retain the above copyright notice, this
33695f3
+ *  list of conditions and the following disclaimer.
33695f3
+ *
33695f3
+ *  Redistributions in binary form must reproduce the above copyright notice,
33695f3
+ *  this list of conditions and the following disclaimer in the documentation
33695f3
+ *  and/or other materials provided with the distribution.
33695f3
+ *
33695f3
+ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
33695f3
+ *  used to endorse or promote products derived from this software without
33695f3
+ *  specific prior written permission.
33695f3
+ *
33695f3
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33695f3
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33695f3
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33695f3
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
33695f3
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33695f3
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33695f3
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33695f3
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33695f3
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33695f3
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33695f3
+ * POSSIBILITY OF SUCH DAMAGE.
33695f3
+ * 
33695f3
+ * Convenience wrappers for using PAM.
33695f3
+ */
33695f3
+
33695f3
+#include "autoconf.h"
33695f3
+#ifdef USE_PAM
33695f3
+#include <sys/types.h>
33695f3
+#include <stdio.h>
33695f3
+#include <stdlib.h>
33695f3
+#include <string.h>
33695f3
+#include <unistd.h>
33695f3
+#include "k5-int.h"
33695f3
+#include "pam.h"
33695f3
+
33695f3
+#ifndef MAXPWSIZE
33695f3
+#define MAXPWSIZE 128
33695f3
+#endif
33695f3
+
33695f3
+static int appl_pam_started;
33695f3
+static pid_t appl_pam_starter = -1;
33695f3
+static int appl_pam_session_opened;
33695f3
+static int appl_pam_creds_initialized;
33695f3
+static int appl_pam_pwchange_required;
33695f3
+static pam_handle_t *appl_pamh;
33695f3
+static struct pam_conv appl_pam_conv;
33695f3
+static char *appl_pam_user;
33695f3
+struct appl_pam_non_interactive_args {
33695f3
+	const char *user;
33695f3
+	const char *password;
33695f3
+};
33695f3
+
33695f3
+int
33695f3
+appl_pam_enabled(krb5_context context, const char *section)
33695f3
+{
33695f3
+	int enabled = 1;
33695f3
+	if ((context != NULL) && (context->profile != NULL)) {
33695f3
+		if (profile_get_boolean(context->profile,
33695f3
+					section,
33695f3
+					USE_PAM_CONFIGURATION_KEYWORD,
33695f3
+					NULL,
33695f3
+					enabled, &enabled) != 0) {
33695f3
+			enabled = 1;
33695f3
+		}
33695f3
+	}
33695f3
+	return enabled;
33695f3
+}
33695f3
+
33695f3
+void
33695f3
+appl_pam_cleanup(void)
33695f3
+{
33695f3
+	if (getpid() != appl_pam_starter) {
33695f3
+		return;
33695f3
+	}
33695f3
+#ifdef DEBUG
33695f3
+	printf("Called to clean up PAM.\n");
33695f3
+#endif
33695f3
+	if (appl_pam_creds_initialized) {
33695f3
+#ifdef DEBUG
33695f3
+		printf("Deleting PAM credentials.\n");
33695f3
+#endif
33695f3
+		pam_setcred(appl_pamh, PAM_DELETE_CRED);
33695f3
+		appl_pam_creds_initialized = 0;
33695f3
+	}
33695f3
+	if (appl_pam_session_opened) {
33695f3
+#ifdef DEBUG
33695f3
+		printf("Closing PAM session.\n");
33695f3
+#endif
33695f3
+		pam_close_session(appl_pamh, 0);
33695f3
+		appl_pam_session_opened = 0;
33695f3
+	}
33695f3
+	appl_pam_pwchange_required = 0;
33695f3
+	if (appl_pam_started) {
33695f3
+#ifdef DEBUG
33695f3
+		printf("Shutting down PAM.\n");
33695f3
+#endif
33695f3
+		pam_end(appl_pamh, 0);
33695f3
+		appl_pam_started = 0;
33695f3
+		appl_pam_starter = -1;
33695f3
+		free(appl_pam_user);
33695f3
+		appl_pam_user = NULL;
33695f3
+	}
33695f3
+}
33695f3
+static int
33695f3
+appl_pam_interactive_converse(int num_msg, const struct pam_message **msg,
33695f3
+			      struct pam_response **presp, void *appdata_ptr)
33695f3
+{
33695f3
+	const struct pam_message *message;
33695f3
+	struct pam_response *resp;
33695f3
+	int i, code;
33695f3
+	char *pwstring, pwbuf[MAXPWSIZE];
33695f3
+	unsigned int pwsize;
33695f3
+	resp = malloc(sizeof(struct pam_response) * num_msg);
33695f3
+	if (resp == NULL) {
33695f3
+		return PAM_BUF_ERR;
33695f3
+	}
33695f3
+	memset(resp, 0, sizeof(struct pam_response) * num_msg);
33695f3
+	code = PAM_SUCCESS;
33695f3
+	for (i = 0; i < num_msg; i++) {
33695f3
+		message = &(msg[0][i]); /* XXX */
33695f3
+		message = msg[i]; /* XXX */
33695f3
+		pwstring = NULL;
33695f3
+		switch (message->msg_style) {
33695f3
+		case PAM_TEXT_INFO:
33695f3
+		case PAM_ERROR_MSG:
33695f3
+			printf("[%s]\n", message->msg ? message->msg : "");
33695f3
+			fflush(stdout);
33695f3
+			resp[i].resp = NULL;
33695f3
+			resp[i].resp_retcode = PAM_SUCCESS;
33695f3
+			break;
33695f3
+		case PAM_PROMPT_ECHO_ON:
33695f3
+		case PAM_PROMPT_ECHO_OFF:
33695f3
+			if (message->msg_style == PAM_PROMPT_ECHO_ON) {
33695f3
+				if (fgets(pwbuf, sizeof(pwbuf),
33695f3
+					  stdin) != NULL) {
33695f3
+					pwbuf[strcspn(pwbuf, "\r\n")] = '\0';
33695f3
+					pwstring = pwbuf;
33695f3
+				}
33695f3
+			} else {
33695f3
+				pwstring = getpass(message->msg ?
33695f3
+						   message->msg :
33695f3
+						   "");
33695f3
+			}
33695f3
+			if ((pwstring != NULL) && (pwstring[0] != '\0')) {
33695f3
+				pwsize = strlen(pwstring);
33695f3
+				resp[i].resp = malloc(pwsize + 1);
33695f3
+				if (resp[i].resp == NULL) {
33695f3
+					resp[i].resp_retcode = PAM_BUF_ERR;
33695f3
+				} else {
33695f3
+					memcpy(resp[i].resp, pwstring, pwsize);
33695f3
+					resp[i].resp[pwsize] = '\0';
33695f3
+					resp[i].resp_retcode = PAM_SUCCESS;
33695f3
+				}
33695f3
+			} else {
33695f3
+				resp[i].resp_retcode = PAM_CONV_ERR;
33695f3
+				code = PAM_CONV_ERR;
33695f3
+			}
33695f3
+			break;
33695f3
+		default:
33695f3
+			break;
33695f3
+		}
33695f3
+	}
33695f3
+	*presp = resp;
33695f3
+	return code;
33695f3
+}
33695f3
+static int
33695f3
+appl_pam_non_interactive_converse(int num_msg,
33695f3
+				  const struct pam_message **msg,
33695f3
+				  struct pam_response **presp,
33695f3
+				  void *appdata_ptr)
33695f3
+{
33695f3
+	const struct pam_message *message;
33695f3
+	struct pam_response *resp;
33695f3
+	int i, code;
33695f3
+	unsigned int pwsize;
33695f3
+	struct appl_pam_non_interactive_args *args;
33695f3
+	const char *pwstring;
33695f3
+	resp = malloc(sizeof(struct pam_response) * num_msg);
33695f3
+	if (resp == NULL) {
33695f3
+		return PAM_BUF_ERR;
33695f3
+	}
33695f3
+	args = appdata_ptr;
33695f3
+	memset(resp, 0, sizeof(struct pam_response) * num_msg);
33695f3
+	code = PAM_SUCCESS;
33695f3
+	for (i = 0; i < num_msg; i++) {
33695f3
+		message = &((*msg)[i]);
33695f3
+		message = msg[i];
33695f3
+		pwstring = NULL;
33695f3
+		switch (message->msg_style) {
33695f3
+		case PAM_TEXT_INFO:
33695f3
+		case PAM_ERROR_MSG:
33695f3
+			break;
33695f3
+		case PAM_PROMPT_ECHO_ON:
33695f3
+		case PAM_PROMPT_ECHO_OFF:
33695f3
+			if (message->msg_style == PAM_PROMPT_ECHO_ON) {
33695f3
+				/* assume "user" */
33695f3
+				pwstring = args->user;
33695f3
+			} else {
33695f3
+				/* assume "password" */
33695f3
+				pwstring = args->password;
33695f3
+			}
33695f3
+			if ((pwstring != NULL) && (pwstring[0] != '\0')) {
33695f3
+				pwsize = strlen(pwstring);
33695f3
+				resp[i].resp = malloc(pwsize + 1);
33695f3
+				if (resp[i].resp == NULL) {
33695f3
+					resp[i].resp_retcode = PAM_BUF_ERR;
33695f3
+				} else {
33695f3
+					memcpy(resp[i].resp, pwstring, pwsize);
33695f3
+					resp[i].resp[pwsize] = '\0';
33695f3
+					resp[i].resp_retcode = PAM_SUCCESS;
33695f3
+				}
33695f3
+			} else {
33695f3
+				resp[i].resp_retcode = PAM_CONV_ERR;
33695f3
+				code = PAM_CONV_ERR;
33695f3
+			}
33695f3
+			break;
33695f3
+		default:
33695f3
+			break;
33695f3
+		}
33695f3
+	}
33695f3
+	*presp = resp;
33695f3
+	return code;
33695f3
+}
33695f3
+void
33695f3
+appl_pam_set_forwarded_ccname(const char *ccname)
33695f3
+{
33695f3
+	char *ccname2;
33695f3
+	if (appl_pam_started && (ccname != NULL) && (strlen(ccname) > 0)) {
33695f3
+		ccname2 = malloc(strlen(KRB5_ENV_CCNAME) + strlen(ccname) + 2);
33695f3
+		if (ccname2 != NULL) {
33695f3
+#ifdef DEBUG
33695f3
+			printf("Setting %s to \"%s\" in PAM environment.\n",
33695f3
+			       KRB5_ENV_CCNAME, ccname);
33695f3
+#endif
33695f3
+			sprintf(ccname2, "%s=%s", KRB5_ENV_CCNAME, ccname);
33695f3
+			pam_putenv(appl_pamh, ccname2);
33695f3
+		}
33695f3
+	}
33695f3
+}
33695f3
+static int
33695f3
+appl_pam_start(const char *service, int interactive,
33695f3
+	       const char *login_username,
33695f3
+	       const char *non_interactive_password,
33695f3
+	       const char *hostname,
33695f3
+	       const char *ruser,
33695f3
+	       const char *tty)
33695f3
+{
33695f3
+	static int exit_handler_registered;
33695f3
+	static struct appl_pam_non_interactive_args args;
33695f3
+	int ret = 0;
33695f3
+	if (appl_pam_started &&
33695f3
+	    (strcmp(login_username, appl_pam_user) != 0)) {
33695f3
+		appl_pam_cleanup();
33695f3
+		appl_pam_user = NULL;
33695f3
+	}
33695f3
+	if (!appl_pam_started) {
33695f3
+#ifdef DEBUG
33695f3
+		printf("Starting PAM up (service=\"%s\",user=\"%s\").\n",
33695f3
+		       service, login_username);
33695f3
+#endif
33695f3
+		memset(&appl_pam_conv, 0, sizeof(appl_pam_conv));
33695f3
+		appl_pam_conv.conv = interactive ?
33695f3
+				     &appl_pam_interactive_converse :
33695f3
+				     &appl_pam_non_interactive_converse;
33695f3
+		memset(&args, 0, sizeof(args));
33695f3
+		args.user = strdup(login_username);
33695f3
+		args.password = non_interactive_password ?
33695f3
+				strdup(non_interactive_password) :
33695f3
+				NULL;
33695f3
+		appl_pam_conv.appdata_ptr = &arg;;
33695f3
+		ret = pam_start(service, login_username,
33695f3
+				&appl_pam_conv, &appl_pamh);
33695f3
+		if (ret == 0) {
33695f3
+			if (hostname != NULL) {
33695f3
+#ifdef DEBUG
33695f3
+				printf("Setting PAM_RHOST to \"%s\".\n", hostname);
33695f3
+#endif
33695f3
+				pam_set_item(appl_pamh, PAM_RHOST, hostname);
33695f3
+			}
33695f3
+			if (ruser != NULL) {
33695f3
+#ifdef DEBUG
33695f3
+				printf("Setting PAM_RUSER to \"%s\".\n", ruser);
33695f3
+#endif
33695f3
+				pam_set_item(appl_pamh, PAM_RUSER, ruser);
33695f3
+			}
33695f3
+			if (tty != NULL) {
33695f3
+#ifdef DEBUG
33695f3
+				printf("Setting PAM_TTY to \"%s\".\n", tty);
33695f3
+#endif
33695f3
+				pam_set_item(appl_pamh, PAM_TTY, tty);
33695f3
+			}
33695f3
+			if (!exit_handler_registered &&
33695f3
+			    (atexit(appl_pam_cleanup) != 0)) {
33695f3
+				pam_end(appl_pamh, 0);
33695f3
+				appl_pamh = NULL;
33695f3
+				ret = -1;
33695f3
+			} else {
33695f3
+				appl_pam_started = 1;
33695f3
+				appl_pam_starter = getpid();
33695f3
+				appl_pam_user = strdup(login_username);
33695f3
+				exit_handler_registered = 1;
33695f3
+			}
33695f3
+		}
33695f3
+	}
33695f3
+	return ret;
33695f3
+}
33695f3
+int
33695f3
+appl_pam_authenticate(const char *service, int interactive,
33695f3
+		      const char *login_username,
33695f3
+		      const char *non_interactive_password,
33695f3
+		      const char *hostname,
33695f3
+		      const char *ruser,
33695f3
+		      const char *tty)
33695f3
+{
33695f3
+	int ret;
33695f3
+	ret = appl_pam_start(service, interactive, login_username,
33695f3
+			     non_interactive_password, hostname, ruser, tty);
33695f3
+	if (ret == 0) {
33695f3
+		ret = pam_authenticate(appl_pamh, 0);
33695f3
+	}
33695f3
+	return ret;
33695f3
+}
33695f3
+int
33695f3
+appl_pam_acct_mgmt(const char *service, int interactive,
33695f3
+		   const char *login_username,
33695f3
+		   const char *non_interactive_password,
33695f3
+		   const char *hostname,
33695f3
+		   const char *ruser,
33695f3
+		   const char *tty)
33695f3
+{
33695f3
+	int ret;
33695f3
+	appl_pam_pwchange_required = 0;
33695f3
+	ret = appl_pam_start(service, interactive, login_username,
33695f3
+			     non_interactive_password, hostname, ruser, tty);
33695f3
+	if (ret == 0) {
33695f3
+#ifdef DEBUG
33695f3
+		printf("Calling pam_acct_mgmt().\n");
33695f3
+#endif
33695f3
+		ret = pam_acct_mgmt(appl_pamh, 0);
33695f3
+		switch (ret) {
33695f3
+		case PAM_IGNORE:
33695f3
+			ret = 0;
33695f3
+			break;
33695f3
+		case PAM_NEW_AUTHTOK_REQD:
33695f3
+			appl_pam_pwchange_required = 1;
33695f3
+			ret = 0;
33695f3
+			break;
33695f3
+		default:
33695f3
+			break;
33695f3
+		}
33695f3
+	}
33695f3
+	return ret;
33695f3
+}
33695f3
+int
33695f3
+appl_pam_requires_chauthtok(void)
33695f3
+{
33695f3
+	return appl_pam_pwchange_required;
33695f3
+}
33695f3
+int
33695f3
+appl_pam_chauthtok(void)
33695f3
+{
33695f3
+	int ret = 0;
33695f3
+	if (appl_pam_started) {
33695f3
+#ifdef DEBUG
33695f3
+		printf("Changing PAM expired authentication token.\n");
33695f3
+#endif
33695f3
+		ret = pam_chauthtok(appl_pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
33695f3
+	}
33695f3
+	return ret;
33695f3
+}
33695f3
+int
33695f3
+appl_pam_session_open(void)
33695f3
+{
33695f3
+	int ret = 0;
33695f3
+	if (appl_pam_started) {
33695f3
+#ifdef DEBUG
33695f3
+		printf("Opening PAM session.\n");
33695f3
+#endif
33695f3
+		ret = pam_open_session(appl_pamh, 0);
33695f3
+		if (ret == 0) {
33695f3
+			appl_pam_session_opened = 1;
33695f3
+		}
33695f3
+	}
33695f3
+	return ret;
33695f3
+}
33695f3
+int
33695f3
+appl_pam_setenv(void)
33695f3
+{
33695f3
+	int ret = 0;
33695f3
+#ifdef HAVE_PAM_GETENVLIST
33695f3
+#ifdef HAVE_PUTENV
33695f3
+	int i;
33695f3
+	char **list;
33695f3
+	if (appl_pam_started) {
33695f3
+		list = pam_getenvlist(appl_pamh);
33695f3
+		for (i = 0; ((list != NULL) && (list[i] != NULL)); i++) {
33695f3
+#ifdef DEBUG
33695f3
+			printf("Setting \"%s\" in environment.\n", list[i]);
33695f3
+#endif
33695f3
+			putenv(list[i]);
33695f3
+		}
33695f3
+	}
33695f3
+#endif
33695f3
+#endif
33695f3
+	return ret;
33695f3
+}
33695f3
+int
33695f3
+appl_pam_cred_init(void)
33695f3
+{
33695f3
+	int ret = 0;
33695f3
+	if (appl_pam_started) {
33695f3
+#ifdef DEBUG
33695f3
+		printf("Initializing PAM credentials.\n");
33695f3
+#endif
33695f3
+		ret = pam_setcred(appl_pamh, PAM_ESTABLISH_CRED);
33695f3
+		if (ret == 0) {
33695f3
+			appl_pam_creds_initialized = 1;
33695f3
+		}
33695f3
+	}
33695f3
+	return ret;
33695f3
+}
33695f3
+#endif
33695f3
diff -up /dev/null krb5-1.7/src/appl/bsd/pam.h
33695f3
--- /dev/null	2009-06-04 10:34:55.169007373 -0400
33695f3
+++ krb5-1.7/src/appl/bsd/pam.h	2009-06-04 13:45:57.000000000 -0400
33695f3
@@ -0,0 +1,65 @@
33695f3
+/*
33695f3
+ * src/appl/bsd/pam.h
33695f3
+ *
33695f3
+ * Copyright 2007,2009 Red Hat, Inc.
33695f3
+ *
33695f3
+ * All Rights Reserved.
33695f3
+ *
33695f3
+ * Redistribution and use in source and binary forms, with or without
33695f3
+ * modification, are permitted provided that the following conditions are met:
33695f3
+ *
33695f3
+ *  Redistributions of source code must retain the above copyright notice, this
33695f3
+ *  list of conditions and the following disclaimer.
33695f3
+ *
33695f3
+ *  Redistributions in binary form must reproduce the above copyright notice,
33695f3
+ *  this list of conditions and the following disclaimer in the documentation
33695f3
+ *  and/or other materials provided with the distribution.
33695f3
+ *
33695f3
+ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
33695f3
+ *  used to endorse or promote products derived from this software without
33695f3
+ *  specific prior written permission.
33695f3
+ *
33695f3
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33695f3
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33695f3
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33695f3
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
33695f3
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33695f3
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33695f3
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33695f3
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33695f3
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33695f3
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33695f3
+ * POSSIBILITY OF SUCH DAMAGE.
33695f3
+ * 
33695f3
+ * Convenience wrappers for using PAM.
33695f3
+ */
33695f3
+
33695f3
+#include <krb5.h>
33695f3
+#ifdef HAVE_SECURITY_PAM_APPL_H
33695f3
+#include <security/pam_appl.h>
33695f3
+#endif
33695f3
+
33695f3
+#define USE_PAM_CONFIGURATION_KEYWORD "use_pam"
33695f3
+
33695f3
+#ifdef USE_PAM
33695f3
+int appl_pam_enabled(krb5_context context, const char *section);
33695f3
+int appl_pam_authenticate(const char *service, int interactive,
33695f3
+			  const char *local_username,
33695f3
+			  const char *non_interactive_password,
33695f3
+			  const char *hostname,
33695f3
+			  const char *ruser,
33695f3
+			  const char *tty);
33695f3
+int appl_pam_acct_mgmt(const char *service, int interactive,
33695f3
+		       const char *local_username,
33695f3
+		       const char *non_interactive_password,
33695f3
+		       const char *hostname,
33695f3
+		       const char *ruser,
33695f3
+		       const char *tty);
33695f3
+int appl_pam_requires_chauthtok(void);
33695f3
+int appl_pam_chauthtok(void);
33695f3
+void appl_pam_set_forwarded_ccname(const char *ccname);
33695f3
+int appl_pam_session_open(void);
33695f3
+int appl_pam_setenv(void);
33695f3
+int appl_pam_cred_init(void);
33695f3
+void appl_pam_cleanup(void);
33695f3
+#endif
33695f3
diff -up krb5-1.7/src/appl/gssftp/configure.in krb5-1.7/src/appl/gssftp/configure.in
33695f3
--- krb5-1.7/src/appl/gssftp/configure.in	2006-03-31 16:00:40.000000000 -0500
33695f3
+++ krb5-1.7/src/appl/gssftp/configure.in	2009-06-04 13:45:57.000000000 -0400
33695f3
@@ -17,6 +17,7 @@ DECLARE_SYS_ERRLIST
33695f3
 AC_REPLACE_FUNCS(getdtablesize)
33695f3
 AC_CHECK_FUNCS(getcwd getdtablesize getusershell seteuid setreuid setresuid strerror getenv)
33695f3
 AC_CHECK_LIB(crypt,crypt) dnl 
33695f3
+KRB5_WITH_PAM
33695f3
 KRB5_AC_LIBUTIL
33695f3
 dnl 
33695f3
 dnl copied from appl/bsd/configure.in
33695f3
diff -up krb5-1.7/src/appl/gssftp/ftpd/ftpd.c krb5-1.7/src/appl/gssftp/ftpd/ftpd.c
33695f3
--- krb5-1.7/src/appl/gssftp/ftpd/ftpd.c	2009-01-28 00:42:11.000000000 -0500
33695f3
+++ krb5-1.7/src/appl/gssftp/ftpd/ftpd.c	2009-06-04 13:45:57.000000000 -0400
33695f3
@@ -67,6 +67,9 @@ static char sccsid[] = "@(#)ftpd.c	5.40 
33695f3
 #ifdef HAVE_SHADOW
33695f3
 #include <shadow.h>
33695f3
 #endif
33695f3
+#ifdef USE_PAM
33695f3
+#include "../../bsd/pam.h"
33695f3
+#endif
33695f3
 #include <grp.h> 
33695f3
 #include <setjmp.h>
33695f3
 #ifndef POSIX_SETJMP
33695f3
@@ -745,6 +748,22 @@ user(name)
33695f3
 				name);
33695f3
 		}
33695f3
 #endif /* GSSAPI */
33695f3
+#ifdef USE_PAM
33695f3
+		if (appl_pam_enabled(kcontext, "ftpd")) {
33695f3
+			if (appl_pam_acct_mgmt(FTP_PAM_SERVICE, 0,
c94eeff
+					       name, "",
33695f3
+					       hostname,
33695f3
+					       NULL,
33695f3
+					       FTP_PAM_SERVICE) != 0) {
33695f3
+					       reply(530, "Login incorrect.");
33695f3
+				return;
33695f3
+			}
33695f3
+			if (appl_pam_requires_chauthtok()) {
33695f3
+				reply(530, "Password change required.");
33695f3
+				return;
33695f3
+			}
33695f3
+		}
33695f3
+#endif
33695f3
 
33695f3
 		if (!authorized && authlevel == AUTHLEVEL_AUTHORIZE) {
33695f3
 			strncat(buf, "; Access denied.",
33695f3
@@ -846,6 +865,10 @@ end_login()
33695f3
 	(void) krb5_seteuid((uid_t)0);
33695f3
 	if (logged_in)
33695f3
 		pty_logwtmp(ttyline, "", "");
33695f3
+#ifdef USE_PAM
33695f3
+	if (appl_pam_enabled(kcontext, "ftpd"))
33695f3
+		appl_pam_cleanup();
33695f3
+#endif
33695f3
 	if (have_creds) {
33695f3
 #ifdef GSSAPI
33695f3
 		krb5_cc_destroy(kcontext, ccache);
33695f3
@@ -954,9 +977,19 @@ pass(passwd)
33695f3
 		 *   kpass fails and the user has no local password
33695f3
 		 *   kpass fails and the provided password doesn't match pw
33695f3
 		 */
33695f3
-		if (pw == NULL || (!kpass(pw->pw_name, passwd) &&
33695f3
-				   (want_creds || !*pw->pw_passwd ||
33695f3
-				    strcmp(xpasswd, pw->pw_passwd)))) {
c94eeff
+		if ((pw == NULL) || (
33695f3
+#ifdef USE_PAM
33695f3
+		    appl_pam_enabled(kcontext, "ftpd") ?
33695f3
+		    (appl_pam_authenticate(FTP_PAM_SERVICE, 0,
33695f3
+					   pw->pw_name, passwd,
33695f3
+					   hostname,
33695f3
+					   NULL,
33695f3
+					   FTP_PAM_SERVICE) != 0) :
33695f3
+#endif
33695f3
+		    (!kpass(pw->pw_name, passwd) &&
33695f3
+		     (want_creds ||
33695f3
+		      !*pw->pw_passwd ||
c94eeff
+		      strcmp(xpasswd, pw->pw_passwd))))) {
33695f3
 			pw = NULL;
33695f3
 			sleep(5);
33695f3
 			if (++login_attempts >= 3) {
33695f3
@@ -973,6 +1006,23 @@ pass(passwd)
33695f3
 	}
33695f3
 	login_attempts = 0;		/* this time successful */
33695f3
 
33695f3
+#ifdef USE_PAM
33695f3
+	if (appl_pam_enabled(kcontext, "ftpd")) {
33695f3
+		if (appl_pam_acct_mgmt(FTP_PAM_SERVICE, 0,
33695f3
+				       pw->pw_name, passwd,
33695f3
+				       hostname,
33695f3
+				       NULL,
33695f3
+				       FTP_PAM_SERVICE) != 0) {
33695f3
+			reply(530, "Login incorrect.");
33695f3
+			return;
33695f3
+		}
33695f3
+		if (appl_pam_requires_chauthtok()) {
33695f3
+			reply(530, "Password change required.");
33695f3
+			return;
33695f3
+		}
33695f3
+	}
33695f3
+#endif
33695f3
+
33695f3
 	login(passwd, 0);
33695f3
 	return;
33695f3
 }
33695f3
@@ -988,6 +1038,18 @@ login(passwd, logincode)
33695f3
 		chown(ccname, pw->pw_uid, pw->pw_gid);
33695f3
 #endif
33695f3
 	}
33695f3
+#ifdef USE_PAM
33695f3
+	if (appl_pam_enabled(kcontext, "ftpd")) {
33695f3
+		if (appl_pam_session_open() != 0) {
33695f3
+			reply(550, "Can't open PAM session.");
33695f3
+			goto bad;
33695f3
+		}
33695f3
+		if (appl_pam_cred_init() != 0) {
33695f3
+			reply(550, "Can't establish PAM credentials.");
33695f3
+			goto bad;
33695f3
+		}
33695f3
+	}
33695f3
+#endif
33695f3
 
33695f3
 	(void) krb5_setegid((gid_t)pw->pw_gid);
33695f3
 	(void) initgroups(pw->pw_name, pw->pw_gid);
33695f3
@@ -1960,6 +2022,10 @@ dologout(status)
33695f3
 		krb5_cc_destroy(kcontext, ccache);
33695f3
 #endif
33695f3
 	}
33695f3
+#ifdef USE_PAM
33695f3
+	if (appl_pam_enabled(kcontext, "ftpd"))
33695f3
+		appl_pam_cleanup();
33695f3
+#endif
33695f3
 	/* beware of flushing buffers after a SIGPIPE */
33695f3
 	_exit(status);
33695f3
 }
33695f3
diff -up krb5-1.7/src/appl/gssftp/ftpd/Makefile.in krb5-1.7/src/appl/gssftp/ftpd/Makefile.in
33695f3
--- krb5-1.7/src/appl/gssftp/ftpd/Makefile.in	2009-01-05 15:27:53.000000000 -0500
33695f3
+++ krb5-1.7/src/appl/gssftp/ftpd/Makefile.in	2009-06-04 13:45:57.000000000 -0400
33695f3
@@ -14,23 +14,25 @@ SETENVOBJ=@SETENVOBJ@
33695f3
 LIBOBJS=@LIBOBJS@
33695f3
 COMERRLIB=$(BUILDTOP)/util/et/libcom_err.a
33695f3
 FTPD_LIBS=@FTPD_LIBS@
33695f3
+PAM_LIBS=@PAM_LIBS@
33695f3
 
33695f3
 SRCS	= $(srcdir)/ftpd.c ftpcmd.c $(srcdir)/popen.c \
33695f3
 	  $(srcdir)/vers.c \
33695f3
 	  $(srcdir)/../ftp/glob.c \
33695f3
 	  $(srcdir)/../ftp/radix.c \
33695f3
 	  $(srcdir)/../ftp/secure.c \
33695f3
+	  $(srcdir)/../../bsd/pam.c \
33695f3
 	  $(srcdir)/../../bsd/getdtablesize.c $(SETENVSRC)
33695f3
 
33695f3
 OBJS	= ftpd.o ftpcmd.o glob.o popen.o vers.o radix.o \
33695f3
-	  secure.o $(LIBOBJS) $(SETENVOBJ)
33695f3
+	  secure.o pam.o getdtablesize.o $(LIBOBJS) $(SETENVOBJ)
33695f3
 
33695f3
 LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)
33695f3
 
33695f3
 all::	ftpd
33695f3
 
33695f3
 ftpd:	$(OBJS) $(PTY_DEPLIB) $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
33695f3
-	$(CC_LINK) -o $@ $(OBJS) $(FTPD_LIBS) $(PTY_LIB) $(UTIL_LIB) $(GSS_LIBS) $(KRB5_BASE_LIBS)
33695f3
+	$(CC_LINK) -o $@ $(OBJS) $(FTPD_LIBS) $(PTY_LIB) $(UTIL_LIB) $(GSS_LIBS) $(KRB5_BASE_LIBS) $(PAM_LIBS)
33695f3
 
33695f3
 generate-files-mac: ftpcmd.c
33695f3
 
33695f3
@@ -62,6 +64,8 @@ secure.o: $(srcdir)/../ftp/secure.c
33695f3
 
33695f3
 getdtablesize.o: $(srcdir)/../../bsd/getdtablesize.c
33695f3
 	$(CC) -c $(ALL_CFLAGS) $(srcdir)/../../bsd/getdtablesize.c
33695f3
+pam.o: $(srcdir)/../../bsd/pam.c
33695f3
+	$(CC) -c $(ALL_CFLAGS) $(srcdir)/../../bsd/pam.c
33695f3
 
33695f3
 setenv.o: $(srcdir)/../../bsd/setenv.c
33695f3
 	$(CC) -c $(ALL_CFLAGS) $(srcdir)/../../bsd/setenv.c
33695f3
diff -up krb5-1.7/src/clients/ksu/main.c krb5-1.7/src/clients/ksu/main.c
33695f3
--- krb5-1.7/src/clients/ksu/main.c	2008-12-01 12:09:59.000000000 -0500
33695f3
+++ krb5-1.7/src/clients/ksu/main.c	2009-06-04 13:45:57.000000000 -0400
33695f3
@@ -25,6 +25,7 @@
33695f3
  * KSU was writen by:  Ari Medvinsky, ari@isi.edu
33695f3
  */
33695f3
 
33695f3
+#include "autoconf.h"
33695f3
 #include "ksu.h"
33695f3
 #include "adm_proto.h"
33695f3
 #include <sys/types.h>
a8aa409
@@ -32,6 +33,10 @@
33695f3
 #include <signal.h>
33695f3
 #include <grp.h>
33695f3
 
33695f3
+#ifdef USE_PAM
33695f3
+#include "../../appl/bsd/pam.h"
33695f3
+#endif
33695f3
+
33695f3
 /* globals */
33695f3
 char * prog_name;
33695f3
 int auth_debug =0;     
a8aa409
@@ -39,6 +44,7 @@
a8aa409
 char k5users_path[MAXPATHLEN];
a8aa409
 char * gb_err = NULL;
a8aa409
 int quiet = 0;
a8aa409
+int force_fork = 0;
a8aa409
 /***********/
a8aa409
 
a8aa409
 #define _DEF_CSH "/bin/csh" 
a8aa409
@@ -585,6 +591,25 @@
a8aa409
 	       prog_name,target_user,client_name,
a8aa409
 	       source_user,ontty());
a8aa409
 	
33695f3
+#ifdef USE_PAM
a8aa409
+	if (appl_pam_enabled(ksu_context, "ksu")) {
a8aa409
+	    if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL,
a8aa409
+				   NULL, source_user,
a8aa409
+				   ttyname(STDERR_FILENO)) != 0) {
a8aa409
+		fprintf(stderr, "Access denied for %s.\n", target_user);
a8aa409
+		sweep_up(ksu_context, cc_target);
a8aa409
+		exit(1);
a8aa409
+	    }
a8aa409
+	    if (appl_pam_requires_chauthtok()) {
a8aa409
+		fprintf(stderr, "Password change required for %s.\n",
a8aa409
+			target_user);
a8aa409
+		sweep_up(ksu_context, cc_target);
a8aa409
+		exit(1);
a8aa409
+	    }
a8aa409
+	    force_fork++;
33695f3
+	}
33695f3
+#endif
33695f3
+
a8aa409
 	/* Run authorization as target.*/
a8aa409
 	if (krb5_seteuid(target_uid)) {
a8aa409
 	    com_err(prog_name, errno, "while switching to target for authorization check");
02e9ad1
@@ -650,6 +675,26 @@
02e9ad1
 	    sweep_up(ksu_context, cc_target);
02e9ad1
 	    exit(1);
02e9ad1
 	}
33695f3
+#ifdef USE_PAM
02e9ad1
+    } else {
02e9ad1
+	/* we always do PAM account management, even for root */
33695f3
+	if (appl_pam_enabled(ksu_context, "ksu")) {
02e9ad1
+	    if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL,
02e9ad1
+				   NULL, source_user,
02e9ad1
+				   ttyname(STDERR_FILENO)) != 0) {
02e9ad1
+		fprintf(stderr, "Access denied for %s.\n", target_user);
33695f3
+		sweep_up(ksu_context, cc_target);
33695f3
+		exit(1);
33695f3
+	    }
02e9ad1
+	    if (appl_pam_requires_chauthtok()) {
02e9ad1
+		fprintf(stderr, "Password change required for %s.\n",
33695f3
+			target_user);
33695f3
+		sweep_up(ksu_context, cc_target);
33695f3
+		exit(1);
33695f3
+	    }
02e9ad1
+	    force_fork++;
02e9ad1
+	}
02e9ad1
+#endif
02e9ad1
     }
02e9ad1
     
02e9ad1
     if( some_rest_copy){ 
02e9ad1
@@ -719,6 +744,32 @@
02e9ad1
 	exit(1);
02e9ad1
     } 			
02e9ad1
     
02e9ad1
+#ifdef USE_PAM
02e9ad1
+    if (appl_pam_enabled(ksu_context, "ksu")) {
02e9ad1
+	if (appl_pam_session_open() != 0) {
02e9ad1
+	    fprintf(stderr, "Error opening session for %s.\n", target_user);
02e9ad1
+	    sweep_up(ksu_context, cc_target);
02e9ad1
+	    exit(1);
02e9ad1
+	}
33695f3
+#ifdef DEBUG
02e9ad1
+	if (auth_debug){
02e9ad1
+	    printf(" Opened PAM session.\n");
02e9ad1
+	}
33695f3
+#endif
02e9ad1
+	if (appl_pam_cred_init()) {
02e9ad1
+	    fprintf(stderr, "Error initializing credentials for %s.\n",
02e9ad1
+		    target_user);
02e9ad1
+	    sweep_up(ksu_context, cc_target);
02e9ad1
+	    exit(1);
02e9ad1
+	}
02e9ad1
+#ifdef DEBUG
02e9ad1
+	if (auth_debug){
02e9ad1
+	    printf(" Initialized PAM credentials.\n");
33695f3
+	}
33695f3
+#endif
02e9ad1
+    }
02e9ad1
+#endif
33695f3
+
02e9ad1
     /* set permissions */
02e9ad1
     if (setgid(target_pwd->pw_gid) < 0) {
02e9ad1
 	perror("ksu: setgid");
02e9ad1
@@ -791,7 +816,7 @@
02e9ad1
 	fprintf(stderr, "program to be execed %s\n",params[0]);
02e9ad1
     }
02e9ad1
     
02e9ad1
-    if( keep_target_cache ) {
02e9ad1
+    if( keep_target_cache && !force_fork ) {
02e9ad1
 	execv(params[0], params);
02e9ad1
 	com_err(prog_name, errno, "while trying to execv %s",
02e9ad1
 		params[0]);
a8aa409
@@ -822,15 +874,34 @@
33695f3
 	    if (ret_pid == -1) {
33695f3
 	    	com_err(prog_name, errno, "while calling waitpid");
33695f3
 	    }
33695f3
-	    sweep_up(ksu_context, cc_target);
33695f3
+	    if( !keep_target_cache ) {
33695f3
+	        sweep_up(ksu_context, cc_target);
33695f3
+	    }
33695f3
 	    exit (statusp);
33695f3
 	case -1:
33695f3
 	    com_err(prog_name, errno, "while trying to fork.");
33695f3
 	    sweep_up(ksu_context, cc_target);
33695f3
 	    exit (1);
33695f3
 	case 0:
33695f3
+#ifdef USE_PAM
33695f3
+	    if (appl_pam_enabled(ksu_context, "ksu")) {
33695f3
+		if (appl_pam_setenv() != 0) {
33695f3
+		    fprintf(stderr, "Error setting up environment for %s.\n",
33695f3
+			    target_user);
33695f3
+		    exit (1);
33695f3
+		}
33695f3
+#ifdef DEBUG
33695f3
+		if (auth_debug){
33695f3
+		    printf(" Set up PAM environment.\n");
33695f3
+		}
33695f3
+#endif
33695f3
+	    }
33695f3
+#endif
33695f3
 	    execv(params[0], params);
33695f3
 	    com_err(prog_name, errno, "while trying to execv %s", params[0]);
33695f3
+	    if( keep_target_cache ) {
33695f3
+	        sweep_up(ksu_context, cc_target);
33695f3
+	    }
33695f3
 	    exit (1);
33695f3
 	}
33695f3
     }
33695f3
diff -up krb5-1.7/src/clients/ksu/Makefile.in krb5-1.7/src/clients/ksu/Makefile.in
33695f3
--- krb5-1.7/src/clients/ksu/Makefile.in	2009-01-05 15:27:53.000000000 -0500
33695f3
+++ krb5-1.7/src/clients/ksu/Makefile.in	2009-06-04 13:45:57.000000000 -0400
33695f3
@@ -15,6 +15,7 @@ SRCS = \
33695f3
 	$(srcdir)/ccache.c \
33695f3
 	$(srcdir)/authorization.c \
33695f3
 	$(srcdir)/main.c \
33695f3
+	$(srcdir)/../../appl/bsd/pam.c \
33695f3
 	$(srcdir)/heuristic.c \
33695f3
 	$(srcdir)/xmalloc.c \
33695f3
 	$(srcdir)/setenv.c
33695f3
@@ -23,13 +24,17 @@ OBJS = \
33695f3
 	ccache.o \
33695f3
 	authorization.o \
33695f3
 	main.o \
33695f3
+	pam.o \
33695f3
 	heuristic.o \
33695f3
 	xmalloc.o @SETENVOBJ@
33695f3
 
33695f3
 all:: ksu
33695f3
 
33695f3
 ksu: $(OBJS) $(KRB5_BASE_DEPLIBS)
33695f3
-	$(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS)
33695f3
+	$(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS) $(PAM_LIBS)
33695f3
+
33695f3
+pam.o: $(srcdir)/../../appl/bsd/pam.c
33695f3
+	$(CC) $(ALL_CFLAGS) -c $<
33695f3
 
33695f3
 clean::
33695f3
 	$(RM) ksu
33695f3
diff -up krb5-1.7/src/config/pre.in krb5-1.7/src/config/pre.in
33695f3
--- krb5-1.7/src/config/pre.in	2009-04-15 16:06:35.000000000 -0400
33695f3
+++ krb5-1.7/src/config/pre.in	2009-06-04 13:45:57.000000000 -0400
33695f3
@@ -181,6 +181,7 @@ LD_UNRESOLVED_PREFIX = @LD_UNRESOLVED_PR
33695f3
 LD_SHLIBDIR_PREFIX = @LD_SHLIBDIR_PREFIX@
33695f3
 LDARGS = @LDARGS@
33695f3
 LIBS = @LIBS@
33695f3
+PAM_LIBS = @PAM_LIBS@
33695f3
 
33695f3
 INSTALL=@INSTALL@
33695f3
 INSTALL_STRIP=
33695f3
diff -up krb5-1.7/src/configure.in krb5-1.7/src/configure.in
33695f3
--- krb5-1.7/src/configure.in	2009-04-15 16:07:03.000000000 -0400
33695f3
+++ krb5-1.7/src/configure.in	2009-06-04 13:45:57.000000000 -0400
33695f3
@@ -1040,6 +1040,8 @@ fi
33695f3
 dnl
33695f3
 AC_CONFIG_SUBDIRS(appl/libpty appl/bsd appl/gssftp appl/telnet)
33695f3
 
33695f3
+KRB5_WITH_PAM
33695f3
+
33695f3
 AC_CONFIG_FILES(krb5-config, [chmod +x krb5-config])
33695f3
 V5_AC_OUTPUT_MAKEFILE(.
33695f3