[2803] in Kerberos-V5-bugs

home help back first fref pref prev next nref lref last post

krb5-appl/483: v4 rcmd support in v5 clients

daemon@ATHENA.MIT.EDU (ghudson@MIT.EDU)
Fri Oct 24 12:43:46 1997

Resent-From: gnats@rt-11.MIT.EDU (GNATS Management)
Resent-To: krb5-unassigned@RT-11.MIT.EDU
Resent-Reply-To: krb5-bugs@MIT.EDU, ghudson@MIT.EDU
Date: Fri, 24 Oct 1997 12:42:22 -0400
From: ghudson@MIT.EDU
Reply-To: ghudson@MIT.EDU
To: krb5-bugs@MIT.EDU


>Number:         483
>Category:       krb5-appl
>Synopsis:       Feature request for v4 rcmd support in v5 clients
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    krb5-unassigned
>State:          open
>Class:          change-request
>Submitter-Id:   unknown
>Arrival-Date:   Fri Oct 24 12:43:01 EDT 1997
>Last-Modified:
>Originator:     Greg Hudson
>Organization:
MIT
>Release:        1.0
>Environment:
	
System: SunOS small-gods 5.5.1 Generic_103640-12 sun4m sparc SUNW,SPARCstation-5
Architecture: sun4

>Description:
krb5 rcmd clients do not interoperate with krb4 rcmd servers.  In the
Athena environment, it is not feasible to upgrade either all of the
clients before all of the servers or vice versa, so two-way
compatibility is a necessity.

I've written a patch to make rlogin, rsh, and rcp talk to krb4 rcmd
servers after trying a krb5 request.  The krb5 request does tend to
fail with a rather alarming error message (e.g. "not enough space"),
which may be due to insufficient checking in the recvauth processing.
I'm not sure.  At any rate, the code works, and it actually reduces
the code size of src/appl/bsd by eliminate duplicate versions of
des_read() and des_write().

I've tested this patch by trying every possible combination of krb4
and krb5 logins to krb4 and krb5 servers of all types, with and
without encryption.  That comes to 30 test cases (32 minus 2 because
there's no v4 encrypted rsh).
>How-To-Repeat:
>Fix:

Index: kcmd.c
===================================================================
RCS file: /afs/dev.mit.edu/source/repository/third/krb5/src/appl/bsd/kcmd.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -c -r1.1 -r1.2
*** kcmd.c	1996/09/12 04:42:06	1.1
--- kcmd.c	1997/10/19 03:44:23	1.2
***************
*** 52,71 ****
  #endif
  #endif
       
  #include <netinet/in.h>
  #include <netdb.h>
       
  #include <errno.h>
  #include "krb5.h"
  
  #include "defines.h"
  
  
  #define START_PORT      5120     /* arbitrary */
  char *default_service = "host";
  
! extern krb5_context bsd_context;
! 
  
  kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
       cred, seqno, server_seqno, laddr, faddr, authopts, anyport)
--- 52,109 ----
  #endif
  #endif
       
+ #ifndef roundup
+ #define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
+ #endif
+ 
  #include <netinet/in.h>
  #include <netdb.h>
       
  #include <errno.h>
  #include "krb5.h"
+ #ifdef KRB5_KRB4_COMPAT
+ #include <kerberosIV/krb.h>
+ #include <kerberosIV/krb4-proto.h>
+ #endif
  
  #include "defines.h"
  
+ extern krb5_context bsd_context;
+ #ifdef KRB5_KRB4_COMPAT
+ extern Key_schedule v4_schedule;
+ #endif
  
+ #define RCMD_BUFSIZ	5120
  #define START_PORT      5120     /* arbitrary */
  char *default_service = "host";
  
! /*
!  * Note that the encrypted rlogin packets take the form of a four-byte
!  * length followed by encrypted data.  On writing the data out, a significant
!  * performance penalty is suffered (at least one RTT per character, two if we
!  * are waiting for a shell to echo) by writing the data separately from the 
!  * length.  So, unlike the input buffer, which just contains the output
!  * data, the output buffer represents the entire packet.
!  */
! 
! static char des_inbuf[2*RCMD_BUFSIZ];	 /* needs to be > largest read size */
! static char des_outpkt[2*RCMD_BUFSIZ+4]; /* needs to be > largest write size */
! static krb5_data desinbuf;
! static krb5_data desoutbuf;
! static krb5_encrypt_block eblock;	 /* eblock for encrypt/decrypt */
! static int (*input)();
! static int (*output)();
! static char storage[2*RCMD_BUFSIZ];	 /* storage for the decryption */
! static int nstored = 0;
! static char *store_ptr = storage;
! static int twrite();
! static int v5_des_read(), v5_des_write();
! #ifdef KRB5_KRB4_COMPAT
! static int v4_des_read(), v4_des_write();
! static C_Block v4_session;
! static int right_justify;
! static int do_lencheck;
! #endif
  
  kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
       cred, seqno, server_seqno, laddr, faddr, authopts, anyport)
***************
*** 180,186 ****
  	    return (-1);
      	}
      	sin.sin_family = hp->h_addrtype;
!     	memcpy((caddr_t)&sin.sin_addr,hp->h_addr, hp->h_length);
      	sin.sin_port = rport;
      	if (connect(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
  	  break;
--- 218,224 ----
  	    return (-1);
      	}
      	sin.sin_family = hp->h_addrtype;
!     	memcpy((caddr_t)&sin.sin_addr,hp->h_addr, sizeof(sin.sin_addr));
      	sin.sin_port = rport;
      	if (connect(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
  	  break;
***************
*** 189,202 ****
  	    lport--;
  	    continue;
      	}
! 	/*
! 	 * don't wait very long for Kerberos kcmd.
! 	 */
!     	if (errno == ECONNREFUSED && timo <= 4) {
! 	    sleep(timo);
! 	    timo *= 2;
! 	    continue;
!     	}
  #if !(defined(tek) || defined(ultrix) || defined(sun) || defined(SYSV))
      	if (hp->h_addr_list[1] != NULL) {
  	    int oerrno = errno;
--- 227,233 ----
  	    lport--;
  	    continue;
      	}
! 
  #if !(defined(tek) || defined(ultrix) || defined(sun) || defined(SYSV))
      	if (hp->h_addr_list[1] != NULL) {
  	    int oerrno = errno;
***************
*** 207,213 ****
  	    perror(0);
  	    hp->h_addr_list++;
  	    memcpy((caddr_t)&sin.sin_addr,hp->h_addr_list[0],
! 		   hp->h_length);
  	    fprintf(stderr, "Trying %s...\n",
  		    inet_ntoa(sin.sin_addr));
  	    continue;
--- 238,244 ----
  	    perror(0);
  	    hp->h_addr_list++;
  	    memcpy((caddr_t)&sin.sin_addr,hp->h_addr_list[0],
! 		   sizeof(sin.sin_addr));
  	    fprintf(stderr, "Trying %s...\n",
  		    inet_ntoa(sin.sin_addr));
  	    continue;
***************
*** 401,406 ****
--- 432,677 ----
  
  
  
+ #ifdef KRB5_KRB4_COMPAT
+ k4cmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, ticket, service, realm,
+       cred, schedule, msg_data, laddr, faddr, authopts, anyport)
+      int *sock;
+      char **ahost;
+      u_short rport;
+      char *locuser, *remuser, *cmd;
+      int *fd2p;
+      KTEXT ticket;
+      char *service;
+      char *realm;
+      CREDENTIALS *cred;
+      Key_schedule schedule;
+      MSG_DAT *msg_data;
+      struct sockaddr_in *laddr, *faddr;
+      long authopts;
+      int anyport;
+ {
+     int s, pid;
+ #ifdef POSIX_SIGNALS
+     sigset_t oldmask, urgmask;
+ #else
+     sigmasktype oldmask;
+ #endif
+     struct sockaddr_in sin, from;
+     char c;
+     int lport = START_PORT;
+     struct hostent *hp;
+     int rc, sin_len;
+     char *host_save;
+     int status;
+ 
+     pid = getpid();
+     hp = gethostbyname(*ahost);
+     if (hp == 0) {
+ 	fprintf(stderr, "%s: unknown host\n", *ahost);
+ 	return (-1);
+     }
+     host_save = malloc(strlen(hp->h_name) + 1);
+     strcpy(host_save, hp->h_name);
+     *ahost = host_save;
+ 
+     /* If realm is null, look up from table */
+     if ((realm == NULL) || (realm[0] == '\0')) {
+ 	realm = krb_realmofhost(host_save);
+     }
+ 
+ #ifdef POSIX_SIGNALS
+     sigemptyset(&urgmask);
+     sigaddset(&urgmask, SIGURG);
+     sigprocmask(SIG_BLOCK, &urgmask, &oldmask);
+ #else
+     oldmask = sigblock(sigmask(SIGURG));
+ #endif /* POSIX_SIGNALS */
+     for (;;) {
+ 	s = getport(&lport);
+ 	if (s < 0) {
+ 	    if (errno == EAGAIN)
+ 		fprintf(stderr, "socket: All ports in use\n");
+ 	    else
+ 		perror("rcmd: socket");
+ #ifdef POSIX_SIGNALS
+ 	    sigprocmask(SIG_SETMASK, &oldmask, (sigset_t*)0);
+ #else
+ 	    sigsetmask(oldmask);
+ #endif /* POSIX_SIGNALS */
+ 	    return (-1);
+ 	}
+ 	sin.sin_family = hp->h_addrtype;
+ 	memcpy((caddr_t)&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
+ 	sin.sin_port = rport;
+ 	if (connect(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
+ 	    break;
+ 	(void) close(s);
+ 	if (errno == EADDRINUSE) {
+ 	    lport--;
+ 	    continue;
+ 	}
+ #if !(defined(tex) || defined(ultrix) || defined(sun) || defined(SYSV))
+ 	if (hp->h_addr_list[1] != NULL) {
+ 	    int oerrno = errno;
+ 
+ 	    fprintf(stderr,
+ 		    "connect to address %s: ", inet_ntoa(sin.sin_addr));
+ 	    errno = oerrno;
+ 	    perror(0);
+ 	    hp->h_addr_list++;
+ 	    memcpy((caddr_t)&sin.sin_addr, hp->h_addr_list[0],
+ 		   sizeof(sin.sin_addr));
+ 	    fprintf(stderr, "Trying %s...\n", inet_ntoa(sin.sin_addr));
+ 	    continue;
+ 	}
+ #endif						/* !(defined(ultrix) || defined(sun)) */
+ 	perror(host_save);
+ #ifdef POSIX_SIGNALS
+ 	sigprocmask(SIG_SETMASK, &oldmask, (sigset_t*)0);
+ #else
+ 	sigsetmask(oldmask);
+ #endif /* POSIX_SIGNALS */
+ 	return (-1);
+     }
+     lport--;
+     if (fd2p == 0) {
+ 	write(s, "", 1);
+ 	lport = 0;
+     } else {
+ 	char num[8];
+ 	int s2 = getport(&lport), s3;
+ 	int len = sizeof (from);
+ 
+ 	if (s2 < 0) {
+ 	    status = -1;
+ 	    goto bad;
+ 	}
+ 	listen(s2, 1);
+ 	(void) sprintf(num, "%d", lport);
+ 	if (write(s, num, strlen(num)+1) != strlen(num)+1) {
+ 	    perror("write: setting up stderr");
+ 	    (void) close(s2);
+ 	    status = -1;
+ 	    goto bad;
+ 	}
+ 	s3 = accept(s2, (struct sockaddr *)&from, &len);
+ 	(void) close(s2);
+ 	if (s3 < 0) {
+ 	    perror("accept");
+ 	    lport = 0;
+ 	    status = -1;
+ 	    goto bad;
+ 	}
+ 	*fd2p = s3;
+ 	from.sin_port = ntohs((u_short)from.sin_port);
+ 	/* This check adds nothing when using Kerberos.  */
+ 	if (! anyport &&
+ 	    (from.sin_family != AF_INET ||
+ 	     from.sin_port >= IPPORT_RESERVED)) {
+ 	    fprintf(stderr, "socket: protocol failure in circuit setup.\n");
+ 	    status = -1;
+ 	    goto bad2;
+ 	}
+     }
+ 
+     /* set up the needed stuff for mutual auth */
+     *faddr = sin;
+     sin_len = sizeof (struct sockaddr_in);
+     if (getsockname(s, (struct sockaddr *)laddr, &sin_len) < 0) {
+ 	perror("getsockname");
+ 	status = -1;
+ 	goto bad2;
+     }
+ 
+     if ((status = krb_sendauth(authopts, s, ticket, service, *ahost,
+ 			       realm, (unsigned long) getpid(), msg_data,
+ 			       cred, schedule,
+ 			       laddr,
+ 			       faddr,
+ 			       "KCMDV0.1")) != KSUCCESS) {
+ 	fprintf(stderr, "krb_sendauth failed: %s\n", krb_get_err_text(status));
+ 	status = -1;
+ 	goto bad2;
+     }
+     (void) write(s, remuser, strlen(remuser)+1);
+     (void) write(s, cmd, strlen(cmd)+1);
+ 
+ reread:
+     if ((rc=read(s, &c, 1)) != 1) {
+ 	if (rc==-1) {
+ 	    perror(*ahost);
+ 	} else {
+ 	    fprintf(stderr,"rcmd: bad connection with remote host\n");
+ 	}
+ 	status = -1;
+ 	goto bad2;
+     }
+     if (c != 0) {
+ 	/* If rlogind was compiled on SunOS4, and it somehow
+ 	   got the shared library version numbers wrong, it
+ 	   may give an ld.so warning about an old version of a
+ 	   shared library.  Just ignore any such warning.
+ 	   Note that the warning is a characteristic of the
+ 	   server; we may not ourselves be running under
+ 	   SunOS4.  */
+ 	if (c == 'l') {
+ 	    char *check = "d.so: warning:";
+ 	    char *p;
+ 	    char cc;
+ 
+ 	    p = check;
+ 	    while (read(s, &c, 1) == 1) {
+ 		if (*p == '\0') {
+ 		    if (c == '\n')
+ 			break;
+ 		} else {
+ 		    if (c != *p)
+ 			break;
+ 		    ++p;
+ 		}
+ 	    }
+ 
+ 	    if (*p == '\0')
+ 		goto reread;
+ 
+ 	    cc = 'l';
+ 	    (void) write(2, &cc, 1);
+ 	    if (p != check)
+ 		(void) write(2, check, p - check);
+ 	}
+ 
+ 	(void) write(2, &c, 1);
+ 	while (read(s, &c, 1) == 1) {
+ 	    (void) write(2, &c, 1);
+ 	    if (c == '\n')
+ 		break;
+ 	}
+ 	status = -1;
+ 	goto bad2;
+     }
+ #ifdef POSIX_SIGNALS
+     sigprocmask(SIG_SETMASK, &oldmask, (sigset_t*)0);
+ #else
+     sigsetmask(oldmask);
+ #endif
+     *sock = s;
+     return (KSUCCESS);
+  bad2:
+     if (lport)
+ 	(void) close(*fd2p);
+  bad:
+     (void) close(s);
+ #ifdef POSIX_SIGNALS
+     sigprocmask(SIG_SETMASK, &oldmask, (sigset_t*)0);
+ #else
+     sigsetmask(oldmask);
+ #endif
+     return (status);
+ }
+ #endif /* KRB5_KRB4_COMPAT */
+ 
+ 
+ 
  getport(alport)
       int *alport;
  {
***************
*** 430,608 ****
      }
  }
  
  
  
! #ifdef HAVE_SETREUID
! #if defined(sun)
! /* The IMP  and ultrix do not like multiple defined routines 
!    and since it does not have users with NFS filesystems 
!    mounted, the ruserok on it's OS will work just fine. 
!    However that is not the case with SUNS who's ruserok which 
!    is provided with the OS has problems with it's seteuid
!    ( which will eventually be traced no doubt to using
!    setreuid(-1,pgid)).
!    Therefore we provide a version of ruserok with fixes
!    the seteuid problem....Drawback - it can only be used
!    by a root process.*/
! 
! #ifndef convex
! ruserok(rhost, superuser, ruser, luser)
!      const char *rhost;
!      int superuser;
!      const char *ruser, *luser;
! {
!     FILE *hostf;
!     char fhost[MAXHOSTNAMELEN];
!     int first = 1;
!     register char *sp, *p;
!     int baselen = -1;
!     int euid = -1;
!     
!     sp = rhost;
!     p = fhost;
!     while (*sp) {
! 	if (*sp == '.') {
! 	    if (baselen == -1)
! 	      baselen = sp - rhost;
! 	    *p++ = *sp++;
! 	} else {
! 	    *p++ = islower(*sp) ? toupper(*sp++) : *sp++;
! 	}
!     }
!     *p = '\0';
!     hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r");
!   again:
!     if (hostf) {
! 	if (!_validuser(hostf, fhost, luser, ruser, baselen)) {
! 	    (void) fclose(hostf);
! 	    if (euid != -1)
! 	      (void) setreuid ( 0,euid);
! 	    return(0);
! 	}
! 	(void) fclose(hostf);
!     }
!     if (first == 1) {
! 	struct stat sbuf;
! 	struct passwd *pwd;
! 	char pbuf[MAXPATHLEN];
! 	
! 	first = 0;
! 	if ((pwd = getpwnam(luser)) == NULL)
! 	  return(-1);
! 	/*
! 	 * Read .rhosts as the local user to avoid NFS mapping the 
! 	 * root uid to something that can't read .rhosts.
! 	 */
! 	euid = geteuid();
! 	if (euid != -1)
! 	  (void) setreuid ( 0,pwd->pw_uid);
! 	(void)strcpy(pbuf, pwd->pw_dir);
! 	(void)strcat(pbuf, "/.rhosts");
! 	if ((hostf = fopen(pbuf, "r")) == NULL){
! 	    if (euid != -1)
! 	      (void) setreuid ( 0,euid);
! 	    return(-1);
! 	}
! 	(void)fstat(fileno(hostf), &sbuf);
! 	if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) {
! 	    fclose(hostf);
! 	    if (euid != -1)
! 	      (void) setreuid ( 0,euid);
! 	    return(-1);
! 	}
! 	goto again;
      }
!     if (euid != -1)
!       (void) setreuid ( 0,euid);
!     return (-1);
  }
  
  
  
! _validuser(hostf, rhost, luser, ruser, baselen)
!      char *rhost, *luser, *ruser;
!      FILE *hostf;
!      int baselen;
  {
!     char *user;
!     char ahost[MAXHOSTNAMELEN];
!     register char *p;
!     
!     while (fgets(ahost, sizeof (ahost), hostf)) {
! 	p = ahost;
! 	while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
! 	    *p = islower(*p) ? toupper(*p) : *p;
! 	    p++;
! 	}
! 	if (*p == ' ' || *p == '\t') {
! 	    *p++ = '\0';
! 	    while (*p == ' ' || *p == '\t')
! 	      p++;
! 	    user = p;
! 	    while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
! 	      p++;
! 	} else
! 	  user = p;
! 	*p = '\0';
! 	if (_checkhost(rhost, ahost, baselen) &&
! 	    !strcmp(ruser, *user ? user : luser)) {
! 	    return (0);
  	}
      }
!     return (-1);
  }
- #endif	/* convex */
  
  
  
! _checkhost(rhost, lhost, len)
!      char *rhost, *lhost;
       int len;
  {
!     static char ldomain[MAXHOSTNAMELEN + 1];
!     static char *domainp = NULL;
!     static int nodomain = 0;
!     register char *cp;
!     
!     if (len == -1)
!       return(!strcmp(rhost, lhost));
!     if (strncmp(rhost, lhost, len))
!       return(0);
!     if (!strcmp(rhost, lhost))
!       return(1);
!     if (*(lhost + len) != '\0')
!       return(0);
!     if (nodomain)
!       return(0);
!     if (!domainp) {
! 	if (gethostname(ldomain, sizeof(ldomain)) == -1) {
! 	    nodomain = 1;
! 	    return(0);
! 	}
! 	ldomain[MAXHOSTNAMELEN] = 0;
! 	if ((domainp = strchr(ldomain, '.')) == (char *)NULL) {
! 	    nodomain = 1;
! 	    return(0);
! 	}
! 	for (cp = ++domainp; *cp; ++cp)
! 	  if (islower(*cp))
! 	    *cp = toupper(*cp);
!     }
!     return(!strcmp(domainp, rhost + len +1));
!     
! }
! #endif /* ! sun */
! #endif /* HAVE_SETREUID */
! 
! 
! #if defined (hpux)
! int setreuid(real,eff)
!      int real,eff;
  {
!     int tmpint = -1;
!     return(setresuid(real,eff,tmpint));
  }
  #endif
  
  
  
--- 701,1042 ----
      }
  }
  
+ void rcmd_stream_init_normal()
+ {
+     input = read;
+     output = twrite;
+ }
  
+ void rcmd_stream_init_krb5(keyblock, encrypt_flag, lencheck)
+      krb5_keyblock *keyblock;
+      int encrypt_flag;
+      int lencheck;
+ {
+     krb5_error_code status;
  
!     if (!encrypt_flag) {
! 	rcmd_stream_init_normal();
! 	return;
!     }
!     desinbuf.data = des_inbuf;
!     desoutbuf.data = des_outpkt+4;	/* Set up des buffers */
!     krb5_use_enctype(bsd_context, &eblock, keyblock->enctype);
!     if ( status = krb5_process_key(bsd_context, &eblock, keyblock)) {
! 	fprintf(stderr, "rcmd: Cannot process session key: %s\n",
! 		error_message(status));
! 	exit(1);
      }
!     do_lencheck = lencheck;
!     input = v5_des_read;
!     output = v5_des_write;
  }
  
+ #ifdef KRB5_KRB4_COMPAT
+ void rcmd_stream_init_krb4(session, encrypt_flag, lencheck, justify)
+      C_Block session;
+      int encrypt_flag;
+      int lencheck;
+      int justify;
+ {
+     if (!encrypt_flag) {
+ 	rcmd_stream_init_normal();
+ 	return;
+     }
+     do_lencheck = lencheck;
+     right_justify = justify;
+     input = v4_des_read;
+     output = v4_des_write;
+     memcpy(v4_session, session, sizeof(v4_session));
+ }
+ #endif
  
+ int rcmd_stream_read(fd, buf, len)
+      int fd;
+      register char *buf;
+      int len;
+ {
+     return (*input)(fd, buf, len);
+ }
  
! int rcmd_stream_write(fd, buf, len)
!      int fd;
!      register char *buf;
!      int len;
  {
!     return (*output)(fd, buf, len);
! }
! 
! /* Because of rcp lossage, translate fd 0 to 1 when writing. */
! static int twrite(fd, buf, len)
!      int fd;
!      char *buf;
!      int len;
! {
!     return write((fd == 0) ? 1 : fd, buf, len);
! }
! 
! static int v5_des_read(fd, buf, len)
!      int fd;
!      char *buf;
!      int len;
! {
!     int nreturned = 0;
!     long net_len,rd_len;
!     int cc;
!     unsigned char c;
!     
!     if (nstored >= len) {
! 	memcpy(buf, store_ptr, len);
! 	store_ptr += len;
! 	nstored -= len;
! 	return(len);
!     } else if (nstored) {
! 	memcpy(buf, store_ptr, nstored);
! 	nreturned += nstored;
! 	buf += nstored;
! 	len -= nstored;
! 	nstored = 0;
!     }
! 
!     /* See the comment in v4_des_read. */
!     while (1) {
! 	cc = krb5_net_read(bsd_context, fd, &c, 1);
! 	/* we should check for non-blocking here, but we'd have
! 	   to make it save partial reads as well. */
! 	if (cc <= 0) return cc; /* read error */
! 	if (cc == 1) {
! 	    if (c == 0 || !do_lencheck) break;
  	}
      }
! 
!     rd_len = c;
!     if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
!     rd_len = (rd_len << 8) | c;
!     if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
!     rd_len = (rd_len << 8) | c;
!     if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
!     rd_len = (rd_len << 8) | c;
! 
!     net_len = krb5_encrypt_size(rd_len,eblock.crypto_entry);
!     if ((net_len <= 0) || (net_len > sizeof(des_inbuf))) {
! 	/* preposterous length, probably out of sync */
! 	errno = EIO;
! 	return(-1);
!     }
!     if ((cc = krb5_net_read(bsd_context, fd, desinbuf.data, net_len)) != net_len) {
! 	/* probably out of sync */
! 	errno = EIO;
! 	return(-1);
!     }
!     /* decrypt info */
!     if ((krb5_decrypt(bsd_context, desinbuf.data,
! 		      (krb5_pointer) storage,
! 		      net_len,
! 		      &eblock, 0))) {
! 	/* probably out of sync */
! 	errno = EIO;
! 	return(-1);
!     }
!     store_ptr = storage;
!     nstored = rd_len;
!     if (nstored > len) {
! 	memcpy(buf, store_ptr, len);
! 	nreturned += len;
! 	store_ptr += len;
! 	nstored -= len;
!     } else {
! 	memcpy(buf, store_ptr, nstored);
! 	nreturned += nstored;
! 	nstored = 0;
!     }
! 
!     return(nreturned);
  }
  
  
  
! static int v5_des_write(fd, buf, len)
!      int fd;
!      char *buf;
       int len;
  {
!     unsigned char *len_buf = (unsigned char *) des_outpkt;
!     
!     desoutbuf.length = krb5_encrypt_size(len,eblock.crypto_entry);
!     if (desoutbuf.length > sizeof(des_outpkt)-4){
! 	errno = EIO;
! 	return(-1);
!     }
!     if ((krb5_encrypt(bsd_context, (krb5_pointer)buf,
! 		      desoutbuf.data,
! 		      len,
! 		      &eblock,
! 		      0))){
! 	errno = EIO;
! 	return(-1);
!     }
! 
!     len_buf[0] = (len & 0xff000000) >> 24;
!     len_buf[1] = (len & 0xff0000) >> 16;
!     len_buf[2] = (len & 0xff00) >> 8;
!     len_buf[3] = (len & 0xff);
! 
!     if (write(fd, des_outpkt,desoutbuf.length+4) != desoutbuf.length+4){
! 	errno = EIO;
! 	return(-1);
!     }
!     else return(len);
! }
! 
! 
! 
! #ifdef KRB5_KRB4_COMPAT
! 
! static int
! v4_des_read(fd, buf, len)
! int fd;
! char *buf;
! int len;
  {
! 	int nreturned = 0;
! 	krb5_ui_4 net_len, rd_len;
! 	int cc;
! 	unsigned char c;
! 
! 	if (nstored >= len) {
! 		memcpy(buf, store_ptr, len);
! 		store_ptr += len;
! 		nstored -= len;
! 		return(len);
! 	} else if (nstored) {
! 		memcpy(buf, store_ptr, nstored);
! 		nreturned += nstored;
! 		buf += nstored;
! 		len -= nstored;
! 		nstored = 0;
! 	}
! 
! 	/* We're fetching the length which is MSB first, and the MSB
! 	   has to be zero unless the client is sending more than 2^24
! 	   (16M) bytes in a single write (which is why this code is used
! 	   in rlogin but not rcp or rsh.) The only reasons we'd get
! 	   something other than zero are:
! 		-- corruption of the tcp stream (which will show up when
! 		   everything else is out of sync too)
! 		-- un-caught Berkeley-style "pseudo out-of-band data" which
! 		   happens any time the user hits ^C twice.
! 	   The latter is *very* common, as shown by an 'rlogin -x -d' 
! 	   using the CNS V4 rlogin.         Mark EIchin 1/95
! 	   */
! 	while (1) {
! 	    cc = krb_net_read(fd, &c, 1);
! 	    if (cc <= 0) return cc; /* read error */
! 	    if (cc == 1) {
! 		if (c == 0 || !do_lencheck) break;
! 	    }
! 	}
! 
! 	net_len = c;
! 	if ((cc = krb_net_read(fd, &c, 1)) != 1) return 0;
! 	net_len = (net_len << 8) | c;
! 	if ((cc = krb_net_read(fd, &c, 1)) != 1) return 0;
! 	net_len = (net_len << 8) | c;
! 	if ((cc = krb_net_read(fd, &c, 1)) != 1) return 0;
! 	net_len = (net_len << 8) | c;
! 
! 	/* Note: net_len is unsigned */
! 	if (net_len > sizeof(des_inbuf)) {
! 		errno = EIO;
! 		return(-1);
! 	}
! 	/* the writer tells us how much real data we are getting, but
! 	   we need to read the pad bytes (8-byte boundary) */
! 	rd_len = roundup(net_len, 8);
! 	if ((cc = krb_net_read(fd, des_inbuf, rd_len)) != rd_len) {
! 		errno = EIO;
! 		return(-1);
! 	}
! 	(void) pcbc_encrypt(des_inbuf,
! 			    storage,
! 			    (net_len < 8) ? 8 : net_len,
! 			    v4_schedule,
! 			    v4_session,
! 			    DECRYPT);
! 	/* 
! 	 * when the cleartext block is < 8 bytes, it is "right-justified"
! 	 * in the block, so we need to adjust the pointer to the data
! 	 */
! 	if (net_len < 8 && right_justify)
! 		store_ptr = storage + 8 - net_len;
! 	else
! 		store_ptr = storage;
! 	nstored = net_len;
! 	if (nstored > len) {
! 		memcpy(buf, store_ptr, len);
! 		nreturned += len;
! 		store_ptr += len;
! 		nstored -= len;
! 	} else {
! 		memcpy(buf, store_ptr, nstored);
! 		nreturned += nstored;
! 		nstored = 0;
! 	}
! 	
! 	return(nreturned);
  }
+ 
+ static int
+ v4_des_write(fd, buf, len)
+ int fd;
+ char *buf;
+ int len;
+ {
+ 	static char garbage_buf[8];
+ 	unsigned char *len_buf = (unsigned char *) des_outpkt;
+ 
+ 	/* 
+ 	 * pcbc_encrypt outputs in 8-byte (64 bit) increments
+ 	 *
+ 	 * it zero-fills the cleartext to 8-byte padding,
+ 	 * so if we have cleartext of < 8 bytes, we want
+ 	 * to insert random garbage before it so that the ciphertext
+ 	 * differs for each transmission of the same cleartext.
+ 	 * if len < 8 - sizeof(long), sizeof(long) bytes of random
+ 	 * garbage should be sufficient; leave the rest as-is in the buffer.
+ 	 * if len > 8 - sizeof(long), just garbage fill the rest.
+ 	 */
+ 
+ #ifdef min
+ #undef min
  #endif
+ #define min(a,b) ((a < b) ? a : b)
+ 
+ 	if (len < 8 && right_justify) {
+ 		krb5_random_confounder(8 - len, garbage_buf);
+ 		/* this "right-justifies" the data in the buffer */
+ 		(void) memcpy(garbage_buf + 8 - len, buf, len);
+ 	}
+ 	(void) pcbc_encrypt((len < 8) ? garbage_buf : buf,
+ 			    des_outpkt+4,
+ 			    (len < 8) ? 8 : len,
+ 			    v4_schedule,
+ 			    v4_session,
+ 			    ENCRYPT);
+ 
+ 	/* tell the other end the real amount, but send an 8-byte padded
+ 	   packet */
+ 	len_buf[0] = (len & 0xff000000) >> 24;
+ 	len_buf[1] = (len & 0xff0000) >> 16;
+ 	len_buf[2] = (len & 0xff00) >> 8;
+ 	len_buf[3] = (len & 0xff);
+ 	if (write(fd, des_outpkt, roundup(len,8)+4) != roundup(len,8)+4) {
+ 		errno = EIO;
+ 		return(-1);
+ 	}
+ 	return(len);
+ }
+ 
+ #endif /* KRB5_KRB4_COMPAT */
  
  
  
***************
*** 627,641 ****
  
  #endif
  
- #ifdef SYSV
- 
- int killpg(pid,sig)
-      int pid,sig;
- {
-     
-     if ( pid >= 0)
-       pid *= -1;
-     return(kill(pid,sig));
- }
- 
- #endif
--- 1061,1063 ----
Index: krcp.c
===================================================================
RCS file: /afs/dev.mit.edu/source/repository/third/krb5/src/appl/bsd/krcp.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -c -r1.1 -r1.2
*** krcp.c	1996/09/12 04:42:06	1.1
--- krcp.c	1997/10/19 03:44:25	1.2
***************
*** 72,105 ****
  #define setreuid(r,e) setresuid(r,e,-1)
  #endif
  #endif
- #ifndef roundup
- #define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
- #endif
  
  #ifdef KERBEROS
  #include "krb5.h"
  #include "com_err.h"
       
  #define RCP_BUFSIZ 4096
       
  int sock;
! struct sockaddr_in foreign;	   /* set up by kcmd used by send_auth */
  char *krb_realm = NULL;
  char *krb_cache = NULL;
  char *krb_config = NULL;
- char des_inbuf[2*RCP_BUFSIZ];          /* needs to be > largest read size */
- char des_outbuf[2*RCP_BUFSIZ];         /* needs to be > largest write size */
- krb5_data desinbuf,desoutbuf;
  krb5_encrypt_block eblock;         /* eblock for encrypt/decrypt */
- krb5_keyblock *session_key;	   /* static key for session */
  krb5_context bsd_context;
  
! void	try_normal();
  char	**save_argv();
  #ifndef HAVE_STRSAVE
  char	*strsave();
  #endif
! int	des_write(), des_read();
  void 	usage(), sink(), source(), rsource(), verifydir(), answer_auth();
  int	response(), hosteq(), okname(), susystem();
  int	encryptflag = 0;
--- 72,109 ----
  #define setreuid(r,e) setresuid(r,e,-1)
  #endif
  #endif
  
  #ifdef KERBEROS
  #include "krb5.h"
  #include "com_err.h"
+ #ifdef KRB5_KRB4_COMPAT
+ #include <kerberosIV/krb.h>
+ #include <kerberosIV/krb4-proto.h>
+ #endif
       
  #define RCP_BUFSIZ 4096
       
  int sock;
! struct sockaddr_in local, foreign; /* set up by kcmd used by v4_send_auth */
  char *krb_realm = NULL;
  char *krb_cache = NULL;
  char *krb_config = NULL;
  krb5_encrypt_block eblock;         /* eblock for encrypt/decrypt */
  krb5_context bsd_context;
  
! #ifdef KRB5_KRB4_COMPAT
! Key_schedule v4_schedule;
! CREDENTIALS v4_cred;
! KTEXT_ST v4_ticket;
! MSG_DAT v4_msg_data;
! #endif
! 
! void	v4_send_auth(), try_normal();
  char	**save_argv();
  #ifndef HAVE_STRSAVE
  char	*strsave();
  #endif
! int	rcmd_stream_write(), rcmd_stream_read();
  void 	usage(), sink(), source(), rsource(), verifydir(), answer_auth();
  int	response(), hosteq(), okname(), susystem();
  int	encryptflag = 0;
***************
*** 108,116 ****
  #define	UCB_RCP	"/bin/rcp"
  #endif
  
- #else /* !KERBEROS */
- #define	des_read	read
- #define	des_write	write
  #endif /* KERBEROS */
  
  int	rem;
--- 112,117 ----
***************
*** 139,145 ****
  void	error KRB5_STDARG_P((char *, va_list));
  #endif
  
! #define	ga()	 	(void) des_write(rem, "", 1)
  
  int main(argc, argv)
       int argc;
--- 140,146 ----
  void	error KRB5_STDARG_P((char *, va_list));
  #endif
  
! #define	ga()	 	(void) rcmd_stream_write(rem, "", 1)
  
  int main(argc, argv)
       int argc;
***************
*** 162,171 ****
      int euid;
      char **orig_argv = save_argv(argc, argv);
  
!     krb5_init_context(&bsd_context);
!     krb5_init_ets(bsd_context);
!     desinbuf.data = des_inbuf;
!     desoutbuf.data = des_outbuf;    /* Set up des buffers */
  #endif
  
      pwd = getpwuid(userid = getuid());
--- 163,173 ----
      int euid;
      char **orig_argv = save_argv(argc, argv);
  
!     status = krb5_init_context(&bsd_context);
!     if (status) {
! 	    com_err(argv[0], status, "while initializing krb5");
! 	    exit(1);
!     }
  #endif
  
      pwd = getpwuid(userid = getuid());
***************
*** 239,244 ****
--- 241,247 ----
  	    
  	  case 'f':		/* "from" */
  	    iamremote = 1;
+ 	    rcmd_stream_init_normal();
  #if defined(KERBEROS)
  	    if (encryptflag)
  	      answer_auth(krb_config, krb_cache);
***************
*** 250,255 ****
--- 253,259 ----
  	    
  	  case 't':		/* "to" */
  	    iamremote = 1;
+ 	    rcmd_stream_init_normal();
  #if defined(KERBEROS)
  	    if (encryptflag)
  	      answer_auth(krb_config, krb_cache);
***************
*** 421,448 ****
  				  &cred,  
  				  0,  /* No seq # */
  				  0,  /* No server seq # */
! 				  (struct sockaddr_in *) 0,
  				  &foreign,
  				  authopts,
  				  0); /* Not any port # */
  		    if (status) {
! 			fprintf(stderr,
! 				"%s: kcmd to host %s failed - %s\n",
! 				orig_argv[0], host,
! 				error_message(status));
  			try_normal(orig_argv);
  		    }
! 		    else {
! 			rem = sock; 
! 			session_key = &cred->keyblock;
! 				   
!     krb5_use_enctype(bsd_context, &eblock, session_key->enctype);
!     if ((status = krb5_process_key(bsd_context, &eblock, session_key))) {
! 	fprintf(stderr, "rcp: send_auth failed krb5_process_key: %s\n",
! 		error_message(status));
! 	exit(1);
!     }
! 		    }
  #else
  		    rem = rcmd(&host, port, pwd->pw_name,
  			       tuser ? tuser : pwd->pw_name,
--- 425,458 ----
  				  &cred,  
  				  0,  /* No seq # */
  				  0,  /* No server seq # */
! 				  &local,
  				  &foreign,
  				  authopts,
  				  0); /* Not any port # */
  		    if (status) {
! #ifdef KRB5_KRB4_COMPAT
! 			fprintf(stderr, "Trying krb4 rcp...\n");
! 			if (strncmp(buf, "-x rcp", 6) == 0)
! 			    memcpy(buf, "rcp -x", 6);
! 			status = k4cmd(&sock, &host, port,
! 				       pwd->pw_name,
! 				       tuser ? tuser : pwd->pw_name, buf,
! 				       0, &v4_ticket, "rcmd", krb_realm,
! 				       NULL, NULL, NULL,
! 				       &local, &foreign, 0L, 0);
! 			if (status)
! 			    try_normal(orig_argv);
! 			if (encryptflag)
! 			    v4_send_auth(host, krb_realm);
! 			rcmd_stream_init_krb4(v4_cred.session, encryptflag, 0,
! 					      0);
! #else
  			try_normal(orig_argv);
+ #endif
  		    }
! 		    else
! 			rcmd_stream_init_krb5(&cred->keyblock, encryptflag, 0);
! 		    rem = sock;
  #else
  		    rem = rcmd(&host, port, pwd->pw_name,
  			       tuser ? tuser : pwd->pw_name,
***************
*** 522,545 ****
  			      authopts,
  			      0); /* Not any port # */
  		if (status) {
! 		    fprintf(stderr,
! 			    "%s: kcmd to host %s failed - %s\n",
! 			    orig_argv[0], host,
! 			    error_message(status));
! 		    try_normal(orig_argv);
! 		    
! 		} else {
! 		    rem = sock; 
! 			session_key = &cred->keyblock;
  				   
-     krb5_use_enctype(bsd_context, &eblock, session_key->enctype);
-     if ((status = krb5_process_key(bsd_context, &eblock, session_key))) {
- 	fprintf(stderr, "rcp: send_auth failed krb5_process_key: %s\n",
- 		error_message(status));
- 	exit(1);
-     }
- 
- 		}
  		euid = geteuid();
  #ifdef HAVE_SETREUID
  		if (euid == 0)
--- 532,559 ----
  			      authopts,
  			      0); /* Not any port # */
  		if (status) {
! #ifdef KRB5_KRB4_COMPAT
! 			fprintf(stderr, "Trying krb4 rcp...\n");
! 			if (strncmp(buf, "-x rcp", 6) == 0)
! 			    memcpy(buf, "rcp -x", 6);
! 			status = k4cmd(&sock, &host, port,
! 				       pwd->pw_name, suser, buf,
! 				       0, &v4_ticket, "rcmd", krb_realm,
! 				       NULL, NULL, NULL,
! 				       &local, &foreign, 0L, 0);
! 			if (status)
! 			    try_normal(orig_argv);
! 			if (encryptflag)
! 			    v4_send_auth(host, krb_realm);
! 			rcmd_stream_init_krb4(v4_cred.session, encryptflag, 0,
! 					      0);
! #else
! 			try_normal(orig_argv);
! #endif
! 		} else
! 		    rcmd_stream_init_krb5(&cred->keyblock, encryptflag, 0);
! 		rem = sock; 
  				   
  		euid = geteuid();
  #ifdef HAVE_SETREUID
  		if (euid == 0)
***************
*** 566,571 ****
--- 580,586 ----
  			   buf, 0);
  		if (rem < 0)
  		  continue;
+ 		rcmd_stream_init_normal();
  #ifdef HAVE_SETREUID
  		(void) setreuid(0, userid);
  		sink(1, argv+argc-1);
***************
*** 741,747 ****
  	     */
  	    (void) sprintf(buf, "T%ld 0 %ld 0\n",
  			   stb.st_mtime, stb.st_atime);
! 	    (void) des_write(rem, buf, strlen(buf));
  	    if (response() < 0) {
  		(void) close(f);
  		continue;
--- 756,762 ----
  	     */
  	    (void) sprintf(buf, "T%ld 0 %ld 0\n",
  			   stb.st_mtime, stb.st_atime);
! 	    (void) rcmd_stream_write(rem, buf, strlen(buf));
  	    if (response() < 0) {
  		(void) close(f);
  		continue;
***************
*** 749,755 ****
  	}
  	(void) sprintf(buf, "C%04o %ld %s\n",
  		       (int) stb.st_mode&07777, (long ) stb.st_size, last);
! 	(void) des_write(rem, buf, strlen(buf));
  	if (response() < 0) {
  	    (void) close(f);
  	    continue;
--- 764,770 ----
  	}
  	(void) sprintf(buf, "C%04o %ld %s\n",
  		       (int) stb.st_mode&07777, (long ) stb.st_size, last);
! 	(void) rcmd_stream_write(rem, buf, strlen(buf));
  	if (response() < 0) {
  	    (void) close(f);
  	    continue;
***************
*** 765,771 ****
  	      amt = stb.st_size - i;
  	    if (readerr == 0 && read(f, bp->buf, amt) != amt)
  	      readerr = errno;
! 	    (void) des_write(rem, bp->buf, amt);
  	}
  	(void) close(f);
  	if (readerr == 0)
--- 780,786 ----
  	      amt = stb.st_size - i;
  	    if (readerr == 0 && read(f, bp->buf, amt) != amt)
  	      readerr = errno;
! 	    (void) rcmd_stream_write(rem, bp->buf, amt);
  	}
  	(void) close(f);
  	if (readerr == 0)
***************
*** 810,823 ****
      if (pflag) {
  	(void) sprintf(buf, "T%ld 0 %ld 0\n",
  		       statp->st_mtime, statp->st_atime);
! 	(void) des_write(rem, buf, strlen(buf));
  	if (response() < 0) {
  	    closedir(d);
  	    return;
  	}
      }
      (void) sprintf(buf, "D%04o %d %s\n", statp->st_mode&07777, 0, last);
!     (void) des_write(rem, buf, strlen(buf));
      if (response() < 0) {
  	closedir(d);
  	return;
--- 825,838 ----
      if (pflag) {
  	(void) sprintf(buf, "T%ld 0 %ld 0\n",
  		       statp->st_mtime, statp->st_atime);
! 	(void) rcmd_stream_write(rem, buf, strlen(buf));
  	if (response() < 0) {
  	    closedir(d);
  	    return;
  	}
      }
      (void) sprintf(buf, "D%04o %d %s\n", statp->st_mode&07777, 0, last);
!     (void) rcmd_stream_write(rem, buf, strlen(buf));
      if (response() < 0) {
  	closedir(d);
  	return;
***************
*** 836,842 ****
  	source(1, bufv);
      }
      closedir(d);
!     (void) des_write(rem, "E\n", 2);
      (void) response();
  }
  
--- 851,857 ----
  	source(1, bufv);
      }
      closedir(d);
!     (void) rcmd_stream_write(rem, "E\n", 2);
      (void) response();
  }
  
***************
*** 845,851 ****
  int response()
  {
      char resp, c, rbuf[RCP_BUFSIZ], *cp = rbuf;
!     if (des_read(rem, &resp, 1) != 1)
        lostconn();
      switch (resp) {
  	
--- 860,866 ----
  int response()
  {
      char resp, c, rbuf[RCP_BUFSIZ], *cp = rbuf;
!     if (rcmd_stream_read(rem, &resp, 1) != 1)
        lostconn();
      switch (resp) {
  	
***************
*** 858,864 ****
        case 1:				/* error, followed by err msg */
        case 2:				/* fatal error, "" */
  	do {
! 	    if (des_read(rem, &c, 1) != 1)
  	      lostconn();
  	    *cp++ = c;
  	} while (cp < &rbuf[RCP_BUFSIZ] && c != '\n');
--- 873,879 ----
        case 1:				/* error, followed by err msg */
        case 2:				/* fatal error, "" */
  	do {
! 	    if (rcmd_stream_read(rem, &c, 1) != 1)
  	      lostconn();
  	    *cp++ = c;
  	} while (cp < &rbuf[RCP_BUFSIZ] && c != '\n');
***************
*** 941,952 ****
        targisdir = 1;
      for (first = 1; ; first = 0) {
  	cp = cmdbuf;
! 	if (des_read(rem, cp, 1) <= 0)
  	  return;
  	if (*cp++ == '\n')
  	  SCREWUP("unexpected '\\n'");
  	do {
! 	    if (des_read(rem, cp, 1) != 1)
  	      SCREWUP("lost connection");
  	} while (*cp++ != '\n');
  	*cp = 0;
--- 956,967 ----
        targisdir = 1;
      for (first = 1; ; first = 0) {
  	cp = cmdbuf;
! 	if (rcmd_stream_read(rem, cp, 1) <= 0)
  	  return;
  	if (*cp++ == '\n')
  	  SCREWUP("unexpected '\\n'");
  	do {
! 	    if (rcmd_stream_read(rem, cp, 1) != 1)
  	      SCREWUP("lost connection");
  	} while (*cp++ != '\n');
  	*cp = 0;
***************
*** 1064,1070 ****
  	      amt = size - i;
  	    count += amt;
  	    do {
! 		j = des_read(rem, cp, amt);
  		if (j <= 0) {
  		    if (j == 0)
  		      error("rcp: dropped connection");
--- 1079,1085 ----
  	      amt = size - i;
  	    count += amt;
  	    do {
! 		j = rcmd_stream_read(rem, cp, amt);
  		if (j <= 0) {
  		    if (j == 0)
  		      error("rcp: dropped connection");
***************
*** 1119,1129 ****
  	error("rcp: fstat: %s\n", error_message(errno));
  	return (NULLBUF);
      }
- #ifdef NOROUNDUP
-     size = 0;
- #else
-     size = roundup(stb.st_blksize, blksize);
- #endif
  
      size = blksize;
      if (bp->cnt < size) {
--- 1134,1139 ----
***************
*** 1165,1171 ****
      (void) vsprintf(cp, fmt, ap);
      va_end(ap);
  
!     (void) des_write(rem, buf, strlen(buf));
      if (iamremote == 0)
        (void) write(2, buf+1, strlen(buf+1));
  }
--- 1175,1181 ----
      (void) vsprintf(cp, fmt, ap);
      va_end(ap);
  
!     (void) rcmd_stream_write(rem, buf, strlen(buf));
      if (iamremote == 0)
        (void) write(2, buf+1, strlen(buf+1));
  }
***************
*** 1257,1262 ****
--- 1267,1276 ----
  
  
  
+ /* This function is mostly vestigial, since under normal operation
+  * the -x flag doesn't get set for the server process for encrypted
+  * rcp.  It only gets called by beta clients attempting user-to-user
+  * authentication. */
  void
    answer_auth(config_file, ccache_file)
      char *config_file;
***************
*** 1317,1465 ****
  	exit(1);
      }
      
!     /* setup eblock for des_read and write */
!     krb5_copy_keyblock(bsd_context, &new_creds->keyblock,&session_key);
      
      /* cleanup */
      krb5_free_cred_contents(bsd_context, &creds);
      krb5_free_creds(bsd_context, new_creds);
      krb5_xfree(msg.data);
-     
-     /* OK process key */
-     krb5_use_enctype(bsd_context, &eblock, session_key->enctype);
-     if ((status = krb5_process_key(bsd_context, &eblock, session_key)))
- 	exit(1);
  
      return;
  }
  
  
  
! char storage[2*RCP_BUFSIZ];		/* storage for the decryption */
! int nstored = 0;
! char *store_ptr = storage;
! 
! int des_read(fd, buf, len)
!      int fd;
!      register char *buf;
!      int len;
! {
!     int nreturned = 0;
!     long net_len,rd_len;
!     int cc;
!     krb5_error_code status;
!     unsigned char len_buf[4];
!     
!     if (!encryptflag)
!       return(read(fd, buf, len));
!     
!     if (nstored >= len) {
! 	memcpy(buf, store_ptr, len);
! 	store_ptr += len;
! 	nstored -= len;
! 	return(len);
!     } else if (nstored) {
! 	memcpy(buf, store_ptr, nstored);
! 	nreturned += nstored;
! 	buf += nstored;
! 	len -= nstored;
! 	nstored = 0;
!     }
!     
!     if ((cc = krb5_net_read(bsd_context, fd, (char *)len_buf, 4)) != 4) {
! 	/* XXX can't read enough, pipe must have closed */
! 	return(0);
!     }
!     rd_len =
! 	((len_buf[0]<<24) | (len_buf[1]<<16) | (len_buf[2]<<8) | len_buf[3]);
!     net_len = krb5_encrypt_size(rd_len,eblock.crypto_entry);
!     if (net_len <= 0 || net_len > sizeof(des_inbuf)) {
! 	/* preposterous length; assume out-of-sync; only
! 	   recourse is to close connection, so return 0 */
! 	error( "rcp: Des_read size problem net_len %d rd_len %d %d.\n",
! 	      net_len,rd_len, len);
! 	errno = E2BIG;
! 	return(-1);
!     }
!     if ((cc = krb5_net_read(bsd_context, fd, desinbuf.data, net_len)) != net_len) {
! 	/* pipe must have closed, return 0 */
! 	error( "rcp: Des_read error: length received %d != expected %d.\n",
! 	      cc,net_len);
! 	return(0);
!     }
!     /* decrypt info */
!     if ((status = krb5_decrypt(bsd_context, desinbuf.data,
! 			       (krb5_pointer) storage,
! 			       net_len,
! 			       &eblock, 0))) {
! 	error("rcp: Des_read cannot decrypt data from network %s.\n",
! 	      error_message(status));
! 	return(0);
!     }
!     store_ptr = storage;
!     nstored = rd_len;
!     if (nstored > len) {
! 	memcpy(buf, store_ptr, len);
! 	nreturned += len;
! 	store_ptr += len;
! 	nstored -= len;
!     } else {
! 	memcpy(buf, store_ptr, nstored);
! 	nreturned += nstored;
! 	nstored = 0;
!     }
!     
!     return(nreturned);
! }
! 
! 
! 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
!      */
!     
!     if (fd == 0)
! 	fd = 1;
!     if (!encryptflag)
!       return(krb5_net_write(bsd_context, fd, buf, len));
!     
!     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, des_write_buf.data, 
- 		      len, &eblock, 0))) {
- 	return(-1);
-     }
-     
-     len_buf[0] = (len & 0xff000000) >> 24;
-     len_buf[1] = (len & 0xff0000) >> 16;
-     len_buf[2] = (len & 0xff00) >> 8;
-     len_buf[3] = (len & 0xff);
-     if ((write(fd, len_buf, 4) != 4) || (write(fd, des_write_buf.data, 
- 	des_write_buf.length) != des_write_buf.length)) {
- 	return(-1);
-     }
-     return(len);
  }
  
  #endif /* KERBEROS */
--- 1331,1376 ----
  	exit(1);
      }
      
!     rcmd_stream_init_krb5(&new_creds->keyblock, encryptflag, 0);
      
      /* cleanup */
      krb5_free_cred_contents(bsd_context, &creds);
      krb5_free_creds(bsd_context, new_creds);
      krb5_xfree(msg.data);
  
      return;
  }
  
  
  
! #ifdef KRB5_KRB4_COMPAT
! void
! v4_send_auth(host,realm)
! char *host;
! char *realm;
  {
! 	long authopts;
  
! 	if ((realm == NULL) || (realm[0] == '\0'))
! 	     realm = krb_realmofhost(host);
! 	/* this needs to be sent again, because the
! 	   rcp process needs the key.  the rshd has
! 	   grabbed the first one. */
! 	authopts = KOPT_DO_MUTUAL;
! 	if ((rem = krb_sendauth(authopts, sock, &v4_ticket,
! 				"rcmd", host,
! 				realm, (unsigned long) getpid(),
! 				&v4_msg_data,
! 				&v4_cred, v4_schedule,
! 				&local,
! 				&foreign,
! 				"KCMDV0.1")) != KSUCCESS) {
! 		fprintf(stderr,
! 			"krb_sendauth mutual fail: %s\n",
! 			krb_get_err_text(rem));
! 		exit(1);
  	}
  }
+ #endif /* KRB5_KRB4_COMPAT */
  
  #endif /* KERBEROS */
Index: krlogin.c
===================================================================
RCS file: /afs/dev.mit.edu/source/repository/third/krb5/src/appl/bsd/krlogin.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -c -r1.1 -r1.2
*** krlogin.c	1996/09/12 04:42:07	1.1
--- krlogin.c	1997/10/19 03:44:28	1.2
***************
*** 129,157 ****
  #endif
  
  
- #ifndef roundup
- #define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
- #endif
- 
  #ifdef KERBEROS
  #include "krb5.h"
  #include "com_err.h"
  #include "defines.h"
       
  #define RLOGIN_BUFSIZ 5120
-      /*
-  * Note that the encrypted rlogin packets take the form of a four-byte
-  *length followed by encrypted data.  On writing the data out, a significant
-  * performance penalty is suffered (at least one RTT per character, two if we
-  * are waiting for a shell to echo) by writing the data separately from the 
-  * length.  So, unlike the input buffer, which just contains the output
-  * data, the output buffer represents the entire packet.
-  */
- 
- char des_inbuf[2*RLOGIN_BUFSIZ];       /* needs to be > largest read size */
- char des_outpkt[2*RLOGIN_BUFSIZ+4];      /* needs to be > largest write size */
- krb5_data desinbuf,desoutbuf;
- krb5_encrypt_block eblock;      /* eblock for encrypt/decrypt */
  
  void try_normal();
  char *krb_realm = (char *)0;
--- 129,143 ----
  #endif
  
  
  #ifdef KERBEROS
  #include "krb5.h"
  #include "com_err.h"
  #include "defines.h"
+ #ifdef KRB5_KRB4_COMPAT
+ #include <kerberosIV/krb.h>
+ #endif
       
  #define RLOGIN_BUFSIZ 5120
  
  void try_normal();
  char *krb_realm = (char *)0;
***************
*** 161,174 ****
  struct sockaddr_in local, foreign;
  krb5_context bsd_context;
  
  #ifndef UCB_RLOGIN
  #define UCB_RLOGIN      "/usr/ucb/rlogin"
  #endif
  
  #include "rpaths.h"
- #else /* !KERBEROS */
- #define des_read read
- #define des_write write
  #endif /* KERBEROS */
  
  # ifndef TIOCPKT_WINDOW
--- 147,162 ----
  struct sockaddr_in local, foreign;
  krb5_context bsd_context;
  
+ #ifdef KRB5_KRB4_COMPAT
+ Key_schedule v4_schedule;
+ CREDENTIALS v4_cred;
+ #endif
+ 
  #ifndef UCB_RLOGIN
  #define UCB_RLOGIN      "/usr/ucb/rlogin"
  #endif
  
  #include "rpaths.h"
  #endif /* KERBEROS */
  
  # ifndef TIOCPKT_WINDOW
***************
*** 338,343 ****
--- 326,335 ----
      int sock;
      krb5_flags authopts;
      krb5_error_code status;
+ #ifdef KRB5_KRB4_COMPAT
+     KTEXT_ST v4_ticket;
+     MSG_DAT v4_msg_data;
+ #endif
  #endif
      int debug_port = 0;
     
***************
*** 472,481 ****
  	exit(1);
      }
  #ifdef KERBEROS
!     krb5_init_context(&bsd_context);
!     krb5_init_ets(bsd_context);
!     desinbuf.data = des_inbuf;
!     desoutbuf.data = des_outpkt+4;	/* Set up des buffers */
  #endif
  
  
--- 464,474 ----
  	exit(1);
      }
  #ifdef KERBEROS
!     status = krb5_init_context(&bsd_context);
!     if (status) {
! 	    com_err(argv[0], status, "while initializing krb5");
! 	    exit(1);
!     }
  #endif
  
  
***************
*** 592,617 ****
  		  authopts,
  		  0);		/* Not any port # */
      if (status) {
! 	/* should check for KDC_PR_UNKNOWN, NO_TKT_FILE here -- XXX */
! 	fprintf(stderr,
! 		"%s: kcmd to host %s failed - %s\n",orig_argv[0], host,
! 		error_message(status));
  	try_normal(orig_argv);
!     }
      rem = sock;
-     
-     /* setup eblock for des_read and write */
-     krb5_use_enctype(bsd_context, &eblock,cred->keyblock.enctype);
-     if ( status = krb5_process_key(bsd_context, &eblock,&cred->keyblock)) {
- 	fprintf(stderr,
- 		"%s: Cannot process session key : %s.\n",
- 		orig_argv[0], error_message(status));
- 	exit(1);
-     }
  #else
      rem = rcmd(&host, debug_port,
  	       null_local_username ? NULL : pwd->pw_name,
  	       name ? name : pwd->pw_name, term, 0);
  #endif /* KERBEROS */
      
      if (rem < 0)
--- 585,612 ----
  		  authopts,
  		  0);		/* Not any port # */
      if (status) {
! #ifdef KRB5_KRB4_COMPAT
! 	fprintf(stderr, "Trying krb4 rlogin...\n");
! 	status = k4cmd(&sock, &host, debug_port,
! 		       null_local_username ? NULL : pwd->pw_name,
! 		       name ? name : pwd->pw_name, term,
! 		       0, &v4_ticket, "rcmd", krb_realm,
! 		       &v4_cred, v4_schedule, &v4_msg_data, &local, &foreign,
! 		       (encrypt_flag) ? KOPT_DO_MUTUAL : 0L, 0);
! 	if (status)
! 	    try_normal(orig_argv);
! 	rcmd_stream_init_krb4(v4_cred.session, encrypt_flag, 1, 1);
! #else
  	try_normal(orig_argv);
! #endif
!     } else
! 	rcmd_stream_init_krb5(&cred->keyblock, encrypt_flag, 1);
      rem = sock;
  #else
      rem = rcmd(&host, debug_port,
  	       null_local_username ? NULL : pwd->pw_name,
  	       name ? name : pwd->pw_name, term, 0);
+     rcmd_stream_init_normal();
  #endif /* KERBEROS */
      
      if (rem < 0)
***************
*** 1063,1071 ****
  #endif
  
  	    if (c != cmdchar)
! 	      (void) des_write(rem, &cmdchar, 1);
  	}
! 	if (des_write(rem, &c, 1) == 0) {
  	    prf("line gone");
  	    break;
  	}
--- 1058,1066 ----
  #endif
  
  	    if (c != cmdchar)
! 	      (void) rcmd_stream_write(rem, &cmdchar, 1);
  	}
! 	if (rcmd_stream_write(rem, &c, 1) == 0) {
  	    prf("line gone");
  	    break;
  	}
***************
*** 1180,1186 ****
      wp->ws_col = htons(winsize.ws_col);
      wp->ws_xpixel = htons(winsize.ws_xpixel);
      wp->ws_ypixel = htons(winsize.ws_ypixel);
!     (void) des_write(rem, obuf, sizeof(obuf));
  }
  
  
--- 1175,1181 ----
      wp->ws_col = htons(winsize.ws_col);
      wp->ws_xpixel = htons(winsize.ws_xpixel);
      wp->ws_ypixel = htons(winsize.ws_ypixel);
!     (void) rcmd_stream_write(rem, obuf, sizeof(obuf));
  }
  
  
***************
*** 1365,1371 ****
  	    bufp += n;
  }
  if (FD_ISSET(rem, &readset)) {
! 	  	rcvcnt = des_read(rem, rcvbuf, sizeof (rcvbuf));
  	if (rcvcnt == 0)
  	  return (0);
  	if (rcvcnt < 0)
--- 1360,1366 ----
  	    bufp += n;
  }
  if (FD_ISSET(rem, &readset)) {
! 	  	rcvcnt = rcmd_stream_read(rem, rcvbuf, sizeof (rcvbuf));
  	if (rcvcnt == 0)
  	  return (0);
  	if (rcvcnt < 0)
***************
*** 1587,1893 ****
      perror("exec");
      exit(1);
  }
- 
- 
- 
- char storage[2*RLOGIN_BUFSIZ];		/* storage for the decryption */
- int nstored = 0;
- char *store_ptr = storage;
- 
- #ifndef OLD_VERSION
- 
- int des_read(fd, buf, len)
-      int fd;
-      register char *buf;
-      int len;
- {
-     int nreturned = 0;
-     long net_len,rd_len;
-     int cc;
-     unsigned char len_buf[4];
-     
-     if (!encrypt_flag)
-       return(read(fd, buf, len));
-     
-     if (nstored >= len) {
- 	memcpy(buf, store_ptr, len);
- 	store_ptr += len;
- 	nstored -= len;
- 	return(len);
-     } else if (nstored) {
- 	memcpy(buf, store_ptr, nstored);
- 	nreturned += nstored;
- 	buf += nstored;
- 	len -= nstored;
- 	nstored = 0;
-     }
-     
- #if 0
-     if ((cc = krb5_net_read(bsd_context, fd, (char *)&len_buf, 4)) != 4) {
- 	/* XXX can't read enough, pipe must have closed */
- 	return(0);
-     }
-     rd_len =
- 	((len_buf[0]<<24) | (len_buf[1]<<16) | (len_buf[2]<<8) | len_buf[3]);
- #else
- 	{
- 	    unsigned char c;
- 	    int gotzero = 0;
- 
- 	    /* See the comment in v4_des_read. */
- 	    do {
- 		cc = krb5_net_read(bsd_context, fd, &c, 1);
- 		/* we should check for non-blocking here, but we'd have
- 		   to make it save partial reads as well. */
- 		if (cc <= 0) return cc; /* read error */
- 		if (cc == 1) {
- 		    if (c == 0) gotzero = 1;
- 		}
- 	    } while (!gotzero);
- 
- 	    if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
- 	    rd_len = c;
- 	    if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
- 	    rd_len = (rd_len << 8) | c;
- 	    if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
- 	    rd_len = (rd_len << 8) | c;
- 	}
- 
  #endif
-     net_len = krb5_encrypt_size(rd_len,eblock.crypto_entry);
-     if ((net_len <= 0) || (net_len > sizeof(des_inbuf))) {
- 	/* preposterous length; assume out-of-sync; only
- 	   recourse is to close connection, so return 0 */
- 	fprintf(stderr,"Read size problem.\n");
- 	return(0);
-     }
-     if ((cc = krb5_net_read(bsd_context, fd, desinbuf.data, net_len)) != net_len) {
- 	/* pipe must have closed, return 0 */
- 	fprintf(stderr,
- 		"Read error: length received %d != expected %d.\n",
- 		cc,net_len);
- 	return(0);
-     }
-     /* decrypt info */
-     if ((krb5_decrypt(bsd_context, desinbuf.data,
- 		      (krb5_pointer) storage,
- 		      net_len,
- 		      &eblock, 0))) {
- 	fprintf(stderr,"Cannot decrypt data from network.\n");
- 	return(0);
-     }
-     store_ptr = storage;
-     nstored = rd_len;
-     if (nstored > len) {
- 	memcpy(buf, store_ptr, len);
- 	nreturned += len;
- 	store_ptr += len;
- 	nstored -= len;
-     } else {
- 	memcpy(buf, store_ptr, nstored);
- 	nreturned += nstored;
- 	nstored = 0;
-     }
-     
-     return(nreturned);
- }
- 
- 
- 
- int des_write(fd, buf, len)
-      int fd;
-      char *buf;
-      int len;
- {
-   unsigned char *len_buf = (unsigned char *) des_outpkt;
-     
-   if (!encrypt_flag)
-       return(write(fd, buf, len));
-     
-     
-     desoutbuf.length = krb5_encrypt_size(len,eblock.crypto_entry);
-     if (desoutbuf.length > sizeof(des_outpkt)-4){
-       	fprintf(stderr,"Write size problem.\n");
- 	return(-1);
-     }
-     if ((krb5_encrypt(bsd_context, (krb5_pointer)buf,
- 		      desoutbuf.data,
- 		      len,
- 		      &eblock,
- 		      0))){
-       	fprintf(stderr,"Write encrypt problem.\n");
- 	return(-1);
-     }
- 
-     len_buf[0] = (len & 0xff000000) >> 24;
-     len_buf[1] = (len & 0xff0000) >> 16;
-     len_buf[2] = (len & 0xff00) >> 8;
-     len_buf[3] = (len & 0xff);
- 
-     if (write(fd, des_outpkt,desoutbuf.length+4) != desoutbuf.length+4){
-       fprintf(stderr,"Could not write out all data\n");
- 	return(-1);
-     }
-     else return(len);
- }
- 
- 
- 
- #else /* Original version  placed here so that testing could be done
- 	 to determine why rlogin with encryption on is slower with
- 	 version 5 as compared to version 4. */
- 
- #define ENCRYPT 1
- #define DECRYPT 0
- 
- 
- 
- int des_read(fd, buf, len)
-      int fd;
-      register char *buf;
-      int len;
- {
-     int nreturned = 0;
-     long net_len, rd_len;
-     int cc;
-     unsigned char len_buf[4];
-     
-     if (!encrypt_flag)
-       return(read(fd, buf, len));
-     
-     if (nstored >= len) {
- 	memcpy(buf, store_ptr, len);
- 	store_ptr += len;
- 	nstored -= len;
- 	return(len);
-     } else if (nstored) {
- 	memcpy(buf, store_ptr, nstored);
- 	nreturned += nstored;
- 	buf += nstored;
- 	len -= nstored;
- 	nstored = 0;
-     }
- #if 0
-     if ((cc = krb5_net_read(bsd_context, fd, len_buf, 4)) != 4) {
- 	/* XXX can't read enough, pipe must have closed */
- 	return(0);
-     }
-     net_len =
- 	((len_buf[0]<<24) | (len_buf[1]<<16) | (len_buf[2]<<8) | len_buf[3]);
- #else
- 	{
- 	    unsigned char c;
- 	    int gotzero = 0;
- 
- 	    /* See the comment in v4_des_read. */
- 	    do {
- 		cc = krb5_net_read(bsd_context, fd, &c, 1);
- 		/* we should check for non-blocking here, but we'd have
- 		   to make it save partial reads as well. */
- 		if (cc < 0) return 0; /* read error */
- 		if (cc == 1) {
- 		    if (c == 0) gotzero = 1;
- 		}
- 	    } while (!gotzero);
- 
- 	    if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
- 	    net_len = c;
- 	    if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
- 	    net_len = (net_len << 8) | c;
- 	    if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
- 	    net_len = (net_len << 8) | c;
- 	}
- #endif
-     if (net_len < 0 || net_len > sizeof(des_inbuf)) {
- 	/* XXX preposterous length, probably out of sync.
- 	   act as if pipe closed */
- 	return(0);
-     }
-     /* the writer tells us how much real data we are getting, but
-        we need to read the pad bytes (8-byte boundary) */
- #ifdef NOROUNDUP
-     rd_len = ((((net_len)+((8)-1))/(8))*(8));
- #else
-     rd_len = roundup(net_len, 8);
- #endif
-     if ((cc = krb5_net_read(bsd_context, fd, des_inbuf, rd_len)) != rd_len) {
- 	/* pipe must have closed, return 0 */
- 	return(0);
-     }
-     (void) mit_des_cbc_encrypt(
- 			       des_inbuf,
- 			       storage,
- 			       (net_len < 8) ? 8 : net_len,
- 			       eblock.priv,
- 			       eblock.key->contents,
- 			       DECRYPT);
-     /*
-      * when the cleartext block is < 8 bytes, it is "right-justified"
-      * in the block, so we need to adjust the pointer to the data
-      */
-     if (net_len < 8)
-       store_ptr = storage + 8 - net_len;
-     else
-       store_ptr = storage;
-     nstored = net_len;
-     if (nstored > len) {
- 	memcpy(buf, store_ptr, len);
- 	nreturned += len;
- 	store_ptr += len;
- 	nstored -= len;
-     } else {
- 	memcpy(buf, store_ptr, nstored);
- 	nreturned += nstored;
- 	nstored = 0;
-     }
-     return(nreturned);
- }
- 
- 
- 
- int des_write(fd, buf, len)
-      int fd;
-      char *buf;
-      int len;
- {
-     static char garbage_buf[8];
-     unsigned char len_buf[4];
-     
-     if (!encrypt_flag)
-       return(write(fd, buf, len));
-     
- #define min(a,b) ((a < b) ? a : b)
-     
-     if (len < 8) {
- 	krb5_random_confounder(bsd_context, 8 - len, &garbage_buf);
- 	/* this "right-justifies" the data in the buffer */
- 	(void) memcpy(garbage_buf + 8 - len, buf, len);
-     }
-     
-     (void) mit_des_cbc_encrypt((len < 8) ? garbage_buf : buf,
- 			       des_outbuf,
- 			       (len < 8) ? 8 : len,
- 			       eblock.priv,
- 			       eblock.key->contents,
- 			       ENCRYPT);
-     
-     /* tell the other end the real amount, but send an 8-byte padded
-        packet */
-     len_buf[0] = (len & 0xff000000) >> 24;
-     len_buf[1] = (len & 0xff0000) >> 16;
-     len_buf[2] = (len & 0xff00) >> 8;
-     len_buf[3] = (len & 0xff);
-     (void) write(fd, len_buf, 4);
- #ifdef NOROUNDUP
-     (void) write(fd, des_outbuf, ((((len)+((8)-1))/(8))*(8)));
- #else
-     (void) write(fd, des_outbuf, roundup(len,8));
- #endif
-     return(len);
- }
- 
- #endif /* OLD_VERSION */
- #endif /* KERBEROS */
  
  
  
--- 1582,1588 ----
Index: krcp.c
===================================================================
RCS file: /afs/dev.mit.edu/source/repository/third/krb5/src/appl/bsd/krcp.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -c -r1.1 -r1.2
*** krcp.c	1996/09/12 04:42:06	1.1
--- krcp.c	1997/10/19 03:44:25	1.2
***************
*** 72,105 ****
  #define setreuid(r,e) setresuid(r,e,-1)
  #endif
  #endif
- #ifndef roundup
- #define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
- #endif
  
  #ifdef KERBEROS
  #include "krb5.h"
  #include "com_err.h"
       
  #define RCP_BUFSIZ 4096
       
  int sock;
! struct sockaddr_in foreign;	   /* set up by kcmd used by send_auth */
  char *krb_realm = NULL;
  char *krb_cache = NULL;
  char *krb_config = NULL;
- char des_inbuf[2*RCP_BUFSIZ];          /* needs to be > largest read size */
- char des_outbuf[2*RCP_BUFSIZ];         /* needs to be > largest write size */
- krb5_data desinbuf,desoutbuf;
  krb5_encrypt_block eblock;         /* eblock for encrypt/decrypt */
- krb5_keyblock *session_key;	   /* static key for session */
  krb5_context bsd_context;
  
! void	try_normal();
  char	**save_argv();
  #ifndef HAVE_STRSAVE
  char	*strsave();
  #endif
! int	des_write(), des_read();
  void 	usage(), sink(), source(), rsource(), verifydir(), answer_auth();
  int	response(), hosteq(), okname(), susystem();
  int	encryptflag = 0;
--- 72,109 ----
  #define setreuid(r,e) setresuid(r,e,-1)
  #endif
  #endif
  
  #ifdef KERBEROS
  #include "krb5.h"
  #include "com_err.h"
+ #ifdef KRB5_KRB4_COMPAT
+ #include <kerberosIV/krb.h>
+ #include <kerberosIV/krb4-proto.h>
+ #endif
       
  #define RCP_BUFSIZ 4096
       
  int sock;
! struct sockaddr_in local, foreign; /* set up by kcmd used by v4_send_auth */
  char *krb_realm = NULL;
  char *krb_cache = NULL;
  char *krb_config = NULL;
  krb5_encrypt_block eblock;         /* eblock for encrypt/decrypt */
  krb5_context bsd_context;
  
! #ifdef KRB5_KRB4_COMPAT
! Key_schedule v4_schedule;
! CREDENTIALS v4_cred;
! KTEXT_ST v4_ticket;
! MSG_DAT v4_msg_data;
! #endif
! 
! void	v4_send_auth(), try_normal();
  char	**save_argv();
  #ifndef HAVE_STRSAVE
  char	*strsave();
  #endif
! int	rcmd_stream_write(), rcmd_stream_read();
  void 	usage(), sink(), source(), rsource(), verifydir(), answer_auth();
  int	response(), hosteq(), okname(), susystem();
  int	encryptflag = 0;
***************
*** 108,116 ****
  #define	UCB_RCP	"/bin/rcp"
  #endif
  
- #else /* !KERBEROS */
- #define	des_read	read
- #define	des_write	write
  #endif /* KERBEROS */
  
  int	rem;
--- 112,117 ----
***************
*** 139,145 ****
  void	error KRB5_STDARG_P((char *, va_list));
  #endif
  
! #define	ga()	 	(void) des_write(rem, "", 1)
  
  int main(argc, argv)
       int argc;
--- 140,146 ----
  void	error KRB5_STDARG_P((char *, va_list));
  #endif
  
! #define	ga()	 	(void) rcmd_stream_write(rem, "", 1)
  
  int main(argc, argv)
       int argc;
***************
*** 162,171 ****
      int euid;
      char **orig_argv = save_argv(argc, argv);
  
!     krb5_init_context(&bsd_context);
!     krb5_init_ets(bsd_context);
!     desinbuf.data = des_inbuf;
!     desoutbuf.data = des_outbuf;    /* Set up des buffers */
  #endif
  
      pwd = getpwuid(userid = getuid());
--- 163,173 ----
      int euid;
      char **orig_argv = save_argv(argc, argv);
  
!     status = krb5_init_context(&bsd_context);
!     if (status) {
! 	    com_err(argv[0], status, "while initializing krb5");
! 	    exit(1);
!     }
  #endif
  
      pwd = getpwuid(userid = getuid());
***************
*** 239,244 ****
--- 241,247 ----
  	    
  	  case 'f':		/* "from" */
  	    iamremote = 1;
+ 	    rcmd_stream_init_normal();
  #if defined(KERBEROS)
  	    if (encryptflag)
  	      answer_auth(krb_config, krb_cache);
***************
*** 250,255 ****
--- 253,259 ----
  	    
  	  case 't':		/* "to" */
  	    iamremote = 1;
+ 	    rcmd_stream_init_normal();
  #if defined(KERBEROS)
  	    if (encryptflag)
  	      answer_auth(krb_config, krb_cache);
***************
*** 421,448 ****
  				  &cred,  
  				  0,  /* No seq # */
  				  0,  /* No server seq # */
! 				  (struct sockaddr_in *) 0,
  				  &foreign,
  				  authopts,
  				  0); /* Not any port # */
  		    if (status) {
! 			fprintf(stderr,
! 				"%s: kcmd to host %s failed - %s\n",
! 				orig_argv[0], host,
! 				error_message(status));
  			try_normal(orig_argv);
  		    }
! 		    else {
! 			rem = sock; 
! 			session_key = &cred->keyblock;
! 				   
!     krb5_use_enctype(bsd_context, &eblock, session_key->enctype);
!     if ((status = krb5_process_key(bsd_context, &eblock, session_key))) {
! 	fprintf(stderr, "rcp: send_auth failed krb5_process_key: %s\n",
! 		error_message(status));
! 	exit(1);
!     }
! 		    }
  #else
  		    rem = rcmd(&host, port, pwd->pw_name,
  			       tuser ? tuser : pwd->pw_name,
--- 425,458 ----
  				  &cred,  
  				  0,  /* No seq # */
  				  0,  /* No server seq # */
! 				  &local,
  				  &foreign,
  				  authopts,
  				  0); /* Not any port # */
  		    if (status) {
! #ifdef KRB5_KRB4_COMPAT
! 			fprintf(stderr, "Trying krb4 rcp...\n");
! 			if (strncmp(buf, "-x rcp", 6) == 0)
! 			    memcpy(buf, "rcp -x", 6);
! 			status = k4cmd(&sock, &host, port,
! 				       pwd->pw_name,
! 				       tuser ? tuser : pwd->pw_name, buf,
! 				       0, &v4_ticket, "rcmd", krb_realm,
! 				       NULL, NULL, NULL,
! 				       &local, &foreign, 0L, 0);
! 			if (status)
! 			    try_normal(orig_argv);
! 			if (encryptflag)
! 			    v4_send_auth(host, krb_realm);
! 			rcmd_stream_init_krb4(v4_cred.session, encryptflag, 0,
! 					      0);
! #else
  			try_normal(orig_argv);
+ #endif
  		    }
! 		    else
! 			rcmd_stream_init_krb5(&cred->keyblock, encryptflag, 0);
! 		    rem = sock;
  #else
  		    rem = rcmd(&host, port, pwd->pw_name,
  			       tuser ? tuser : pwd->pw_name,
***************
*** 522,545 ****
  			      authopts,
  			      0); /* Not any port # */
  		if (status) {
! 		    fprintf(stderr,
! 			    "%s: kcmd to host %s failed - %s\n",
! 			    orig_argv[0], host,
! 			    error_message(status));
! 		    try_normal(orig_argv);
! 		    
! 		} else {
! 		    rem = sock; 
! 			session_key = &cred->keyblock;
  				   
-     krb5_use_enctype(bsd_context, &eblock, session_key->enctype);
-     if ((status = krb5_process_key(bsd_context, &eblock, session_key))) {
- 	fprintf(stderr, "rcp: send_auth failed krb5_process_key: %s\n",
- 		error_message(status));
- 	exit(1);
-     }
- 
- 		}
  		euid = geteuid();
  #ifdef HAVE_SETREUID
  		if (euid == 0)
--- 532,559 ----
  			      authopts,
  			      0); /* Not any port # */
  		if (status) {
! #ifdef KRB5_KRB4_COMPAT
! 			fprintf(stderr, "Trying krb4 rcp...\n");
! 			if (strncmp(buf, "-x rcp", 6) == 0)
! 			    memcpy(buf, "rcp -x", 6);
! 			status = k4cmd(&sock, &host, port,
! 				       pwd->pw_name, suser, buf,
! 				       0, &v4_ticket, "rcmd", krb_realm,
! 				       NULL, NULL, NULL,
! 				       &local, &foreign, 0L, 0);
! 			if (status)
! 			    try_normal(orig_argv);
! 			if (encryptflag)
! 			    v4_send_auth(host, krb_realm);
! 			rcmd_stream_init_krb4(v4_cred.session, encryptflag, 0,
! 					      0);
! #else
! 			try_normal(orig_argv);
! #endif
! 		} else
! 		    rcmd_stream_init_krb5(&cred->keyblock, encryptflag, 0);
! 		rem = sock; 
  				   
  		euid = geteuid();
  #ifdef HAVE_SETREUID
  		if (euid == 0)
***************
*** 566,571 ****
--- 580,586 ----
  			   buf, 0);
  		if (rem < 0)
  		  continue;
+ 		rcmd_stream_init_normal();
  #ifdef HAVE_SETREUID
  		(void) setreuid(0, userid);
  		sink(1, argv+argc-1);
***************
*** 741,747 ****
  	     */
  	    (void) sprintf(buf, "T%ld 0 %ld 0\n",
  			   stb.st_mtime, stb.st_atime);
! 	    (void) des_write(rem, buf, strlen(buf));
  	    if (response() < 0) {
  		(void) close(f);
  		continue;
--- 756,762 ----
  	     */
  	    (void) sprintf(buf, "T%ld 0 %ld 0\n",
  			   stb.st_mtime, stb.st_atime);
! 	    (void) rcmd_stream_write(rem, buf, strlen(buf));
  	    if (response() < 0) {
  		(void) close(f);
  		continue;
***************
*** 749,755 ****
  	}
  	(void) sprintf(buf, "C%04o %ld %s\n",
  		       (int) stb.st_mode&07777, (long ) stb.st_size, last);
! 	(void) des_write(rem, buf, strlen(buf));
  	if (response() < 0) {
  	    (void) close(f);
  	    continue;
--- 764,770 ----
  	}
  	(void) sprintf(buf, "C%04o %ld %s\n",
  		       (int) stb.st_mode&07777, (long ) stb.st_size, last);
! 	(void) rcmd_stream_write(rem, buf, strlen(buf));
  	if (response() < 0) {
  	    (void) close(f);
  	    continue;
***************
*** 765,771 ****
  	      amt = stb.st_size - i;
  	    if (readerr == 0 && read(f, bp->buf, amt) != amt)
  	      readerr = errno;
! 	    (void) des_write(rem, bp->buf, amt);
  	}
  	(void) close(f);
  	if (readerr == 0)
--- 780,786 ----
  	      amt = stb.st_size - i;
  	    if (readerr == 0 && read(f, bp->buf, amt) != amt)
  	      readerr = errno;
! 	    (void) rcmd_stream_write(rem, bp->buf, amt);
  	}
  	(void) close(f);
  	if (readerr == 0)
***************
*** 810,823 ****
      if (pflag) {
  	(void) sprintf(buf, "T%ld 0 %ld 0\n",
  		       statp->st_mtime, statp->st_atime);
! 	(void) des_write(rem, buf, strlen(buf));
  	if (response() < 0) {
  	    closedir(d);
  	    return;
  	}
      }
      (void) sprintf(buf, "D%04o %d %s\n", statp->st_mode&07777, 0, last);
!     (void) des_write(rem, buf, strlen(buf));
      if (response() < 0) {
  	closedir(d);
  	return;
--- 825,838 ----
      if (pflag) {
  	(void) sprintf(buf, "T%ld 0 %ld 0\n",
  		       statp->st_mtime, statp->st_atime);
! 	(void) rcmd_stream_write(rem, buf, strlen(buf));
  	if (response() < 0) {
  	    closedir(d);
  	    return;
  	}
      }
      (void) sprintf(buf, "D%04o %d %s\n", statp->st_mode&07777, 0, last);
!     (void) rcmd_stream_write(rem, buf, strlen(buf));
      if (response() < 0) {
  	closedir(d);
  	return;
***************
*** 836,842 ****
  	source(1, bufv);
      }
      closedir(d);
!     (void) des_write(rem, "E\n", 2);
      (void) response();
  }
  
--- 851,857 ----
  	source(1, bufv);
      }
      closedir(d);
!     (void) rcmd_stream_write(rem, "E\n", 2);
      (void) response();
  }
  
***************
*** 845,851 ****
  int response()
  {
      char resp, c, rbuf[RCP_BUFSIZ], *cp = rbuf;
!     if (des_read(rem, &resp, 1) != 1)
        lostconn();
      switch (resp) {
  	
--- 860,866 ----
  int response()
  {
      char resp, c, rbuf[RCP_BUFSIZ], *cp = rbuf;
!     if (rcmd_stream_read(rem, &resp, 1) != 1)
        lostconn();
      switch (resp) {
  	
***************
*** 858,864 ****
        case 1:				/* error, followed by err msg */
        case 2:				/* fatal error, "" */
  	do {
! 	    if (des_read(rem, &c, 1) != 1)
  	      lostconn();
  	    *cp++ = c;
  	} while (cp < &rbuf[RCP_BUFSIZ] && c != '\n');
--- 873,879 ----
        case 1:				/* error, followed by err msg */
        case 2:				/* fatal error, "" */
  	do {
! 	    if (rcmd_stream_read(rem, &c, 1) != 1)
  	      lostconn();
  	    *cp++ = c;
  	} while (cp < &rbuf[RCP_BUFSIZ] && c != '\n');
***************
*** 941,952 ****
        targisdir = 1;
      for (first = 1; ; first = 0) {
  	cp = cmdbuf;
! 	if (des_read(rem, cp, 1) <= 0)
  	  return;
  	if (*cp++ == '\n')
  	  SCREWUP("unexpected '\\n'");
  	do {
! 	    if (des_read(rem, cp, 1) != 1)
  	      SCREWUP("lost connection");
  	} while (*cp++ != '\n');
  	*cp = 0;
--- 956,967 ----
        targisdir = 1;
      for (first = 1; ; first = 0) {
  	cp = cmdbuf;
! 	if (rcmd_stream_read(rem, cp, 1) <= 0)
  	  return;
  	if (*cp++ == '\n')
  	  SCREWUP("unexpected '\\n'");
  	do {
! 	    if (rcmd_stream_read(rem, cp, 1) != 1)
  	      SCREWUP("lost connection");
  	} while (*cp++ != '\n');
  	*cp = 0;
***************
*** 1064,1070 ****
  	      amt = size - i;
  	    count += amt;
  	    do {
! 		j = des_read(rem, cp, amt);
  		if (j <= 0) {
  		    if (j == 0)
  		      error("rcp: dropped connection");
--- 1079,1085 ----
  	      amt = size - i;
  	    count += amt;
  	    do {
! 		j = rcmd_stream_read(rem, cp, amt);
  		if (j <= 0) {
  		    if (j == 0)
  		      error("rcp: dropped connection");
***************
*** 1119,1129 ****
  	error("rcp: fstat: %s\n", error_message(errno));
  	return (NULLBUF);
      }
- #ifdef NOROUNDUP
-     size = 0;
- #else
-     size = roundup(stb.st_blksize, blksize);
- #endif
  
      size = blksize;
      if (bp->cnt < size) {
--- 1134,1139 ----
***************
*** 1165,1171 ****
      (void) vsprintf(cp, fmt, ap);
      va_end(ap);
  
!     (void) des_write(rem, buf, strlen(buf));
      if (iamremote == 0)
        (void) write(2, buf+1, strlen(buf+1));
  }
--- 1175,1181 ----
      (void) vsprintf(cp, fmt, ap);
      va_end(ap);
  
!     (void) rcmd_stream_write(rem, buf, strlen(buf));
      if (iamremote == 0)
        (void) write(2, buf+1, strlen(buf+1));
  }
***************
*** 1257,1262 ****
--- 1267,1276 ----
  
  
  
+ /* This function is mostly vestigial, since under normal operation
+  * the -x flag doesn't get set for the server process for encrypted
+  * rcp.  It only gets called by beta clients attempting user-to-user
+  * authentication. */
  void
    answer_auth(config_file, ccache_file)
      char *config_file;
***************
*** 1317,1465 ****
  	exit(1);
      }
      
!     /* setup eblock for des_read and write */
!     krb5_copy_keyblock(bsd_context, &new_creds->keyblock,&session_key);
      
      /* cleanup */
      krb5_free_cred_contents(bsd_context, &creds);
      krb5_free_creds(bsd_context, new_creds);
      krb5_xfree(msg.data);
-     
-     /* OK process key */
-     krb5_use_enctype(bsd_context, &eblock, session_key->enctype);
-     if ((status = krb5_process_key(bsd_context, &eblock, session_key)))
- 	exit(1);
  
      return;
  }
  
  
  
! char storage[2*RCP_BUFSIZ];		/* storage for the decryption */
! int nstored = 0;
! char *store_ptr = storage;
! 
! int des_read(fd, buf, len)
!      int fd;
!      register char *buf;
!      int len;
! {
!     int nreturned = 0;
!     long net_len,rd_len;
!     int cc;
!     krb5_error_code status;
!     unsigned char len_buf[4];
!     
!     if (!encryptflag)
!       return(read(fd, buf, len));
!     
!     if (nstored >= len) {
! 	memcpy(buf, store_ptr, len);
! 	store_ptr += len;
! 	nstored -= len;
! 	return(len);
!     } else if (nstored) {
! 	memcpy(buf, store_ptr, nstored);
! 	nreturned += nstored;
! 	buf += nstored;
! 	len -= nstored;
! 	nstored = 0;
!     }
!     
!     if ((cc = krb5_net_read(bsd_context, fd, (char *)len_buf, 4)) != 4) {
! 	/* XXX can't read enough, pipe must have closed */
! 	return(0);
!     }
!     rd_len =
! 	((len_buf[0]<<24) | (len_buf[1]<<16) | (len_buf[2]<<8) | len_buf[3]);
!     net_len = krb5_encrypt_size(rd_len,eblock.crypto_entry);
!     if (net_len <= 0 || net_len > sizeof(des_inbuf)) {
! 	/* preposterous length; assume out-of-sync; only
! 	   recourse is to close connection, so return 0 */
! 	error( "rcp: Des_read size problem net_len %d rd_len %d %d.\n",
! 	      net_len,rd_len, len);
! 	errno = E2BIG;
! 	return(-1);
!     }
!     if ((cc = krb5_net_read(bsd_context, fd, desinbuf.data, net_len)) != net_len) {
! 	/* pipe must have closed, return 0 */
! 	error( "rcp: Des_read error: length received %d != expected %d.\n",
! 	      cc,net_len);
! 	return(0);
!     }
!     /* decrypt info */
!     if ((status = krb5_decrypt(bsd_context, desinbuf.data,
! 			       (krb5_pointer) storage,
! 			       net_len,
! 			       &eblock, 0))) {
! 	error("rcp: Des_read cannot decrypt data from network %s.\n",
! 	      error_message(status));
! 	return(0);
!     }
!     store_ptr = storage;
!     nstored = rd_len;
!     if (nstored > len) {
! 	memcpy(buf, store_ptr, len);
! 	nreturned += len;
! 	store_ptr += len;
! 	nstored -= len;
!     } else {
! 	memcpy(buf, store_ptr, nstored);
! 	nreturned += nstored;
! 	nstored = 0;
!     }
!     
!     return(nreturned);
! }
! 
! 
! 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
!      */
!     
!     if (fd == 0)
! 	fd = 1;
!     if (!encryptflag)
!       return(krb5_net_write(bsd_context, fd, buf, len));
!     
!     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, des_write_buf.data, 
- 		      len, &eblock, 0))) {
- 	return(-1);
-     }
-     
-     len_buf[0] = (len & 0xff000000) >> 24;
-     len_buf[1] = (len & 0xff0000) >> 16;
-     len_buf[2] = (len & 0xff00) >> 8;
-     len_buf[3] = (len & 0xff);
-     if ((write(fd, len_buf, 4) != 4) || (write(fd, des_write_buf.data, 
- 	des_write_buf.length) != des_write_buf.length)) {
- 	return(-1);
-     }
-     return(len);
  }
  
  #endif /* KERBEROS */
--- 1331,1376 ----
  	exit(1);
      }
      
!     rcmd_stream_init_krb5(&new_creds->keyblock, encryptflag, 0);
      
      /* cleanup */
      krb5_free_cred_contents(bsd_context, &creds);
      krb5_free_creds(bsd_context, new_creds);
      krb5_xfree(msg.data);
  
      return;
  }
  
  
  
! #ifdef KRB5_KRB4_COMPAT
! void
! v4_send_auth(host,realm)
! char *host;
! char *realm;
  {
! 	long authopts;
  
! 	if ((realm == NULL) || (realm[0] == '\0'))
! 	     realm = krb_realmofhost(host);
! 	/* this needs to be sent again, because the
! 	   rcp process needs the key.  the rshd has
! 	   grabbed the first one. */
! 	authopts = KOPT_DO_MUTUAL;
! 	if ((rem = krb_sendauth(authopts, sock, &v4_ticket,
! 				"rcmd", host,
! 				realm, (unsigned long) getpid(),
! 				&v4_msg_data,
! 				&v4_cred, v4_schedule,
! 				&local,
! 				&foreign,
! 				"KCMDV0.1")) != KSUCCESS) {
! 		fprintf(stderr,
! 			"krb_sendauth mutual fail: %s\n",
! 			krb_get_err_text(rem));
! 		exit(1);
  	}
  }
+ #endif /* KRB5_KRB4_COMPAT */
  
  #endif /* KERBEROS */
Index: krlogind.c
===================================================================
RCS file: /afs/dev.mit.edu/source/repository/third/krb5/src/appl/bsd/krlogind.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -c -r1.4 -r1.5
*** krlogind.c	1997/09/20 06:52:34	1.4
--- krlogind.c	1997/10/19 03:47:16	1.5
***************
*** 216,243 ****
  
  AUTH_DAT	*v4_kdata;
  Key_schedule v4_schedule;
- int v4_des_read(), v4_des_write();
- 
- #define RLOGIND_BUFSIZ 5120
- 
- int v5_des_read(), v5_des_write();
  
  #include "com_err.h"
       
  #define SECURE_MESSAGE  "This rlogin session is using DES encryption for all data transmissions.\r\n"
- /*
-  * Note that the encrypted rlogin packets take the form of a four-byte
-  *length followed by encrypted data.  On writing the data out, a significant
-  * performance penalty is suffered (at least one RTT per character, two if we
-  * are waiting for a shell to echo) by writing the data separately from the 
-  * length.  So, unlike the input buffer, which just contains the output
-  * data, the output buffer represents the entire packet.
-  */
-  int (*des_read)(), (*des_write)();
- char des_inbuf[2*RLOGIND_BUFSIZ]; /* needs to be > largest read size */
- char des_outpkt[2*RLOGIND_BUFSIZ+4];/* needs to be > largest write size */
- krb5_data desinbuf,desoutbuf;
- krb5_encrypt_block eblock;        /* eblock for encrypt/decrypt */
  
  krb5_authenticator      *kdata;
  krb5_ticket     *ticket = 0;
--- 216,225 ----
***************
*** 249,256 ****
  #define ARGSTR	"k54ciepPD:S:M:L:?"
  #else /* !KERBEROS */
  #define ARGSTR	"rpPD:?"
- #define (*des_read)  read
- #define (*des_write) write
  #endif /* KERBEROS */
  
  #ifndef LOGIN_PROGRAM
--- 231,236 ----
***************
*** 556,568 ****
      if (fromp->sin_family != AF_INET)
        fatal(f, "Permission denied - Malformed from address\n");
      
! #ifdef KERBEROS
! 
! 	/* setup des buffers */
!     desinbuf.data = des_inbuf;
!     desoutbuf.data = des_outpkt+4;    /* Set up des buffers */
! 
! #else /* !KERBEROS */
      if (fromp->sin_port >= IPPORT_RESERVED ||
  	fromp->sin_port < IPPORT_RESERVED/2)
        fatal(f, "Permission denied - Connection from bad port");
--- 536,542 ----
      if (fromp->sin_family != AF_INET)
        fatal(f, "Permission denied - Malformed from address\n");
      
! #ifndef KERBEROS
      if (fromp->sin_port >= IPPORT_RESERVED ||
  	fromp->sin_port < IPPORT_RESERVED/2)
        fatal(f, "Permission denied - Connection from bad port");
***************
*** 579,584 ****
--- 553,559 ----
      getstr(f, rusername, sizeof(rusername), "remuser");
      getstr(f, lusername, sizeof(lusername), "locuser");
      getstr(f, term, sizeof(term), "Terminal type");
+     rcmd_stream_init_normal();
  #endif
      
      write(f, "", 1);
***************
*** 754,760 ****
      
  #if defined(KERBEROS) 
      if (do_encrypt) {
! 	if (((*des_write)(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE))) < 0){
  	    sprintf(buferror, "Cannot encrypt-write network.");
  	    fatal(p,buferror);
  	}
--- 729,735 ----
      
  #if defined(KERBEROS) 
      if (do_encrypt) {
! 	if (rcmd_stream_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE)) < 0){
  	    sprintf(buferror, "Cannot encrypt-write network.");
  	    fatal(p,buferror);
  	}
***************
*** 924,930 ****
  	    }
  	}
  	if (FD_ISSET(f, &ibits)) {
! 	    fcc = (*des_read)(f, fibuf, sizeof (fibuf));
  	    if (fcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
  	      fcc = 0;
  	    else {
--- 899,905 ----
  	    }
  	}
  	if (FD_ISSET(f, &ibits)) {
! 	    fcc = rcmd_stream_read(f, fibuf, sizeof (fibuf));
  	    if (fcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
  	      fcc = 0;
  	    else {
***************
*** 982,988 ****
  #endif
  	}
  	if (FD_ISSET(f, &obits) && pcc > 0) {
! 	    cc = (*des_write)(f, pbp, pcc);
  	    if (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
  		/* also shouldn't happen */
  		sleep(5);
--- 957,963 ----
  #endif
  	}
  	if (FD_ISSET(f, &obits) && pcc > 0) {
! 	    cc = rcmd_stream_write(f, pbp, pcc);
  	    if (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
  		/* also shouldn't happen */
  		sleep(5);
***************
*** 1021,1027 ****
      buf[0] = '\01';		/* error indicator */
      (void) sprintf(buf + 1, "%s: %s.\r\n",progname, msg);
      if ((f == netf) && (pid > 0))
!       (void) (*des_write)(f, buf, strlen(buf));
      else
        (void) write(f, buf, strlen(buf));
      syslog(LOG_ERR,"%s\n",msg);
--- 996,1002 ----
      buf[0] = '\01';		/* error indicator */
      (void) sprintf(buf + 1, "%s: %s.\r\n",progname, msg);
      if ((f == netf) && (pid > 0))
!       (void) rcmd_stream_write(f, buf, strlen(buf));
      else
        (void) write(f, buf, strlen(buf));
      syslog(LOG_ERR,"%s\n",msg);
***************
*** 1144,1149 ****
--- 1119,1126 ----
      /* NOTREACHED */
  }
  
+ #endif /* KERBEROS */
+ 
  
  
  void getstr(fd, buf, cnt, err)
***************
*** 1169,1334 ****
  
  
  
- char storage[2*RLOGIND_BUFSIZ];             /* storage for the decryption */
- int nstored = 0;
- char *store_ptr = storage;
- 
- int
- v5_des_read(fd, buf, len)
-      int fd;
-      register char *buf;
-      int len;
- {
-     int nreturned = 0;
-     krb5_ui_4 net_len,rd_len;
-     int cc,retry;
- #if 0
-     unsigned char len_buf[4];
- #endif
-     
-     if (!do_encrypt)
-       return(read(fd, buf, len));
-     
-     if (nstored >= len) {
- 	memcpy(buf, store_ptr, len);
- 	store_ptr += len;
- 	nstored -= len;
- 	return(len);
-     } else if (nstored) {
- 	memcpy(buf, store_ptr, nstored);
- 	nreturned += nstored;
- 	buf += nstored;
- 	len -= nstored;
- 	nstored = 0;
-     }
-     
- #if 0
-     if ((cc = krb5_net_read(bsd_context, fd, (char *)len_buf, 4)) != 4) {
- 	if ((cc < 0)  && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
- 	    return(cc);
- 	/* XXX can't read enough, pipe must have closed */
- 	return(0);
-     }
-     rd_len =
- 	(((krb5_ui_4)len_buf[0]<<24) |
- 	 ((krb5_ui_4)len_buf[1]<<16) |
- 	 ((krb5_ui_4)len_buf[2]<<8) |
- 	 (krb5_ui_4)len_buf[3]);
- #else
- 	{
- 	    unsigned char c;
- 	    int gotzero = 0;
- 
- 	    /* See the comment in v4_des_read. */
- 	    do {
- 		cc = krb5_net_read(bsd_context, fd, &c, 1);
- 		/* we should check for non-blocking here, but we'd have
- 		   to make it save partial reads as well. */
- 		if (cc <= 0) return 0; /* read error */
- 		if (cc == 1) {
- 		    if (c == 0) gotzero = 1;
- 		}
- 	    } while (!gotzero);
- 
- 	    if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
- 	    rd_len = c;
- 	    if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
- 	    rd_len = (rd_len << 8) | c;
- 	    if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
- 	    rd_len = (rd_len << 8) | c;
- 	}
- #endif
-     net_len = krb5_encrypt_size(rd_len,eblock.crypto_entry);
-     /* note net_len is unsigned */
-     if (net_len > sizeof(des_inbuf)) {
- 	/* XXX preposterous length, probably out of sync.
- 	   act as if pipe closed */
- 	syslog(LOG_ERR,"Read size problem.");
- 	return(0);
-     }
-     retry = 0;
-   datard:
-     if ((cc = krb5_net_read(bsd_context,fd,desinbuf.data,net_len)) != net_len) {
- 	/* XXX can't read enough, pipe must have closed */
- 	if ((cc < 0)  && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
- 	    retry++;
- 	    sleep(1);
- 	    if (retry > MAXRETRIES){
- 		syslog(LOG_ERR,
- 		       "des_read retry count exceeded %d\n",
- 		       retry);
- 		return(0);
- 	    }
- 	    goto datard;
- 	}
- 	syslog(LOG_ERR,
- 	       "Read data received %d != expected %d.",
- 	       cc, net_len);
- 	return(0);
-     }
-     /* decrypt info */
-     if ((krb5_decrypt(bsd_context, desinbuf.data,
- 		      (krb5_pointer) storage,
- 		      net_len,
- 		      &eblock, 0))) {
- 	syslog(LOG_ERR,"Read decrypt problem.");
- 	return(0);
-     }
-     store_ptr = storage;
-     nstored = rd_len;
-     if (nstored > len) {
- 	memcpy(buf, store_ptr, len);
- 	nreturned += len;
- 	store_ptr += len;
- 	nstored -= len;
-     } else {
- 	memcpy(buf, store_ptr, nstored);
- 	nreturned += nstored;
- 	nstored = 0;
-     }
-     return(nreturned);
- }
-     
- 
- int
- v5_des_write(fd, buf, len)
-      int fd;
-      char *buf;
-      int len;
- {
-   unsigned char *len_buf = (unsigned char *) des_outpkt;
-     
-     if (!do_encrypt)
-       return(write(fd, buf, len));
-     
-     
-     desoutbuf.length = krb5_encrypt_size(len,eblock.crypto_entry);
-     if (desoutbuf.length > sizeof(des_outpkt)-4){
- 	syslog(LOG_ERR,"Write size problem.");
- 	return(-1);
-     }
-     if ((krb5_encrypt(bsd_context, (krb5_pointer)buf,
- 		      desoutbuf.data,
- 		      len,
- 		      &eblock,
- 		      0))){
- 	syslog(LOG_ERR,"Write encrypt problem.");
- 	return(-1);
-     }
- 
-     len_buf[0] = (len & 0xff000000) >> 24;
-     len_buf[1] = (len & 0xff0000) >> 16;
-     len_buf[2] = (len & 0xff00) >> 8;
-     len_buf[3] = (len & 0xff);
- 
-     if (write(fd, des_outpkt,desoutbuf.length+4) != desoutbuf.length+4){
- 	syslog(LOG_ERR,"Could not write out all data.");
- 	return(-1);
-     }
-     else return(len);
- }
- #endif /* KERBEROS */
- 
  void usage()
  {
  #ifdef KERBEROS
--- 1146,1151 ----
***************
*** 1513,1520 ****
  #ifdef KRB5_KRB4_COMPAT
      if (auth_sys == KRB5_RECVAUTH_V4) {
  
! 	des_read  = v4_des_read;
! 	des_write = v4_des_write;
  
  	/* We do not really know the remote user's login name.
           * Assume it to be the same as the first component of the
--- 1330,1336 ----
  #ifdef KRB5_KRB4_COMPAT
      if (auth_sys == KRB5_RECVAUTH_V4) {
  
! 	rcmd_stream_init_krb4(v4_kdata->session, do_encrypt, 1, 1);
  
  	/* We do not really know the remote user's login name.
           * Assume it to be the same as the first component of the
***************
*** 1539,1562 ****
  				      &client)))
  	return status;
  
!     des_read  = v5_des_read;
!     des_write = v5_des_write;
  
      getstr(netf, rusername, sizeof(rusername), "remuser");
  
      if ((status = krb5_unparse_name(bsd_context, client, &krusername)))
  	return status;
      
-     /* Setup up eblock if encrypted login session */
-     /* otherwise zero out session key */
-     if (do_encrypt) {
- 	krb5_use_enctype(bsd_context, &eblock,
- 			 ticket->enc_part2->session->enctype);
- 	if ((status = krb5_process_key(bsd_context, &eblock,
- 				       ticket->enc_part2->session)))
- 	    fatal(netf, "Permission denied");
-     }      
- 
      if ((status = krb5_read_message(bsd_context, (krb5_pointer)&netf, &inbuf)))
  	fatal(netf, "Error reading message");
  
--- 1355,1367 ----
  				      &client)))
  	return status;
  
!     rcmd_stream_init_krb5(ticket->enc_part2->session, do_encrypt, 1);
  
      getstr(netf, rusername, sizeof(rusername), "remuser");
  
      if ((status = krb5_unparse_name(bsd_context, client, &krusername)))
  	return status;
      
      if ((status = krb5_read_message(bsd_context, (krb5_pointer)&netf, &inbuf)))
  	fatal(netf, "Error reading message");
  
***************
*** 1568,1742 ****
      return 0;
  }
  
- 
- #ifdef KRB5_KRB4_COMPAT
- 
- int
- v4_des_read(fd, buf, len)
- int fd;
- register char *buf;
- int len;
- {
- 	int nreturned = 0;
- 	krb5_ui_4 net_len, rd_len;
- 	int cc;
- #if 0
- 	unsigned char len_buf[4];
- #endif
- 
- 	if (!do_encrypt)
- 		return(read(fd, buf, len));
- 
- 	if (nstored >= len) {
- 		memcpy(buf, store_ptr, len);
- 		store_ptr += len;
- 		nstored -= len;
- 		return(len);
- 	} else if (nstored) {
- 		memcpy(buf, store_ptr, nstored);
- 		nreturned += nstored;
- 		buf += nstored;
- 		len -= nstored;
- 		nstored = 0;
- 	}
- 
- #if 0
- 	if ((cc = krb_net_read(fd, (char *)len_buf, 4)) != 4) {
- 		/* XXX can't read enough, pipe
- 		   must have closed */
- 		return(0);
- 	}
-  	net_len = (((krb5_ui_4)len_buf[0]<<24) |
- 		   ((krb5_ui_4)len_buf[1]<<16) |
- 		   ((krb5_ui_4)len_buf[2]<<8) |
- 		   (krb5_ui_4)len_buf[3]);
- #else
- 	{
- 	    unsigned char c;
- 	    int gotzero = 0;
- 
- 	    /* We're fetching the length which is MSB first, and the MSB
- 	       has to be zero unless the client is sending more than 2^24
- 	       (16M) bytes in a single write (which is why this code is in
- 	       rlogin but not rcp or rsh.) The only reasons we'd get something
- 	       other than zero are:
- 	           -- corruption of the tcp stream (which will show up when
- 		      everything else is out of sync too)
- 		   -- un-caught Berkeley-style "pseudo out-of-band data" which
- 		      happens any time the user hits ^C twice.
- 	       The latter is *very* common, as shown by an 'rlogin -x -d' 
- 	       using the CNS V4 rlogin.         Mark EIchin 1/95
- 	      */
- 	    do {
- 		cc = krb_net_read(fd, &c, 1);
- 		if (cc <= 0) return 0; /* read error */
- 		if (cc == 1) {
- 		    if (c == 0) gotzero = 1;
- 		}
- 	    } while (!gotzero);
- 
- 	    if ((cc = krb_net_read(fd, &c, 1)) != 1) return 0;
- 	    net_len = c;
- 	    if ((cc = krb_net_read(fd, &c, 1)) != 1) return 0;
- 	    net_len = (net_len << 8) | c;
- 	    if ((cc = krb_net_read(fd, &c, 1)) != 1) return 0;
- 	    net_len = (net_len << 8) | c;
- 	}
- 
- #endif
- 	/* Note: net_len is unsigned */
- 	if (net_len > sizeof(des_inbuf)) {
- 		/* XXX preposterous length, probably out of sync.
- 		   act as if pipe closed */
- 		return(0);
- 	}
- 	/* the writer tells us how much real data we are getting, but
- 	   we need to read the pad bytes (8-byte boundary) */
- 	rd_len = roundup(net_len, 8);
- 	if ((cc = krb_net_read(fd, des_inbuf, rd_len)) != rd_len) {
- 		/* XXX can't read enough, pipe
- 		   must have closed */
- 		return(0);
- 	}
- 	(void) pcbc_encrypt(des_inbuf,
- 			    storage,
- 			    (net_len < 8) ? 8 : net_len,
- 			    v4_schedule,
- 			    v4_kdata->session,
- 			    DECRYPT);
- 	/* 
- 	 * when the cleartext block is < 8 bytes, it is "right-justified"
- 	 * in the block, so we need to adjust the pointer to the data
- 	 */
- 	if (net_len < 8)
- 		store_ptr = storage + 8 - net_len;
- 	else
- 		store_ptr = storage;
- 	nstored = net_len;
- 	if (nstored > len) {
- 		memcpy(buf, store_ptr, len);
- 		nreturned += len;
- 		store_ptr += len;
- 		nstored -= len;
- 	} else {
- 		memcpy(buf, store_ptr, nstored);
- 		nreturned += nstored;
- 		nstored = 0;
- 	}
- 	
- 	return(nreturned);
- }
- 
- int
- v4_des_write(fd, buf, len)
- int fd;
- char *buf;
- int len;
- {
- 	static char garbage_buf[8];
- 	unsigned char *len_buf = (unsigned char *) des_outpkt;
- 
- 	if (!do_encrypt)
- 		return(write(fd, buf, len));
- 
- 	/* 
- 	 * pcbc_encrypt outputs in 8-byte (64 bit) increments
- 	 *
- 	 * it zero-fills the cleartext to 8-byte padding,
- 	 * so if we have cleartext of < 8 bytes, we want
- 	 * to insert random garbage before it so that the ciphertext
- 	 * differs for each transmission of the same cleartext.
- 	 * if len < 8 - sizeof(long), sizeof(long) bytes of random
- 	 * garbage should be sufficient; leave the rest as-is in the buffer.
- 	 * if len > 8 - sizeof(long), just garbage fill the rest.
- 	 */
- 
- #ifdef min
- #undef min
- #endif
- #define min(a,b) ((a < b) ? a : b)
- 
- 	if (len < 8) {
- 		krb5_random_confounder(8 - len, garbage_buf);
- 		/* this "right-justifies" the data in the buffer */
- 		(void) memcpy(garbage_buf + 8 - len, buf, len);
- 	}
- 	(void) pcbc_encrypt((len < 8) ? garbage_buf : buf,
- 			    des_outpkt+4,
- 			    (len < 8) ? 8 : len,
- 			    v4_schedule,
- 			    v4_kdata->session,
- 			    ENCRYPT);
- 
- 	/* tell the other end the real amount, but send an 8-byte padded
- 	   packet */
- 	len_buf[0] = (len & 0xff000000) >> 24;
- 	len_buf[1] = (len & 0xff0000) >> 16;
- 	len_buf[2] = (len & 0xff00) >> 8;
- 	len_buf[3] = (len & 0xff);
- 	(void) write(fd, des_outpkt, roundup(len,8)+4);
- 	return(len);
- }
- 
- #endif /* KRB5_KRB4_COMPAT */
  #endif /* KERBEROS */
--- 1373,1376 ----
Index: krshd.c
===================================================================
RCS file: /afs/dev.mit.edu/source/repository/third/krb5/src/appl/bsd/krshd.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -c -r1.4 -r1.5
*** krshd.c	1997/09/20 06:53:31	1.4
--- krshd.c	1997/10/19 03:47:18	1.5
***************
*** 149,154 ****
--- 149,158 ----
  #include "krb5.h"
  #include "com_err.h"
  #include "loginpaths.h"
+ #ifdef KRB5_KRB4_COMPAT
+ #include <kerberosIV/krb.h>
+ Key_schedule v4_schedule;
+ #endif
  
  #define ARGSTR	"ek54ciD:S:M:AP:?L:"
  
***************
*** 157,176 ****
  
  #define MAXRETRIES 4
  
- char des_inbuf[2*RSHD_BUFSIZ];    /* needs to be > largest read size */
- krb5_encrypt_block eblock;        /* eblock for encrypt/decrypt */
- char des_outbuf[2*RSHD_BUFSIZ];   /* needs to be > largest write size */
- krb5_data desinbuf,desoutbuf;
  krb5_context bsd_context;
  char *srvtab = NULL;
  krb5_keytab keytab = NULL;
  krb5_ccache ccache = NULL;
  void fatal();
- int v5_des_read();
- int v5_des_write();
  
- int (*des_read)() = v5_des_read;
- int (*des_write)() = v5_des_write;
  int require_encrypt = 0;
  int do_encrypt = 0;
  int anyport = 0;
--- 161,172 ----
***************
*** 180,187 ****
  #else /* !KERBEROS */
  
  #define ARGSTR	"RD:?"
- int (*des_read)() = read;
- int (*des_write)() = write;
       
  #endif /* KERBEROS */
       
--- 176,181 ----
***************
*** 639,646 ****
      }
  #ifdef KERBEROS
      netf = f;
-     desinbuf.data = des_inbuf;
-     desoutbuf.data = des_outbuf;
      if ( (fromp->sin_port >= IPPORT_RESERVED ||
  	    fromp->sin_port < IPPORT_RESERVED/2))
        non_privileged = 1;
--- 633,638 ----
***************
*** 758,769 ****
  	error("Authentication failed: %s\n", error_message(status));
  	exit(1);
      }
-     if (!strncmp(cmdbuf, "-x ", 3))
- 	do_encrypt = 1;
  #else
      getstr(f, remuser, sizeof(remuser), "remuser");
      getstr(f, locuser, sizeof(locuser), "locuser");
      getstr(f, cmdbuf, sizeof(cmdbuf), "command");
  #endif /* KERBEROS */
      
  #ifdef CRAY
--- 750,760 ----
  	error("Authentication failed: %s\n", error_message(status));
  	exit(1);
      }
  #else
      getstr(f, remuser, sizeof(remuser), "remuser");
      getstr(f, locuser, sizeof(locuser), "locuser");
      getstr(f, cmdbuf, sizeof(cmdbuf), "command");
+     rcmd_stream_init_normal();
  #endif /* KERBEROS */
      
  #ifdef CRAY
***************
*** 1213,1219 ****
  			shutdown(s, 1+1);
  			FD_CLR(pv[0], &readfrom);
  		    } else {
! 			(void) (*des_write)(s, buf, cc);
  		    }
  		}
  		if (FD_ISSET(pw[0], &ready)) {
--- 1204,1210 ----
  			shutdown(s, 1+1);
  			FD_CLR(pv[0], &readfrom);
  		    } else {
! 			(void) rcmd_stream_write(s, buf, cc);
  		    }
  		}
  		if (FD_ISSET(pw[0], &ready)) {
***************
*** 1224,1235 ****
  			shutdown(f, 1+1);
  			FD_CLR(pw[0], &readfrom);
  		    } else {
! 			(void) (*des_write)(f, buf, cc);
  		    }
  		}
  		if (port&&FD_ISSET(s, &ready)) {
  		    /* read from the alternate channel, signal the child */
! 		    if ((*des_read)(s, &sig, 1) <= 0) {
  			FD_CLR(s, &readfrom);
  		    } else {
  #ifdef POSIX_SIGNALS
--- 1215,1226 ----
  			shutdown(f, 1+1);
  			FD_CLR(pw[0], &readfrom);
  		    } else {
! 			(void) rcmd_stream_write(f, buf, cc);
  		    }
  		}
  		if (port&&FD_ISSET(s, &ready)) {
  		    /* read from the alternate channel, signal the child */
! 		    if (rcmd_stream_read(s, &sig, 1) <= 0) {
  			FD_CLR(s, &readfrom);
  		    } else {
  #ifdef POSIX_SIGNALS
***************
*** 1245,1251 ****
  		if (FD_ISSET(f, &ready)) {
  		    /* read from the net, write to child stdin */
  		    errno = 0;
! 		    cc = (*des_read)(f, buf, sizeof(buf));
  		    if (cc <= 0) {
  			(void) close(px[1]);
  			FD_CLR(f, &readfrom);
--- 1236,1242 ----
  		if (FD_ISSET(f, &ready)) {
  		    /* read from the net, write to child stdin */
  		    errno = 0;
! 		    cc = rcmd_stream_read(f, buf, sizeof(buf));
  		    if (cc <= 0) {
  			(void) close(px[1]);
  			FD_CLR(f, &readfrom);
***************
*** 1805,1810 ****
--- 1796,1803 ----
      getstr(netf, cmdbuf, sizeof(cmdbuf), "command");
  
      if (auth_sys == KRB5_RECVAUTH_V4) {
+ 	rcmd_stream_init_normal();
+ 	
  	/* We do not really know the remote user's login name.
           * Assume it to be the same as the first component of the
  	 * principal's name. 
***************
*** 1868,1881 ****
      }
      krb5_free_authenticator(bsd_context, authenticator);
  
-     
-     /* Setup eblock for encrypted sessions. */
-     krb5_use_enctype(bsd_context, &eblock, ticket->enc_part2->session->enctype);
-     if ((status = krb5_process_key(bsd_context, &eblock,
- 				   ticket->enc_part2->session)))
- 	fatal(netf, "Permission denied");
  
!     /* Null out the "session" because eblock.key references the session
       * key here, and we do not want krb5_free_ticket() to destroy it. */
      ticket->enc_part2->session = 0;
  
--- 1861,1872 ----
      }
      krb5_free_authenticator(bsd_context, authenticator);
  
  
!     if (!strncmp(cmdbuf, "-x ", 3))
! 	do_encrypt = 1;
!     rcmd_stream_init_krb5(ticket->enc_part2->session, do_encrypt, 0);
! 
!     /* Null out the "session" because kcmd.c references the session
       * key here, and we do not want krb5_free_ticket() to destroy it. */
      ticket->enc_part2->session = 0;
  
***************
*** 1896,2032 ****
      krb5_free_ticket(bsd_context, ticket);
      return 0;
  }
  
  
- char storage[2*RSHD_BUFSIZ];               /* storage for the decryption */
- int nstored = 0;
- char *store_ptr = storage;
- 
- int
- v5_des_read(fd, buf, len)
-      int fd;
-      register char *buf;
-      int len;
- {
-     int nreturned = 0;
-     krb5_ui_4 net_len,rd_len;
-     int cc,retry;
-     unsigned char len_buf[4];
-     
-     if (!do_encrypt)
-       return(read(fd, buf, len));
-     
-     if (nstored >= len) {
- 	memcpy(buf, store_ptr, len);
- 	store_ptr += len;
- 	nstored -= len;
- 	return(len);
-     } else if (nstored) {
- 	memcpy(buf, store_ptr, nstored);
- 	nreturned += nstored;
- 	buf += nstored;
- 	len -= nstored;
- 	nstored = 0;
-     }
-     
-     if ((cc = krb5_net_read(bsd_context, fd, (char *)len_buf, 4)) != 4) {
- 	if ((cc < 0)  && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
- 	    return(cc);
- 	/* XXX can't read enough, pipe must have closed */
- 	return(0);
-     }
-     rd_len =
- 	((len_buf[0]<<24) |
- 	 (len_buf[1]<<16) |
- 	 (len_buf[2]<<8) |
- 	 len_buf[3]);
-     net_len = krb5_encrypt_size(rd_len, eblock.crypto_entry);
-     /* note: net_len is unsigned */
-     if (net_len > sizeof(des_inbuf)) {
- 	/* XXX preposterous length, probably out of sync.
- 	   act as if pipe closed */
- 	syslog(LOG_ERR,"Read size problem (rd_len=%d, net_len=%d)",
- 	       rd_len, net_len);
- 	return(0);
-     }
-     retry = 0;
-   datard:
-     if ((cc = krb5_net_read(bsd_context, fd, desinbuf.data, net_len)) != net_len) {
- 	/* XXX can't read enough, pipe must have closed */
- 	if ((cc < 0)  && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
- 	    retry++;
- 	    if (retry > MAXRETRIES){
- 		syslog(LOG_ERR, "des_read retry count exceeded %d\n", retry);
- 		return(0);
- 	    }
- 	    sleep(1);
- 	    goto datard;
- 	}
- 	syslog(LOG_ERR,
- 	       "Read data received %d != expected %d.",
- 	       cc, net_len);
- 	return(0);
-     }
- 
-     /* decrypt info */
-     if (krb5_decrypt(bsd_context, desinbuf.data, (krb5_pointer) storage, net_len,
- 		     &eblock, 0)) {
- 	syslog(LOG_ERR,"Read decrypt problem.");
- 	return(0);
-     }
- 
-     store_ptr = storage;
-     nstored = rd_len;
-     if (nstored > len) {
- 	memcpy(buf, store_ptr, len);
- 	nreturned += len;
- 	store_ptr += len;
- 	nstored -= len;
-     } else {
- 	memcpy(buf, store_ptr, nstored);
- 	nreturned += nstored;
- 	nstored = 0;
-     }
-     return(nreturned);
- }
-     
- 
- int
- v5_des_write(fd, buf, len)
-      int fd;
-      char *buf;
-      int len;
- {
-     unsigned char len_buf[4];
-     
-     if (!do_encrypt)
-       return(write(fd, buf, len));
-     
-     desoutbuf.length = krb5_encrypt_size(len, eblock.crypto_entry);
-     if (desoutbuf.length > sizeof(des_outbuf)){
- 	syslog(LOG_ERR,"Write size problem (%d > %d)",
- 	       desoutbuf.length, sizeof(des_outbuf));
- 	return(-1);
-     }
- 
-     if (krb5_encrypt(bsd_context, (krb5_pointer)buf, desoutbuf.data, len, &eblock, 0)) {
- 	syslog(LOG_ERR,"Write encrypt problem.");
- 	return(-1);
-     }
-     
-     len_buf[0] = (len & 0xff000000) >> 24;
-     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){
- 	syslog(LOG_ERR,"Could not write out all data.");
- 	return(-1);
-     }
-     else return(len);
- }
- 
  
  void fatal(f, msg)
       int f;
--- 1887,1895 ----
      krb5_free_ticket(bsd_context, ticket);
      return 0;
  }
+ #endif /* KERBEROS */
  
  
  
  void fatal(f, msg)
       int f;
***************
*** 2040,2046 ****
      buf[0] = '\01';             /* error indicator */
      (void) sprintf(buf + 1, "%s: %s.\r\n",progname, msg);
      if ((f == netf) && (pid > 0))
!       (void) (*des_write)(f, buf, strlen(buf));
      else
        (void) write(f, buf, strlen(buf));
      syslog(LOG_ERR,"%s\n",msg);
--- 1903,1909 ----
      buf[0] = '\01';             /* error indicator */
      (void) sprintf(buf + 1, "%s: %s.\r\n",progname, msg);
      if ((f == netf) && (pid > 0))
!       (void) rcmd_stream_write(f, buf, strlen(buf));
      else
        (void) write(f, buf, strlen(buf));
      syslog(LOG_ERR,"%s\n",msg);
***************
*** 2056,2059 ****
      }
      exit(1);
  }
- #endif /* KERBEROS */
--- 1919,1921 ----
>Audit-Trail:
>Unformatted:

home help back first fref pref prev next nref lref last post