Merge with Cygnus sources, changes from Mark Eichin, Marc Horowitz, Chris
authorKen Raeburn <raeburn@mit.edu>
Wed, 1 May 1996 03:17:43 +0000 (03:17 +0000)
committerKen Raeburn <raeburn@mit.edu>
Wed, 1 May 1996 03:17:43 +0000 (03:17 +0000)
Provenzano and me:

* Makefile.in (install): Install correct set of man pages, and check for
failures.
* kshd.M, klogind.M: Renamed from kr*.M versions.
* login.M: New file. Man page for login with some description of new features.

* rlogin.M: Remove references to using program with target hostname as argv[0].
* rsh.M: Ditto.  Also document -f, -F, -x options.

* login.c: Massive changes.  Split much functionality out of main and into
separate file sections: terminal flag settings, Kerberos 4 and 5 support, UNIX
password support, mail check, signal handler handling, some other support
routines.  Revamp controlling tty and process group handling.  For AFS
configuration, use setpag and run aklog.  Try validating password using krb5.
Always set tty flags, not just for rlogin session.  When validating tickets,
treat an existing key file that doesn't contain the key we think we want
(possibly because DNS was spoofed) as an error condition.
* Makefile.in (LOGINLIBS): List libkrb524.a here.
(LIBOBJS): Not here.
(login.krb5): Reverse the order of LIBOBJS and LOGINLIBS.
* configure.in: Check for --with-afs.  Add AFS libs and define SETPAG if
supplied.

* login.c (KRB5_GET_TICKETS, KRB4_GET_TICKETS, KRB_RUN_AKLOG): new macros
selecting single signon options.  krb5.conf profile support for control over
authentication options, above the compile time selection.
(conf_affirmative): new function, recognize yes/no in profile value.
(login_get_kconf): new function, look for all [login] flags and set them in
appropriate globals (via login_conf_set array.)
(main, sleepexit, destroy_tickets): Check the new login_* flags.
(main): rename KRB4_USE_524 to KRB4_CONVERT.

* configure.in: Added checks for tcsetpgrp, tcgetpgrp, setpgid.
* krlogind.c (control): Use tcgetpgrp if it's available.

* loginpaths.h (RPATH, LPATH, LPATH_root): Define HP/UX 9.04 versions,
conditionalized on __hpux and !hpux.

* login.c and configure.in: instead of checking _IBMR2 and __sgi__, write
configure tests to check for the existence of /etc/environment and
/etc/TIMEZONE files, respectively.

* forward.c (rd_and_store_for_creds) : If chown fails then only pass failure
back if owner is different than intended owner. This is to make rsh.exp test
work without requiring root privlidges.

* login.c (main): Don't set TERM to an empty value.
(stypeof) [__hpux]: Return null if unknown.

* krlogin.c (catchild): remove hp/ux kludge because of aclocal.m4 fix.
(speeds): test __hpux for hpux speed list.
(main): test __hpux for use of FIOSSAIOSTAT and FIOSSAIOOWN
(USE_TERMIO): test __hpux for bsdtty/ptyio headers.
* krlogind.c: test __hpux for bsdtty/ptyio headers.
(doit): test __hpux for use of setpgrp2.
* krcp.c (main): test __hpux as well for remsh vs. rsh.

* krcp.c (des_write): Make sure the buffer for the encrypted data is large
enough. Only return an error in malloc fails.

* krsh.c (main): Always turn on anyport -A option.

* krlogind.c (ptsname): Declare if it's going to be used.

* krshd.c (main): Use basename of argv[0] for progname.

* login.c (dofork): On linux, TIOCNOTTY causes us to die on a SIGHUP, so don't
even try it.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@7881 dc483132-0cff-0310-8789-dd5450dbe970

13 files changed:
src/appl/bsd/ChangeLog
src/appl/bsd/Makefile.in
src/appl/bsd/configure.in
src/appl/bsd/forward.c
src/appl/bsd/krcp.c
src/appl/bsd/krlogin.c
src/appl/bsd/krlogind.c
src/appl/bsd/krsh.c
src/appl/bsd/krshd.c
src/appl/bsd/login.c
src/appl/bsd/loginpaths.h
src/appl/bsd/rlogin.M
src/appl/bsd/rsh.M

index 93148ff5b1384b6c4571c28404f72c6c447cbd8f..21e8a1277c6c4b04ab4dd893c5a7a7f34ea3a387 100644 (file)
@@ -1,14 +1,81 @@
 Mon Apr 29 17:02:44 1996  Ken Raeburn  <raeburn@cygnus.com>
 
+       Merge with Cygnus sources, changes from Mark Eichin, Marc
+       Horowitz, Chris Provenzano and me:
+
        * Makefile.in (install): Install correct set of man pages, and
        check for failures.
        * kshd.M, klogind.M: Renamed from kr*.M versions.
-
-       Wed Sep 13 23:19:17 1995  Mark Eichin  <eichin@cygnus.com>
-
        * login.M: New file. Man page for login with some description of
        new features.
 
+       * rlogin.M: Remove references to using program with target
+       hostname as argv[0].
+       * rsh.M: Ditto.  Also document -f, -F, -x options.
+
+       * login.c: Massive changes.  Split much functionality out of main
+       and into separate file sections: terminal flag settings, Kerberos
+       4 and 5 support, UNIX password support, mail check, signal handler
+       handling, some other support routines.  Revamp controlling tty and
+       process group handling.  For AFS configuration, use setpag and run
+       aklog.  Try validating password using krb5.  Always set tty flags,
+       not just for rlogin session.  When validating tickets, treat an
+       existing key file that doesn't contain the key we think we want
+       (possibly because DNS was spoofed) as an error condition.
+       * Makefile.in (LOGINLIBS): List libkrb524.a here.
+       (LIBOBJS): Not here.
+       (login.krb5): Reverse the order of LIBOBJS and LOGINLIBS.
+       * configure.in: Check for --with-afs.  Add AFS libs and define
+       SETPAG if supplied.
+
+       * login.c (KRB5_GET_TICKETS, KRB4_GET_TICKETS, KRB_RUN_AKLOG): new
+       macros selecting single signon options.  krb5.conf profile support
+       for control over authentication options, above the compile time
+       selection.
+       (conf_affirmative): new function, recognize yes/no in profile
+       value.
+       (login_get_kconf): new function, look for all [login] flags and
+       set them in appropriate globals (via login_conf_set array.)
+       (main, sleepexit, destroy_tickets): Check the new login_* flags.
+       (main): rename KRB4_USE_524 to KRB4_CONVERT.
+
+       * configure.in: Added checks for tcsetpgrp, tcgetpgrp, setpgid.
+       * krlogind.c (control): Use tcgetpgrp if it's available.
+
+       * loginpaths.h (RPATH, LPATH, LPATH_root): Define HP/UX 9.04
+       versions, conditionalized on __hpux and !hpux.
+
+       * login.c and configure.in: instead of checking _IBMR2 and
+       __sgi__, write configure tests to check for the existence of
+       /etc/environment and /etc/TIMEZONE files, respectively.
+
+       * forward.c (rd_and_store_for_creds) : If chown fails then only
+       pass failure back if owner is different than intended owner. This
+       is to make rsh.exp test work without requiring root privlidges.
+
+       * login.c (main): Don't set TERM to an empty value.
+       (stypeof) [__hpux]: Return null if unknown.
+
+       * krlogin.c (catchild): remove hp/ux kludge because of aclocal.m4 fix.
+       (speeds): test __hpux for hpux speed list.
+       (main): test __hpux for use of FIOSSAIOSTAT and FIOSSAIOOWN
+       (USE_TERMIO): test __hpux for bsdtty/ptyio headers.
+       * krlogind.c: test __hpux for bsdtty/ptyio headers.
+       (doit): test __hpux for use of setpgrp2.
+       * krcp.c (main): test __hpux as well for remsh vs. rsh.
+
+       * krcp.c (des_write): Make sure the buffer for the encrypted data
+       is large enough. Only return an error in malloc fails.
+
+       * krsh.c (main): Always turn on anyport -A option.
+
+       * krlogind.c (ptsname): Declare if it's going to be used.
+
+       * krshd.c (main): Use basename of argv[0] for progname.
+
+       * login.c (dofork): On linux, TIOCNOTTY causes us to die on a
+       SIGHUP, so don't even try it.
+
 Sun Apr 21 12:52:35 1996  Richard Basch  <basch@lehman.com>
 
        * krshd.c: If checksumming is required & ALWAYS_V5_KUSEROK is
@@ -294,13 +361,14 @@ Fri Jan 19 10:45:29 1996  Sam Hartman  <hartmans@tertius.mit.edu>
        (recvauth): Fix accidental memory leak with authenticator and fix
        include correct username in checksum
 
-       * kcmd.c: Send authenticator with checksum of command line and remote user.
+       * kcmd.c: Send authenticator with checksum of command line and
+       remote user.
 
        * krlogin.c (des_read): Return 0 or -1 on close/error respectively.
 
 Wed Jan 17 15:14:33 1996  Sam Hartman  <hartmans@tertius.mit.edu>
 
-       * krlogin.c ((reader): Use select to find out-of-band data, not signals.
+       * krlogin.c (reader): Use select to find out-of-band data, not signals.
        (oob): No longer a signal handler; just a function.
        (writer): get rid of copytochild setup as sigurg no longer needed
        (main): Don't block SIGURG
index de249d94ef2b9ad64a669b9cc5574182821c891f..013f0d487e6892301a679a7c131c115e172f0e6d 100644 (file)
@@ -3,7 +3,7 @@ LOCALINCLUDE=-I$(SRCTOP)/include/kerberosIV
 SETENVSRC=@SETENVSRC@
 SETENVOBJ=@SETENVOBJ@
 
-LOGINLIBS = @LOGINLIBS@
+LOGINLIBS = ../../krb524/libkrb524.a @LOGINLIBS@
 LIBOBJS=@LIBOBJS@
 
 LOCAL_LIBRARIES=-lpty
@@ -71,7 +71,7 @@ install::
 # referenced by klogind.
 #
 login.krb5: login.o  $(SETENVOBJ) $(LIBOBJS) $(DEPLIBS)
-       $(LD) $(LDFLAGS) $(LDARGS) -o login.krb5 login.o $(SETENVOBJ) $(LIBOBJS) $(LIBS) $(LOGINLIBS)
+       $(LD) $(LDFLAGS) $(LDARGS) -o login.krb5 login.o $(SETENVOBJ) $(LIBOBJS) $(LOGINLIBS) $(LIBS)
 
 install::
        $(INSTALL_PROGRAM) login.krb5 $(DESTDIR)$(SERVER_BINDIR)/login.krb5
index 1792fa404e638539f4da3eca5eabf274ae0064ba..cb7ae23f579ec002e4e26af01ed29041e6e0d750 100644 (file)
@@ -1,5 +1,14 @@
 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
 AC_PROG_INSTALL
 dnl dbm libs for use of an_to_ln
 AC_CHECK_LIB(util,main)
@@ -7,11 +16,10 @@ USE_ANAME
 AC_CHECK_LIB(crypt,crypt)
 dnl
 dnl AIX has them all; SCO might too
-LOGINLIBS=
 AC_CHECK_LIB(odm,main,
   AC_CHECK_LIB(s,main,
     AC_CHECK_LIB(cfg,main, 
-      LOGINLIBS="-lodm -ls -lcfg" 
+      LOGINLIBS="$LOGINLIBS -lodm -ls -lcfg" 
       )))
 dnl
 dnl Make our operating system-specific security checks and definitions for
@@ -53,6 +61,9 @@ AC_FUNC_CHECK(grantpt,AC_DEFINE(HAVE_GRANTPT))
 AC_FUNC_CHECK(openpty,AC_DEFINE(HAVE_OPENPTY))
 AC_FUNC_CHECK(setlogin,AC_DEFINE(HAVE_SETLOGIN))
 AC_FUNC_CHECK(logwtmp,AC_DEFINE(HAVE_LOGWTMP))
+AC_FUNC_CHECK(tcgetpgrp,AC_DEFINE(HAVE_TCGETPGRP))
+AC_FUNC_CHECK(tcsetpgrp,AC_DEFINE(HAVE_TCSETPGRP))
+AC_FUNC_CHECK(setpgid,AC_DEFINE(HAVE_SETPGID))
 AC_CHECK_HEADERS(unistd.h stdlib.h string.h sys/filio.h sys/sockio.h )
 AC_CHECK_HEADERS(sys/label.h sys/tty.h ttyent.h lastlog.h sys/select.h )
 AC_CHECK_HEADERS(sys/ptyvar.h utmp.h utmpx.h sys/time.h)
@@ -161,6 +172,47 @@ if test $krb5_cv_shadow_pwd = yes; then
 AC_DEFINE(HAVE_SHADOW)
 fi
 dnl
+dnl
+AC_MSG_CHECKING([/etc/environment])
+AC_CACHE_VAL(krb5_cv_etc_environment,
+[AC_C_CROSS
+if test $ac_cv_c_cross = yes; then
+errprint(__file__:__line__: warning: Cannot check for file existence when cross compiling
+)dnl
+AC_MSG_ERROR(Cannot check for file existence when cross compiling)
+else
+if test -r /etc/environment; then
+krb5_cv_etc_environment=yes
+else
+krb5_cv_etc_environment=no
+fi
+fi])
+AC_MSG_RESULT($krb5_cv_etc_environment)
+if test $krb5_cv_etc_environment = yes; then
+AC_DEFINE(HAVE_ETC_ENVIRONMENT)
+fi
+dnl
+dnl
+AC_MSG_CHECKING([/etc/TIMEZONE])
+AC_CACHE_VAL(krb5_cv_etc_timezone,
+[AC_C_CROSS
+if test $ac_cv_c_cross = yes; then
+errprint(__file__:__line__: warning: Cannot check for file existence when cross compiling
+)dnl
+AC_MSG_ERROR(Cannot check for file existence when cross compiling)
+else
+if test -r /etc/TIMEZONE; then
+krb5_cv_etc_timezone=yes
+else
+krb5_cv_etc_timezone=no
+fi
+fi])
+AC_MSG_RESULT($krb5_cv_etc_timezone)
+if test $krb5_cv_etc_timezone = yes; then
+AC_DEFINE(HAVE_ETC_TIMEZONE)
+fi
+dnl
+dnl
 KRB5_CHECK_PROTOS
 dnl
 ADD_DEF(-DKERBEROS)
index 8c74eb2e473c4fff73097024b1fa92b0a7f38a93..54594b9b9783a75bbcb88a4f95a9302e120ddca5 100644 (file)
@@ -23,6 +23,8 @@
 #include <stdio.h>
 #include <pwd.h>
 #include <netdb.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include "k5-int.h"
 
@@ -65,7 +67,18 @@ rd_and_store_for_creds(context, auth_context, inbuf, ticket, lusername, ccache)
     if (retval = krb5_cc_store_cred(context, *ccache, *creds)) 
        goto cleanup;
 
-    retval = chown(ccname+5, pwd->pw_uid, -1);
+    if (retval = chown(ccname+5, pwd->pw_uid, -1)) {
+       /* 
+        * If the file owner is the same as the user id then return ok.
+        * This is for testing only --proven
+        */
+       struct stat statbuf;
+
+       if (stat(ccname + 5, & statbuf) == 0) {
+           if (statbuf.st_uid == pwd->pw_uid)
+               retval = 0;
+       }
+    }
     
 cleanup:
     krb5_free_creds(context, *creds);
index 32a6eb1a861977eb5a306d0539b67cc3d9a235b2..36ad114cebabf7dd7cf2671c367ae1e9e84e3079 100644 (file)
@@ -381,7 +381,7 @@ int main(argc, argv)
                      suser = pwd->pw_name;
                    else if (!okname(suser))
                      continue;
-#ifdef hpux
+#if defined(hpux) || defined(__hpux)
                    (void) sprintf(buf, "remsh %s -l %s -n %s %s '%s%s%s:%s'",
 #else
                    (void) sprintf(buf, "rsh %s -l %s -n %s %s '%s%s%s:%s'",
@@ -391,7 +391,7 @@ int main(argc, argv)
                                   tuser ? "@" : "",
                                   thost, targ);
               } else
-#ifdef hpux
+#if defined(hpux) || defined(__hpux)
                   (void) sprintf(buf, "remsh %s -n %s %s '%s%s%s:%s'",
 #else
                    (void) sprintf(buf, "rsh %s -n %s %s '%s%s%s:%s'",
@@ -1125,7 +1125,7 @@ struct buffer *allocbuf(bp, fd, blksize)
     size = roundup(stb.st_blksize, blksize);
 #endif
 
-      size = blksize;
+    size = blksize;
     if (bp->cnt < size) {
        if (bp->buf != 0)
          free(bp->buf);
@@ -1413,33 +1413,41 @@ int des_read(fd, buf, len)
 }
 
 
-
 int des_write(fd, buf, len)
      int fd;
      char *buf;
      int len;
 {
+    static krb5_data des_write_buf;
+    static int des_write_maxsize;
     unsigned char len_buf[4];
-/* Note that rcp depends on the same
- * file descriptor being both input and output to the remote
- * side.  This is bogus, especially when rcp
- * is being run by a rsh that pipes. Fix it here because
- * it would require significantly more work in other places. --hartmans 1/96*/
+
+    /* 
+     * Note that rcp depends on the same file descriptor being both 
+     * input and output to the remote side.  This is bogus, especially 
+     * when rcp is being run by a rsh that pipes. Fix it here because it 
+     * would require significantly more work in other places. --hartmans 1/96
+     */
     
     if (fd == 0)
        fd = 1;
     if (!encryptflag)
       return(krb5_net_write(bsd_context, fd, buf, len));
     
-    desoutbuf.length = krb5_encrypt_size(len,eblock.crypto_entry);
-    if (desoutbuf.length > (int) sizeof(des_outbuf)){
-       return(-1);
+    des_write_buf.length = krb5_encrypt_size(len,eblock.crypto_entry);
+
+    if (des_write_buf.length > des_write_maxsize) {
+       if (des_write_buf.data) 
+           free(des_write_buf.data);
+       des_write_maxsize = des_write_buf.length;
+       if ((des_write_buf.data = malloc(des_write_maxsize)) == NULL) {
+           des_write_maxsize = 0;
+           return(-1);
+       }
     }
-    if (( krb5_encrypt(bsd_context, (krb5_pointer)buf,
-                      desoutbuf.data,
-                      len,
-                      &eblock,
-                      0))){
+
+    if ((krb5_encrypt(bsd_context, (krb5_pointer)buf, des_write_buf.data, 
+                     len, &eblock, 0))) {
        return(-1);
     }
     
@@ -1447,11 +1455,11 @@ int des_write(fd, buf, len)
     len_buf[1] = (len & 0xff0000) >> 16;
     len_buf[2] = (len & 0xff00) >> 8;
     len_buf[3] = (len & 0xff);
-    (void) write(fd, len_buf, 4);
-    if (write(fd, desoutbuf.data,desoutbuf.length) != desoutbuf.length){
+    if ((write(fd, len_buf, 4) != 4) || (write(fd, des_write_buf.data, 
+       des_write_buf.length) != des_write_buf.length)) {
        return(-1);
     }
-    else return(len);
+    return(len);
 }
 
 #endif /* KERBEROS */
index e8b205da886d32ee42cd6c94f780bf0878efabfa..831806c626742a9734a6be68d13480dc06893b5c 100644 (file)
@@ -192,7 +192,7 @@ int flowcontrol;                    /* Since emacs can alter the
                                           the original characteristics */
 int    confirm = 0;                    /* ask if ~. is given before dying. */
 int    litout;
-#ifdef hpux
+#if defined(hpux) || defined(__hpux)
 char   *speeds[] =
 { "0", "50", "75", "110", "134", "150", "200", "300", "600",
     "900", "1200", "1800", "2400", "3600", "4800", "7200", "9600",
@@ -674,7 +674,7 @@ char        deferase, defkill;
 
 #ifdef USE_TERMIO
 char defvtim, defvmin;
-#ifdef hpux
+#if defined(hpux) || defined(__hpux)
 #include <sys/bsdtty.h>
 #include <sys/ptyio.h>
 #endif
@@ -951,13 +951,8 @@ int signo;
 #ifdef WAIT_USES_INT
     if (pid < 0 || (pid == child && !WIFSTOPPED(status)))
       done(status);
-#else
-#if defined(hpux)
-    /* I think this one is wrong: XXX -- [eichin:19940727.1853EST] */
-    if ((pid < 0) || ((pid == child) && (!WIFSTOPPED(status.w_stopval))))
 #else
     if ((pid < 0) || ((pid == child) && (!WIFSTOPPED(status))))
-#endif
        done((int)(status.w_termsig | status.w_retcode));
 #endif
     goto again;
index 26fb2cd216d51df1317d3b84733d2dcee0e2f8fc..0a44c8debf2ce1b1fc58ffe53256e3b590c1e8dc 100644 (file)
@@ -129,7 +129,7 @@ char copyright[] =
      
 #include <signal.h>
 
-#ifdef hpux
+#if defined(hpux) || defined(__hpux)
 #include <sys/ptyio.h>
 #endif
 #ifdef sysvimp
@@ -181,11 +181,15 @@ char copyright[] =
 #include <sys/filio.h>
 #endif
 
-
 #ifndef HAVE_KILLPG
 #define killpg(pid, sig) kill(-(pid), (sig))
 #endif
 
+#ifdef HAVE_PTSNAME
+/* HP/UX 9.04 has but does not declare ptsname.  */
+extern char *ptsname ();
+#endif
+
 #ifdef NO_WINSIZE
 struct winsize {
     unsigned short ws_row, ws_col;
@@ -325,7 +329,7 @@ int main(argc, argv)
     
     progname = *argv;
     
-pty_init();
+    pty_init();
     
 #ifndef LOG_NDELAY
 #define LOG_NDELAY 0
@@ -342,7 +346,6 @@ pty_init();
     openlog(progname, LOG_PID | LOG_NDELAY, LOG_AUTH);
 #endif /* 4.2 syslog */
     
-    
     /* Analyse parameters. */
     opterr = 0;
     while ((ch = getopt(argc, argv, ARGSTR)) != EOF)
@@ -619,7 +622,7 @@ int syncpipe[2];
        new_termio.c_lflag |= (ICANON|ECHO|ISIG|IEXTEN);
        new_termio.c_iflag|= (IXON|IXANY|BRKINT|INLCR|ICRNL);
 #endif /*Do we need binary stream?*/
-new_termio.c_iflag &= ~(ISTRIP);
+       new_termio.c_iflag &= ~(ISTRIP);
        /* new_termio.c_iflag = 0; */
        /* new_termio.c_oflag = 0; */
        new_termio.c_cc[VMIN] = 1;
@@ -821,7 +824,7 @@ int control(pty, cp, n)
      int n;
 {
     struct winsize w;
-    int pgrp;
+    int pgrp, got_pgrp;
     
     if (n < (int) 4+sizeof (w) || cp[2] != 's' || cp[3] != 's')
       return (0);
@@ -833,7 +836,13 @@ int control(pty, cp, n)
     w.ws_xpixel = ntohs(w.ws_xpixel);
     w.ws_ypixel = ntohs(w.ws_ypixel);
     (void)ioctl(pty, TIOCSWINSZ, &w);
-    if (ioctl(pty, TIOCGPGRP, &pgrp) >= 0)
+#ifdef HAVE_TCGETPGRP
+    pgrp = tcgetpgrp (pty);
+    got_pgrp = pgrp != -1;
+#else
+    got_pgrp = ioctl(pty, TIOCGPGRP, &pgrp) >= 0;
+#endif
+    if (got_pgrp)
       (void) killpg(pgrp, SIGWINCH);
 #endif
     return (4+sizeof (w));
@@ -855,14 +864,14 @@ void protocol(f, p)
     struct sigaction sa;
 #endif
 #ifdef TIOCPKT
-       register tiocpkt_on = 0;
-       int on = 1;
+    register tiocpkt_on = 0;
+    int on = 1;
 #endif
     
 #if defined(TIOCPKT) && !defined(__svr4__) || defined(solaris20)
-       /* if system has TIOCPKT, try to turn it on. Some drivers
+    /* if system has TIOCPKT, try to turn it on. Some drivers
      * may not support it. Save flag for later. 
-        */
+     */
    if ( ioctl(p, TIOCPKT, &on) < 0)
        tiocpkt_on = 0;
    else tiocpkt_on = 1;
@@ -964,7 +973,7 @@ void protocol(f, p)
            else if (pcc <= 0)
              break;
 #ifdef TIOCPKT
-               else if (tiocpkt_on) {
+           else if (tiocpkt_on) {
              if (pibuf[0] == 0)
                pbp++, pcc--;
              else {
@@ -974,7 +983,7 @@ void protocol(f, p)
                  }
                  pcc = 0;
              }
-               }
+           }
 #endif
        }
        if (FD_ISSET(f, &obits) && pcc > 0) {
@@ -1444,7 +1453,7 @@ recvauth(valid_checksum)
                                  &auth_sys,    /* which authentication system*/
                                  &v4_kdata, v4_schedule, v4_version))) {
 
-      if (auth_sys == KRB5_RECVAUTH_V5) {
+       if (auth_sys == KRB5_RECVAUTH_V5) {
            /*
             * clean up before exiting
             */
index 88c630e2321f8fefc4cc2992680840bfd08816b9..0a59cb3ddce04d79d1e979bff07293712d0b070a 100644 (file)
@@ -142,7 +142,7 @@ main(argc, argv0)
 #ifdef KERBEROS
     krb5_flags authopts;
     krb5_error_code status;
-    int fflag = 0, Fflag = 0, Aflag = 0;
+    int fflag = 0, Fflag = 0;
 #endif  /* KERBEROS */
     int debug_port = 0;
 
@@ -226,7 +226,6 @@ main(argc, argv0)
        goto another;
     }
     if (argc > 0 && !strncmp(*argv, "-A", 2)) {
-        Aflag++;
        argv++, argc--;
        goto another;
     }
@@ -355,7 +354,7 @@ main(argc, argv0)
                  (struct sockaddr_in *) 0,
                  (struct sockaddr_in *) 0,
                  authopts,
-                 Aflag);       /* Any port #? */
+                 1);   /* Always set anyport, there is no need not to. --proven */
     if (status) {
         /* check NO_TKT_FILE or equivalent... */
        fprintf(stderr,
index b3e265692477df66745fb02801800cf9862e8c8f..64b1b2974e28aad685915416ef4d1b10c3650c03 100644 (file)
@@ -263,7 +263,8 @@ int main(argc, argv)
     secflag = sysconf(_SC_CRAY_SECURE_SYS);
 #endif
     
-    progname = *argv;
+    progname = strrchr (*argv, '/');
+    progname = progname ? progname + 1 : *argv;
     
 #ifndef LOG_ODELAY /* 4.2 syslog */
     openlog(progname, LOG_PID);
@@ -415,8 +416,7 @@ int main(argc, argv)
     
     if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
                   sizeof (on)) < 0)
-       syslog(LOG_WARNING,
-            "setsockopt (SO_KEEPALIVE): %m");
+       syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
 #if defined(BSD) && BSD+0 >= 43
     linger.l_onoff = 1;
     linger.l_linger = 60;                      /* XXX */
@@ -1288,12 +1288,12 @@ if(port)
        int i;
        char *buf = (char *)malloc(strlen(getenv("KRB5CCNAME"))
                                          +strlen("KRB5CCNAME=")+1);
-                                         if (buf) {
-                                                 sprintf(buf, "KRB5CCNAME=%s",getenv("KRB5CCNAME"));
+       if (buf) {
+         sprintf(buf, "KRB5CCNAME=%s",getenv("KRB5CCNAME"));
 
-                                                 for (i = 0; envinit[i]; i++);
-                                                 envinit[i] =buf;
-                                         }
+         for (i = 0; envinit[i]; i++);
+         envinit[i] =buf;
+       }
     }
 
     /* If we do anything else, make sure there is space in the array. */
index d1e98e23ac0bfcb39890b0270ee4d20d3695713b..778d73d4e1a33084253016f249e7d5da0446f334 100644 (file)
@@ -27,19 +27,51 @@ char copyright[] =
 
 /* based on @(#)login.c        5.25 (Berkeley) 1/6/89 */
 
+/* While the code may be compiled with some of these options turned off,
+   the default will be to turn them *all* on if v4 compatibility is
+   available, and allow them to be configured via krb5.conf. */
+/* The configuration is of the form
+   [login]
+   # login stanza
+   krb5_get_tickets = 1
+   # use password to get v5 tickets
+   krb4_get_tickets = 1
+   # use password to get v4 tickets
+   krb4_convert = 1
+   # use kerberos conversion daemon to get v4 tickets
+   krb_run_aklog = 1
+   # attempt to run aklog
+   aklog_path = $(prefix)/bin/aklog
+   # where to find it [not yet implemented]
+   accept_passwd = 0
+   # don't accept plaintext passwords [not yet implemented]
+*/
+#define KRB5_GET_TICKETS
+int login_krb5_get_tickets = 1;
+#ifdef KRB5_KRB4_COMPAT
+#define KRB4_GET_TICKETS
+int login_krb4_get_tickets = 1;
+#define KRB4_CONVERT
+int login_krb4_convert = 1;
+#define KRB_RUN_AKLOG
+int login_krb_run_aklog = 1;
+#endif /* KRB5_KRB4_COMPAT */
+int login_accept_passwd = 0;
+
 /*
  * login [ name ]
  * login -r hostname   (for rlogind)
  * login -h hostname   (for telnetd, etc.)
- * login -f name       (for pre-authenticated login: datakit, xterm, etc.)
+ * login -f name       (for pre-authenticated login: datakit, xterm, etc.,
+ *                      does not allow preauthenticated login as root)
  * login -F name       (for pre-authenticated login: datakit, xterm, etc.,
  *                      allows preauthenticated login as root)
  * login -e name       (for pre-authenticated encrypted, must do term
  *                      negotiation)
- * ifdef KRB4
+ * ifdef KRB4_KLOGIN
  * login -k hostname (for Kerberos V4 rlogind with password access)
  * login -K hostname (for Kerberos V4 rlogind with restricted access)
- * endif KRB4 
+ * endif KRB4_KLOGIN
  *
  * only one of: -r -f -e -k -K -F
  * only one of: -r -h -k -K
@@ -68,6 +100,8 @@ char copyright[] =
 #include <utmp.h>
 #include <signal.h>
 
+#include <assert.h>
+
 #ifdef HAVE_LASTLOG_H
 #include <lastlog.h>
 #endif
@@ -87,13 +121,54 @@ char copyright[] =
 #include <stdio.h>
 #include <grp.h>
 #include <pwd.h>
-#include <setjmp.h>
 #include <string.h>
 
+#include <setjmp.h>
+#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
+
+#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 HAVE_SHADOW
 #include <shadow.h>
 #endif
 
+#ifdef KRB5_GET_TICKETS
+/* #include "krb5.h" */
+/* need k5-int.h to get ->profile from krb5_context */
+#include "k5-int.h"
+#include "osconf.h"
+#endif /* KRB5_GET_TICKETS */
+
+#ifdef KRB4_KLOGIN
+/* support for running under v4 klogind, -k -K flags */
+#define KRB4
+#endif
+
+#ifdef KRB4_GET_TICKETS
+/* support for prompting for v4 initial tickets */
+#define KRB4
+#endif
+
 #ifdef KRB4
 #include <krb.h>
 #include <netdb.h>
@@ -106,6 +181,12 @@ char copyright[] =
 #endif /* BIND_HACK */
 #endif /* KRB4 */
 
+#ifndef __STDC__
+#ifndef volatile
+#define volatile
+#endif
+#endif
+
 #include "loginpaths.h"
 
 #ifdef POSIX_TERMIOS
@@ -144,15 +225,6 @@ char copyright[] =
 #define QUOTAWARN      "/usr/ucb/quota" /* warn user about quotas */
 #endif
 
-#define PROTOTYPE_DIR  "/usr/athena/lib/prototype_tmpuser"
-#define TEMP_DIR_PERM  0711
-
-#define NOATTACH       "/etc/noattach"
-#define NOCREATE       "/etc/nocreate"
-#define NOREMOTE       "/etc/noremote"
-#define REGISTER       "/usr/etc/go_register"
-#define GET_MOTD       "/bin/athena/get_message"
-
 #ifndef NO_UT_HOST
 #ifndef UT_HOSTSIZE
 /* linux defines it directly in <utmp.h> */
@@ -164,6 +236,11 @@ char copyright[] =
 #define        UT_NAMESIZE     sizeof(((struct utmp *)0)->ut_name)
 #endif
 
+#ifndef HAVE_SETPRIORITY
+/* if we don't have it, punt it cleanly */
+#define setpriority(which,who,prio)
+#endif /* HAVE_SETPRIORITY */
+
 #define MAXENVIRON     32
 
 /*
@@ -172,44 +249,23 @@ char copyright[] =
  */
 int    timeout = 300;
 
-struct passwd *pwd;
-#ifdef HAVE_SHADOW
-struct spwd *spwd;
-#endif
-
 char term[64], *hostname, *username;
 
-#ifndef POSIX_TERMIOS
-struct sgttyb sgttyb;
-struct tchars tc = {
-       CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
-};
-struct ltchars ltc = {
-       CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT
-};
-#endif
+extern int errno;
 
-#ifdef KRB4
+#ifdef KRB4_GET_TICKETS
 #define KRB_ENVIRON    "KRBTKFILE"     /* Ticket file environment variable */
 #define KRB_TK_DIR     "/tmp/tkt_"     /* Where to put the ticket */
 #define MAXPWSIZE      128             /* Biggest string accepted for KRB4
                                           passsword */
-
-AUTH_DAT *kdata = (AUTH_DAT *) NULL;
-KTEXT ticket = (KTEXT) NULL;
-char tkfile[MAXPATHLEN];
-int krbflag = 0;                       /* set if tickets have been obtained */
-#ifdef SETPAG
-int pagflag = 0;                       /* true if setpag() has been called */
-#endif /* SETPAG */
-#endif /* KRB4 */
+#endif /* KRB4_GET_TICKETS */
 
 char *getenv();
 void dofork();
 
 int doremotelogin(), do_krb_login(), rootterm();
-void lgetstr(), doremoteterm(), getloginname(), checknologin(), sleepexit();
-void dolastlog(), motd();
+void lgetstr(), getloginname(), checknologin(), sleepexit();
+void dolastlog(), motd(), check_mail();
 
 #ifndef HAVE_STRSAVE
 char * strsave();
@@ -218,6 +274,783 @@ char * strsave();
 typedef krb5_sigtype sigtype;
 
 
+#ifndef HAVE_INITGROUPS
+static int initgroups(char* name, gid_t basegid) {
+  gid_t others[NGROUPS_MAX+1];
+  int ngrps;
+
+  others[0] = basegid;
+  ngrps = getgroups(NGROUPS_MAX, others+1);
+  return setgroups(ngrps+1, others);
+}
+#endif
+
+#ifdef KRB5_GET_TICKETS
+static struct login_confs {
+       char *flagname;
+       int *flag;
+} login_conf_set[] = {
+       "krb5_get_tickets", &login_krb5_get_tickets,
+#ifdef KRB5_KRB4_COMPAT
+       "krb4_get_tickets", &login_krb4_get_tickets,
+       "krb4_convert", &login_krb4_convert,
+       "krb4_run_aklog", &login_krb_run_aklog,
+#endif /* KRB5_KRB4_COMPAT */
+};
+static char *conf_yes[] = {
+       "y", "yes", "true", "t", "1", "on",
+       0
+};
+static char *conf_no[] = {
+       "n", "no", "false", "nil", "0", "off",
+       0
+};
+/* 1 = true, 0 = false, -1 = ambiguous */
+static int conf_affirmative(s)
+       char *s;
+{
+       char **p;
+       for(p=conf_yes; *p; p++) {
+               if (!strcasecmp(*p,s))
+                       return 1;
+       }
+       for(p=conf_no; *p; p++) {
+               if (!strcasecmp(*p,s))
+                       return 0;
+       }
+       /* ambiguous */
+       return -1;
+}
+#endif /* KRB5_GET_TICKETS */
+
+#ifdef KRB5_GET_TICKETS
+krb5_data tgtname = {
+    0,
+    KRB5_TGS_NAME_SIZE,
+    KRB5_TGS_NAME
+};
+#endif
+
+#ifdef KRB5_GET_TICKETS
+/* get flags (listed above) from the profile */
+void login_get_kconf(k)
+       krb5_context k;
+{
+       int i, max_i;
+       const char* kconf_names[3];
+       char **kconf_val;
+       int retval;
+
+       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) {
+                       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;
+                       }
+               }
+       }
+}
+#endif /* KRB5_GET_TICKETS */
+
+\f
+/* UNIX password support */
+
+struct passwd *pwd;
+static char *salt;
+
+#ifdef HAVE_SHADOW
+struct spwd *spwd;
+#endif
+
+void lookup_user (name)
+    char *name;
+{
+    pwd = getpwnam (name);
+    salt = pwd ? pwd->pw_passwd : "xx";
+#ifdef HAVE_SHADOW
+    spwd = getspnam (name);
+    if (spwd)
+       salt = spwd->sp_pwdp;
+#endif
+}
+
+int unix_needs_passwd ()
+{
+#ifdef HAVE_SHADOW
+    if (spwd)
+       return spwd->sp_pwdp[0] != 0;
+#endif
+    if (pwd)
+       return pwd->pw_passwd[0] != 0;
+    return 1;
+}
+
+int unix_passwd_okay (pass)
+    char *pass;
+{
+    char user_pwcopy[9], *namep;
+    char *crypt ();
+
+    assert (pwd != 0);
+
+    /* copy the first 8 chars of the password for unix crypt */
+    strncpy(user_pwcopy, pass, sizeof(user_pwcopy));
+    user_pwcopy[8]='\0';
+    namep = crypt(user_pwcopy, salt);
+    memset (user_pwcopy, 0, sizeof(user_pwcopy));
+    /* ... and wipe the copy now that we have the string */
+
+    /* verify the local password string */
+#ifdef HAVE_SHADOW
+    if (spwd)
+       return !strcmp(namep, spwd->sp_pwdp);
+#endif
+    return !strcmp (namep, pwd->pw_passwd);
+}
+\f
+/* Kerberos support */
+#ifdef KRB5_GET_TICKETS
+krb5_context kcontext;
+krb5_ccache ccache;
+static int got_v5_tickets, got_v4_tickets;
+char ccfile[MAXPATHLEN+6];     /* FILE:path+\0 */
+int krbflag;                   /* set if tickets have been obtained */
+
+#ifdef KRB4_GET_TICKETS
+AUTH_DAT *kdata = (AUTH_DAT *) NULL;
+KTEXT ticket = (KTEXT) NULL;
+char tkfile[MAXPATHLEN];
+char realm[REALM_SZ];
+#endif
+
+void k_init (ttyn)
+    char *ttyn;
+{
+    krb5_init_context(&kcontext);
+    krb5_init_ets(kcontext);
+    login_get_kconf(kcontext);
+
+    /* Set up the credential cache environment variable */
+    if (!getenv(KRB5_ENV_CCNAME)) {
+       sprintf(ccfile, "FILE:/tmp/krb5cc_%s", strrchr(ttyn, '/')+1);
+       setenv(KRB5_ENV_CCNAME, ccfile, 1);
+       unlink(ccfile+strlen("FILE:"));
+    } else {
+       /* note it correctly */
+       strcpy(ccfile, getenv(KRB5_ENV_CCNAME));
+    }
+
+#ifdef KRB4_GET_TICKETS
+    if (krb_get_lrealm(realm, 1) != KSUCCESS) {
+       strncpy(realm, KRB_REALM, sizeof(realm));
+    }
+    if (login_krb4_get_tickets) {
+       /* Set up the ticket file environment variable */
+       strncpy(tkfile, KRB_TK_DIR, sizeof(tkfile));
+       strncat(tkfile, strrchr(ttyn, '/')+1,
+               sizeof(tkfile) - strlen(tkfile));
+       (void) unlink (tkfile);
+       setenv(KRB_ENVIRON, tkfile, 1);
+    }
+#endif
+
+#ifdef BIND_HACK
+    /* Set name server timeout to be reasonable,
+       so that people don't take 5 minutes to
+       log in.  Can you say abstraction violation? */
+    _res.retrans = 1;
+#endif /* BIND_HACK */
+}
+
+int k5_get_password (user_pwstring, pwsize)
+    char *user_pwstring;
+{
+    krb5_error_code code;
+    char prompt[255];                  
+    sprintf(prompt,"Password for %s: ", username);
+
+    /* reduce opportunities to be swapped out */
+    code = krb5_read_password(kcontext, prompt, 0, user_pwstring, &pwsize);
+    if (code || pwsize == 0) {
+       fprintf(stderr, "Error while reading password for '%s'\n", username);
+       /* reading password failed... */
+       return 0;
+    }
+    if (pwsize == 0) {
+       fprintf(stderr, "No password read\n");
+       /* reading password failed... */
+       return 0;
+    }
+    return 1;
+}
+
+#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
+int krb5_options = 0;
+krb5_deltat krb5_ticket_lifetime = KRB5_DEFAULT_LIFE;
+
+int try_krb5 (me_p, pass)
+    krb5_principal *me_p;
+    char *pass;
+{
+    krb5_error_code code;
+    krb5_principal server, me;
+    krb5_creds my_creds;
+    krb5_timestamp now;
+    krb5_deltat lifetime = krb5_ticket_lifetime;
+
+    /* set up credential cache -- obeying KRB5_ENV_CCNAME 
+       set earlier */
+    /* (KRB5_ENV_CCNAME == "KRB5CCNAME" via osconf.h) */
+    if (code = krb5_cc_default(kcontext, &ccache)) {
+       com_err("login", code, "while getting default ccache");
+       return 0;
+    }
+    /* setup code from v5 kinit */
+    memset((char *)&my_creds, 0, sizeof(my_creds));
+
+    code = krb5_parse_name (kcontext, username, &me);
+    if (code) {
+       com_err ("login", code, "when parsing name %s",username);
+       return 0;
+    }
+    *me_p = my_creds.client = me;
+
+    code = krb5_cc_initialize (kcontext, ccache, me);
+    if (code) {
+       com_err ("login", code, 
+                "when initializing cache");
+       return 0;
+    }
+
+    code = krb5_build_principal_ext(kcontext, &server,
+                                   krb5_princ_realm(kcontext, me)->length,
+                                   krb5_princ_realm(kcontext, me)->data,
+                                   tgtname.length, tgtname.data,
+                                   krb5_princ_realm(kcontext, me)->length,
+                                   krb5_princ_realm(kcontext, me)->data,
+                                   0);
+    if (code) {
+       com_err("login", code,
+               "while building server name");
+       goto nuke_ccache;
+    }
+
+    my_creds.server = server;
+    code = krb5_timeofday(kcontext, &now);
+    if (code) {
+       com_err("login", code,
+               "while getting time of day");
+       goto nuke_ccache;
+    }
+    my_creds.times.starttime = 0; /* start timer when 
+                                    request gets to KDC */
+    my_creds.times.endtime = now + lifetime;
+    my_creds.times.renew_till = 0;
+
+    code = krb5_get_in_tkt_with_password(kcontext, krb5_options,
+                                        0, NULL, 0 /*preauth*/,
+                                        pass,
+                                        ccache,
+                                        &my_creds, 0);
+
+    if (code) {
+       if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
+           fprintf (stderr,
+                    "%s: Kerberos password incorrect\n", 
+                    username);
+       else
+           com_err ("login", code,
+                    "while getting initial credentials");
+    nuke_ccache:
+       krb5_cc_destroy (kcontext, ccache);
+       return 0;
+    } else {
+       /* get_name pulls out just the name not the
+          type */
+       strcpy(ccfile, krb5_cc_get_name(kcontext, ccache));
+       (void) chown(ccfile, pwd->pw_uid, pwd->pw_gid);
+       krbflag = got_v5_tickets = 1;
+       return 1;
+    }
+}
+
+int have_v5_tickets (me)
+    krb5_principal *me;
+{
+    if (krb5_cc_default (kcontext, &ccache))
+       return 0;
+    if (krb5_cc_get_principal (kcontext, ccache, me)) {
+       krb5_cc_close (kcontext, ccache);
+       return 0;
+    }
+    krbflag = 1;
+    return 1;
+}
+
+#ifdef KRB4_CONVERT
+try_convert524 (kcontext, me)
+     krb5_context kcontext;
+     krb5_principal me;
+{
+    krb5_principal kpcserver;
+    krb5_error_code kpccode;
+    int kpcval;
+    krb5_creds increds, *v5creds;
+    CREDENTIALS v4creds;
+
+    if (!got_v5_tickets)
+       return 0;
+
+    /* or do this directly with krb524_convert_creds_kdc */
+    krb524_init_ets(kcontext);
+    /* cc->ccache, already set up */
+    /* client->me, already set up */
+    if ((kpccode = krb5_build_principal(kcontext,
+                                       &kpcserver, 
+                                       krb5_princ_realm(kcontext, me)->length,
+                                       krb5_princ_realm(kcontext, me)->data,
+                                       "krbtgt",
+                                       krb5_princ_realm(kcontext, me)->data,
+                                       NULL))) {
+      com_err("login/v4", kpccode,
+             "while creating service principal name");
+      return 0;
+    }
+
+    memset((char *) &increds, 0, sizeof(increds));
+    increds.client = me;
+    increds.server = kpcserver;
+    increds.times.endtime = 0;
+    increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+    if ((kpccode = krb5_get_credentials(kcontext, 0, 
+                                       ccache,
+                                       &increds, 
+                                       &v5creds))) {
+       com_err("login/v4", kpccode,
+               "getting V5 credentials");
+       return 0;
+    }
+    if ((kpccode = krb524_convert_creds_kdc(kcontext, 
+                                           v5creds,
+                                           &v4creds))) {
+       com_err("login/v4", kpccode, 
+               "converting to V4 credentials");
+       return 0;
+    }
+    /* this is stolen from the v4 kinit */
+    /* initialize ticket cache */
+    if ((kpcval = in_tkt(v4creds.pname,v4creds.pinst)
+        != KSUCCESS)) {
+       com_err("login/v4", kpcval,
+               "trying to create the V4 ticket file");
+       return 0;
+    }
+    /* stash ticket, session key, etc. for future use */
+    if ((kpcval = krb_save_credentials(v4creds.service,
+                                      v4creds.instance,
+                                      v4creds.realm, 
+                                      v4creds.session,
+                                      v4creds.lifetime,
+                                      v4creds.kvno,
+                                      &(v4creds.ticket_st), 
+                                      v4creds.issue_date))) {
+       com_err("login/v4", kpcval,
+               "trying to save the V4 ticket");
+       return 0;
+    }
+    got_v4_tickets = 1;
+    strcpy(tkfile, tkt_string());
+    (void) chown(tkfile, pwd->pw_uid, pwd->pw_gid);
+    return 1;
+}
+#endif
+
+#ifdef KRB4_GET_TICKETS
+try_krb4 (me, user_pwstring)
+    krb5_principal me;
+    char *user_pwstring;
+{
+    int krbval, kpass_ok = 0;
+
+    krbval = krb_get_pw_in_tkt(username, "", realm,
+                              "krbtgt", realm, 
+                              DEFAULT_TKT_LIFE,
+                              user_pwstring);
+
+    switch (krbval) {
+    case INTK_OK:
+       kpass_ok = 1;
+       krbflag = 1;
+       strcpy(tkfile, tkt_string());
+       (void) chown(tkfile, pwd->pw_uid, pwd->pw_gid);
+       break;  
+       /* These errors should be silent */
+       /* So the Kerberos database can't be probed */
+    case KDC_NULL_KEY:
+    case KDC_PR_UNKNOWN:
+    case INTK_BADPW:
+    case KDC_PR_N_UNIQUE:
+    case -1:
+       break;
+#if 0 /* I want to see where INTK_W_NOTALL comes from before letting
+        kpass_ok be set in that case.  KR  */
+       /* These should be printed but are not fatal */
+    case INTK_W_NOTALL:
+       krbflag = 1;
+       kpass_ok = 1;
+       fprintf(stderr, "Kerberos error: %s\n",
+               krb_get_err_text(krbval));
+       break;
+#endif
+    default:
+       fprintf(stderr, "Kerberos error: %s\n",
+               krb_get_err_text(krbval));
+       break;
+    }
+    got_v4_tickets = kpass_ok;
+    return kpass_ok;
+}
+#endif /* KRB4_GET_TICKETS */
+
+/* Kerberos ticket-handling routines */
+
+#ifdef KRB4_GET_TICKETS
+/* call already conditionalized on login_krb4_get_tickets */
+/*
+ * Verify the Kerberos ticket-granting ticket just retrieved for the
+ * user.  If the Kerberos server doesn't respond, assume the user is
+ * trying to fake us out (since we DID just get a TGT from what is
+ * supposedly our KDC).  If the rcmd.<host> service is unknown (i.e.,
+ * the local srvtab doesn't have it), let her in.
+ *
+ * Returns 1 for confirmation, -1 for failure, 0 for uncertainty.
+ */
+int verify_krb_v4_tgt (realm)
+    char *realm;
+{
+    char hostname[MAXHOSTNAMELEN], phost[BUFSIZ];
+    struct hostent *hp;
+    KTEXT_ST ticket;
+    AUTH_DAT authdata;
+    unsigned long addr;
+    static /*const*/ char rcmd[] = "rcmd";
+    char key[8];
+    int krbval, retval, have_keys;
+
+    if (gethostname(hostname, sizeof(hostname)) == -1) {
+       perror ("cannot retrieve local hostname");
+       return -1;
+    }
+    strncpy (phost, krb_get_phost (hostname), sizeof (phost));
+    phost[sizeof(phost)-1] = 0;
+    hp = gethostbyname (hostname);
+    if (!hp) {
+       perror ("cannot retrieve local host address");
+       return -1;
+    }
+    memcpy ((char *) &addr, (char *)hp->h_addr, sizeof (addr));
+    /* Do we have rcmd.<host> keys? */
+#if 0 /* Be paranoid.  If srvtab exists, assume it must contain the
+        right key.  */
+    have_keys = read_service_key (rcmd, phost, realm, 0, KEYFILE, key)
+       ? 0 : 1;
+    memset (key, 0, sizeof (key));
+#else
+    have_keys = 0 == access (KEYFILE, F_OK);
+#endif
+    krbval = krb_mk_req (&ticket, rcmd, phost, realm, 0);
+    if (krbval == KDC_PR_UNKNOWN) {
+       /*
+        * Our rcmd.<host> principal isn't known -- just assume valid
+        * for now?  This is one case that the user _could_ fake out.
+        */
+       if (have_keys)
+           return -1;
+       else
+           return 0;
+    }
+    else if (krbval != KSUCCESS) {
+       printf ("Unable to verify Kerberos TGT: %s\n", 
+               krb_get_err_text(krbval));
+#ifndef SYSLOG42
+       syslog (LOG_NOTICE|LOG_AUTH, "Kerberos TGT bad: %s",
+               krb_get_err_text(krbval));
+#endif
+       return -1;
+    }
+    /* got ticket, try to use it */
+    krbval = krb_rd_req (&ticket, rcmd, phost, addr, &authdata, "");
+    if (krbval != KSUCCESS) {
+       if (krbval == RD_AP_UNDEC && !have_keys)
+           retval = 0;
+       else {
+           retval = -1;
+           printf ("Unable to verify `rcmd' ticket: %s\n",
+                   krb_get_err_text(krbval));
+       }
+#ifndef SYSLOG42
+       syslog (LOG_NOTICE|LOG_AUTH, "can't verify rcmd ticket: %s;%s\n",
+               krb_get_err_text(krbval),
+               retval
+               ? "srvtab found, assuming failure"
+               : "no srvtab found, assuming success");
+#endif
+       goto EGRESS;
+    }
+    /*
+     * The rcmd.<host> ticket has been received _and_ verified.
+     */
+    retval = 1;
+    /* do cleanup and return */
+EGRESS:
+    memset (&ticket, 0, sizeof (ticket));
+    memset (&authdata, 0, sizeof (authdata));
+    return retval;
+}
+#endif /* KRB4_GET_TICKETS */
+
+/* call already conditionalized on login_krb5_get_tickets */
+/*
+ * Verify the Kerberos ticket-granting ticket just retrieved for the
+ * user.  If the Kerberos server doesn't respond, assume the user is
+ * trying to fake us out (since we DID just get a TGT from what is
+ * supposedly our KDC).  If the host/<host> service is unknown (i.e.,
+ * the local keytab doesn't have it), let her in.
+ *
+ * Returns 1 for confirmation, -1 for failure, 0 for uncertainty.
+ */
+int verify_krb_v5_tgt (c, realm)
+    krb5_context c;
+    char *realm;
+{
+    char phost[BUFSIZ];
+    krb5_ccache ccdef;
+    int retval, have_keys;
+    krb5_principal princ;
+    krb5_keyblock *kb = 0;
+    krb5_error_code krbval;
+    krb5_data packet;
+    krb5_auth_context auth_context = NULL;
+    krb5_ticket *ticket = NULL;
+
+    /* XXX This is to work around a library bug.  I'm not sure if it's
+       been fixed for beta-6, so leave this in for now.  Remove it (and
+       fix the bug if necessary) after beta-6 ships.  */
+    sleep(2);
+
+    /* get the server principal for the local host */
+    /* (use defaults of "host" and canonicalized local name) */
+    krbval = krb5_sname_to_principal(c, 0, 0, KRB5_NT_SRV_HST, &princ);
+    if (krbval) {
+           com_err ("login", krbval, "constructing local service name");
+           return -1;
+    }
+
+    /* since krb5_sname_to_principal has done the work for us, just
+       extract the name directly */
+    strncpy(phost, krb5_princ_component(c, princ, 1)->data, BUFSIZ);
+
+    /* Do we have host/<host> keys? */
+    /* (use default keytab, kvno IGNORE_VNO to get the first match,
+       and enctype is currently ignored anyhow.) */
+    krbval = krb5_kt_read_service_key (c, NULL, princ, 0, ENCTYPE_DES_CBC_CRC, &kb);
+    if (kb)
+       krb5_free_keyblock (c, kb);
+    /* any failure means we don't have keys at all. */
+    have_keys = krbval ? 0 : 1;
+
+    /* set up credential cache -- obeying KRB5_ENV_CCNAME set earlier */
+    /* (KRB5_ENV_CCNAME == "KRB5CCNAME" via osconf.h) */
+    if (krbval = krb5_cc_default(c, &ccdef)) {
+       com_err("login", krbval, "while getting default ccache");
+       return -1;
+    }
+    /* talk to the kdc and construct the ticket */
+    krbval = krb5_mk_req(c, &auth_context, 0, "host", phost,
+                        0, ccdef, &packet);
+    /* wipe the auth context for mk_req */
+    if (auth_context) {
+       krb5_auth_con_free(c, auth_context);
+       auth_context = NULL;
+    }
+    if (krbval == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) {
+           /* we have a service key, so something should be 
+              in the database, therefore this error packet could
+              have come from an attacker. */
+           if (have_keys) { retval = -1; goto EGRESS; }
+           /* but if it is unknown and we've got no key, we don't
+              have any security anyhow, so it is ok. */
+           else { retval = 0; goto EGRESS; }
+    }
+    else if (krbval) {
+           com_err("login", krbval, 
+                   "Unable to verify Kerberos V5 TGT: %s", phost);
+#ifndef SYSLOG42
+           syslog (LOG_NOTICE|LOG_AUTH, "Kerberos V5 TGT bad: %s", 
+                   error_message(krbval));
+#endif
+           retval = -1;
+           goto EGRESS;
+    }
+    /* got ticket, try to use it */
+    krbval = krb5_rd_req(c, &auth_context, &packet, 
+                        princ, NULL, NULL, &ticket);
+    if (krbval) {
+       if (!have_keys)
+           /* The krb5 errors aren't specified well, but I think
+              these values cover the cases we expect.  */
+           switch (krbval) {
+               /* no keytab */
+           case ENOENT:
+               /* keytab found, missing entry */
+#if 0 /* Don't depend on the nameserver for security.  Assume that if
+        we have a keytab, it must contain the right host/FQDN key.  */
+           case KRB5_KT_NOTFOUND:
+#endif
+               retval = 0;
+               break;
+           default:
+               /* unexpected error: fail */
+               retval = -1;
+               break;
+           }
+       else
+           /* Any error here is bad.  */
+           retval = -1;
+       com_err("login", krbval, "Unable to verify host ticket");
+#ifndef SYSLOG42
+       syslog (LOG_NOTICE|LOG_AUTH, "can't verify v5 ticket: %s; %s\n",
+               error_message(krbval),
+               retval
+               ? "keytab found, assuming failure"
+               : "no keytab found, assuming success");
+#endif
+       goto EGRESS;
+    }
+    /*
+     * The host/<host> ticket has been received _and_ verified.
+     */
+    retval = 1;
+    /* do cleanup and return */
+EGRESS:
+    if (auth_context) krb5_auth_con_free(c, auth_context);
+    krb5_free_principal(c, princ);
+    /* possibly ticket and packet need freeing here as well */
+    /* memset (&ticket, 0, sizeof (ticket)); */
+    return retval;
+}
+
+destroy_tickets()
+{
+       krb5_context c;
+       krb5_ccache cache;
+
+       if (login_krb5_get_tickets) {
+       krb5_init_context(&c);
+       
+       if(!krb5_cc_default(c, &cache))
+               krb5_cc_destroy (c, cache);
+       }
+#ifdef KRB4_GET_TICKETS
+       if (login_krb4_get_tickets)
+       dest_tkt();
+#endif /* KRB4_GET_TICKETS */
+}
+
+#endif /* KRB5_GET_TICKETS */
+\f
+/* AFS support routines */
+#ifdef SETPAG
+
+int pagflag = 0;                       /* true if setpag() has been called */
+
+static sigjmp_buf setpag_buf;
+
+static sigtype sigsys ()
+{
+    siglongjmp(setpag_buf, 1);
+}
+
+static int try_afscall ()
+{
+    handler sa, osa;
+    volatile int retval = 0;
+
+    (void) &retval;
+    handler_init (sa, sigsys);
+    handler_swap (SIGSYS, sa, osa);
+    if (sigsetjmp(setpag_buf, 1) == 0) {
+       setpag ();
+       retval = 1;
+    }
+    handler_set (SIGSYS, osa);
+    return retval;
+}
+
+/* This doesn't seem to be declared in the AFS header files.  */
+extern ktc_ForgetAllTokens (), setpag ();
+
+#define try_setpag()   try_afscall(setpag)
+#define try_unlog()    try_afscall(ktc_ForgetAllTokens)
+#endif /* SETPAG */
+
+void
+afs_login ()
+{
+#ifdef KRB4_GET_TICKETS
+#ifdef SETPAG
+    if (login_krb4_get_tickets && pwd->pw_uid) {
+       /* Only reset the pag for non-root users. */
+       /* This allows root to become anything. */
+       pagflag = try_setpag ();
+    }
+#endif
+#endif /* KRB4_GET_TICKETS */
+#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 */
+       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);
+       }
+    }
+#endif /* KRB_RUN_AKLOG */
+}
+
+void
+afs_cleanup ()
+{
+#ifdef SETPAG
+    if (pagflag)
+      try_unlog ();
+#endif
+}
+\f
+/* Main routines */
 #define EXCL_AUTH_TEST if (rflag || kflag || Kflag || eflag || fflag || Fflag ) { \
                                fprintf(stderr, \
                                    "login: only one of -r, -k, -K, -e, -F, and -f allowed.\n"); \
@@ -230,16 +1063,54 @@ typedef krb5_sigtype sigtype;
                                exit(1);\
                        }
 
-#ifndef HAVE_INITGROUPS
-int initgroups(char* name, gid_t basegid) {
-  gid_t others[NGROUPS_MAX+1];
-  int ngrps;
-
-  others[0] = basegid;
-  ngrps = getgroups(NGROUPS_MAX, others+1);
-  return setgroups(ngrps+1, others);
+static void
+read_env_vars_from_file (filename)
+    char *filename;
+{
+    FILE *fp;
+    char *p, *eq;
+    char tbuf[MAXPATHLEN+2];
+
+    if ((fp = fopen("/etc/environment", "r")) != NULL) {
+       while (fgets(tbuf, sizeof(tbuf), fp)) {
+           if (tbuf[0] == '#')
+               continue;
+           eq = strchr(tbuf, '=');
+           if (eq == 0)
+               continue;
+           p = strchr (tbuf, '\n');
+           if (p)
+               *p = 0;
+           *eq++ = 0;
+           /* Don't override, in case -p was used.  */
+           setenv (tbuf, eq, 0);
+       }
+       fclose(fp);
+    }
 }
+
+static void
+log_repeated_failures (tty, hostname)
+    char *tty, *hostname;
+{
+    if (hostname) {
+#ifdef UT_HOSTSIZE
+       syslog(LOG_ERR,
+              "REPEATED LOGIN FAILURES ON %s FROM %.*s, %.*s",
+              tty, UT_HOSTSIZE, hostname, UT_NAMESIZE,
+              username);
+#else
+       syslog(LOG_ERR,
+              "REPEATED LOGIN FAILURES ON %s FROM %s, %.*s",
+              tty, hostname, UT_NAMESIZE,
+              username);
 #endif
+    }
+    else
+       syslog(LOG_ERR,
+              "REPEATED LOGIN FAILURES ON %s, %.*s",
+              tty, UT_NAMESIZE, username);
+}
 
 int main(argc, argv)
        int argc;
@@ -248,46 +1119,34 @@ int main(argc, argv)
        extern int optind;
        extern char *optarg, **environ;
        struct group *gr;
-       register int ch, i;
-       register char *p;
+       int ch;
+       char *p;
        int fflag, hflag, pflag, rflag, Fflag, cnt;
        int kflag, Kflag, eflag;
        int quietlog, passwd_req, ioctlval;
        sigtype timedout();
-       char *domain, *salt, **envinit, *ttyn, *tty;
+       char *domain, **envinit, *ttyn, *tty;
        char tbuf[MAXPATHLEN + 2];
        char *ttyname(), *stypeof(), *crypt(), *getpass();
        time_t login_time;
+       int retval;
+#ifdef KRB5_GET_TICKETS
+       krb5_principal me;
+#endif /* KRB5_GET_TICKETS */
        char *ccname = 0;   /* name of forwarded cache */
-int retval;
-       
+       char *tz = 0;
+
        off_t lseek();
-#ifdef POSIX_TERMIOS
-       struct termios tc;
-#endif
-#ifdef POSIX_SIGNALS
-       struct sigaction sa;
-#endif
+       handler sa;
 
-#ifdef POSIX_SIGNALS
-       (void)sigemptyset(&sa.sa_mask);
-       sa.sa_flags = 0;
-       sa.sa_handler = timedout;
-       (void)sigaction(SIGALRM, &sa, (struct sigaction *)0);
-#else
-       (void)signal(SIGALRM, timedout);
-#endif
+       handler_init (sa, timedout);
+       handler_set (SIGALRM, sa);
        (void)alarm((u_int)timeout);
-#ifdef POSIX_SIGNALS
-       sa.sa_handler = SIG_IGN;
-       (void)sigaction(SIGALRM, &sa, (struct sigaction *)0);
-#else
-       (void)signal(SIGQUIT, SIG_IGN);
-       (void)signal(SIGINT, SIG_IGN);
-#endif
-#ifdef HAVE_SETPRIORITY
-       (void)setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
-#endif
+
+       handler_init (sa, SIG_IGN);
+       handler_set (SIGQUIT, sa);
+       handler_set (SIGINT, sa);
+       setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
 #ifdef OQUOTA
        (void)quota(Q_SETUID, 0, 0, 0);
 #endif
@@ -356,7 +1215,7 @@ int retval;
                                *p = '\0';
                        hostname = optarg;
                        break;
-#ifdef KRB4
+#ifdef KRB4_KLOGIN
                case 'k':
                case 'K':
                        EXCL_AUTH_TEST;
@@ -382,7 +1241,7 @@ int retval;
                                *p = '\0';
                        hostname = optarg;
                        break;
-#endif /* KRB4 */
+#endif /* KRB4_KLOGIN */
                case 'e':
                        EXCL_AUTH_TEST;
                        if (getuid()) {
@@ -422,85 +1281,14 @@ int retval;
 #endif
        (void)fcntl(0, F_SETFL, ioctlval);
 
-#ifdef POSIX_TERMIOS
-       (void)tcgetattr(0, &tc);
-#else
-       (void)ioctl(0, TIOCGETP, (char *)&sgttyb);
-#endif
-
        /*
         * If talking to an rlogin process, propagate the terminal type and
         * baud rate across the network.
         */
        if (eflag)
                lgetstr(term, sizeof(term), "Terminal type");
-#ifdef POSIX_TERMIOS
-       if (rflag || kflag || Kflag || eflag)
-               doremoteterm(&tc);
-       tc.c_cc[VMIN] = 1;
-       tc.c_cc[VTIME] = 0;
-#ifndef NO_INIT_CC
-       tc.c_cc[VERASE] = CERASE;
-       tc.c_cc[VKILL] = CKILL;
-       tc.c_cc[VEOF] = CEOF;
-       tc.c_cc[VINTR] = CINTR;
-       tc.c_cc[VQUIT] = CQUIT;
-       tc.c_cc[VSTART] = CSTART;
-       tc.c_cc[VSTOP] = CSTOP;
-#ifndef CNUL
-#define CNUL CEOL
-#endif
-       tc.c_cc[VEOL] = CNUL;
-       /* The following are common extensions to POSIX */
-#ifdef VEOL2
-       tc.c_cc[VEOL2] = CNUL;
-#endif
-#ifdef VSUSP
-#if !defined(CSUSP) && defined(CSWTCH)
-#define CSUSP CSWTCH
-#endif
-       tc.c_cc[VSUSP] = CSUSP;
-#endif
-#ifdef VDSUSP
-       tc.c_cc[VDSUSP] = CDSUSP;
-#endif
-#ifdef VLNEXT
-       tc.c_cc[VLNEXT] = CLNEXT;
-#endif
-#ifdef VREPRINT
-       tc.c_cc[VREPRINT] = CRPRNT;
-#endif
-#ifdef VDISCRD
-       tc.c_cc[VDISCRD] = CFLUSH;
-#endif
-#ifdef VDISCARD
-#ifndef CDISCARD
-#define CDISCARD CFLUSH
-#endif
-        tc.c_cc[VDISCARD] = CDISCARD;
-#endif
-#ifdef VWERSE
-       tc.c_cc[VWERSE] = CWERASE;
-#endif
-#ifdef VWERASE
-        tc.c_cc[VWERASE] = CWERASE;
-#endif
-#ifdef VSTATUS
-#ifdef CSTATUS
-        tc.c_cc[VSTATUS] = CSTATUS;
-#endif /* CSTATUS */
-#endif /* VSTATUS */
-#endif /* NO_INIT_CC */
-       tcsetattr(0, TCSANOW, &tc);
-#else
-       if (rflag || kflag || Kflag || eflag)
-               doremoteterm(&sgttyb);
-       sgttyb.sg_erase = CERASE;
-       sgttyb.sg_kill = CKILL;
-       (void)ioctl(0, TIOCSLTC, (char *)&ltc);
-       (void)ioctl(0, TIOCSETC, (char *)&tc);
-       (void)ioctl(0, TIOCSETP, (char *)&sgttyb);
-#endif
+       term_init (rflag || kflag || Kflag || eflag);
+
        for (cnt = getdtablesize(); cnt > 2; cnt--)
                (void) close(cnt);
 
@@ -520,36 +1308,35 @@ int retval;
        openlog("login", LOG_ODELAY, LOG_AUTH);
 #endif /* 4.2 syslog */
 
+/******* begin askpw *******/
+       /* overall:
+          ask for username if we don't have it already
+          look it up in local pw or shadow file (to get crypt string)
+          ask for password
+          try and get v4, v5 tickets with it
+          try and use the tickets against the local srvtab
+          if the password matches, always let them in
+          if the ticket decrypts, let them in.
+          v5 needs to work, does v4?
+          */
+
+#ifdef KRB5_GET_TICKETS
+       k_init (ttyn);
+#endif
+
        for (cnt = 0;; username = NULL) {
-#ifdef KRB4
-               char pp[9], pp2[MAXPWSIZE], *namep;
-               int krbval;
-               char realm[REALM_SZ];
+#ifdef KRB5_GET_TICKETS
                int kpass_ok,lpass_ok;
-#ifdef NOENCRYPTION
-#define read_long_pw_string placebo_read_pw_string
-#else
-#define read_long_pw_string des_read_pw_string
-#endif
-               int read_long_pw_string();
-#endif /* KRB4 */
-#if defined(TIOCSETD)&&(!defined(POSIX_TERMIOS))
-               ioctlval = 0;
-               (void)ioctl(0, TIOCSETD, (char *)&ioctlval);
-#endif
+               char user_pwstring[MAXPWSIZE];
+               /* variables from v5 kinit */
+#endif /* KRB5_GET_TICKETS */
+
                if (username == NULL) {
                        fflag = Fflag = 0;
                        getloginname();
-               }
-
-               if ((pwd = getpwnam(username)))
-                       salt = pwd->pw_passwd;
-               else
-                       salt = "xx";
-#ifdef HAVE_SHADOW
-               if (spwd = getspnam(username))
-                   salt = spwd->sp_pwdp;
-#endif
+               }
+
+               lookup_user (username); /* sets pwd */
 
                /* if user not super-user, check for disabled logins */
                if (pwd == NULL || pwd->pw_uid)
@@ -580,96 +1367,56 @@ int retval;
                 * If no remote login authentication and a password exists
                 * for this user, prompt for one and verify it.
                 */
-               if (!passwd_req) break;
-#ifdef HAVE_SHADOW
-               if (spwd) {
-                   if (!*(spwd->sp_pwdp)) break;
-               } else
-#endif
-                   if (pwd && !*(pwd->pw_passwd))
-                       break;
+               if (!passwd_req)
+                   break;
 
-#ifdef KRB4
+               if (! unix_needs_passwd ())
+                   break;
+
+               /* we have several sets of code:
+                  1) get v5 tickets alone -DKRB5_GET_TICKETS
+                  2) get v4 tickets alone [** don't! only get them *with* v5 **]
+                  3) get both tickets -DKRB5_GET_TICKETS -DKRB4_GET_TICKETS
+                  3a) use krb524 calls to get the v4 tickets -DKRB4_CONVERT plus (3).
+                  4) get no tickets and use the password file (none of thes defined.)
+                  
+                  Likewise we need to (optionally?) test these tickets against local srvtabs.
+                  */
+#ifdef KRB5_GET_TICKETS
+               if (login_krb5_get_tickets) {
+               /* rename these to something more verbose */
                kpass_ok = 0;
                lpass_ok = 0;
 
-#ifdef HAVE_SETPRIORITY
-               (void) setpriority(PRIO_PROCESS, 0, -4 + PRIO_OFFSET);
-#endif
-               if (read_long_pw_string(pp2, sizeof(pp2)-1, "Password: ", 0)) {
-                   /* reading password failed... */
-#ifdef HAVE_SETPRIORITY
-                   (void) setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
-#endif
+               setpriority(PRIO_PROCESS, 0, -4 + PRIO_OFFSET);
+               if (! k5_get_password (user_pwstring, sizeof (user_pwstring))) {
                    goto bad_login;
                }
-               if (!pwd)               /* avoid doing useless work */
-                   goto bad_login;
 
-               /* Modifications for Kerberos authentication -- asp */
-               (void) strncpy(pp, pp2, sizeof(pp));
-               pp[8]='\0';
-               namep = crypt(pp, salt);
-               memset (pp, 0, sizeof(pp));     /* To the best of my recollection, Senator... */
+               /* now that we have the password, we've obscured things
+                  sufficiently, and can avoid trying tickets */
+               if (!pwd)
+                       goto bad_login;
+
+               lpass_ok = unix_passwd_okay (user_pwstring);
 
-#ifdef HAVE_SHADOW
-               if (spwd)
-                   lpass_ok = !strcmp(namep, spwd->sp_pwdp);
-               else
-#endif
-                   lpass_ok = !strcmp (namep, pwd->pw_passwd);
-               
                if (pwd->pw_uid != 0) { /* Don't get tickets for root */
+                       try_krb5 (&me, user_pwstring);
 
-                   if (krb_get_lrealm(realm, 1) != KSUCCESS) {
-                       (void) strncpy(realm, KRB_REALM, sizeof(realm));
-                   }
-#ifdef BIND_HACK
-                   /* Set name server timeout to be reasonable,
-                      so that people don't take 5 minutes to
-                      log in.  Can you say abstraction violation? */
-                   _res.retrans = 1;
-#endif /* BIND_HACK */
+#ifdef KRB4_GET_TICKETS
+                       if (login_krb4_get_tickets
+                           && (!got_v5_tickets
+                               || !login_krb4_convert))
+                           try_krb4 (me, user_pwstring);
+#endif
+                       krbflag = got_v5_tickets || got_v4_tickets;
+                       memset (user_pwstring, 0, sizeof(user_pwstring));
+                       /* password wiped, so we can relax */
+                       setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
 
-                   krbval = krb_get_pw_in_tkt(username, "", realm, "krbtgt",
-                                              realm, DEFAULT_TKT_LIFE, pp2);
-                   memset (pp2, 0, sizeof(pp2));
-#ifdef HAVE_SETPRIORITY
-                   (void) setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
-#endif
-                   switch (krbval) {
-                   case INTK_OK:
-                       kpass_ok = 1;
-                       krbflag = 1;
-                       strcpy(tkfile, tkt_string());
-                       (void) chown(tkfile, pwd->pw_uid, pwd->pw_gid);
-                       break;  
-
-                   /* These errors should be silent */
-                   /* So the Kerberos database can't be probed */
-                   case KDC_NULL_KEY:
-                   case KDC_PR_UNKNOWN:
-                   case INTK_BADPW:
-                   case KDC_PR_N_UNIQUE:
-                   case -1:
-                       break;
-                   /* These should be printed but are not fatal */
-                   case INTK_W_NOTALL:
-                       krbflag = 1;
-                       kpass_ok = 1;
-                       fprintf(stderr, "Kerberos error: %s\n",
-                               krb_err_txt[krbval]);
-                       break;
-                   default:
-                       fprintf(stderr, "Kerberos error: %s\n",
-                               krb_err_txt[krbval]);
-                       break;
-                   }
                } else {
-                   (void) memset (pp2, 0, sizeof(pp2));
-#ifdef HAVE_SETPRIORITY
-                   (void) setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
-#endif
+                       memset (user_pwstring, 0, sizeof(user_pwstring));
+                       setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
                }
 
                /* Policy: If local password is good, user is good.
@@ -682,52 +1429,41 @@ int retval;
                   if (kpass_ok)
                   */
                if (lpass_ok)
-                   break;
-bad_login:
-               if (krbflag)
-                   dest_tkt();         /* clean up tickets if login fails */
-#else /* !KRB4 */
-#ifdef HAVE_SETPRIORITY
-               (void) setpriority(PRIO_PROCESS, 0, -4 + PRIO_OFFSET);
-#endif
-               p = crypt(getpass("Password:"), salt);
-#ifdef HAVE_SETPRIORITY
-               (void) setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
-#endif
-#ifdef HAVE_SHADOW
-               if (spwd && !strcmp(p, spwd->sp_pwdp))
-                   break;
-               else
-#endif
-                   if (pwd && !strcmp(p, pwd->pw_passwd))
                        break;
-#endif /* KRB4 */
+               if (got_v5_tickets
+                   && verify_krb_v5_tgt(kcontext, realm) != -1)
+                       break;  /* we're ok */
+#ifdef KRB4_GET_TICKETS
+               if (login_krb4_get_tickets) {
+                   if (got_v4_tickets
+                       && ! got_v5_tickets
+                       && verify_krb_v4_tgt(realm) != -1)
+                       break;  /* we're ok */
+               }
+#endif /* KRB4_GET_TICKETS */
+       bad_login:
+               setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
+               if (krbflag)
+                       destroy_tickets(); /* clean up tickets if login fails */
 
+               }
+#endif /* KRB5_GET_TICKETS */
+#ifdef OLD_PASSWD
+               p = getpass ("Password:");
+               /* conventional password only */
+               if (unix_passwd_okay (p))
+                   break;
+#endif /* OLD_PASSWD */
                printf("Login incorrect\n");
                if (++cnt >= 5) {
-                       if (hostname)
-#ifdef UT_HOSTSIZE
-                           syslog(LOG_ERR,
-                               "REPEATED LOGIN FAILURES ON %s FROM %.*s, %.*s",
-                               tty, UT_HOSTSIZE, hostname, UT_NAMESIZE,
-                               username);
-#else
-                           syslog(LOG_ERR,
-                               "REPEATED LOGIN FAILURES ON %s FROM %s, %.*s",
-                               tty, hostname, UT_NAMESIZE,
-                               username);
-#endif
-                       else
-                           syslog(LOG_ERR,
-                               "REPEATED LOGIN FAILURES ON %s, %.*s",
-                               tty, UT_NAMESIZE, username);
+                       log_repeated_failures (tty, hostname);
 /* irix has no tichpcl */
 #ifdef TIOCHPCL
                        (void)ioctl(0, TIOCHPCL, (char *)0);
 #endif
                        sleepexit(1);
                }
-       }
+       } /* end of password retry loop */
 
        /* committed to login -- turn off timeout */
        (void)alarm((u_int)0);
@@ -770,7 +1506,6 @@ bad_login:
                sleepexit(0);
        }
 #endif
-
        if (chdir(pwd->pw_dir) < 0) {
                printf("No directory %s!\n", pwd->pw_dir);
                if (chdir("/"))
@@ -801,17 +1536,26 @@ bad_login:
            (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
 
        (void)chmod(ttyn, 0620);
-#ifdef KRB4
-#ifdef SETPAG
-       if (pwd->pw_uid) {
-           /* Only reset the pag for non-root users. */
-           /* This allows root to become anything. */
-           pagflag = 1;
-           setpag();
+
+#ifdef KRB4_GET_TICKETS
+       if (login_krb4_get_tickets && login_krb4_convert && !got_v4_tickets) {
+
+           /* Maybe telnetd got tickets for us?  */
+           if (!got_v5_tickets && have_v5_tickets (&me))
+               got_v5_tickets = 1;
+
+           if (got_v5_tickets)
+               try_convert524 (kcontext, me);
+
        }
 #endif
-       /* Fork so that we can call kdestroy */
-       dofork();
+
+#ifdef KRB5_GET_TICKETS
+       if (login_krb4_get_tickets || login_krb5_get_tickets) {
+           /* Fork so that we can call kdestroy */
+           dofork();
+       }
+#endif /* KRB4_GET_TICKETS */
 
 /* If the user's shell does not do job control we should put it in a
    different process group than than us, and set the tty process group
@@ -819,25 +1563,48 @@ bad_login:
    telnetd or rlogind if they don't properly detach from their
    controlling tty, which is the case (under SunOS at least.) */
 
-       { int p = getpid(); 
-          if (setpgrp(p,p) < 0) perror("login.krb5: setpgrp");
-         if (ioctl(0, TIOCSPGRP, &p) < 0) perror("login.krb5: tiocspgrp");
-        }
-
-/* SunOS has an ioctl which can set the controlling tty and make sure
-   that no other process also has it.  That's exactly what we want to
-   do for the shell we are about to exec, since it is the documented
-   way to avoid the problem noted just above. */
+       {
+          int p = getpid(); 
+          struct sigaction sa, osa;
 
-#ifdef sun
-#ifdef TIOCSCTTY
-       { if (setsid() < 0) perror("login.krb5: setsid");
-         if (ioctl(0, TIOCSCTTY, 1) < 0) perror("login.krb5: tiocsctty");
-        }
+          /* this will set the PGID to the PID. */
+#ifdef HAVE_SETPGID
+          if (setpgid(p,p) < 0) perror("login.krb5: setpgid");
+#else
+#ifdef SETPGRP_TWOARG
+          if (setpgrp(p,p) < 0) perror("login.krb5: setpgrp");
+#else
+          if (setpgrp() < 0) perror("login.krb5: setpgrp");
 #endif
 #endif
 
-#endif /* KRB4 */
+          /* This will cause SIGTTOU to be ignored for the duration
+             of the TIOCSPGRP.  If this is not done, and the parent's
+             process group is the foreground pgrp of the tty, then
+             this will suspend the child, which is bad. */
+
+          sa.sa_flags = 0;
+          sa.sa_handler = SIG_IGN;
+          sigemptyset(&(sa.sa_mask));
+
+          if (sigaction(SIGTTOU, &sa, &osa))
+             perror("login.krb5: sigaction(SIGTTOU, SIG_IGN)");
+
+          /* This will set the foreground process group of the
+             controlling terminal to this process group (containing
+             only this process). */
+#ifdef HAVE_TCSETPGRP
+          if (tcsetpgrp(0, p) < 0) perror("login.krb5: tcsetpgrp");
+#else
+          if (ioctl(0, TIOCSPGRP, &p) < 0) perror("login.krb5: tiocspgrp");
+#endif
+
+          /* This will reset the SIGTTOU handler */
+
+          if (sigaction(SIGTTOU, &osa, NULL))
+             perror("login.krb5: sigaction(SIGTTOU, [old handler])");
+        }
+
        (void)setgid((gid_t) pwd->pw_gid);
        (void) initgroups(username, pwd->pw_gid);
 
@@ -872,69 +1639,41 @@ bad_login:
                pwd->pw_shell = BSHELL;
 #if defined(NTTYDISC) && defined(TIOCSETD)
        /* turn on new line discipline for the csh */
-       else if (!strcmp(pwd->pw_shell, "/bin/csh")) {
+       if (!strcmp(pwd->pw_shell, "/bin/csh")) {
                ioctlval = NTTYDISC;
                (void)ioctl(0, TIOCSETD, (char *)&ioctlval);
        }
 #endif
 
        ccname = getenv("KRB5CCNAME");  /* save cache */
+       tz = getenv("TZ");      /* and time zone */
 
        /* destroy environment unless user has requested preservation */
-       envinit = (char **)malloc(MAXENVIRON * sizeof(char *));
-       if (envinit == 0) {
+       if (!pflag) {
+           envinit = (char **)malloc(MAXENVIRON * sizeof(char *));
+           if (envinit == 0) {
                fprintf(stderr, "Can't malloc empty environment.\n");
                sleepexit(1);
+           }
+           envinit[0] = NULL;
+           environ = envinit;
        }
-       if (!pflag)
-               environ = envinit;
 
-       i = 0;
+       setenv ("LOGNAME", pwd->pw_name, 1);
+       setenv ("LOGIN", pwd->pw_name, 1);
 
-#ifdef _IBMR2
-       {
-           FILE *fp;
-           if ((fp = fopen("/etc/environment", "r")) != NULL) {
-               while(fgets(tbuf, sizeof(tbuf), fp)) {
-                   if ((tbuf[0] == '#') || (strchr(tbuf, '=') == 0))
-                       continue;
-                   for (p = tbuf; *p; p++)
-                       if (*p == '\n') {
-                           *p = '\0';
-                           break;
-                       }
-                   envinit[i++] = strsave(tbuf);
-               }
-               fclose(fp);
-           }
-       }
-#endif
-/* Set login timezone for date information (PDG) */
-#ifdef __sgi__
-    {
-        FILE *fp;
-        if ((fp = fopen("/etc/TIMEZONE", "r")) != NULL) {
-        while(fgets(tbuf, sizeof(tbuf), fp)) {
-            if ((tbuf[0] == '#') || (strchr(tbuf, '=') == 0))
-            continue;
-            for (p = tbuf; *p; p++)
-            if (*p == '\n') {
-                *p = '\0';
-                break;
-            }
-            envinit[i++] = strsave(tbuf);
-        }
-        fclose(fp);
-        }
-    }
+       /* read the /etc/environment file on AIX */
+#ifdef HAVE_ETC_ENVIRONMENT
+       read_env_vars_from_file ("/etc/environment");
 #endif
 
-       sprintf(tbuf,"LOGNAME=%s",pwd->pw_name);
-       envinit[i++] = strsave(tbuf);
-       sprintf(tbuf,"LOGIN=%s",pwd->pw_name);
-       envinit[i++] = strsave(tbuf);
-
-       envinit[i++] = NULL;
+       /* Set login timezone for date information (sgi PDG) */
+#ifdef HAVE_ETC_TIMEZONE
+       read_env_vars_from_file ("/etc/TIMEZONE");
+#else
+       if (tz)
+           setenv ("TZ", tz, 0);
+#endif
 
        if (ccname)
                setenv("KRB5CCNAME", ccname, 0);
@@ -946,24 +1685,24 @@ bad_login:
 
        if (term[0] == '\0')
                (void) strncpy(term, stypeof(tty), sizeof(term));
-       (void)setenv("TERM", term, 0);
-#ifdef KRB4
+       if (term[0])
+               (void)setenv("TERM", term, 0);
+#ifdef KRB4_GET_TICKETS
        /* tkfile[0] is only set if we got tickets above */
-       if (tkfile[0])
+       if (login_krb4_get_tickets && tkfile[0])
            (void) setenv(KRB_ENVIRON, tkfile, 1);
-#endif /* KRB4 */
-
-#if 0
-       strcpy(wgfile, "/tmp/wg.XXXXXX");
-       mktemp(wgfile);
-       setenv("WGFILE", wgfile, 0);
-#endif
+#endif /* KRB4_GET_TICKETS */
+#ifdef KRB5_GET_TICKETS
+       /* ccfile[0] is only set if we got tickets above */
+       if (login_krb5_get_tickets && ccfile[0])
+           (void) setenv(KRB5_ENV_CCNAME, ccfile, 1);
+#endif /* KRB5_GET_TICKETS */
 
        if (tty[sizeof("tty")-1] == 'd')
                syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
        if (pwd->pw_uid == 0)
                if (hostname)
-#ifdef KRB4
+#ifdef KRB4_KLOGIN
                        if (kdata) {
                            /* @*$&@#*($)#@$ syslog doesn't handle very
                               many arguments */
@@ -983,7 +1722,7 @@ bad_login:
 #endif
                            syslog(LOG_NOTICE, "%s", buf);
                        } else {
-#endif /* KRB4 */
+#endif /* KRB4_KLOGIN */
 #ifdef UT_HOSTSIZE
                        syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s",
                            tty, UT_HOSTSIZE, hostname);
@@ -991,7 +1730,7 @@ bad_login:
                        syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %s",
                            tty, hostname);
 #endif
-#ifdef KRB4
+#ifdef KRB4_KLOGIN
                        }
                else 
                        if (kdata) {
@@ -1001,43 +1740,30 @@ bad_login:
                                   kdata->pname, kdata->pinst,
                                   kdata->prealm);
                        } 
-#endif /* KRB4 */
+#endif /* KRB4_KLOGIN */
                else
                        syslog(LOG_NOTICE, "ROOT LOGIN %s", tty);
 
-       if (!quietlog) {
-               struct stat st;
+       afs_login ();
 
-#ifdef KRB4
+       if (!quietlog) {
+#ifdef KRB4_KLOGIN
                if (!krbflag && !fflag && !Fflag && !eflag )
                    printf("\nWarning: No Kerberos tickets obtained.\n\n");
-#endif /* KRB4 */
-#ifndef NO_MOTD
-               motd();
-#endif
-               (void)sprintf(tbuf, "%s/%s", MAILDIR, pwd->pw_name);
-               if (stat(tbuf, &st) == 0 && st.st_size != 0)
-                       printf("You have %smail.\n",
-                           (st.st_mtime > st.st_atime) ? "new " : "");
+#endif /* KRB4_KLOGIN */
+               motd ();
+               check_mail ();
        }
 
 #ifndef OQUOTA
        if (! access( QUOTAWARN, X_OK)) (void) system(QUOTAWARN);
 #endif
-#ifdef POSIX_SIGNALS
-       sa.sa_handler = SIG_DFL;
-       (void)sigaction(SIGALRM, &sa, (struct sigaction *)0);
-       (void)sigaction(SIGQUIT, &sa, (struct sigaction *)0);
-       (void)sigaction(SIGINT, &sa, (struct sigaction *)0);
-
-       sa.sa_handler = SIG_IGN;
-       (void)sigaction(SIGTSTP, &sa, (struct sigaction *)0);
-#else
-       (void)signal(SIGALRM, SIG_DFL);
-       (void)signal(SIGQUIT, SIG_DFL);
-       (void)signal(SIGINT, SIG_DFL);
-       (void)signal(SIGTSTP, SIG_IGN);
-#endif
+       handler_init (sa, SIG_DFL);
+       handler_set (SIGALRM, sa);
+       handler_set (SIGQUIT, sa);
+       handler_set (SIGINT, sa);
+       handler_init (sa, SIG_IGN);
+       handler_set (SIGTSTP, sa);
 
        tbuf[0] = '-';
        (void) strcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ?
@@ -1048,6 +1774,150 @@ bad_login:
        exit(0);
 }
 
+char *speeds[] = {
+       "0", "50", "75", "110", "134", "150", "200", "300", "600",
+       "1200", "1800", "2400", "4800", "9600", "19200", "38400",
+};
+#define        NSPEEDS (sizeof(speeds) / sizeof(speeds[0]))
+
+#ifdef POSIX_TERMIOS
+/* this must be in sync with the list above */
+speed_t b_speeds[] = {
+       B0, B50, B75, B110, B134, B150, B200, B300, B600,
+       B1200, B1800, B2400, B4800, B9600, B19200, B38400,
+};
+#endif
+
+term_init (do_rlogin)
+{
+       int line_speed = -1;
+
+       if (do_rlogin) {
+           register char *cp = strchr(term, '/'), **cpp;
+           char *speed;
+
+           if (cp) {
+               *cp++ = '\0';
+               speed = cp;
+               cp = strchr(speed, '/');
+               if (cp)
+                   *cp++ = '\0';
+               for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++)
+                   if (strcmp(*cpp, speed) == 0) {
+                       line_speed = cpp-speeds;
+                       break;
+                   }
+           }
+       }
+#ifdef POSIX_TERMIOS
+       {
+           struct termios tc;
+
+           (void)tcgetattr(0, &tc);
+           if (line_speed != -1) {
+               cfsetispeed(&tc, b_speeds[line_speed]);
+               cfsetospeed(&tc, b_speeds[line_speed]);
+           }
+           tc.c_cc[VMIN] = 1;
+           tc.c_cc[VTIME] = 0;
+#ifndef NO_INIT_CC
+           tc.c_cc[VERASE] = CERASE;
+           tc.c_cc[VKILL] = CKILL;
+           tc.c_cc[VEOF] = CEOF;
+           tc.c_cc[VINTR] = CINTR;
+           tc.c_cc[VQUIT] = CQUIT;
+           tc.c_cc[VSTART] = CSTART;
+           tc.c_cc[VSTOP] = CSTOP;
+#ifndef CNUL
+#define CNUL CEOL
+#endif
+           tc.c_cc[VEOL] = CNUL;
+           /* The following are common extensions to POSIX */
+#ifdef VEOL2
+           tc.c_cc[VEOL2] = CNUL;
+#endif
+#ifdef VSUSP
+#if !defined(CSUSP) && defined(CSWTCH)
+#define CSUSP CSWTCH
+#endif
+           tc.c_cc[VSUSP] = CSUSP;
+#endif
+#ifdef VDSUSP
+           tc.c_cc[VDSUSP] = CDSUSP;
+#endif
+#ifdef VLNEXT
+           tc.c_cc[VLNEXT] = CLNEXT;
+#endif
+#ifdef VREPRINT
+           tc.c_cc[VREPRINT] = CRPRNT;
+#endif
+#ifdef VDISCRD
+           tc.c_cc[VDISCRD] = CFLUSH;
+#endif
+#ifdef VDISCARD
+#ifndef CDISCARD
+#define CDISCARD CFLUSH
+#endif
+           tc.c_cc[VDISCARD] = CDISCARD;
+#endif
+#ifdef VWERSE
+           tc.c_cc[VWERSE] = CWERASE;
+#endif
+#ifdef VWERASE
+           tc.c_cc[VWERASE] = CWERASE;
+#endif
+#if defined (VSTATUS) && defined (CSTATUS)
+           tc.c_cc[VSTATUS] = CSTATUS;
+#endif /* VSTATUS && CSTATUS */
+#endif /* NO_INIT_CC */
+           /* set all standard echo, edit, and job control options */
+           /* but leave any extensions */
+           tc.c_lflag |= ECHO|ECHOE|ECHOK|ICANON|ISIG|IEXTEN;
+           tc.c_lflag &= ~(NOFLSH|TOSTOP);
+#ifdef ECHOCTL
+           /* Not POSIX, but if we have it, we probably want it */
+           tc.c_lflag |= ECHOCTL;
+#endif
+#ifdef ECHOKE
+           /* Not POSIX, but if we have it, we probably want it */
+           tc.c_lflag |= ECHOKE;
+#endif
+           tc.c_iflag |= ICRNL|BRKINT;
+           tc.c_oflag |= ONLCR|OPOST|TAB3;
+           tcsetattr(0, TCSANOW, &tc);
+       }
+
+#else /* not POSIX_TERMIOS */
+
+       {
+           struct sgttyb sgttyb;
+           static struct tchars tc = {
+               CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
+           };
+           static struct ltchars ltc = {
+               CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT
+           };
+
+           (void) ioctl(0, TIOCGETP, (char *)&sgttyb);
+           if (line_speed != -1)
+               sgttyb.sg_ispeed = sgttyb.sg_ospeed = line_speed;
+           sgttyb.sg_flags = ECHO|CRMOD|ANYP|XTABS;
+           sgttyb.sg_erase = CERASE;
+           sgttyb.sg_kill = CKILL;
+           (void)ioctl(0, TIOCSLTC, (char *)&ltc);
+           (void)ioctl(0, TIOCSETC, (char *)&tc);
+           (void)ioctl(0, TIOCSETP, (char *)&sgttyb);
+#if defined(TIOCSETD)
+           {
+               int ioctlval;
+               ioctlval = 0;
+               (void)ioctl(0, TIOCSETD, (char *)&ioctlval);
+           }
+#endif
+       }
+#endif
+}
+
 void getloginname()
 {
        register int ch;
@@ -1096,58 +1966,42 @@ int rootterm(tty)
 #endif /* HAVE_TTYENT_H */
 }
 
-#ifdef POSIX_SETJMP
+#ifndef NO_MOTD
 sigjmp_buf motdinterrupt;
-#else
-jmp_buf motdinterrupt;
-#endif
+sigtype
+sigint()
+{
+       siglongjmp(motdinterrupt, 1);
+}
 
 void motd()
 {
        register int fd, nchars;
        char tbuf[8192];
-       sigtype sigint();
-#ifdef POSIX_SIGNALS
-       struct sigaction sa, osa;
-#else
-       sigtype (*oldint)();
-#endif
+       handler sa, osa;
 
        if ((fd = open(MOTDFILE, O_RDONLY, 0)) < 0)
                return;
-#ifdef POSIX_SIGNALS
-       (void)sigemptyset(&sa.sa_mask);
-       sa.sa_flags = 0;
-       sa.sa_handler = sigint;
-       (void)sigaction(SIGINT, &sa, &osa);
-#else
-       oldint = signal(SIGINT, sigint);
-#endif
-#ifdef POSIX_SETJMP
+       handler_init (sa, sigint);
+       handler_swap (SIGINT, sa, osa);
        if (sigsetjmp(motdinterrupt, 1) == 0)
                while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
                        (void)write(fileno(stdout), tbuf, nchars);
-#else
-       if (setjmp(motdinterrupt) == 0)
-               while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
-                       (void)write(fileno(stdout), tbuf, nchars);
-#endif
-#ifdef POSIX_SIGNALS
-       (void)sigaction(SIGINT, &osa, (struct sigaction *)0);
-#else
-       (void)signal(SIGINT, oldint);
-#endif
+       handler_set (SIGINT, osa);
        (void)close(fd);
 }
-
-sigtype
-sigint()
-{
-#ifdef POSIX_SETJMP
-       siglongjmp(motdinterrupt, 1);
 #else
-       longjmp(motdinterrupt, 1);
+void motd () { }
 #endif
+
+void check_mail ()
+{
+    char tbuf[MAXPATHLEN+2];
+    struct stat st;
+    (void)sprintf(tbuf, "%s/%s", MAILDIR, pwd->pw_name);
+    if (stat(tbuf, &st) == 0 && st.st_size != 0)
+       printf("You have %smail.\n",
+              (st.st_mtime > st.st_atime) ? "new " : "");
 }
 
 void checknologin()
@@ -1199,7 +2053,11 @@ void dolastlog(quiet, tty)
 }
 
 #undef UNKNOWN
+#ifdef __hpux
+#define UNKNOWN 0
+#else
 #define        UNKNOWN "su"
+#endif
 
 char *
 stypeof(ttyid)
@@ -1230,7 +2088,7 @@ int doremotelogin(host)
        return(ruserok(host, (pwd->pw_uid == 0), rusername, username));
 }
 
-#ifdef KRB4
+#ifdef KRB4_KLOGIN
 int do_krb_login(host, strict)
        char *host;
        int strict;
@@ -1276,7 +2134,7 @@ int do_krb_login(host, strict)
                            instance, &sin,
                            (struct sockaddr_in *)0,
                            kdata, "", (bit_64 *) 0, version))) {
-               printf("Kerberos rlogin failed: %s\r\n",krb_err_txt[rc]);
+               printf("Kerberos rlogin failed: %s\r\n",krb_get_err_text(rc));
                if (strict) {
 paranoid:
                        /*
@@ -1322,7 +2180,7 @@ paranoid:
        }
        return(0);
 }
-#endif /* KRB4 */
+#endif /* KRB4_KLOGIN */
 
 void lgetstr(buf, cnt, err)
        char *buf, *err;
@@ -1344,79 +2202,19 @@ void lgetstr(buf, cnt, err)
        } while (ch);
 }
 
-char *speeds[] = {
-       "0", "50", "75", "110", "134", "150", "200", "300", "600",
-       "1200", "1800", "2400", "4800", "9600", "19200", "38400",
-};
-#define        NSPEEDS (sizeof(speeds) / sizeof(speeds[0]))
-
-#ifdef POSIX_TERMIOS
-/* this must be in sync with the list above */
-speed_t b_speeds[] = {
-       B0, B50, B75, B110, B134, B150, B200, B300, B600,
-       B1200, B1800, B2400, B4800, B9600, B19200, B38400,
-};
-#endif
-
-void doremoteterm(tp)
-#ifdef POSIX_TERMIOS
-       struct termios *tp;
-#else
-       struct sgttyb *tp;
-#endif
-{
-       register char *cp = strchr(term, '/'), **cpp;
-       char *speed;
-
-       if (cp) {
-               *cp++ = '\0';
-               speed = cp;
-               cp = strchr(speed, '/');
-               if (cp)
-                       *cp++ = '\0';
-               for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++)
-                       if (strcmp(*cpp, speed) == 0) {
-#ifdef POSIX_TERMIOS
-                               cfsetispeed(tp, b_speeds[cpp-speeds]);
-                               cfsetospeed(tp, b_speeds[cpp-speeds]);
-#else
-                               tp->sg_ispeed = tp->sg_ospeed = cpp-speeds;
-#endif
-                               break;
-                       }
-       }
-#ifdef POSIX_TERMIOS
-       /* set all standard echo, edit, and job control options */
-       /* but leave any extensions */
-       tp->c_lflag |= ECHO|ECHOE|ECHOK|ICANON|ISIG|IEXTEN;
-       tp->c_lflag &= ~(NOFLSH|TOSTOP);
-#ifdef ECHOCTL
-       /* Not POSIX, but if we have it, we probably want it */
-       tp->c_lflag |= ECHOCTL;
-#endif
-#ifdef ECHOKE
-       /* Not POSIX, but if we have it, we probably want it */
-       tp->c_lflag |= ECHOKE;
-#endif
-       tp->c_iflag |= ICRNL|BRKINT;
-       tp->c_oflag |= ONLCR|OPOST|TAB3;
-#else /* !POSIX_TERMIOS */
-       tp->sg_flags = ECHO|CRMOD|ANYP|XTABS;
-#endif
-}
-
 void sleepexit(eval)
        int eval;
 {
-#ifdef KRB4
-       if (krbflag)
-           (void) dest_tkt();
-#endif /* KRB4 */
+#ifdef KRB4_GET_TICKETS
+       if (login_krb4_get_tickets && krbflag)
+           (void) destroy_tickets();
+#endif /* KRB4_GET_TICKETS */
        sleep((u_int)5);
        exit(eval);
 }
 
-#ifdef KRB4
+#ifdef KRB4_GET_TICKETS
+/* call already conditionalized on login_krb4_get_tickets */
 /*
  * This routine handles cleanup stuff, and the like.
  * It exits only in the child process.
@@ -1431,10 +2229,15 @@ dofork()
     update_ref_count(1);
 #endif
     if(!(child=fork()))
-           return; /* Child process */
+           return; /* Child process returns */
+
+    /* The parent continues here */
 
     { /* Try and get rid of our controlling tty.  On SunOS, this may or may
        not work depending on if our parent did a setsid before exec-ing us. */
+#ifndef __linux__
+      /* On linux, TIOCNOTTY causes us to die on a
+       SIGHUP, so don't even try it. */
 #ifdef TIOCNOTTY
       { int fd;
         if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
@@ -1443,10 +2246,15 @@ dofork()
         }
       }
 #endif
+#endif /* __linux__ */
 #ifdef HAVE_SETSID
       (void)setsid();
 #endif
+#ifdef SETPGRP_TWOARG
       (void)setpgrp(0, 0);
+#else
+      (void)setpgrp();
+#endif
     } 
 
     /* Setup stuff?  This would be things we could do in parallel with login */
@@ -1464,12 +2272,9 @@ dofork()
 #endif
     
     /* Cleanup stuff */
-    /* Run dest_tkt to destroy tickets */
-    (void) dest_tkt();         /* If this fails, we lose quietly */
-#ifdef SETPAG
-    if (pagflag)
-       ktc_ForgetAllTokens();
-#endif
+    /* Run destroy_tickets to destroy tickets */
+    (void) destroy_tickets();          /* If this fails, we lose quietly */
+    afs_cleanup ();
 #ifdef _IBMR2
     update_ref_count(-1);
 #endif
@@ -1477,7 +2282,7 @@ dofork()
     /* Leave */
     exit(0);
 }
-#endif /* KRB4 */
+#endif /* KRB4_GET_TICKETS */
 
 
 #ifndef HAVE_STRSAVE
index a07b40c2a1dce1cee2be6b36dce2f25263ee2c4d..2f2de0bb81cd7000d6efdd2c817b7a73c8666a3b 100644 (file)
 /* hpux 8, both hppa and s300 */
 #define LPATH "/bin:/usr/bin:/usr/contrib/bin:/usr/local/bin"
 #define RPATH "/bin:/usr/bin:/usr/contrib/bin:/usr/local/bin"
+#else
+#ifdef __hpux /* 9.04 */
+#define LPATH_root ":/bin:/usr/bin:/etc"
+#define LPATH "/bin:/usr/bin"
+#define RPATH "/bin:/usr/bin:/usr/contrib/bin:/usr/local/bin"
+#endif
 #endif
 
 #ifdef NeXT
index b7e8765f39e7d910127f13c9a85b38d6f7b499b2..d3774d58588317983f724e043b4a4985940b25ae 100644 (file)
@@ -54,38 +54,6 @@ realm ] [
 .B \-l
 username ]
 .PP
-.br
-rhost [
-\fB\-e\fR\fIc\fR
-] [
-.B \-8
-] [
-.B \-c
-] [
-.B \-a
-] [
-.B \-f
-] [
-.B \-F
-] [
-.B \-t
-termtype ] [
-.B \-n
-] [
-.B \-7
-] [
-.B \-d
-] [
-.B \-k
-realm ] [
-.B \-x
-] [
-.B \-noflow
-] [
-.B \-L
-] [
-.B \-l
-username ]
 .SH DESCRIPTION
 .I Rlogin
 connects your terminal on the current local host system
@@ -213,8 +181,6 @@ significantly increases CPU utilization.
 rsh(1), kerberos(3), krb_sendauth(3), krb_realmofhost(3),
 rlogin(1) [UCB version]
 .SH FILES
-/usr/hosts/*           for \fIrhost\fP version of the command
-.br
 \&.k5login             in the user's home directory
 .SH BUGS
 More of the environment should be propagated.
index 95ddfd0f11a0a86ebaabc739166df200e2a1f9af..d073832b5327df30e292e5386fc170ac52ed175a 100644 (file)
@@ -33,20 +33,10 @@ username
 ] [
 .B \-k
 realm ] [
-.B \-A
-] command
-.br
-host
-[
-.B \-l
-username
+.B \-f | \-F
 ] [
-.B \-n
-] [
-.B \-d
+.B \-x
 ] [
-.B \-k
-realm ] [
 .B \-A
 ] command
 .SH DESCRIPTION
@@ -79,6 +69,21 @@ account name using the aname -> lname mapping rules (see \fIkrb5_anadd(8)\fP
 for more details).
 .PP
 The
+.B \-x
+option causes the network session traffic to be encrypted.
+.PP
+The
+.B \-f
+and
+.B \-F
+options cause Kerberos credentials to be forwarded to the remote machine for
+use by the specified \fIcommand\fR.  They will be removed when \fIcommand\fR
+finishes.  If
+.B \-F
+is used, the forwarded credentials are themselves forwardable to other
+machines.
+.PP
+The
 .B \-k
 \fIrealm\fP option causes 
 .I rsh
@@ -129,18 +134,10 @@ appends
 .I remotefile
 to
 .I otherremotefile.
-.PP
-The host names for local machines are also commands in the directory
-/usr/hosts; if you put this directory in your search path
-then the
-.B rsh
-on the command line can be omitted.
 .SH FILES
 .ta 2i
 /etc/hosts
 .br
-/usr/hosts/*
-.br
 \&.k5login             in the user's home directory
 .DT
 .SH SEE ALSO