--- NetKit-0.09/rlogind/Makefile.origpam	Sun Dec 29 12:28:32 1996
+++ NetKit-0.09/rlogind/Makefile	Thu Apr 10 10:04:24 1997
@@ -8,6 +8,7 @@
 ifeq ($(USE_PAM),1)
 CFLAGS += -DUSE_PAM
 LIBS += -ldl -lpam -lpam_misc
+OBJS += sockconv.c
 endif
 
 ifeq ($(USE_GLIBC),1)
--- NetKit-0.09/rlogind/rlogind.c.origpam	Sun Dec 29 12:26:21 1996
+++ NetKit-0.09/rlogind/rlogind.c	Thu Apr 10 10:17:09 1997
@@ -88,6 +88,10 @@
 #include <sys/types.h>
 #include <security/pam_appl.h>
 #include <security/pam_misc.h>
+
+
+int sock_conv(int num_msg, const struct pam_message **msgm,
+		struct pam_response **response, void *appdata_ptr);
 #endif
 
 pid_t forkpty(int *, char *, struct termios *, struct winsize *);
@@ -171,7 +175,8 @@
 	argv += optind;
 
 #ifdef USE_PAM
-        if (_check_rhosts_file==0 || deny_all_hosts_equiv || allow_root_rhosts)
+        if (_check_rhosts_file==0 || deny_all_rhosts_hequiv || 
+		allow_root_rhosts)
             syslog(LOG_ERR, "-l, -L, and -h functionality has been moved to "
                             "pam_rhosts_auth in /etc/pam.conf");
 #endif
@@ -578,7 +583,7 @@
 #ifdef USE_PAM
 	char c;
 	static struct pam_conv conv = {
-	  misc_conv,
+	  sock_conv,
 	  NULL
 	};
         int retval;
@@ -588,9 +593,13 @@
 	getstr(lusername, sizeof(lusername), "locuser too long");
 	getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long");
 
-	pwd = getpwnam(lusername);
-	if (pwd == NULL)
-		return(-1);
+	/* This is a security boo-boo. If the account doesn't exist, get
+	   the password anyway.
+
+	    pwd = getpwnam(lusername);
+	    if (pwd == NULL)
+		    return(-1);
+	*/
 
 #ifdef USE_PAM
        retcode = pam_start("rlogin", lusername, &conv, &pamh);
@@ -627,17 +636,32 @@
        } while (0); /* We have the while(0) here because it is either using
 		       that and the breaks, or goto's */
 	/* eww. -dah */
+	/* well, replace it with goto's if you like!  I won't tell! -mkj */
 
 
 	if (retval == PAM_SUCCESS) {
+		char *ln;
+
+		pam_get_item (pamh, PAM_USER, &ln);
+		if (ln && *ln) {
+			strncpy(lusername, ln, NMAX);
+		} else {
+			/* Authentication was not sufficient for rlogind's
+			* requiredments; fall through to login quietly to
+			* avoid giving away sensitive info like whether an
+			* account exists */
+			return (-1);
+		}
+		pwd = getpwnam(lusername);
+
                if (setgid(pwd->pw_gid) != 0) {
                        fprintf(stderr, "cannot assume gid\n");
-                       return (0);
+                       return (-1);
                }
 
                if (initgroups(lusername, pwd->pw_gid) != 0) {
                        fprintf(stderr, "cannot initgroups\n");
-                       return (0);
+                       return (-1);
                }
 
                retval = pam_setcred(pamh, PAM_CRED_ESTABLISH);
@@ -645,12 +669,23 @@
 
 	if (retval != PAM_SUCCESS) {
 		syslog(LOG_ERR,"PAM authentication failed for in.rlogind");
-		fatal(STDERR_FILENO, "login failed", 0);
-		/* no return */
+		return -1;
 	}
 	return 0;
 
 #else /* !USE_PAM */
+	/* PAM does all this kind of stuff for us, and this also
+	 * opens up a security hole because it differentiates
+	 * r{sh,login} <host> -l<bad_username>
+	 * from
+	 * r{sh,login} <host> -l<existing_username>
+	 * This should probably be fixed for the non-PAM case so
+	 * that it prompts for a password and then rejects it,
+	 * but I don't care about the non-PAM case...
+	*/
+	pwd = getpwnam(lusername);
+	if (pwd == NULL)
+		return(-1);
 
 	if (deny_all_rhosts_hequiv) {
 		return -1;
--- NetKit-0.09/rlogind/sockconv.c.origpam	Thu Apr 10 10:04:24 1997
+++ NetKit-0.09/rlogind/sockconv.c	Thu Apr 10 10:04:24 1997
@@ -0,0 +1,149 @@
+/*
+ * $Id: misc_conv.c,v 1.2 1996/07/07 23:59:56 morgan Exp $
+ *
+ * A generic conversation function for text based applications
+ *
+ * Written by Andrew Morgan <morgan@physics.ucla.edu>
+ *    modified for socket file descriptors by Erik Troan <ewt@redhat.com>
+ *
+ * $Log: misc_conv.c,v $
+ * Revision 1.2  1996/07/07 23:59:56  morgan
+ * changed the name of the misc include file
+ *
+ * Revision 1.1  1996/05/02 05:17:06  morgan
+ * Initial revision
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define __USE_BSD                /* needed for prototype for getpass() */
+#include <unistd.h>
+
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
+
+int sock_conv(int num_msg, const struct pam_message **msgm,
+		     struct pam_response **response, void *appdata_ptr);
+
+#define INPUTSIZE PAM_MAX_MSG_SIZE
+
+#define CONV_ECHO_ON  1
+#define CONV_ECHO_OFF 0
+
+static char *read_string(int echo, const char *remark)
+{
+     char buffer[INPUTSIZE];
+     char *text;
+     int charsRead = 0;
+     char * nl = "\n\r";
+ 
+     fprintf(stderr,"%s",remark);
+
+     while (charsRead < (INPUTSIZE - 1)) {
+	  read(0, &buffer[charsRead], 1);
+	 
+	  if (buffer[charsRead] == '\r') {
+	       write(1, nl, 2);
+	       buffer[charsRead] = '\0';
+	       break;
+	  }
+
+	  if (echo) {
+	       write(1, &buffer[charsRead], 1);
+	  }
+
+	  charsRead++;
+     }
+
+     text = xstrdup(buffer);  /* get some space for this text */
+
+     return (text);
+}
+
+#define REPLY_CHUNK 5
+
+static void drop_reply(struct pam_response *reply, int replies)
+{
+     int i;
+
+     for (i=0; i<replies; ++i) {
+	  _pam_overwrite(reply[i].resp);      /* might be a password */
+	  free(reply[i].resp);
+     }
+     if (reply)
+	  free(reply);
+}
+
+int sock_conv(int num_msg, const struct pam_message **msgm,
+		     struct pam_response **response, void *appdata_ptr)
+{
+     int count=0,replies=0,space=0;
+     struct pam_response *reply=NULL;
+     char *string=NULL;
+
+     for (count=0; count < num_msg; ++count) {
+	  switch (msgm[count]->msg_style) {
+	  case PAM_PROMPT_ECHO_OFF:
+	       string = read_string(CONV_ECHO_OFF,msgm[count]->msg);
+	       if (string == NULL) {
+		    drop_reply(reply,replies);
+		    return (PAM_CONV_ERR);
+	       }
+	       break;
+	  case PAM_PROMPT_ECHO_ON:
+	       string = read_string(CONV_ECHO_ON,msgm[count]->msg);
+	       if (string == NULL) {
+		    drop_reply(reply,replies);
+		    return (PAM_CONV_ERR);
+	       }
+	       break;
+	  case PAM_ERROR_MSG:
+	       fprintf(stderr,"%s\n",msgm[count]->msg);
+	       break;
+	  case PAM_TEXT_INFO:
+	       fprintf(stderr,"%s\n",msgm[count]->msg);
+	       break;
+	  default:
+	       fprintf(stderr, "erroneous conversation (%d)\n"
+		       ,msgm[count]->msg_style);
+	       drop_reply(reply,replies);
+	       return (PAM_CONV_ERR);
+	  }
+
+	  if (string) {     /* must add to reply array */
+	       struct pam_response *ptmp;
+
+	       /* do we need a larger reply array ? */
+
+	       if (space <= replies) {
+		    space += REPLY_CHUNK;
+		    ptmp = (struct pam_response *)
+			 realloc(reply, space*sizeof(struct pam_response));
+		    if (ptmp == NULL) {
+			 drop_reply(reply,replies);
+			 return PAM_CONV_ERR;        /* ran out of memory */
+		    }
+		    reply = ptmp;                       /* enlarged array */
+	       }
+
+	       /* add string to list of responses */
+
+	       reply[replies].resp_retcode = 0;
+	       reply[replies++].resp = string;
+	       string = NULL;
+	  }
+     }
+
+     /* do we need to bother with a response? */
+     if (reply) {
+
+	  /* note, this pam_response structure (array) will be
+	   * free()'d by the module */
+
+	  *response = reply;
+     }
+     
+     return PAM_SUCCESS;
+}
