diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/aclocal.m4 krb5-current/src/aclocal.m4
--- krb5-current-orig/src/aclocal.m4	2003-04-02 02:00:14.000000000 -0600
+++ krb5-current/src/aclocal.m4	2003-04-02 13:09:54.000000000 -0600
@@ -1304,6 +1304,54 @@
 ])
 dnl
 dnl
+dnl KRB5_AFS
+dnl
+AC_DEFUN(KRB5_AFS, [
+	AFS_LIBS=
+
+	AC_ARG_WITH([afs],
+[  --without-afs        don't have afs libraries to build against (default)
+  --with-afs=AFSDIR    use preinstalled AFS library tree],,with_afs=no)dnl
+	if test $with_afs != no; then
+		dnl allow a default dir
+		if test $with_afs = yes; then
+			with_afs=/usr/afsws
+		fi
+
+        AC_DEFINE(KRB5_AFS_SETPAG)
+        AFS_LIBS="$AFS_LIBS -L$with_afs/lib -L$with_afs/lib/afs"
+		AFS_LIBS="$AFS_LIBS -lauth -lsys -lrx -llwp -lafsutil"
+        # yes, -lsys is in there twice - it has to be due to transarc library
+        # weirdness
+
+		case $krb5_cv_host in
+		*-*-solaris*)
+			AFS_LIBS="$AFS_LIBS -lc -L/usr/ucblib -lucb -R/usr/ucblib"
+			;;
+		*-*-hpux11*)
+			AFS_LIBS="$AFS_LIBS -lBSD -lm -lnsl"
+			;;
+		*-*-hpux*)
+			AFS_LIBS="$AFS_LIBS -lBSD -lm"
+			;;
+		*-*-netbsd*)
+			AFS_LIBS="$AFS_LIBS -lcompat"
+			;;
+		esac
+	fi
+	AC_MSG_RESULT([Using AFS libs: $AFS_LIBS])
+	AC_SUBST(AFS_LIBS)
+
+	dnl
+	dnl Enable forcing login to always allocate a pag
+	AC_ARG_WITH([afs-setpag-always],
+	[  --with-afs-setpag-always    Always allocate a AFS PAG, even for root],[
+		AC_MSG_RESULT([Always allocate a AFS PAG, even for root])
+		AC_DEFINE(KRB5_AFS_SETPAG_ALWAYS)
+	])
+])
+dnl
+dnl
 dnl Check if we need the prototype for a function - we give it a bogus 
 dnl prototype and if it complains - then a valid prototype exists on the 
 dnl system.
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/bsd/configure.in krb5-current/src/appl/bsd/configure.in
--- krb5-current-orig/src/appl/bsd/configure.in	2003-03-03 02:00:14.000000000 -0600
+++ krb5-current/src/appl/bsd/configure.in	2003-04-02 13:09:54.000000000 -0600
@@ -1,14 +1,8 @@
 AC_INIT(krlogind.c)
 CONFIG_RULES
 LOGINLIBS=
-AC_ARG_WITH([afs],
-[  --without-afs        don't have afs libraries to build against (default)
-  --with-afs=AFSDIR    use preinstalled AFS library tree],
-,with_afs=no)dnl
-if test $with_afs != no; then
-	AC_DEFINE(SETPAG)
-	LOGINLIBS="$LOGINLIBS -L$with_afs/lib -L$with_afs/lib/afs -lauth -lsys -lrx -llwp"
-fi
+KRB5_AFS
+LOGINLIBS="$LOGINLIBS $AFS_LIBS"
 AC_PROG_INSTALL
 dnl dbm libs for use of an_to_ln
 AC_CHECK_LIB(util,main)
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/bsd/krcp.c krb5-current/src/appl/bsd/krcp.c
--- krb5-current-orig/src/appl/bsd/krcp.c	2001-12-07 02:00:47.000000000 -0600
+++ krb5-current/src/appl/bsd/krcp.c	2003-04-02 13:09:54.000000000 -0600
@@ -107,6 +107,8 @@
 int	response(void), hosteq(char *, char *), okname(char *), 
     susystem(char *);
 int	encryptflag = 0;
+int encrypt_option_flag = -1;
+int forward_flag = -1;
 
 #ifndef UCB_RCP
 #define	UCB_RCP	"/bin/rcp"
@@ -154,6 +156,7 @@
     char buf[RCP_BUFSIZ], cmdbuf[30];
     char *cmd = cmdbuf;
     struct servent *sp;
+	struct servent defaultservent;
     static char curhost[256];
 #ifdef POSIX_SIGNALS
     struct sigaction sa;
@@ -198,13 +201,16 @@
 	    port = htons(atoi(*argv));
 	    goto next_arg;
 
-	  case 'N':
+	  case 'n':
 	    forcenet++;
 	    break;
 
 #ifdef KERBEROS
 	  case 'x':
-	    encryptflag++;
+		encrypt_option_flag = 1;
+		break;
+	  case 'X':
+		encrypt_option_flag = 0;
 	    break;
 	  case 'k':		/* Change kerberos realm */
 	    argc--, argv++;
@@ -236,6 +242,20 @@
 	    }
 	    strcpy(krb_config, *argv);	
 	    goto next_arg;
+      case 'F':     /* Forward credentials */
+        if (forward_flag != -1) {
+        fprintf(stderr, "Cannot use both -F and -n.\n");
+        exit(1);
+        }
+        forward_flag = 1;
+        break;
+      case 'N':     /* Don't forward credentials */
+        if (forward_flag != -1) {
+        fprintf(stderr, "Cannot use both -F and -n.\n");
+        exit(1);
+        }
+        forward_flag = 0;
+        break;
 	  case 'P':
 	    if (!strcmp (*argv, "O"))
 		kcmd_proto = KCMD_OLD_PROTOCOL;
@@ -254,7 +274,7 @@
 	    iamremote = 1;
 	    rcmd_stream_init_normal();
 #if defined(KERBEROS)
-	    if (encryptflag)
+	    if (encryptflag || encrypt_option_flag == 1)
 	      answer_auth(krb_config, krb_cache);
 #endif /* KERBEROS */
 
@@ -266,7 +286,7 @@
 	    iamremote = 1;
 	    rcmd_stream_init_normal();
 #if defined(KERBEROS)
-	    if (encryptflag)
+	    if (encryptflag || encrypt_option_flag == 1)
 	      answer_auth(krb_config, krb_cache);
 #endif /* KERBEROS */
 
@@ -295,8 +315,8 @@
     
       if (sp == NULL) {
 #ifdef KERBEROS
-	fprintf(stderr, "rcp: kshell/tcp: unknown service\n");
-	try_normal(orig_argv);
+	sp = &defaultservent;
+	sp->s_port = htons(544);
 #else
 	fprintf(stderr, "rcp: shell/tcp: unknown service\n");
 	exit(1);
@@ -306,6 +326,31 @@
     }
 
 #ifdef KERBEROS
+    {
+    krb5_data realm;
+ 
+    if (krb_realm) {
+        realm.data = krb_realm;
+    } else {
+        krb5_get_default_realm(bsd_context, &realm.data);
+    }
+ 
+    if (encrypt_option_flag == -1) {
+        krb5_appdefault_boolean(bsd_context, "rcp", &realm, "encrypt",
+                    0, &encryptflag);
+    } else {
+        encryptflag = encrypt_option_flag;
+    }
+ 
+    if (forward_flag == -1) {
+        krb5_appdefault_boolean(bsd_context, "rcp", &realm, "forward",
+                    0, &forward_flag);
+    }
+ 
+    if (! krb_realm)
+        free(realm.data);
+    }
+
     if (krb_realm != NULL)
 	cmdsiz += strlen(krb_realm);
     if (krb_cache != NULL)
@@ -425,7 +470,8 @@
 				   cmd, targ);
 		    host = thost;
 #ifdef KERBEROS
-		    authopts = AP_OPTS_MUTUAL_REQUIRED;
+		    authopts = AP_OPTS_MUTUAL_REQUIRED | 
+				(forward_flag ? OPTS_FORWARD_CREDS : 0);
 		    status = kcmd(&sock, &host,
 				  port,
 				  pwd->pw_name,
@@ -556,7 +602,8 @@
 		}
 		(void) sprintf(buf, "%s -f %s", cmd, src);
 #ifdef KERBEROS
-		authopts = AP_OPTS_MUTUAL_REQUIRED;
+		authopts = AP_OPTS_MUTUAL_REQUIRED |
+			(forward_flag ? OPTS_FORWARD_CREDS : 0);
 		status = kcmd(&sock, &host,
 			      port,
 			      pwd->pw_name,  suser,
@@ -1252,7 +1299,7 @@
 {
 #ifdef KERBEROS
     fprintf(stderr,
-	    "Usage: \trcp [-PN | -PO] [-p] [-x] [-k realm] f1 f2; or:\n\trcp [-PN | -PO] [-r] [-p] [-x] [-k realm] f1 ... fn d2\n");
+	    "Usage: \trcp [-PN | -PO] [-p] [-x] [-X] [-k realm] f1 f2; or:\n\trcp [-PN | -PO] [-r] [-p] [-x] [-X] [-k realm] f1 ... fn d2\n");
 #else
     fputs("usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn d2\n", stderr);
 #endif
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/bsd/krlogin.c krb5-current/src/appl/bsd/krlogin.c
--- krb5-current-orig/src/appl/bsd/krlogin.c	2002-05-23 02:00:16.000000000 -0500
+++ krb5-current/src/appl/bsd/krlogin.c	2003-04-02 13:09:54.000000000 -0600
@@ -167,6 +167,8 @@
 void try_normal();
 char *krb_realm = (char *)0;
 int encrypt_flag = 0;
+int encrypt_option_flag = -1;
+int no_forward = 0;
 int fflag = 0, Fflag = 0;
 krb5_creds *cred;
 struct sockaddr_in local, foreign;
@@ -492,7 +494,12 @@
 	goto another;
     }
     if (argc > 0 && !strcmp(*argv, "-x")) {
-	encrypt_flag++;
+    encrypt_option_flag = 1;
+    argv++, argc--;
+    goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-X")) {
+    encrypt_option_flag = 0;
 	argv++, argc--;
 	goto another;
     }
@@ -514,6 +521,11 @@
 	argv++, argc--;
 	goto another;
     }
+    if (argc > 0 && !strcmp(*argv, "-N")) {
+	no_forward++;
+	argv++, argc--;
+	goto another;
+    }
     if (argc > 0 && !strcmp(*argv, "-PO")) {
 	kcmd_proto = KCMD_OLD_PROTOCOL;
 	argv++, argc--;
@@ -554,6 +566,25 @@
 	    com_err(argv[0], status, "while initializing krb5");
 	    exit(1);
     }
+
+    {
+        krb5_data realm;
+        int eflag;
+
+        if (krb_realm) {
+                realm.data = krb_realm;
+        } else {
+                krb5_get_default_realm(bsd_context, &realm.data);
+        }
+
+        krb5_appdefault_boolean(bsd_context, "rlogin", &realm, "encrypt", 0,
+                                &eflag);
+        
+        encrypt_flag = encrypt_option_flag == -1 ? eflag : encrypt_option_flag;
+
+        if (! krb_realm)
+                free(realm.data);
+    }
 #endif
 
 
@@ -654,6 +685,24 @@
 #ifdef KERBEROS
     authopts = AP_OPTS_MUTUAL_REQUIRED;
 
+	if (! (fflag || Fflag) && ! no_forward) {
+	krb5_data realm;
+
+	if (krb_realm) {
+		realm.data = krb_realm;
+	} else {
+		krb5_get_default_realm(bsd_context, &realm.data);
+	}
+
+	krb5_appdefault_boolean(bsd_context, "rlogin", &realm, "forward", 0,
+				&fflag);
+	krb5_appdefault_boolean(bsd_context, "rlogin", &realm, "forwardable", 0,
+				&Fflag);
+
+	if (! krb_realm)
+		free(realm.data);
+    }
+
     /* Piggy-back forwarding flags on top of authopts; */
     /* they will be reset in kcmd */
     if (fflag || Fflag)
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/bsd/krlogind.c krb5-current/src/appl/bsd/krlogind.c
--- krb5-current-orig/src/appl/bsd/krlogind.c	2003-03-05 02:00:16.000000000 -0600
+++ krb5-current/src/appl/bsd/krlogind.c	2003-04-02 13:09:54.000000000 -0600
@@ -107,6 +107,10 @@
  *              remote realms.
  *       Note:  Root logins are always logged.
  */
+#if 1 /* UMR_ONLY */
+#define LOG_ALL_LOGINS
+#define LOG_OTHER_USERS
+#endif
 
 /*
  * This is usually done in the Makefile.  Actually, these sources may
@@ -250,6 +254,7 @@
 
 int non_privileged = 0; /* set when connection is seen to be from */
 			/* a non-privileged port */
+int retain_ccache = 0;
 
 #ifdef KRB5_KRB4_COMPAT
 AUTH_DAT	*v4_kdata;
@@ -389,6 +394,9 @@
 		   error_message(status));
 	    exit(1);
     }
+
+    /* Blow away any KRB5CCNAME passed from inetd */
+    unsetenv("KRB5CCNAME");
 #endif
     
     /* Analyse parameters. */
@@ -1162,8 +1170,8 @@
 {
     pty_cleanup (line, pid, 1);
     shutdown(netf, 2);
-    if (ccache)
-	krb5_cc_destroy(bsd_context, ccache);
+    if (ccache && !retain_ccache)
+		krb5_cc_destroy(bsd_context, ccache);
     exit(1);
 }
 
@@ -1569,6 +1577,11 @@
 					  ticket, &ccache))) {
          fatal(netf, "Can't get forwarded credentials");
     }
+
+    krb5_appdefault_boolean(bsd_context, "rlogind",
+			   krb5_princ_realm(bsd_context, client),
+			   "retain_ccache", retain_ccache, &retain_ccache);
+
     return 0;
 }
 
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/bsd/krsh.c krb5-current/src/appl/bsd/krsh.c
--- krb5-current-orig/src/appl/bsd/krsh.c	2002-06-26 02:00:25.000000000 -0500
+++ krb5-current/src/appl/bsd/krsh.c	2003-04-02 13:09:54.000000000 -0600
@@ -102,6 +102,7 @@
 #endif
 
 int	encrypt_flag = 0;
+int	encrypt_option_flag = -1;
 char	*krb_realm = (char *)0;
 void	try_normal(char **);
 
@@ -149,6 +150,7 @@
     krb5_error_code status;
     krb5_auth_context auth_context;
     int fflag = 0, Fflag = 0;
+	int no_forward = 0;
 #ifdef KRB5_KRB4_COMPAT
     KTEXT_ST v4_ticket;
     MSG_DAT v4_msg_data;
@@ -215,7 +217,13 @@
      */
     if (argc > 0 && !strncmp(*argv, "-x", 2)) {
 	argv++, argc--;
+	encrypt_option_flag = 1;
+	goto another;
+    }
+    if (argc > 0 && !strncmp(*argv, "-X", 2)) {
+	argv++, argc--;
 	encrypt_flag++;
+	encrypt_option_flag = 0;
 	goto another;
     }
     if (argc > 0 && !strncmp(*argv, "-f", 2)) {
@@ -236,6 +244,11 @@
 	argv++, argc--;
 	goto another;
     }
+    if (argc > 0 && !strncmp(*argv, "-N", 2)) {
+	no_forward++;
+	argv++, argc--;
+	goto another;
+    }
     if (argc > 0 && !strncmp(*argv, "-A", 2)) {
 	argv++, argc--;
 	goto another;
@@ -316,6 +329,34 @@
 	fprintf(stderr, "who are you?\n");
 	exit(1);
     }
+
+#ifdef KERBEROS
+    status = krb5_init_context(&bsd_context);
+    if (status) {
+	    com_err(argv[0], status, "while initializing krb5");
+	    exit(1);
+    }
+
+    {
+	krb5_data realm;
+	int eflag;
+
+	if (krb_realm) {
+		realm.data = krb_realm;
+	} else {
+		krb5_get_default_realm(bsd_context, &realm.data);
+	}
+
+	krb5_appdefault_boolean(bsd_context, "rsh", &realm, "encrypt", 0,
+				&eflag);
+
+	encrypt_flag = encrypt_option_flag == -1 ? eflag : encrypt_option_flag;
+
+	if (! krb_realm)
+		free(realm.data);
+    }
+#endif
+
     cc = 0;
     for (ap = argv; *ap; ap++)
       cc += strlen(*ap) + 1;
@@ -354,13 +395,25 @@
     }
 
 #ifdef KERBEROS
-    status = krb5_init_context(&bsd_context);
-    if (status) {
-	    com_err(argv[0], status, "while initializing krb5");
-	    exit(1);
-    }
     authopts = AP_OPTS_MUTUAL_REQUIRED;
 
+    if (! (fflag || Fflag) && !no_forward) {
+	krb5_data realm;
+
+	if (krb_realm) {
+		realm.data = krb_realm;
+	} else {
+		krb5_get_default_realm(bsd_context, &realm.data);
+	}
+
+	krb5_appdefault_boolean(bsd_context, "rsh", &realm, "forward", 0,
+				&fflag);
+	krb5_appdefault_boolean(bsd_context, "rsh", &realm, "forwardable", 0,
+				&Fflag);
+	if (!krb_realm)
+		free(realm.data);
+    }
+
     /* Piggy-back forwarding flags on top of authopts; */
     /* they will be reset in kcmd */
     if (fflag || Fflag)
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/bsd/krshd.c krb5-current/src/appl/bsd/krshd.c
--- krb5-current-orig/src/appl/bsd/krshd.c	2003-01-02 02:00:12.000000000 -0600
+++ krb5-current/src/appl/bsd/krshd.c	2003-04-02 13:09:54.000000000 -0600
@@ -69,6 +69,10 @@
  *             three DEFINES.
  *       Note:  Root account access is always logged.
  */
+#if 1 /* UMR_ONLY */
+#define LOG_ALL_LOGINS
+#define LOG_OTHER_USERS
+#endif
      
 #define SERVE_NON_KRB     
 #define LOG_REMOTE_REALM
@@ -110,6 +114,7 @@
 #include <pwd.h>
 #include <ctype.h>
 #include <string.h>
+#include <setjmp.h>
 #include <libpty.h>
 #include <sys/wait.h>
      
@@ -211,6 +216,9 @@
 int maxhostlen = 0;
 int stripdomain = 1;
 int always_ip = 0;
+int retain_ccache = 0;
+int afs_retain_token = 0;
+int run_aklog = 0;
 
 static krb5_error_code recvauth(int netfd, struct sockaddr *peersin,
 				int *valid_checksum);
@@ -273,6 +281,77 @@
 }
 #endif
 
+typedef krb5_sigtype sigtype;
+
+#ifndef POSIX_SETJMP
+#undef sigjmp_buf
+#undef sigsetjmp
+#undef siglongjmp
+#define sigjmp_buf      jmp_buf
+#define sigsetjmp(j,s)  setjmp(j)
+#define siglongjmp      longjmp
+#endif
+
+#if !defined(SIGSYS) && defined(__linux__)
+/* Linux doesn't seem to have SIGSYS */
+#define SIGSYS        SIGUNUSED
+#endif
+
+#ifdef POSIX_SIGNALS
+typedef struct sigaction handler;
+#define handler_init(H,F)		(sigemptyset(&(H).sa_mask), \
+					 (H).sa_flags=0, \
+					 (H).sa_handler=(F))
+#define handler_swap(S,NEW,OLD)		sigaction(S, &NEW, &OLD)
+#define handler_set(S,OLD)		sigaction(S, &OLD, NULL)
+#else
+typedef sigtype (*handler)();
+#define handler_init(H,F)		((H) = (F))
+#define handler_swap(S,NEW,OLD)		((OLD) = signal ((S), (NEW)))
+#define handler_set(S,OLD)		(signal ((S), (OLD)))
+#endif
+
+#ifdef KRB5_AFS_SETPAG
+extern setpag(), ktc_ForgetAllTokens();
+
+static int pagflag = 0;
+
+static sigjmp_buf setpag_buf;
+
+static sigtype sigsys()
+{
+	siglongjmp(setpag_buf, 1);
+}
+
+static int try_afscall(scall)
+	int (*scall)();
+{
+	handler sa, osa;
+	volatile int retval = 0;
+
+	(void) &retval;
+	handler_init(sa, sigsys);
+	handler_swap(SIGSYS, sa, osa);
+	if (sigsetjmp(setpag_buf, 1) == 0) {
+	    (*scall)();
+	    retval = 1;
+	}
+	handler_set(SIGSYS, osa);
+	return retval;
+}
+
+#define try_setpag()	try_afscall(setpag)
+#define try_unlog()	try_afscall(ktc_ForgetAllTokens)
+#endif /* KRB5_AFS_SETPAG */
+
+static void
+afs_cleanup()
+{
+#ifdef KRB5_AFS_SETPAG
+    if (pagflag)
+	try_unlog();
+#endif /* KRB5_AFS_SETPAG */
+}
 
 int main(argc, argv)
      int argc;
@@ -316,6 +395,9 @@
 		   error_message(status));
 	    exit(1);
     }
+
+    /* Blow away any KRB5CCNAME passed from inetd */
+    unsetenv("KRB5CCNAME");
 #endif
     
     /* Analyze parameters. */
@@ -567,6 +649,7 @@
     syslog(LOG_INFO ,"Daemon terminated via signal %d.", signumber);
     if (ccache)
 	krb5_cc_destroy(bsd_context, ccache);
+	afs_cleanup();
     exit(0);
 }
 
@@ -1315,8 +1398,10 @@
 #endif
 	    /* Finish session in wmtp */
 	    pty_logwtmp(ttyn,"","");
-	    if (ccache)
-		krb5_cc_destroy(bsd_context, ccache);
+	    if (ccache && !retain_ccache)
+			krb5_cc_destroy(bsd_context, ccache);
+		if (!afs_retain_token)
+			afs_cleanup();
 	    exit(0);
 	}
 #if defined(HAVE_SETSID)&&(!defined(ULTRIX))
@@ -1365,6 +1450,11 @@
            because on some systems initgroups outputs an error message
            if not called by root.  */
         initgroups(pwd->pw_name, pwd->pw_gid);
+#ifdef KERBEROS
+#ifdef KRB5_AFS_SETPAG
+	    pagflag = try_setpag();
+#endif
+#endif
     }
 #endif
 #ifdef	HAVE_SETLUID
@@ -1471,6 +1561,31 @@
     environ = envinit;
     
 #ifdef KERBEROS
+    /*
+     * Since we have to run aklog as the user, _not_ root, we need to run
+     * it now (if we're supposed to.  Do The Right Thing if run_aklog is
+     * set
+     */
+   if (run_aklog) {
+	char *aklog_path;
+	struct stat st;
+
+	krb5_appdefault_string(bsd_context, "rshd",
+			       krb5_princ_realm(bsd_context, client),
+			       "krb5_aklog_path", KPROGDIR "/aklog",
+			       &aklog_path);
+		
+	/*
+	 * Make sure it exists before we try to run it
+	 */
+		
+	if (stat (aklog_path, &st) == 0) {
+	    system(aklog_path);
+	}
+
+	free(aklog_path);
+    }
+
     /* To make Kerberos rcp work correctly, we must ensure that we
        invoke Kerberos rcp on this end, not normal rcp, even if the
        shell startup files change PATH.  */
@@ -1526,6 +1641,7 @@
   signout_please:
     if (ccache)
 	krb5_cc_destroy(bsd_context, ccache);
+	afs_cleanup();
     ccache = NULL;
     pty_logwtmp(ttyn,"","");
     exit(1);
@@ -2009,6 +2125,26 @@
 		  error_message(errno));
 	    exit(1);
 	}
+	/*
+	 * Check our appdefaults profile entry to see if we're supposed to
+	 * run aklog.  If so, then just set "run_aklog" for later; we
+	 * need to run aklog as the user, not as root
+	 */
+	
+	krb5_appdefault_boolean(bsd_context, "rshd",
+				krb5_princ_realm(bsd_context, client),
+				"krb5_run_aklog", 0, &run_aklog);
+	
+	krb5_appdefault_boolean(bsd_context, "rshd",
+				krb5_princ_realm(bsd_context, client),
+				"retain_ccache", retain_ccache,
+				&retain_ccache);
+	
+	krb5_appdefault_boolean(bsd_context, "rshd",
+				krb5_princ_realm(bsd_context, client),
+				"afs_retain_token", afs_retain_token,
+				&afs_retain_token);
+
     }
     krb5_free_ticket(bsd_context, ticket);
     return 0;
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/bsd/login.c krb5-current/src/appl/bsd/login.c
--- krb5-current-orig/src/appl/bsd/login.c	2003-02-06 02:00:15.000000000 -0600
+++ krb5-current/src/appl/bsd/login.c	2003-04-02 13:09:54.000000000 -0600
@@ -36,15 +36,35 @@
    # use password to get v4 tickets
    krb4_convert = 0
    # use kerberos conversion daemon to get v4 tickets
-   krb_run_aklog = 0
+   krb4_run_aklog = 0
    # attempt to run aklog
    aklog_path = $(prefix)/bin/aklog
-   # where to find it [not yet implemented]
+   # where to find it
    accept_passwd = 0
    # don't accept plaintext passwords [not yet implemented]
+   forwardable = 0
+   # The initial TGT is forwardable
+   krb5_run_aklog = 0
+   # Run a Kerberos 5 aklog (doesn't need Kerberos 4 credentials)
+   krb5_aklog_path = $(prefix)/bin/aklog
+   # Path to Kerberos 5 aklog
+   default_lifetime = (null)
+   # Default ticket lifetime (10 hours)
+   retain_ccache = 0
+   # Don't destroy the credential cache upon logout
+   afs_retain_token = 0
+   # Don't destroy AFS tokens upon logout
+   check_quota = 1
+   # Run "quota" to check the user's disk quota
 */
 #define KRB5_GET_TICKETS
 int login_krb5_get_tickets = 1;
+int login_krb5_forwardable_tgt = 0;
+int login_krb5_run_aklog = 0;
+int login_krb5_retain_ccache = 0;
+char *login_krb5_aklog_path = 0;
+char *login_krb5_default_lifetime = 0;
+int login_afs_retain_token = 0;
 
 #ifdef KRB5_KRB4_COMPAT
 #define KRB4_GET_TICKETS
@@ -76,6 +96,15 @@
  * only one of: -r -h -k -K
  */
 
+#if 1 /* UMR_ONLY */
+#define NO_MOTD
+#define MO_MAILCHECK
+#define NO_LASTLOG
+#define NO_SLEEP
+#define NO_RETRY_LIMIT
+#define NO_ROOT_TERMINAL
+#endif
+
 #include <libpty.h>
 
 #ifdef HAVE_UNISTD_H
@@ -363,6 +392,10 @@
     {"krb4_convert", &login_krb4_convert},
     {"krb4_run_aklog", &login_krb_run_aklog},
 #endif /* KRB5_KRB4_COMPAT */
+    { "forwardable", &login_krb5_forwardable_tgt, },
+    { "krb5_run_aklog", &login_krb5_run_aklog, },
+    { "retain_ccache", &login_krb5_retain_ccache, },
+    { "afs_retain_token", &login_afs_retain_token, },
 };
 
 static char *conf_yes[] = {
@@ -375,6 +408,14 @@
     0
 };
 
+static struct login_conf_strings {
+    char *confname;
+    char **varname;
+} login_string_set[] = {
+    { "krb5_aklog_path", &login_krb5_aklog_path, },
+    { "default_lifetime", &login_krb5_default_lifetime, },
+};
+
 /* 1 = true, 0 = false, -1 = ambiguous */
 static int conf_affirmative(s)
      char *s;
@@ -408,36 +449,31 @@
      krb5_context k;
 {
     int i, max_i;
-    const char* kconf_names[3];
-    char **kconf_val;
     int retval;
+	krb5_data realm;
+	
+	krb5_get_default_realm(k, &realm.data);
 
     max_i = sizeof(login_conf_set)/sizeof(struct login_confs);
     for (i = 0; i<max_i; i++) {
-	kconf_names[0] = "login";
-	kconf_names[1] = login_conf_set[i].flagname;
-	kconf_names[2] = 0;
-	retval = profile_get_values(k->profile, 
-				    kconf_names, &kconf_val);
-	if (retval) {
-	    /* ignore most (all?) errors */
-	} else if (kconf_val && *kconf_val) {
-	    switch(conf_affirmative(*kconf_val)) {
-	    case 1:
-		*login_conf_set[i].flag = 1;
-		break;
-	    case 0:
-		*login_conf_set[i].flag = 0;
-		break;
-	    default:
-	    case -1:
-		com_err("login/kconf", 0,
-			"invalid flag value %s for flag %s",
-			*kconf_val, kconf_names[1]);
-		break;
-	    }
+		krb5_appdefault_boolean(k, "login", &realm,
+					login_conf_set[i].flagname,
+					*login_conf_set[i].flag,
+					login_conf_set[i].flag);
 	}
+
+	max_i = sizeof(login_string_set) / sizeof(struct login_conf_strings);
+	for (i = 0; i < max_i; i++) {
+		krb5_appdefault_string(k, "login", &realm,
+				       login_string_set[i].confname,
+				       "", login_string_set[i].varname);
+		if (!login_string_set[i].varname[0]) {
+			free(login_string_set[i].varname);
+			login_string_set[i].varname = NULL;
+		}
     }
+
+	free(realm.data);
 }
 
 /* UNIX password support */
@@ -522,14 +558,6 @@
 {
 #ifdef KRB5_GET_TICKETS
     krb5_error_code retval;
-    
-    retval = krb5_init_secure_context(&kcontext);
-    if (retval) {
-	com_err("login", retval, "while initializing krb5");
-	exit(1);
-    }
-
-    login_get_kconf(kcontext);
 
     /* Set up the credential cache environment variable */
     if (!getenv(KRB5_ENV_CCNAME)) {
@@ -542,6 +570,14 @@
 	strncpy(ccfile, getenv(KRB5_ENV_CCNAME), sizeof(ccfile));
 	ccfile[sizeof(ccfile) - 1] = '\0';
     }
+
+    retval = krb5_init_secure_context(&kcontext);
+    if (retval) {
+	com_err("login", retval, "while initializing krb5");
+	exit(1);
+    }
+
+    login_get_kconf(kcontext);
 #endif
 
 #ifdef KRB4_GET_TICKETS
@@ -598,6 +634,8 @@
 {
     krb5_error_code code;
     krb5_principal me;
+	krb5_get_init_creds_opt opt;
+	krb5_deltat lifetime;
 
     code = krb5_parse_name(kcontext, username, &me);
     if (code) {
@@ -607,9 +645,25 @@
 
     *me_p = me;
 
+    /*
+     * Use the lifetime from the profile if we were given one
+     */
+
+    if (login_krb5_default_lifetime && *login_krb5_default_lifetime) {
+       krb5_deltat tmplife;
+       if (! krb5_string_to_deltat(login_krb5_default_lifetime, &tmplife))
+	   lifetime = tmplife;
+    }
+
+	krb5_get_init_creds_opt_init(&opt);
+	krb5_get_init_creds_opt_set_tkt_life(&opt, lifetime);
+	
+	if (login_krb5_forwardable_tgt)
+		krb5_get_init_creds_opt_set_forwardable(&opt, 1);
+
     code = krb5_get_init_creds_password(kcontext, &my_creds, me, pass,
 					krb5_prompter_posix, NULL,
-					0, NULL, NULL);
+					0, NULL, &opt);
     if (code) {
 	if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
 	    fprintf (stderr,
@@ -890,7 +944,7 @@
 }
 
 /* AFS support routines */
-#ifdef SETPAG
+#ifdef KRB5_AFS_SETPAG
 
 int pagflag = 0;			/* true if setpag() has been called */
 
@@ -928,40 +982,97 @@
 #define try_setpag()	(setpag() == 0)
 #define try_unlog()	(ktc_ForgetAllTokens() == 0)
 #endif /* SIGSYS */
-#endif /* SETPAG */
+#endif /* KRB5_AFS_SETPAG */
+
+/*
+ * Since we have to allocate a PAG _before_ we fork, we need to move
+ * this into a separate function.
+ */
 
 static void
-afs_login ()
+krb_afs_setpag ()
 {
-#if defined(KRB4_GET_TICKETS) && defined(SETPAG)
-    if (login_krb4_get_tickets && pwd->pw_uid) {
-	/* Only reset the pag for non-root users. */
-	/* This allows root to become anything. */
+	/* Allocating a PAG isn't that harmful ... */
+#ifdef KRB5_AFS_SETPAG
+    if ( (
+#ifdef KRB4_GET_TICKETS
+	login_krb4_get_tickets
+#else /* KRB4_GET_TICKETS */
+	1
+#endif
+	||
+#ifdef KRB5_GET_TICKETS
+	login_krb5_get_tickets
+#else
+	1
+#endif /* KRB5_GET_TICKETS */
+#ifdef KRB5_AFS_SETPAG_ALWAYS
+	/* always get a pag, even for root */
+	) ) {
+#else
+	) && pwd->pw_uid) {
+#endif
+ 	/* Only reset the pag for non-root users. */
+ 	/* This allows root to become anything. */
 	pagflag = try_setpag ();
     }
-#endif
+#endif /* KRB5_AFS_SETPAG */
+}
+
+void
+krb_afs_login (me)
+        krb5_principal me;
+{
 #ifdef KRB_RUN_AKLOG
     if (got_v4_tickets && login_krb_run_aklog) {
-	/* KPROGDIR is $(prefix)/bin */
-	char aklog_path[MAXPATHLEN];
-	struct stat st;
-	/* construct the name */
-	/* get this from profile later */
-	aklog_path[sizeof(aklog_path) - 1] = '\0';
-	strncpy (aklog_path, KPROGDIR, sizeof(aklog_path) - 1);
-	strncat (aklog_path, "/aklog", sizeof(aklog_path) - 1 - strlen(aklog_path));
-	/* only run it if we can find it */
-	if (stat (aklog_path, &st) == 0) {
-	    system(aklog_path);
-	}
-    }
+        /* KPROGDIR is $(prefix)/bin */
+        char aklog_path[MAXPATHLEN];
+        struct stat st;
+        /* construct the name */
+        /* get this from profile later */
+        strcpy (aklog_path, KPROGDIR);
+        strcat (aklog_path, "/aklog");
+        /* only run it if we can find it */
+        if (stat (aklog_path, &st) == 0) {
+            system(aklog_path);
+        }
+    } else
 #endif /* KRB_RUN_AKLOG */
+#ifdef KRB5_GET_TICKETS
+    /*
+     * Note that we check to see if we have valid credentials already
+     * in place here (because we might have forwarded them)
+     */
+    if (login_krb5_run_aklog && (got_v5_tickets || have_v5_tickets(me))) {
+        /*
+         * Check the profile for a path to aklog, otherwise use the
+         * default of KPROGDIR
+         */
+        char aklog_path[MAXPATHLEN];
+        struct stat st;
+
+        if (login_krb5_aklog_path && *login_krb5_aklog_path) {
+                strcpy(aklog_path, login_krb5_aklog_path);
+        } else {
+                strcpy(aklog_path, KPROGDIR);
+                strcat(aklog_path, "/aklog");
+        }
+        /*
+         * Make sure it's there
+         */
+        if (stat (aklog_path, &st) == 0) {
+            system(aklog_path);
+        }
+    }
+#else
+        { }
+#endif /* KRB5_GET_TICKETS */
 }
 
 static void
-afs_cleanup ()
+krb_afs_cleanup ()
 {
-#ifdef SETPAG
+#ifdef KRB5_AFS_SETPAG
     if (pagflag)
       try_unlog ();
 #endif
@@ -1400,6 +1511,7 @@
 	    break;
 #endif /* OLD_PASSWD */
 	printf("Login incorrect\n");
+#ifndef NO_RETRY_LIMIT
 	if (++cnt >= 5) {
 	    log_repeated_failures (tty, hostname);
 	    /* irix has no tichpcl */
@@ -1408,6 +1520,7 @@
 #endif
 	    sleepexit(1);
 	}
+#endif
     } /* end of password retry loop */
 
     /* committed to login -- turn off timeout */
@@ -1454,14 +1567,6 @@
     }
 #endif
 
-    if (chdir(pwd->pw_dir) < 0) {
-	printf("No directory %s!\n", pwd->pw_dir);
-	if (chdir("/"))
-	    exit(0);
-	pwd->pw_dir = "/";
-	printf("Logging in with home = \"/\".\n");
-    }
-
     /* nothing else left to fail -- really log in */
     {
 	struct utmp utmp;
@@ -1476,6 +1581,17 @@
     quietlog = access(HUSHLOGIN, F_OK) == 0;
     dolastlog(hostname, quietlog, tty);
 
+    if (!hflag && !rflag && !kflag && !Kflag && !eflag) {	/* XXX */
+	static struct winsize win = { 0, 0, 0, 0 };
+
+	(void)ioctl(0, TIOCSWINSZ, (char *)&win);
+    }
+
+#if defined(sun)
+	/* Set owner/group/permissions of framebuffer devices */
+	(void) set_fb_attrs(ttyn, pwd->pw_uid, pwd->pw_gid);
+#endif
+
     (void)chown(ttyn, pwd->pw_uid,
 		(gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
 
@@ -1495,11 +1611,13 @@
 #endif
 
 #ifdef KRB5_GET_TICKETS
-    if (login_krb5_get_tickets)
+    if (login_krb5_get_tickets && 
+		(login_krb5_retain_ccache == 0 || login_afs_retain_token == 0))
 	dofork();
 #endif
 #ifdef KRB4_GET_TICKETS
-    else if (login_krb4_get_tickets)
+    else if (login_krb4_get_tickets &&
+		(login_krb5_retain_ccache == 0 || login_afs_retain_token == 0))
 	dofork();
 #endif
 
@@ -1515,15 +1633,30 @@
 
 	/* this will set the PGID to the PID. */
 #ifdef HAVE_SETPGID
-	if (setpgid(pid,pid) < 0)
-	    perror("login.krb5: setpgid");
+	   if (setpgid(pid,pid) < 0) {
+		/*
+		 * Ignore errors if we didn't fork, since we're probably
+		 * already a session leader
+		 */
+
+		if ((login_krb5_retain_ccache == 0) ||
+		    (login_afs_retain_token == 0))
+			perror("login.krb5: setpgid");
 #elif defined(SETPGRP_TWOARG)
-	if (setpgrp(pid,pid) < 0)
-	    perror("login.krb5: setpgrp");
+	   if (setpgrp(pid,pid) < 0) {
 #else
-	if (setpgrp() < 0)
-	    perror("login.krb5: setpgrp");
+       if (setpgrp() < 0) {
 #endif
+		/*
+		 * Ignore errors if we didn't fork, since we're probably
+		 * already a session leader
+		 */
+		
+        if ((login_krb5_retain_ccache == 0) ||
+            (login_afs_retain_token == 0))
+            perror("login.krb5: setpgrp");
+
+        }
 
 	/* This will cause SIGTTOU to be ignored for the duration
 	   of the TIOCSPGRP.  If this is not done, and the parent's
@@ -1557,6 +1690,8 @@
     (void) setgid((gid_t) pwd->pw_gid);
     (void) initgroups(username, pwd->pw_gid);
 
+    krb_afs_setpag();
+
     /*
      * The V5 ccache and V4 ticket file are both created as root.
      * They need to be owned by the user, and chown (a) assumes
@@ -1770,7 +1905,24 @@
     if (ccname)
 	setenv("KRB5CCNAME", ccname, 1);
 
+	krb_afs_login (me);
+
+	if (chdir(pwd->pw_dir) < 0) {
+		printf("No directory %s!\n", pwd->pw_dir);
+		if (chdir("/")) {
+			printf("cannot chdir to /!\n");
+			sleepexit(1);
+		}
+		pwd->pw_dir = "/";
+		printf("Logging in with home = \"/\".\n");
+	}
+
     setenv("HOME", pwd->pw_dir, 1);
+#ifdef LPATH_root
+	if (pwd->pw_uid == (uid_t) 0)
+	    setenv("PATH", LPATH_root, 1);
+	else
+#endif
     setenv("PATH", LPATH, 1);
     setenv("USER", pwd->pw_name, 1);
     setenv("SHELL", pwd->pw_shell, 1);
@@ -1839,8 +1991,12 @@
 		    syslog(LOG_NOTICE, "ROOT LOGIN %s", tty);
 		}
 	    }
-
-    afs_login();
+	else
+		if (hostname)
+			syslog(LOG_INFO, "%s login on %s from %s",
+			       pwd->pw_name, tty, hostname);
+		else
+			syslog(LOG_INFO, "%s login on %s", pwd->pw_name, tty);
 
     if (!quietlog) {
 #ifdef KRB4_KLOGIN
@@ -2025,8 +2181,38 @@
     register int ch;
     register char *p;
     static char nbuf[UT_NAMESIZE + 1];
+#ifdef solaris
+	char *ttyprompt = NULL;
+	static int firsttime = 1;
+#endif
+
+#ifdef sgi
+	/*
+	 * Seems to be a race condition in Irix that sometimes eats the
+	 * first character.  Write a null byte to fix this.
+	 */
+
+	putchar('\0');
+#endif
 
     for (;;) {
+#ifdef solaris
+		/*
+		 * getty prints 'login:' for us, so we want to avoid printing
+		 * it again. getty also sets the environment variable TTYPROMPT
+		 * so if it is present, don't print the login prompt.
+		 *
+		 * However, we only want to do this the first time through.
+		 */
+		ttyprompt = getenv("TTYPROMPT");
+		
+		if ((ttyprompt) && (*ttyprompt != '\0')) {
+			if (! firsttime)
+				printf("%s", ttyprompt);
+			else
+				firsttime = 0;
+		} else
+#endif /* solaris */
 	printf("login: ");
 	for (p = nbuf; (ch = getchar()) != '\n'; ) {
 	    if (ch == EOF)
@@ -2055,21 +2241,21 @@
     exit(0);
 }
 
-#ifndef HAVE_TTYENT_H
-int root_tty_security = 1;
-#endif
-
+#if !defined(NO_ROOT_TERMINAL) && defined(HAVE_TTYENT_H)
 int rootterm(tty)
 	char *tty;
 {
-#ifndef HAVE_TTYENT_H
-    return(root_tty_security);
-#else
     struct ttyent *t;
 
     return((t = getttynam(tty)) && t->ty_status&TTY_SECURE);
-#endif /* HAVE_TTYENT_H */
 }
+#else
+int rootterm(tty)
+	char *tty;
+{
+    return 1;
+}
+#endif
 
 #ifndef NO_MOTD
 sigjmp_buf motdinterrupt;
@@ -2136,6 +2322,7 @@
      int quiet;
      char *tty;
 {
+#ifndef NO_LASTLOG
 #if defined(HAVE_LASTLOG_H) || (defined(BSD) && (BSD >= 199103))
     struct lastlog ll;
     time_t lltime;
@@ -2176,6 +2363,7 @@
 	(void)close(fd);
     }
 #endif
+#endif
 }
 
 #undef	UNKNOWN
@@ -2342,7 +2530,9 @@
     if (login_krb4_get_tickets && krbflag)
 	(void) destroy_tickets();
 #endif /* KRB4_GET_TICKETS */
+#ifndef NO_SLEEP
     sleep((u_int)5);
+#endif
     exit(eval);
 }
 
@@ -2430,8 +2620,11 @@
     
     /* Cleanup stuff */
     /* Run destroy_tickets to destroy tickets */
-    (void) destroy_tickets();		/* If this fails, we lose quietly */
-    afs_cleanup ();
+    if (! login_krb5_retain_ccache)
+        (void) destroy_tickets();	/* If this fails, we lose quietly */
+
+    if (! login_afs_retain_token)
+	krb_afs_cleanup();
 #ifdef _IBMR2
     update_ref_count(-1);
 #endif
@@ -2507,3 +2700,136 @@
     enduserdb();
 }
 #endif
+
+#if defined(sun)
+/*
+ * set_fb_attrs -- change owner/group/permissions of framebuffers
+ *		   listed in /etc/fbtab.
+ *
+ * Note:
+ * Exiting from set_fb_attrs upon error is not advisable
+ * since it would disable logins on console devices.
+ *
+ * File format:
+ * console mode device_name[:device_name ...]
+ * # begins a comment and may appear anywhere on a line.
+ *
+ * Example:
+ * /dev/console 0660 /dev/fb:/dev/cgtwo0:/dev/bwtwo0
+ * /dev/console 0660 /dev/gpone0a:/dev/gpone0b
+ *
+ * Description:
+ * The example above sets the owner/group/permissions of the listed
+ * devices to uid/gid/0660 if ttyn is /dev/console
+ */
+
+#define	FIELD_DELIMS 	" \t\n"
+#define	COLON 		":"
+#define COLON_C         ':'
+#define WILDCARD        "/*"
+#define WILDCARD_LEN    2
+#define MAX_LINELEN     256
+#ifdef solaris
+#define FBTAB           "/etc/logindevperm"
+#else /* solaris */
+#define FBTAB           "/etc/fbtab"
+#endif /* solaris */
+
+
+set_fb_attrs(ttyn, uid, gid)
+	char *ttyn;
+	int uid;
+	int gid;
+{
+	char line[MAX_LINELEN];
+	char *console;
+	char *mode_str;
+	char *dev_list;
+	char *device;
+	char *ptr;
+	int  mode;
+	long strtol();
+	FILE *fp;
+
+	if ((fp = fopen(FBTAB, "r")) == NULL)
+		return;
+	while (fgets(line, MAX_LINELEN, fp)) {
+		if (ptr = strchr(line, '#'))
+			*ptr = '\0';	/* handle comments */
+		if ((console = strtok(line, FIELD_DELIMS)) == NULL)
+			continue;	/* ignore blank lines */
+		if (strcmp(console, ttyn) != 0)
+			continue;	/* ignore non-consoles */
+		mode_str = strtok((char *)NULL, FIELD_DELIMS);
+		if (mode_str == NULL) {
+			(void) fprintf(stderr, "%s: invalid entry -- %s\n",
+				FBTAB, line);
+			continue;
+		}
+		/* convert string to octal value */
+		mode = (int) strtol(mode_str, (char **)NULL, 8);
+		if (mode < 0 || mode > 0777) {
+			(void) fprintf(stderr, "%s: invalid mode -- %s\n",
+				FBTAB, mode_str);
+			continue;
+		}
+		dev_list = strtok((char *)NULL, FIELD_DELIMS);
+		if (dev_list == NULL) {
+			(void) fprintf(stderr, "%s: %s -- empty device list\n",
+				FBTAB, console);
+			continue;
+		}
+#ifdef solaris
+		device = strtok(dev_list, COLON);
+		while (device) {
+		    ptr = strstr(device, WILDCARD);
+		    if (ptr && 
+			(strlen(device) - (ptr - &device[0])) == WILDCARD_LEN){
+			/* The device was a (legally-specified) directory. */
+			DIR           *dev_dir;
+			struct dirent *dir_e;
+			char dev_file[MAXPATHLEN];
+			
+			*ptr = '\0'; /* Remove the wildcard from the dir name. */
+
+			if ((dev_dir = opendir(device)) == (DIR *) NULL) {
+			    syslog(LOG_ERR, "bad device %s%s in %s, ignored",
+				   device, WILDCARD, FBTAB);
+			    continue;
+			}
+			
+			/* Directory is open; alter its files. */
+			/* Must link with /usr/lib/libc.a before 
+			   /usr/ucblib/libucb.a or the d_name structs
+			   miss the first two characters of the filename */
+			while (dir_e = readdir(dev_dir)) {
+			    if (strcmp(dir_e->d_name, "..") &&
+				strcmp(dir_e->d_name, ".")) {
+				strcpy(dev_file, device);
+				strcat(dev_file, "/");
+				strcat(dev_file, dir_e->d_name);
+
+				(void) chown(dev_file, uid, gid);
+				(void) chmod(dev_file, mode);
+			    }
+			}
+			(void) closedir(dev_dir);
+		    } else {
+			/* 'device' was not a directory, so we can just do it. */
+			(void) chown(device, uid, gid);
+			(void) chmod(device, mode);
+		    }
+		    device = strtok((char *)NULL, COLON); /* Move thru list. */
+#else /* solaris */
+		device = strtok(dev_list, COLON);
+		while (device) {
+			(void) chown(device, uid, gid);
+			(void) chmod(device, mode);
+			device = strtok((char *)NULL, COLON);
+#endif /* solaris */
+		}
+	}
+	(void) fclose(fp);
+}
+#endif /* sun */
+
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/bsd/loginpaths.h krb5-current/src/appl/bsd/loginpaths.h
--- krb5-current-orig/src/appl/bsd/loginpaths.h	2002-03-07 02:00:38.000000000 -0600
+++ krb5-current/src/appl/bsd/loginpaths.h	2003-04-02 13:09:54.000000000 -0600
@@ -1,3 +1,8 @@
+#if 1 /* UMR_ONLY */
+#undef _PATH_DEFPATH
+#define _PATH_DEFPATH "/usr/bin:/bin:/sbin:/etc:/usr/sbin:/usr/etc"
+#endif
+
 /* here are actual path values from each operating system supported. */
 /* LPATH is from rlogin, for login.c; RPATH is from rsh, for rshd.c */
 #ifdef sun
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/gssftp/configure.in krb5-current/src/appl/gssftp/configure.in
--- krb5-current-orig/src/appl/gssftp/configure.in	2003-01-10 02:00:13.000000000 -0600
+++ krb5-current/src/appl/gssftp/configure.in	2003-04-02 13:09:54.000000000 -0600
@@ -75,6 +75,11 @@
 	;;
 esac
 dnl
+dnl check for afs
+dnl
+KRB5_AFS
+FTPD_LIBS="$FTPD_LIBS $AFS_LIBS"
+dnl
 dnl
 dnl
 AC_SUBST(FTPD_LIBS)
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/gssftp/ftp/ftp_var.h krb5-current/src/appl/gssftp/ftp/ftp_var.h
--- krb5-current-orig/src/appl/gssftp/ftp/ftp_var.h	2002-11-09 02:00:14.000000000 -0600
+++ krb5-current/src/appl/gssftp/ftp/ftp_var.h	2003-04-02 13:09:54.000000000 -0600
@@ -142,6 +142,10 @@
 
 extern int	options;	/* used during socket creation */
 
+#ifdef KERBEROS5
+extern int	forward;	/* Should we forward credentials? */
+#endif
+
 /*
  * Format of command table.
  */
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/gssftp/ftp/main.c krb5-current/src/appl/gssftp/ftp/main.c
--- krb5-current-orig/src/appl/gssftp/ftp/main.c	2002-11-09 02:00:14.000000000 -0600
+++ krb5-current/src/appl/gssftp/ftp/main.c	2003-04-02 13:09:54.000000000 -0600
@@ -96,6 +96,11 @@
 extern char realm[];
 #endif /* KRB5_KRB4_COMPAT */
 
+#ifdef KERBEROS5
+#include <krb5.h>
+#include <com_err.h>
+#endif
+
 static void cmdscanner (int);
 static char *slurpstring (void);
 
@@ -112,6 +117,12 @@
 #endif
 	char homedir[MAXPATHLEN];
 	char *progname = argv[0];
+#ifdef KERBEROS5
+	krb5_context context;
+	krb5_ccache ccache;
+	krb5_error_code code = 0;
+	krb5_principal princ = NULL;
+#endif
 
 #ifdef _WIN32
 	DWORD optionValue = SO_SYNCHRONOUS_NONALERT;
@@ -132,11 +143,39 @@
 	memcpy(&staticsp,sp,sizeof(struct servent));
 	sp = &staticsp;
 #endif /* KRB5_KRB4_COMPAT */
+
+	forward = 0;
+
+#ifdef KERBEROS5
+	krb5_init_context(&context);
+	krb5_init_ets(context);
+
+	/*
+	 * Forward credentials if we get a command-line flag or if we
+	 * have the right stuff set in the profile, _AND_ if our TGT
+	 * is forwardable
+	 */
+
+	if ((code = krb5_cc_default(context, &ccache)) != 0) {
+		com_err(argv[0], code, "while reading credential cache");
+	}
+
+	if ((code == 0) && 
+	    (code = krb5_cc_get_principal(context, ccache, &princ)) != 0) {
+		com_err(argv[0], code, "while getting primary principal");
+	}
+
+	if (code == 0) {
+		krb5_appdefault_boolean(context, "ftp",
+					krb5_princ_realm(context, princ),
+					"forward", 0, &forward);
+	}
+#endif /* KERBEROS5 */
+
 	doglob = 1;
 	interactive = 1;
 	autoauth = 1;
 	autologin = 1;
-	forward = 0;
 	autoencrypt = 0;
 	argc--, argv++;
 	while (argc > 0 && **argv == '-') {
@@ -188,6 +227,10 @@
 			case 'f':
 				forward = 1;
 				break;
+			
+			case 'F':
+				forward = 0;
+				break;
 
 			case 'x':
 				autoencrypt = 1;
@@ -204,6 +247,52 @@
 	nextopt:
 		argc--, argv++;
 	}
+
+#ifdef KERBEROS5
+
+	if (code != 0)
+		forward = 0;
+
+	if (forward) {
+		krb5_creds creds, mcreds;
+
+		creds.client = princ;
+		code = krb5_build_principal(context, &creds.server,
+					    krb5_princ_realm(context, princ)->length,
+					    krb5_princ_realm(context, princ)->data,
+					    "krbtgt",
+					    krb5_princ_realm(context, princ)->data, 0);
+		
+		if (code != 0) {
+			com_err(argv[0], code, "while building TGT principal");
+			forward = 0;
+		}
+
+		if (code == 0)
+			code = krb5_cc_retrieve_cred(context, ccache, 0,
+						     &creds, &mcreds);
+		
+		if (code == 0) {
+			krb5_free_principal(context, creds.server);
+
+			if ((mcreds.ticket_flags & TKT_FLG_FORWARDABLE) == 0)
+				forward = 0;
+			
+			krb5_free_cred_contents(context, &mcreds);
+		}
+
+		if (code != 0)
+			forward = 0;
+	}
+
+	krb5_cc_close(context, ccache);
+
+	if (princ)
+		krb5_free_principal(context, princ);
+	krb5_free_context(context);
+
+#endif /* KERBEROS5 */
+
 	fromatty = isatty(fileno(stdin));
 	if (fromatty)
 		verbose++;
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/gssftp/ftp/Makefile.in krb5-current/src/appl/gssftp/ftp/Makefile.in
--- krb5-current-orig/src/appl/gssftp/ftp/Makefile.in	2002-12-24 02:00:13.000000000 -0600
+++ krb5-current/src/appl/gssftp/ftp/Makefile.in	2003-04-02 13:09:54.000000000 -0600
@@ -5,7 +5,7 @@
 #
 # appl/gssftp/ftp/Makefile.in
 #
-DEFINES = -DGSSAPI -DFTP_BUFSIZ=10240
+DEFINES = -DGSSAPI -DFTP_BUFSIZ=10240 -DKERBEROS5
 PROG_LIBPATH=-L$(TOPLIBD)
 PROG_RPATH=$(KRB5_LIBDIR)
 
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/gssftp/ftpd/ftpd.c krb5-current/src/appl/gssftp/ftpd/ftpd.c
--- krb5-current-orig/src/appl/gssftp/ftpd/ftpd.c	2003-01-04 02:00:15.000000000 -0600
+++ krb5-current/src/appl/gssftp/ftpd/ftpd.c	2003-04-02 13:09:54.000000000 -0600
@@ -41,6 +41,10 @@
 static char sccsid[] = "@(#)ftpd.c	5.40 (Berkeley) 7/2/91";
 #endif /* not lint */
 
+#if 1 /* UMR_ONLY */
+#define NO_SLEEP
+#endif
+
 /*
  * FTP server.
  */
@@ -198,7 +202,7 @@
 int	maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
 int	logging;
 int	authlevel;
-int	want_creds;
+int	want_creds = 1; /* UMR - added =1 */
 int	guest;
 int	restricted;
 int	type;
@@ -828,8 +832,10 @@
 	 * Delay before reading passwd after first failed
 	 * attempt to slow down passwd-guessing programs.
 	 */
+#ifndef NO_SLEEP
 	if (login_attempts)
 		sleep((unsigned) login_attempts);
+#endif
 }
 
 /*
@@ -936,6 +942,8 @@
 #endif /* GSSAPI */
 #endif /* KRB5_KRB4_COMPAT */
 	char ccname[MAXPATHLEN];
+	char ccnameset[MAXPATHLEN];
+	int retval;
 
 #ifdef GSSAPI
 	memset((char *)&my_creds, 0, sizeof(my_creds));
@@ -944,6 +952,8 @@
 	my_creds.client = me;
 
 	sprintf(ccname, "FILE:/tmp/krb5cc_ftpd%ld", (long) getpid());
+	sprintf(ccnameset, "KRB5CCNAME=%s", ccname);
+	putenv(ccnameset);
 	if (krb5_cc_resolve(kcontext, ccname, &ccache))
 		return(0);
 	if (krb5_cc_initialize(kcontext, ccache, me))
@@ -965,12 +975,48 @@
 	my_creds.times.endtime = now + 60 * 60 * 10;
 	my_creds.times.renew_till = 0;
 
-	if (krb5_get_in_tkt_with_password(kcontext, 0,
+	if (retval = krb5_get_in_tkt_with_password(kcontext, 0,
 					  0, NULL, 0 /*preauth*/,
 					  passwd,
 					  ccache,
 					  &my_creds, 0))
+	{
+		syslog(LOG_ERR, "krb5_gitwp failed: %s", error_message(retval));
 		goto nuke_ccache;
+	}
+	else
+	{
+		int run_aklog = 0;
+
+/* this is all a hack for umr */
+		krb5_appdefault_boolean(kcontext, "ftpd",
+			krb5_princ_realm(kcontext, me),
+			"krb5_run_aklog", 0, &run_aklog);
+
+		if (run_aklog) {
+			char *aklog_path;
+			struct stat st;
+
+			krb5_appdefault_string(kcontext, "ftpd",
+                    			  krb5_princ_realm(kcontext, me),
+                    			  "krb5_aklog_path", KPROGDIR "/aklog",
+                    			  &aklog_path);
+
+			/*
+			* Make sure it exists before we try to run it
+			*/
+
+			if (stat (aklog_path, &st) == 0) {
+				setpag();
+				system(aklog_path);
+			}
+
+			free(aklog_path);
+		}
+
+		krb5_cc_destroy(kcontext, ccache);
+		return 1;
+	}
 
 	if (!want_creds) {
 		krb5_cc_destroy(kcontext, ccache);
@@ -1042,7 +1088,7 @@
 {
 	char *xpasswd, *salt;
 
-	if (authorized && !want_creds) {
+	if (authorized && !want_creds || have_creds ) {
 		reply(202, "PASS command superfluous.");
 		return;
 	}
@@ -1074,7 +1120,9 @@
 				   (want_creds || !*pw->pw_passwd ||
 				    strcmp(xpasswd, pw->pw_passwd)))) {
 			pw = NULL;
+#ifndef NO_SLEEP
 			sleep(5);
+#endif
 			if (++login_attempts >= 3) {
 				reply(421,
 				      "Login incorrect, closing connection.");
@@ -1363,7 +1411,9 @@
 			break;
 		if (errno != EADDRINUSE || tries > 10)
 			goto bad;
+#ifndef NO_SLEEP
 		sleep(tries);
+#endif
 	}
 	(void) krb5_seteuid((uid_t)pw->pw_uid);
 #ifdef IP_TOS
@@ -2894,6 +2944,7 @@
 	OM_uint32 major_status, minor_status;
 	krb5_principal me;
 	char ccname[MAXPATHLEN];
+	static char ccnameset[MAXPATHLEN];
 #ifdef KRB5_KRB4_COMPAT
 	krb5_principal kpcserver;
 	krb5_creds increds, *v5creds;
@@ -2905,6 +2956,8 @@
 		return;
 
 	sprintf(ccname, "FILE:/tmp/krb5cc_ftpd%ld", (long) getpid());
+	sprintf(ccnameset, "KRB5CCNAME=%s", ccname);
+	putenv(ccnameset);
 	if (krb5_cc_resolve(kcontext, ccname, &ccache))
 		return;
 	if (krb5_cc_initialize(kcontext, ccache, me))
@@ -2915,6 +2968,35 @@
 	if (major_status != GSS_S_COMPLETE)
 		goto cleanup;
 
+	{
+		int run_aklog = 0;
+
+		krb5_appdefault_boolean(kcontext, "ftpd",
+			krb5_princ_realm(kcontext, me),
+			"krb5_run_aklog", 0, &run_aklog);
+
+		if (run_aklog) {
+			char *aklog_path;
+			struct stat st;
+
+			krb5_appdefault_string(kcontext, "ftpd",
+                    			  krb5_princ_realm(kcontext, me),
+                    			  "krb5_aklog_path", KPROGDIR "/aklog",
+                    			  &aklog_path);
+
+			/*
+			* Make sure it exists before we try to run it
+			*/
+
+			if (stat (aklog_path, &st) == 0) {
+				setpag();
+				system(aklog_path);
+			}
+
+			free(aklog_path);
+		}
+	}
+
 #ifdef KRB5_KRB4_COMPAT
 	/* Convert krb5 creds to krb4 */
 
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/gssftp/ftpd/Makefile.in krb5-current/src/appl/gssftp/ftpd/Makefile.in
--- krb5-current-orig/src/appl/gssftp/ftpd/Makefile.in	2002-12-24 02:00:14.000000000 -0600
+++ krb5-current/src/appl/gssftp/ftpd/Makefile.in	2003-04-02 13:09:54.000000000 -0600
@@ -5,7 +5,7 @@
 #
 # appl/gssftp/ftpd/Makefile.in
 #
-DEFINES = -DGSSAPI -DFTP_BUFSIZ=10240 #-DNOCONFIDENTIAL
+DEFINES = -DGSSAPI -DFTP_BUFSIZ=10240 -DKPROGDIR=\"$(CLIENT_BINDIR)\" #-DNOCONFIDENTIAL
 PROG_LIBPATH=-L$(TOPLIBD)
 PROG_RPATH=$(KRB5_LIBDIR)
 
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/telnet/libtelnet/auth-proto.h krb5-current/src/appl/telnet/libtelnet/auth-proto.h
--- krb5-current-orig/src/appl/telnet/libtelnet/auth-proto.h	2002-11-16 02:00:16.000000000 -0600
+++ krb5-current/src/appl/telnet/libtelnet/auth-proto.h	2003-04-02 13:09:54.000000000 -0600
@@ -56,6 +56,9 @@
  * or implied warranty.
  */
 
+#ifndef LIBTELNET_AUTH_PROTO_H
+#define LIBTELNET_AUTH_PROTO_H
+
 #if	defined(AUTHENTICATION)
 Authenticator *findauthenticator (int, int);
 
@@ -101,6 +104,14 @@
 void kerberos5_reply (Authenticator *, unsigned char *, int);
 int kerberos5_status (Authenticator *, char *, int);
 void kerberos5_printsub (unsigned char *, int, unsigned char *, unsigned int);
+
+struct kerberos5_config_opts {
+        char    *optname;
+        int     *optvar;
+};
+
+void kerberos5_defaults (struct kerberos5_config_opts *);
 void kerberos5_cleanup (void);
 #endif
 #endif
+#endif
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/telnet/libtelnet/kerberos5.c krb5-current/src/appl/telnet/libtelnet/kerberos5.c
--- krb5-current-orig/src/appl/telnet/libtelnet/kerberos5.c	2003-04-02 02:00:19.000000000 -0600
+++ krb5-current/src/appl/telnet/libtelnet/kerberos5.c	2003-04-02 13:09:54.000000000 -0600
@@ -200,12 +200,20 @@
     krb5_error_code retval;
     krb5_ccache ccache;
     char *ccname;
+    krb5_data realm;
+    int retain_ccache = 0;
     
     if (telnet_context == 0)
 	return;
 
+    krb5_get_default_realm(telnet_context, &realm.data);
+ 
+    krb5_appdefault_boolean(telnet_context, "telnetd", &realm,
+			    "retain_ccache", retain_ccache, &retain_ccache);
+    free(realm.data);
+
     ccname = getenv("KRB5CCNAME");
-    if (ccname) {
+    if (ccname && !retain_ccache) {
 	retval = krb5_cc_resolve(telnet_context, ccname, &ccache);
 	if (!retval)
 	    retval = krb5_cc_destroy(telnet_context, ccache);
@@ -731,13 +739,20 @@
 	if (level < AUTH_USER)
 		return(level);
 
+	/*
+	* Always copy in UserNameRequested if the authentication
+	* is valid, because the higher level routines need it.
+	* the name buffer comes from telnetd/telnetd{-ktd}.c
+	*/
+	if (UserNameRequested) {
+		strncpy(name, UserNameRequested, 255);
+		name[255] = '\0';
+	}
+
 	if (UserNameRequested &&
 	    krb5_kuserok(telnet_context, ticket->enc_part2->client, 
 			 UserNameRequested))
 	{
-		/* the name buffer comes from telnetd/telnetd{-ktd}.c */
-		strncpy(name, UserNameRequested, 255);
-		name[255] = '\0';
 		return(AUTH_VALID);
 	} else
 		return(AUTH_USER);
@@ -888,4 +903,29 @@
 }
 #endif	/* FORWARD */
 
+void
+kerberos5_defaults(opts)
+	struct kerberos5_config_opts *opts;
+{
+	struct kerberos5_config_opts *opt;
+	krb5_data realm;
+
+	if (!telnet_context) {
+		krb5_init_context(&telnet_context);
+	}
+
+	if (! telnet_krb5_realm) {
+		krb5_get_default_realm(telnet_context, &realm.data);
+	} else {
+		realm.data = strdup(telnet_krb5_realm);
+	}
+
+	for (opt = opts; opt->optname != 0; opt++)
+		krb5_appdefault_boolean(telnet_context, "telnet", &realm,
+					opt->optname, *(opt->optvar),
+					opt->optvar);
+
+	free(realm.data);
+}
+
 #endif /* KRB5 */
Only in krb5-current/src/appl/telnet/libtelnet: kerberos5.c.orig
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/telnet/libtelnet/kerberos.c krb5-current/src/appl/telnet/libtelnet/kerberos.c
--- krb5-current-orig/src/appl/telnet/libtelnet/kerberos.c	2002-12-13 02:00:17.000000000 -0600
+++ krb5-current/src/appl/telnet/libtelnet/kerberos.c	2003-04-02 13:09:54.000000000 -0600
@@ -612,10 +612,17 @@
 	if (level < AUTH_USER)
 		return(level);
 
-	if (UserNameRequested && !kuserok(&adat, UserNameRequested)) {
+	/*
+	* Always copy in UserNameRequested if the authentication
+	* is valid, because the higher level routines need it.
+	*/
+	if (UserNameRequested) {
 		/* the name buffer comes from telnetd/telnetd{-ktd}.c */
 		strncpy(kname, UserNameRequested, 255);
 		name[255] = '\0';
+	}
+
+	if (UserNameRequested && !kuserok(&adat, UserNameRequested)) {
 		return(AUTH_VALID);
 	} else
 		return(AUTH_USER);
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/telnet/telnet/commands.c krb5-current/src/appl/telnet/telnet/commands.c
--- krb5-current-orig/src/appl/telnet/telnet/commands.c	2002-11-16 02:00:16.000000000 -0600
+++ krb5-current/src/appl/telnet/telnet/commands.c	2003-04-02 13:09:54.000000000 -0600
@@ -1761,24 +1761,7 @@
 			*cp = '=';
 		}
 	}
-	/*
-	 * Special case for DISPLAY variable.  If it is ":0.0" or
-	 * "unix:0.0", we have to get rid of "unix" and insert our
-	 * hostname.
-	 */
-	if ((ep = env_find("DISPLAY"))
-	    && ((*ep->value == ':')
-	        || (strncmp((char *)ep->value, "unix:", 5) == 0))) {
-		char hbuf[256+1];
-		char *cp2 = strchr((char *)ep->value, ':');
 
-		gethostname(hbuf, 256);
-		hbuf[256] = '\0';
-		cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1);
-		sprintf((char *)cp, "%s%s", hbuf, cp2);
-		free(ep->value);
-		ep->value = (unsigned char *)cp;
-	}
 	/*
 	 * If USER is not defined, but LOGNAME is, then add
 	 * USER with the value from LOGNAME.  By default, we
@@ -1788,8 +1771,67 @@
 		env_define((unsigned char *)"USER", ep->value);
 		env_unexport((unsigned char *)"USER");
 	}
-	env_export((unsigned char *)"DISPLAY");
 	env_export((unsigned char *)"PRINTER");
+
+	/* DISPLAY is done in the next function, which is called after the
+	socket to the remote host is opened */
+}
+
+	void
+env_update_display(sockfd)
+	int sockfd;
+{
+	register char *cp;
+	register struct env_lst *ep;
+    register struct hostent *hp = 0;
+    struct sockaddr_in sin;
+	int res;
+	int len;
+	int got_fqdn = 0;	
+
+	/*
+	 * Special case for DISPLAY variable.  If it is ":0.0" or
+	 * "unix:0.0", we have to get rid of "unix" and insert our
+	 * hostname (or FQDN if possible).
+	 */
+	if ((ep = env_find("DISPLAY"))
+	    && ((*ep->value == ':')
+	        || (strncmp((char *)ep->value, "unix:", 5) == 0))) {
+
+		char *cp2 = strchr((char *)ep->value, ':');
+
+		/* attempt to look up local host name based on socket address */
+		memset((char *)&sin, 0, sizeof(sin));
+		res = getsockname(sockfd, (struct sockaddr *) &sin, &len);
+		if ( !res ) {
+			if ( sin.sin_addr.s_addr != inet_addr("127.0.0.1") ) {
+				hp = gethostbyaddr((char *) &sin.sin_addr, 
+					sizeof(struct in_addr), sin.sin_family);
+			
+				if ( hp )
+				{
+	                cp = (char *)malloc(strlen(hp->h_name) +
+                                   strlen(cp2) + 1);
+	                sprintf((char *)cp, "%s%s", hp->h_name, cp2);
+	                free(ep->value);
+	                ep->value = (unsigned char *)cp;
+					got_fqdn = 1;
+				}
+			}
+		}
+
+		if ( !got_fqdn ) { /* fall back to using local hostname */
+			char hbuf[256+1];
+
+			gethostname(hbuf, 256);
+			hbuf[256] = '\0';
+			cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1);
+			sprintf((char *)cp, "%s%s", hbuf, cp2);
+			free(ep->value);
+			ep->value = (unsigned char *)cp;
+		}
+	}
+	env_export((unsigned char *)"DISPLAY");
 }
 
 	struct env_lst *
@@ -2640,6 +2682,10 @@
 	}
 	connected++;
 
+	/* update the DISPLAY using the actual socket address instead of
+		possible bogus local host name */
+	env_update_display(net);
+
 #if	defined(AUTHENTICATION) || defined(ENCRYPTION)
 	auth_encrypt_connect(connected);
 #endif	/* defined(AUTHENTICATION) || defined(ENCRYPTION) */
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/telnet/telnet/main.c krb5-current/src/appl/telnet/telnet/main.c
--- krb5-current-orig/src/appl/telnet/telnet/main.c	2002-11-16 02:00:17.000000000 -0600
+++ krb5-current/src/appl/telnet/telnet/main.c	2003-04-02 13:09:54.000000000 -0600
@@ -88,7 +88,7 @@
 	    prompt,
 #ifdef	AUTHENTICATION
 	    " [-8] [-E] [-K] [-L] [-X atype] [-a] [-d] [-e char] [-k realm]",
-	    "\n\t[-l user] [-f/-F] [-n tracefile] ",
+	    "\n\t[-l user] [-f/-F/-N] [-n tracefile] ",
 #else
 	    " [-8] [-E] [-L] [-a] [-d] [-e char] [-l user] [-n tracefile]",
 	    "\n\t",
@@ -103,7 +103,7 @@
 	    "[-r] ",
 #endif
 #ifdef	ENCRYPTION
-	    "[-x] [host-name [port]]"
+	    "[-x/-p] [host-name [port]]"
 #else
 	    "[host-name [port]]"
 #endif
@@ -128,12 +128,33 @@
 	int ch;
 	char *user;
 #ifdef	FORWARD
+	int forward = 0;
+	int forwardable = 0;
 	extern int forward_flags;
 #endif	/* FORWARD */
 #ifdef ENCRYPTION
+	int encrypt = 0;
 	extern int auth_enable_encrypt;
 #endif /* ENCRYPTION */
 
+#if defined(KRB5)
+	struct kerberos5_config_opts krb5_opts[] = {
+		{ "forward", NULL, },
+		{ "forwardable", NULL, },
+		{ "encrypt", NULL, },
+		{ "autologin", NULL, },
+		{ "forceencrypt", NULL, },
+		{ NULL, NULL, }
+	};
+	/* weird, used to work before */
+	krb5_opts[0].optvar = &forward;
+	krb5_opts[1].optvar = &forwardable;
+	krb5_opts[2].optvar = &encrypt;
+	krb5_opts[3].optvar = &autologin;
+	krb5_opts[4].optvar = &wantencryption;
+#endif
+
+
 	tninit();		/* Clear out things */
 #if	defined(CRAY) && !defined(__STDC__)
 	_setlist_init();	/* Work around compiler bug */
@@ -151,7 +172,11 @@
 	rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
 	autologin = -1;
 
-	while ((ch = getopt(argc, argv, "8EKLS:X:acde:fFk:l:n:rt:x")) != -1) {
+#if defined(KRB5)
+	kerberos5_defaults(krb5_opts);
+#endif
+
+	while ((ch = getopt(argc, argv, "8EKLS:X:acde:fFNk:l:n:rt:xp")) != -1) {
 		switch(ch) {
 		case '8':
 			eight = 3;	/* binary output and input */
@@ -205,13 +230,7 @@
 			break;
 		case 'f':
 #if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
-			if (forward_flags & OPTS_FORWARD_CREDS) {
-			    fprintf(stderr, 
-				    "%s: Only one of -f and -F allowed.\n",
-				    prompt);
-			    usage();
-			}
-			forward_flags |= OPTS_FORWARD_CREDS;
+			forward = 1;
 #else
 			fprintf(stderr,
 			 "%s: Warning: -f ignored, no Kerberos V5 support.\n", 
@@ -220,20 +239,23 @@
 			break;
 		case 'F':
 #if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
-			if (forward_flags & OPTS_FORWARD_CREDS) {
-			    fprintf(stderr, 
-				    "%s: Only one of -f and -F allowed.\n",
-				    prompt);
-			    usage();
-			}
-			forward_flags |= OPTS_FORWARD_CREDS;
-			forward_flags |= OPTS_FORWARDABLE_CREDS;
+			forwardable = 1;
 #else
 			fprintf(stderr,
 			 "%s: Warning: -F ignored, no Kerberos V5 support.\n", 
 				prompt);
 #endif
 			break;
+		case 'N':
+#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
+			forward = 0;
+			forwardable = 0;
+#else
+			fprintf(stderr,
+			 "%s: Warning: -N ignored, no Kerberos V5 support.\n", 
+				prompt);
+#endif
+			break;
 		case 'k':
 #if defined(AUTHENTICATION) && defined(KRB4)
 		    {
@@ -293,23 +315,49 @@
 			break;
 		case 'x':
 #ifdef	ENCRYPTION
-			encrypt_auto(1);
-			decrypt_auto(1);
 			wantencryption = 1;
-			autologin = 1;
-			auth_enable_encrypt = 1;
 #else
 			fprintf(stderr,
 			    "%s: Warning: -x ignored, no ENCRYPT support.\n",
 								prompt);
 #endif
 			break;
+		case 'p':
+#ifdef	ENCRYPTION
+			encrypt = 0;
+			wantencryption = 0;
+#else
+			fprintf(stderr,
+			    "%s: Warning: -p ignored, no ENCRYPT support.\n",
+								prompt);
+#endif
+			break;
 		case '?':
 		default:
 			usage();
 			/* NOTREACHED */
 		}
 	}
+
+	/* Set up ticket forwarding */
+#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
+	if ( forward )
+		forward_flags |= OPTS_FORWARD_CREDS;
+	if ( forwardable ) {
+		forward_flags |= OPTS_FORWARD_CREDS;
+		forward_flags |= OPTS_FORWARDABLE_CREDS;
+	}
+#endif
+
+#if defined(ENCRYPTION)
+	if ( encrypt || wantencryption ) {
+		autologin = 1;
+		encrypt_auto(1);
+		decrypt_auto(1);
+		auth_enable_encrypt = 1;
+	}
+#endif
+
 	if (autologin == -1)
 		autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1;
 
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/telnet/telnet/telnet.0.txt krb5-current/src/appl/telnet/telnet/telnet.0.txt
--- krb5-current-orig/src/appl/telnet/telnet/telnet.0.txt	2000-01-20 20:12:01.000000000 -0600
+++ krb5-current/src/appl/telnet/telnet/telnet.0.txt	2003-04-02 13:09:54.000000000 -0600
@@ -4,8 +4,8 @@
      tteellnneett - user interface to the TELNET protocol
 
 SSYYNNOOPPSSIISS
-     tteellnneett [--88] [--EE] [--FF] [--KK] [--LL] [--SS _t_o_s] [--XX _a_u_t_h_t_y_p_e] [--aa] [--cc] [--dd] [--ee
-            _e_s_c_a_p_e_c_h_a_r] [--ff] [--kk _r_e_a_l_m] [--ll _u_s_e_r] [--nn _t_r_a_c_e_f_i_l_e] [--rr] [--xx]
+     tteellnneett [--88] [--EE] [--FF] [--KK] [--LL] [--NN] [--SS _t_o_s] [--XX _a_u_t_h_t_y_p_e] [--aa] [--cc] [--dd] [--ee
+            _e_s_c_a_p_e_c_h_a_r] [--ff] [--kk _r_e_a_l_m] [--ll _u_s_e_r] [--nn _t_r_a_c_e_f_i_l_e] [--rr] [--xx--pp]
             [_h_o_s_t [port]]
 
 DDEESSCCRRIIPPTTIIOONN
@@ -32,6 +32,8 @@
      --LL      Specifies an 8-bit data path on output.  This causes the BINARY
              option to be negotiated on output.
 
+     --NL      Disables any ticket forwarding.
+
      --SS _t_o_s  Sets the IP type-of-service (TOS) option for the telnet connec-
              tion to the value _t_o_s_, which can be a numeric TOS value or, on
              systems that support it, a symbolic TOS name found in the
@@ -77,6 +79,8 @@
              Opens _t_r_a_c_e_f_i_l_e for recording trace information.  See the sseett
              ttrraacceeffiillee command below.
 
+     --pp      Force plaintext/non-encrypted connection.
+
      --rr      Specifies a user interface similar to rlogin(1).  In this mode,
              the escape character is set to the tilde (~) character, unless
              modified by the -e option.
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/telnet/telnet/telnet.1 krb5-current/src/appl/telnet/telnet/telnet.1
--- krb5-current-orig/src/appl/telnet/telnet/telnet.1	2000-01-20 20:12:01.000000000 -0600
+++ krb5-current/src/appl/telnet/telnet/telnet.1	2003-04-02 13:09:54.000000000 -0600
@@ -40,7 +40,7 @@
 \fItos\fP] [\fB\-X\fP \fIauthtype\fP] [\fB\-a\fP] [\fB\-c\fP]
 [\fB\-d\fP] [\fB\-e\fP \fIescapechar\fP] [\fB\-f\fP] [\fB\-k\fP
 \fIrealm\fP] [\fB\-l\fP \fIuser\fP] [\fB\-n\fP \fItracefile\fP]
-[\fB\-r\fP] [\fB\-x\fP] [\fIhost\fP [\fIport\fP]]
+[\fB\-r\fP] [\fB\-x/-p\fP] [\fIhost\fP [\fIport\fP]]
 .SH DESCRIPTION
 The 
 .B telnet
@@ -78,6 +78,9 @@
 Specify an 8-bit data path on output.  This causes the BINARY option to
 be negotiated on output.
 .TP
+.B \-N
+Disable any ticket forwarding.
+.TP
 \fB\-S\fP \fItos\fP
 Set the IP type-of-service (TOS) option for the telnet connection to the
 value
@@ -146,6 +149,9 @@
 .B open
 command.
 .TP
+.B \-p
+Force plaintext/non-encrypted connection
+.TP
 \fB\-n\fP \fItracefile\fP
 Open
 .I tracefile
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/telnet/telnet/telnet.c krb5-current/src/appl/telnet/telnet/telnet.c
--- krb5-current-orig/src/appl/telnet/telnet/telnet.c	2002-11-16 02:00:17.000000000 -0600
+++ krb5-current/src/appl/telnet/telnet/telnet.c	2003-04-02 13:09:54.000000000 -0600
@@ -1044,11 +1044,15 @@
 		case ENCRYPT_START:
 			if (my_want_state_is_dont(TELOPT_ENCRYPT))
 				return;
+			if ( ! encrypt_is_encrypting() )
+				printf("Encrypted session established.\n");
 			encrypt_start(subpointer, SB_LEN());
 			break;
 		case ENCRYPT_END:
 			if (my_want_state_is_dont(TELOPT_ENCRYPT))
 				return;
+			if ( encrypt_is_encrypting() )
+				printf("Session encryption terminated.\n");
 			encrypt_end();
 			break;
 		case ENCRYPT_SUPPORT:
@@ -2300,17 +2304,17 @@
     }
 #endif	/* defined(AUTHENTICATION) || defined(ENCRYPTION)  */
 #   if !defined(TN3270)
+    if (telnetport) {
 #if	defined(AUTHENTICATION)
     if (autologin)
 	send_will(TELOPT_AUTHENTICATION, 1);
 #endif
 #ifdef	ENCRYPTION
-    if (telnetport || wantencryption) {
+    if (wantencryption) {
 	send_do(TELOPT_ENCRYPT, 1);
 	send_will(TELOPT_ENCRYPT, 1);
     }
 #endif	/* ENCRYPTION */
-    if (telnetport) {
 	send_do(TELOPT_SGA, 1);
 	send_will(TELOPT_TTYPE, 1);
 	send_will(TELOPT_NAWS, 1);
@@ -2364,6 +2368,7 @@
 	    if (printed_encrypt == 0) {
 		    printed_encrypt = 1;
 		    printf("Waiting for encryption to be negotiated...\n");
+		    fflush(stdout);
 		    /*
 		     * Turn on MODE_TRAPSIG and then turn off localchars 
 		     * so that ^C will cause telnet to exit.
@@ -2378,7 +2383,7 @@
 	    telnet_spin();
 	}
 	if (printed_encrypt) {
-		printf("done.\n");
+		/* removed message here, since lower level msg does it */
 		intr_waiting = 0;
 		setconnmode(0);
 	}
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/telnet/telnetd/sys_term.c krb5-current/src/appl/telnet/telnetd/sys_term.c
--- krb5-current-orig/src/appl/telnet/telnetd/sys_term.c	2002-11-16 02:00:17.000000000 -0600
+++ krb5-current/src/appl/telnet/telnetd/sys_term.c	2003-04-02 13:09:54.000000000 -0600
@@ -1402,6 +1402,10 @@
 		close(pty);
 #endif
 	closelog();
+#if defined(AUTHENTICATION)
+	if ( autologin != AUTH_VALID )
+		kerberos5_cleanup();
+#endif
 	execv(login_program, argv);
 
 	syslog(LOG_ERR, "%s: %m", login_program);
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/appl/telnet/telnetd/telnetd.c krb5-current/src/appl/telnet/telnetd/telnetd.c
--- krb5-current-orig/src/appl/telnet/telnetd/telnetd.c	2003-01-10 02:00:17.000000000 -0600
+++ krb5-current/src/appl/telnet/telnetd/telnetd.c	2003-04-02 13:09:54.000000000 -0600
@@ -31,6 +31,10 @@
  * SUCH DAMAGE.
  */
 
+#if 1 /* UMR_ONLY */
+#define VAGUE_TELNETD_BANNER
+#endif
+
 #ifndef lint
 static char copyright[] =
 "@(#) Copyright (c) 1989, 1993\n\
@@ -200,6 +204,7 @@
 	struct utsname name;
 	static char banner[1024];
 	
+#ifndef VAGUE_TELNETD_BANNER
 	if (uname(&name) < 0)
 		sprintf(banner, "\r\nError getting hostname: %s\r\n",
 		    strerror(errno));
@@ -212,6 +217,10 @@
 		    name.sysname, name.release, name.version);
 #endif
 	}
+#else
+	sprintf(banner, "\r\nKerberos Login (%%h) (%%t)\r\n\r\n");
+#endif
+
 	return banner;
 }
 
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/clients/configure.in krb5-current/src/clients/configure.in
--- krb5-current-orig/src/clients/configure.in	2003-01-10 02:00:18.000000000 -0600
+++ krb5-current/src/clients/configure.in	2003-04-02 13:09:54.000000000 -0600
@@ -11,7 +11,7 @@
   SETENVOBJ=
 fi
 AC_SUBST(SETENVOBJ)
-AC_CHECK_HEADERS(unistd.h pwd.h arpa/inet.h)
+AC_CHECK_HEADERS(unistd.h pwd.h arpa/inet.h sys/stat.h)
 case $krb5_cv_host in
 alpha*-dec-osf*)
 	AC_CHECK_LIB(security,setluid,
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/clients/kinit/kinit.c krb5-current/src/clients/kinit/kinit.c
--- krb5-current-orig/src/clients/kinit/kinit.c	2002-11-06 02:00:23.000000000 -0600
+++ krb5-current/src/clients/kinit/kinit.c	2003-04-02 13:09:54.000000000 -0600
@@ -38,6 +38,10 @@
 #include <stdio.h>
 #include <time.h>
 
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
 #ifdef GETOPT_LONG
 #include <getopt.h>
 #else
@@ -131,10 +135,12 @@
     int forwardable;
     int proxiable;
     int addresses;
+	int run_aklog;
 
     int not_forwardable;
     int not_proxiable;
     int no_addresses;
+	int not_run_aklog;
 
     int verbose;
 
@@ -339,6 +345,12 @@
 		    opts->starttime = abs_starttime - time(0);
 		}
 	    }
+		if ( opts->run_aklog )
+		{
+			fprintf(stderr, "Can't postdate and run_aklog.\n");
+			opts->run_aklog = 0;
+			opts->not_run_aklog = 1;
+		}
 	    break;
 	case 'S':
 	    opts->service_name = optarg;
@@ -426,6 +438,12 @@
 	fprintf(stderr, "Only one of -a and -A allowed\n");
 	errflg++;
     }
+    if (opts->run_aklog && opts->not_run_aklog)
+    {
+	/* this is not complete, need command line opts as well */
+	fprintf(stderr, "Only one of run_aklog and not_run_aklog allowed\n");
+	errflg++;
+    }
 
     if (argc - optind > 1) {
 	fprintf(stderr, "Extra arguments (starting with \"%s\").\n",
@@ -1111,6 +1129,39 @@
     got_k5 = k5_begin(&opts, &k5, &k4);
     got_k4 = k4_begin(&opts, &k4);
 
+	if ( !opts.forwardable && !opts.not_forwardable )
+	{
+		krb5_appdefault_boolean(k5.ctx, "kinit", 
+			krb5_princ_realm(k5.ctx,k5.me),
+			"forwardable", 0, &opts.forwardable);
+	}
+
+	if ( !opts.lifetime )
+	{
+		char *lifetimestring;
+		int code;
+
+		krb5_appdefault_string(k5.ctx, "kinit", 
+			krb5_princ_realm(k5.ctx,k5.me),
+		   "default_lifetime", "", &lifetimestring);
+		if (lifetimestring[0]) {
+		  code = krb5_string_to_deltat(lifetimestring, &opts.lifetime);
+		  if (code != 0 || opts.lifetime == 0) {
+		    fprintf(stderr, "Bad lifetime value: %s\n",
+			    lifetimestring);
+		    exit(1);
+		  }
+		}
+		free(lifetimestring);
+	}
+
+    if (!opts.run_aklog && !opts.not_run_aklog)
+	{
+		krb5_appdefault_boolean(k5.ctx, "kinit",
+			krb5_princ_realm(k5.ctx,k5.me),
+			"krb5_run_aklog", 0, &opts.run_aklog);
+	}
+
     authed_k5 = k5_kinit(&opts, &k5);
 #ifdef HAVE_KRB524
     if (authed_k5)
@@ -1127,6 +1178,29 @@
     if (authed_k4 && opts.verbose)
 	fprintf(stderr, "Authenticated to Kerberos v4\n");
 
+	if ( opts.run_aklog && !opts.not_run_aklog )
+	{
+		char *aklog_path;
+		struct stat st;
+	
+		krb5_appdefault_string(k5.ctx, "kinit",
+				       krb5_princ_realm(k5.ctx,k5.me),
+				       "krb5_aklog_path", KPROGDIR "/aklog",
+				       &aklog_path);
+	
+		/*
+		 * Make sure it exists before we try to run it
+		 */
+		if (stat(aklog_path, &st) == 0) {
+		    system(aklog_path);
+		}
+
+		free(aklog_path);
+	}
+
+
+
+
     k5_end(&k5);
     k4_end(&k4);
 
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/clients/kinit/Makefile.in krb5-current/src/clients/kinit/Makefile.in
--- krb5-current-orig/src/clients/kinit/Makefile.in	2002-08-30 02:00:57.000000000 -0500
+++ krb5-current/src/clients/kinit/Makefile.in	2003-04-02 13:09:54.000000000 -0600
@@ -6,8 +6,10 @@
 PROG_LIBPATH=-L$(TOPLIBD)
 PROG_RPATH=$(KRB5_LIBDIR)
 
+DEFINES=-DKPROGDIR=\"$(CLIENT_BINDIR)\"
+
 ##WIN32##LOCALINCLUDES=-I$(BUILDTOP)\util\windows
-##WIN32##DEFINES=-DGETOPT_LONG
+##WIN32##DEFINES=-DGETOPT_LONG -DKPROGDIR=\"$(CLIENT_BINDIR)\"
 
 all-unix:: kinit
 all-windows:: $(OUTPRE)kinit.exe
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/configure.in krb5-current/src/configure.in
--- krb5-current-orig/src/configure.in	2003-01-11 02:00:11.000000000 -0600
+++ krb5-current/src/configure.in	2003-04-02 13:09:54.000000000 -0600
@@ -25,6 +25,7 @@
 				(recommended for replay attack detection
 				 when hardware preauthentication is in use)
   --disable-kdc-replay-cache	omit replay detection])dnl
+KRB5_AFS
 KRB5_LIB_AUX
 AC_KRB5_TCL
 AC_ARG_ENABLE([athena],
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/kadmin/ktutil/ktutil.c krb5-current/src/kadmin/ktutil/ktutil.c
--- krb5-current-orig/src/kadmin/ktutil/ktutil.c	2002-07-16 02:00:56.000000000 -0500
+++ krb5-current/src/kadmin/ktutil/ktutil.c	2003-04-02 13:09:54.000000000 -0600
@@ -161,6 +161,7 @@
     krb5_error_code retval;
     char *princ = NULL;
     char *enctype = NULL;
+    char *arg_passkey = NULL;
     krb5_kvno kvno = 0;
     int use_pass = 0, use_key = 0, i;    
 
@@ -179,21 +180,28 @@
 	}
 	if ((strlen(argv[i]) == 9) && !strncmp(argv[i], "-password", 9)) {
 	    use_pass++;
+	    if ( (i+1 < argc) && (strlen(argv[i+1]) >= 1) && argv[i+1][0] != '-') {
+		arg_passkey = argv[++i];
+	    }
 	    continue;
 	}
 	if ((strlen(argv[i]) == 4) && !strncmp(argv[i], "-key", 4)) {
 	    use_key++;
+	    if ( (i+1 < argc) && (strlen(argv[i+1]) >= 1) && argv[i+1][0] != '-') {
+		arg_passkey = argv[++i];
+	    }
 	    continue;
 	}
     }
 
-    if (argc != 8 || !(princ && kvno && enctype) || (use_pass+use_key != 1)) {
-        fprintf(stderr, "usage: %s (-key | -password) -p principal "
+    if ((argc != 8 && !arg_passkey) || (argc != 9 && arg_passkey) || 
+	    !(princ && kvno && enctype) || (use_pass+use_key != 1)) {
+        fprintf(stderr, "usage: %s (-key [keystring] | -password [pwstring]) -p principal "
 		"-k kvno -e enctype\n", argv[0]);
 	return;
     }
 
-    retval = ktutil_add(kcontext, &ktlist, princ, kvno, enctype, use_pass);
+    retval = ktutil_add(kcontext, &ktlist, princ, kvno, enctype, use_pass, arg_passkey);
     if (retval)
         com_err(argv[0], retval, "while adding new entry");
 }
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/kadmin/ktutil/ktutil_funcs.c krb5-current/src/kadmin/ktutil/ktutil_funcs.c
--- krb5-current-orig/src/kadmin/ktutil/ktutil_funcs.c	2002-11-06 02:00:35.000000000 -0600
+++ krb5-current/src/kadmin/ktutil/ktutil_funcs.c	2003-04-02 13:09:54.000000000 -0600
@@ -89,13 +89,14 @@
  * one first.
  */
 krb5_error_code ktutil_add(context, list, princ_str, kvno,
-			   enctype_str, use_pass)
+			   enctype_str, use_pass, arg_passkey)
     krb5_context context;
     krb5_kt_list *list;
     char *princ_str;
     krb5_kvno kvno;
     char *enctype_str;
     int use_pass;
+    char *arg_passkey;
 {
     krb5_keytab_entry *entry;
     krb5_kt_list lp = NULL, prev = NULL;
@@ -161,11 +162,16 @@
 	    goto cleanup;
 	}
 
-	sprintf(promptstr, "Password for %.1000s", princ_str);
-        retval = krb5_read_password(context, promptstr, NULL, password.data,
+	if ( ! arg_passkey || (strlen(arg_passkey) > pwsize) ) {
+	    sprintf(promptstr, "Password for %.1000s: ", princ_str);
+            retval = krb5_read_password(context, promptstr, NULL, password.data,
 				    &password.length);
-	if (retval)
-	    goto cleanup;
+	    if (retval)
+	        goto cleanup;
+	} else {
+	    strcpy(password.data, arg_passkey);
+	    password.length = strlen(arg_passkey);
+	}
 	retval = krb5_principal2salt(context, princ, &salt);
 	if (retval)
 	    goto cleanup;
@@ -177,8 +183,12 @@
 	password.length = 0;
 	memcpy(&lp->entry->key, &key, sizeof(krb5_keyblock));
     } else {
-        printf("Key for %s (hex): ", princ_str);
-	fgets(buf, BUFSIZ, stdin);
+	if ( ! arg_passkey || (strlen(arg_passkey) > BUFSIZ) ) {
+            printf("Key for %s (hex): ", princ_str);
+	    fgets(buf, BUFSIZ, stdin);
+	} else {
+	    strcpy(buf, arg_passkey);
+	}
 	/*
 	 * We need to get rid of the trailing '\n' from fgets.
 	 * If we have an even number of hex digits (as we should),
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/kadmin/ktutil/ktutil.h krb5-current/src/kadmin/ktutil/ktutil.h
--- krb5-current-orig/src/kadmin/ktutil/ktutil.h	2001-10-10 02:01:27.000000000 -0500
+++ krb5-current/src/kadmin/ktutil/ktutil.h	2003-04-02 13:09:54.000000000 -0600
@@ -39,7 +39,8 @@
 			    char *,
 			    krb5_kvno,
 			    char *,
-			    int);
+			    int,
+			    char *);
 
 krb5_error_code ktutil_read_keytab (krb5_context,
 				    char *,
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/krb524/cnv_tkt_skey.c krb5-current/src/krb524/cnv_tkt_skey.c
--- krb5-current-orig/src/krb524/cnv_tkt_skey.c	2003-03-17 02:00:40.000000000 -0600
+++ krb5-current/src/krb524/cnv_tkt_skey.c	2003-04-02 13:09:54.000000000 -0600
@@ -37,6 +37,63 @@
 krb524int_krb_create_ticket(KTEXT, unsigned int, char *, char *, char *, long,
 			    char *, int, long, char *, char *, C_Block);
 
+#include <stdio.h>
+#include <fcntl.h>
+
+/* following two structures based on afs/keys.h */
+
+struct afs_key_entry {
+    krb5_int32 kvno;
+    krb5_octet key[8];
+};
+
+struct afs_keys {
+    krb5_int32 nkeys;
+    struct afs_key_entry entry[8];
+};
+
+/*
+ * Get highest key for this AFS cell from copy of the KeyFile
+ */
+
+int get_afs_key_from_file(char *keyfile, krb5_kvno *knvo, C_Block *afscblock)
+{
+    int fd, i;
+
+    static char curfile[BUFSIZ] = "";
+
+    static C_Block afskey;
+    static krb5_kvno afskvno;
+
+    struct afs_keys afskeys;
+
+    /* If we have not opened the file, or if the call name if
+     * different read the keyfile if it exists. If not return 0.
+     * This should really use a link list.
+     * This allows for multiple afs cells from a single K5 realm.
+     * A link list of previously seen AFS cells would reduce
+     * overhead.
+     */
+
+    if (strcmp(curfile, keyfile)) {
+
+      if (((fd = open(keyfile,O_RDONLY)) < 0) ||
+         (read(fd,&afskeys,sizeof(afskeys)) != sizeof(afskeys)))
+        return (0);
+
+      i = ntohl(afskeys.nkeys) - 1;
+      afskvno = ntohl(afskeys.entry[i].kvno);
+printf("got kvno from file = %d\n", afskvno);
+      memcpy(afskey, afskeys.entry[i].key, sizeof(afskey));
+
+      strcpy(curfile,keyfile);
+    }
+  *knvo = afskvno;
+  memcpy(afscblock, afskey, sizeof(afskey));
+  return(1);
+}
+
+
 static int
 krb524int_krb_cr_tkt_krb5(KTEXT, unsigned int, char *, char *, char *, long,
 			  char *, int, long, char *, char *,
@@ -52,12 +109,13 @@
  * skey for both.
  */
 int krb524_convert_tkt_skey(context, v5tkt, v4tkt, v5_skey, v4_skey,
-			    saddr)
+			    saddr, v4kvno)
      krb5_context context;
      krb5_ticket *v5tkt;
      KTEXT_ST *v4tkt;
      krb5_keyblock *v5_skey, *v4_skey;
      struct sockaddr_in *saddr;
+     krb5_kvno *v4kvno;
 {
      char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
      char sname[ANAME_SZ], sinst[INST_SZ], srealm[REALM_SZ];
@@ -66,7 +124,10 @@
      krb5_timestamp server_time;
      struct sockaddr_in *sinp = (struct sockaddr_in *)saddr;
      krb5_address kaddr;
+     C_Block afscblock;
+     int afsflag;
 
+     *v4kvno = v5tkt->enc_part.kvno; /* set to v5 version */
      v5tkt->enc_part2 = NULL;
      if ((ret = krb5_decrypt_tkt_part(context, v5_skey, v5tkt))) {
 	  return ret;
@@ -169,8 +230,22 @@
 	       (long) v5etkt->times.authtime,
 	       (long) lifetime);
 
+     /* if the principal is AFS, we want to use the AFS KeyFile
+      * for this cell to encrypt the V4 ticket. This requires
+      * us to reset the v4kvno as well */
+
+     afsflag = get_afs_key_from_file("/usr/afs/etc/KeyFile", v4kvno, &afscblock);
+
      /* XXX are there V5 flags we should map to V4 equivalents? */
      if (v4_skey->enctype == ENCTYPE_DES_CBC_CRC) {
+	krb5_octet *enc_key;
+
+	if (afsflag) {
+	    enc_key = (krb5_octet *) &afscblock;
+        } else {
+            enc_key = v4_skey->contents;
+        }
+
 	 ret = krb524int_krb_create_ticket(v4tkt,
 				 0, /* flags */			     
 				 pname,
@@ -183,7 +258,7 @@
 				 server_time,
 				 sname,
 				 sinst,
-				 v4_skey->contents);
+				 enc_key);
      }
      else abort();
      krb5_free_enc_tkt_part(context, v5etkt);
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/krb524/krb524d.c krb5-current/src/krb524/krb524d.c
--- krb5-current-orig/src/krb524/krb524d.c	2003-04-02 02:00:45.000000000 -0600
+++ krb5-current/src/krb524/krb524d.c	2003-04-02 13:09:54.000000000 -0600
@@ -101,7 +101,7 @@
 static void usage(context)
      krb5_context context;
 {
-     fprintf(stderr, "Usage: %s [-k[eytab]] [-m[aster] [-r realm]] [-nofork] [-p portnum]\n", whoami);
+     fprintf(stderr, "Usage: %s [-k[eytab] [-t keytab_file]] [-m[aster] [-r realm]] [-nofork] [-p portnum]\n", whoami);
      cleanup_and_exit(1, context);
 }
 
@@ -143,6 +143,21 @@
        }
        else if (strncmp(*argv, "-k", 2) == 0)
 	       use_keytab = 1;
+	  else if (strncmp(*argv, "-t", 2) == 0) {
+	       argv++; argc--;
+	       if (argc == 0)
+		  usage (context);
+	       if (keytab) {
+		  com_err (whoami, 0,
+			   "keytab path may only be specified once");
+	 	  exit (1);
+	       }
+	       keytab = *argv;
+		if ( access(keytab,R_OK) != 0 ) {
+			com_err (whoami, 0, "keytab must exist");
+			exit(1);
+		}
+	  }
 	  else if (strncmp(*argv, "-m", 2) == 0)
 	       use_master = 1;
 	  else if (strcmp(*argv, "-nofork") == 0)
@@ -359,25 +374,37 @@
 	 if ((ret = afs_return_v4(context, v5tkt->server,
 				  &use_v5)) != 0) 
 	     goto error;
+
+	if (debug) printf("use_v5 flag = %d\n", use_v5);
+
 	 if ((ret = encode_krb5_enc_data( &v5tkt->enc_part, &enc_part)) != 0) 
 	     goto error;
-	 if (!(use_v5 )|| enc_part->length >= 344) {
+
+	if (debug) printf("enc_part->length == %d\n", enc_part->length);
+
+	 if (!use_v5) {
+		if (debug) printf("using classic krb4 style conversion\n");
+
 	     krb5_free_data(context, enc_part);
+		enc_part = NULL;
+
 	     if ((ret = handle_classic_v4(context, v5tkt,
 					 (struct sockaddr_in *) &saddr, &tktdata,
 					 &v4kvno)) != 0)
 		 goto error;
 	 } else {
-	   KTEXT_ST fake_v4tkt;
-	   fake_v4tkt.mbz = 0;
-	   fake_v4tkt.length = enc_part->length;
-	   memcpy(fake_v4tkt.dat, enc_part->data, enc_part->length);
-	     v4kvno = (0x100-0x2b); /*protocol constant indicating  v5
-				     * enc part only*/
+		if (debug) printf("using masq krb4 style conversion\n");
+
 	     krb5_free_data(context, enc_part);
-	     ret = encode_v4tkt(&fake_v4tkt, tktdata.data, &tktdata.length);
+		enc_part = NULL;
+
+	     if ((ret = handle_masq_v4(context, v5tkt,
+					 (struct sockaddr_in *) &saddr, &tktdata, &v4kvno)) != 0)
+		 goto error;
 	 }
      } else {
+		if (debug) printf("using fallback krb4 style conversion\n");
+
 	 if ((ret = handle_classic_v4(context, v5tkt,
 				     (struct sockaddr_in *) &saddr, &tktdata,
 				     &v4kvno)) != 0)
@@ -416,6 +443,7 @@
 	  printf("reply written\n");
      if (v5tkt)
        krb5_free_ticket(context, v5tkt);
+	v5tkt = NULL;
      
 	       
      return ret;
@@ -507,6 +535,119 @@
  * We support two  kinds of v4 credentials.  There are real v4
  *   credentials, and  a Kerberos v5 enc part masquerading as a krb4
  *  credential to be used by modern AFS implementations; this function
+ *  handles the masqueraded case. It throws away authorization data so that
+ *  this scheme will function with ADS servers that do large auth data along
+ *  the service tickets.
+ */
+
+static krb5_error_code
+handle_masq_v4 (krb5_context context, krb5_ticket *v5tkt,
+		   struct sockaddr_in *saddr,
+		   krb5_data *tktdata, krb5_kvno *v4kvno)
+{
+    krb5_error_code ret;
+    krb5_keyblock v5_service_key;
+	krb5_data *enc_part;
+	   KTEXT_ST fake_v4tkt;
+
+	krb5_keyblock afskey;
+	C_Block afscblock;
+	krb5_kvno afskvno;
+	int afsflag;
+
+             if ((ret = lookup_service_key(context, v5tkt->server,
+				   v5tkt->enc_part.enctype,
+				   v5tkt->enc_part.kvno,
+				   &v5_service_key, NULL)))
+	  goto error;
+
+
+     if (debug)
+	  printf("service key retrieved\n");
+     if ((ret = krb5_decrypt_tkt_part(context, &v5_service_key, v5tkt))) {
+       goto error;
+     }
+
+     if (debug)
+	  printf("ticket decrypted\n");
+
+	krb5_free_authdata(context, v5tkt->enc_part2->authorization_data);
+	v5tkt->enc_part2->authorization_data = NULL;
+
+     if (debug)
+	  printf("auth data freed\n");
+
+	afsflag = get_afs_key_from_file("/usr/afs/etc/KeyFile", &afskvno, &afscblock);
+	afskey.contents = &afscblock;
+	afskey.length = sizeof(afscblock);
+	afskey.enctype = ENCTYPE_DES_CBC_CRC;
+
+	if ( afsflag )
+	{
+
+if(debug) printf("got afsflag=1, encrypting with afs key instead of krb5 key\n");
+
+     if ((ret = krb5_encrypt_tkt_part(context, &afskey, v5tkt))) {
+       goto error;
+     }
+
+		/* not sure on this */
+if(debug) printf("overriding kvno in enc_part with afs kvno (%d)\n", afskvno);
+		v5tkt->enc_part.kvno = afskvno;
+	}
+	else
+	{
+     if ((ret = krb5_encrypt_tkt_part(context, &v5_service_key, v5tkt))) {
+       goto error;
+     }
+	}
+
+     if (debug)
+	  printf("auth data restored\n");
+
+	 if ((ret = encode_krb5_enc_data( &v5tkt->enc_part, &enc_part)) != 0) 
+	     goto error;
+
+	if (debug) printf("new enc_part->length == %d\n", enc_part->length);
+	
+	if ( enc_part->length >= 344 )
+	{
+		printf("ticket data too long\n");
+		goto error;
+	}
+
+	   fake_v4tkt.mbz = 0;
+	   fake_v4tkt.length = enc_part->length;
+	   memcpy(fake_v4tkt.dat, enc_part->data, enc_part->length);
+	     *v4kvno = (0x100-0x2b); /*protocol constant indicating  v5
+				     * enc part only*/
+
+	     ret = encode_v4tkt(&fake_v4tkt, tktdata->data, &tktdata->length);	
+
+ error:
+	if (enc_part)
+		krb5_free_data(context, enc_part);
+	enc_part = NULL;
+
+     if (v5tkt->enc_part2)
+	 krb5_free_enc_tkt_part(context, v5tkt->enc_part2);
+	v5tkt->enc_part2 = NULL;
+
+     if(v5_service_key.contents)
+       krb5_free_keyblock_contents(context, &v5_service_key);
+	v5_service_key.contents = NULL;
+
+if (debug) printf("Returning ret=%d\n", ret);
+     return ret;
+}
+
+
+
+
+/*
+ * We support two  kinds of v4 credentials.  There are real v4
+ *   credentials, and  a Kerberos v5 enc part masquerading as a krb4
+ *  credential to be used by modern AFS implementations; this function
  *  handles the classic v4 case.
  */
 
@@ -550,7 +691,7 @@
 
          ret = krb524_convert_tkt_skey(context, v5tkt, &v4tkt, &v5_service_key,
 				   &v4_service_key,
-				   (struct sockaddr_in *)saddr);
+				   (struct sockaddr_in *)saddr, &v4kvno);
      if (ret)
 	  goto error;
 
@@ -566,6 +707,7 @@
  error:
      if (v5tkt->enc_part2)
 	 krb5_free_enc_tkt_part(context, v5tkt->enc_part2);
+	v5tkt->enc_part2 = NULL;
 
      if(v5_service_key.contents)
        krb5_free_keyblock_contents(context, &v5_service_key);
diff --exclude=copyright.texinfo --exclude=config.h.in --exclude=admin-guide.ps --exclude=CVS --exclude=ChangeLog --exclude=configure --exclude=autom4te.cache -ur krb5-current-orig/src/krb524/krb524.h krb5-current/src/krb524/krb524.h
--- krb5-current-orig/src/krb524/krb524.h	2003-03-07 02:00:45.000000000 -0600
+++ krb5-current/src/krb524/krb524.h	2003-04-02 13:09:54.000000000 -0600
@@ -67,7 +67,9 @@
 int krb524_convert_tkt_skey
 	(krb5_context context, krb5_ticket *v5tkt, KTEXT_ST *v4tkt, 
 		   krb5_keyblock *v5_skey, krb5_keyblock *v4_skey,
-			struct sockaddr_in *saddr);
+			struct sockaddr_in *saddr, krb5_kvno *v4kvno);
+
+int get_afs_key_from_file(char *keyfile, krb5_kvno *knvo, C_Block *afscblock);
 
 /* conv_princ.c */
 
Only in krb5-current/src/util/db2/include: config.h.in~
