diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /usr.bin/rlogin |
initial import of NetBSD tree
Diffstat (limited to 'usr.bin/rlogin')
-rw-r--r-- | usr.bin/rlogin/Makefile | 14 | ||||
-rw-r--r-- | usr.bin/rlogin/des_rw.c | 209 | ||||
-rw-r--r-- | usr.bin/rlogin/kcmd.c | 313 | ||||
-rw-r--r-- | usr.bin/rlogin/krb.h | 53 | ||||
-rw-r--r-- | usr.bin/rlogin/krcmd.c | 164 | ||||
-rw-r--r-- | usr.bin/rlogin/rlogin.1 | 185 | ||||
-rw-r--r-- | usr.bin/rlogin/rlogin.c | 910 |
7 files changed, 1848 insertions, 0 deletions
diff --git a/usr.bin/rlogin/Makefile b/usr.bin/rlogin/Makefile new file mode 100644 index 00000000000..b53f6bd52bc --- /dev/null +++ b/usr.bin/rlogin/Makefile @@ -0,0 +1,14 @@ +# $NetBSD: Makefile,v 1.5 1995/03/21 07:58:28 cgd Exp $ +# @(#)Makefile 8.1 (Berkeley) 7/19/93 + +PROG= rlogin +SRCS= rlogin.c +#SRCS+= krcmd.c kcmd.c des_rw.c +#DPADD= ${LIBKRB} ${LIBDES} +#CFLAGS+=-DKERBEROS -DCRYPT +#LDADD= -lkrb -ldes +BINOWN= root +BINMODE=4555 +#INSTALLFLAGS=-fschg + +.include <bsd.prog.mk> diff --git a/usr.bin/rlogin/des_rw.c b/usr.bin/rlogin/des_rw.c new file mode 100644 index 00000000000..592e5ba7cd7 --- /dev/null +++ b/usr.bin/rlogin/des_rw.c @@ -0,0 +1,209 @@ +/* $NetBSD: des_rw.c,v 1.2 1995/03/21 07:58:30 cgd Exp $ */ + +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)des_rw.c 8.1 (Berkeley) 6/6/93"; +#else +static char rcsid[] = "$NetBSD: des_rw.c,v 1.2 1995/03/21 07:58:30 cgd Exp $"; +#endif +#endif /* not lint */ + +#ifdef CRYPT +#ifdef KERBEROS +#include <sys/param.h> + +#include <kerberosIV/des.h> +#include <kerberosIV/krb.h> + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +static unsigned char des_inbuf[10240], storage[10240], *store_ptr; +static bit_64 *key; +static u_char *key_schedule; + +/* XXX these should be in a kerberos include file */ +int krb_net_read __P((int, char *, int)); +#ifdef notdef +/* XXX too hard to make this work */ +int des_pcbc_encrypt __P((des_cblock *, des_cblock *, long, + des_key_schedule, des_cblock *, int)); +#endif + +/* + * NB: These routines will not function properly if NBIO + * is set + */ + +/* + * des_set_key + * + * Set des encryption/decryption key for use by the des_read and + * des_write routines + * + * The inkey parameter is actually the DES initial vector, + * and the insched is the DES Key unwrapped for faster decryption + */ + +void +des_set_key(inkey, insched) + bit_64 *inkey; + u_char *insched; +{ + key = inkey; + key_schedule = insched; +} + +void +des_clear_key() +{ + bzero((char *) key, sizeof(C_Block)); + bzero((char *) key_schedule, sizeof(Key_schedule)); +} + + +int +des_read(fd, buf, len) + int fd; + register char *buf; + int len; +{ + int nreturned = 0; + long net_len, rd_len; + int nstored = 0; + + if (nstored >= len) { + (void) bcopy(store_ptr, buf, len); + store_ptr += len; + nstored -= len; + return(len); + } else if (nstored) { + (void) bcopy(store_ptr, buf, nstored); + nreturned += nstored; + buf += nstored; + len -= nstored; + nstored = 0; + } + + if (krb_net_read(fd, (char *)&net_len, sizeof(net_len)) != + sizeof(net_len)) { + /* XXX can't read enough, pipe + must have closed */ + return(0); + } + net_len = ntohl(net_len); + if (net_len <= 0 || net_len > sizeof(des_inbuf)) { + /* preposterous length; assume out-of-sync; only + recourse is to close connection, so return 0 */ + 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 (krb_net_read(fd, (char *)des_inbuf, rd_len) != rd_len) { + /* pipe must have closed, return 0 */ + return(0); + } + (void) des_pcbc_encrypt(des_inbuf, /* inbuf */ + storage, /* outbuf */ + net_len, /* length */ + key_schedule, /* DES key */ + key, /* IV */ + DECRYPT); /* direction */ + + if(net_len < 8) + store_ptr = storage + 8 - net_len; + else + store_ptr = storage; + + nstored = net_len; + if (nstored > len) { + (void) bcopy(store_ptr, buf, len); + nreturned += len; + store_ptr += len; + nstored -= len; + } else { + (void) bcopy(store_ptr, buf, nstored); + nreturned += nstored; + nstored = 0; + } + + return(nreturned); +} + +static unsigned char des_outbuf[10240]; /* > longest write */ + +int +des_write(fd, buf, len) + int fd; + char *buf; + int len; +{ + static int seeded = 0; + static char garbage_buf[8]; + long net_len, garbage; + + if(len < 8) { + if(!seeded) { + seeded = 1; + srandom((int) time((long *)0)); + } + garbage = random(); + /* insert random garbage */ + (void) bcopy(&garbage, garbage_buf, MIN(sizeof(long),8)); + /* this "right-justifies" the data in the buffer */ + (void) bcopy(buf, garbage_buf + 8 - len, len); + } + /* pcbc_encrypt outputs in 8-byte (64 bit) increments */ + + (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf, + des_outbuf, + (len < 8) ? 8 : len, + key_schedule, /* DES key */ + key, /* IV */ + ENCRYPT); + + /* tell the other end the real amount, but send an 8-byte padded + packet */ + net_len = htonl(len); + (void) write(fd, &net_len, sizeof(net_len)); + (void) write(fd, des_outbuf, roundup(len,8)); + return(len); +} +#endif /* KERBEROS */ +#endif /* CRYPT */ diff --git a/usr.bin/rlogin/kcmd.c b/usr.bin/rlogin/kcmd.c new file mode 100644 index 00000000000..16772d4e251 --- /dev/null +++ b/usr.bin/rlogin/kcmd.c @@ -0,0 +1,313 @@ +/* $NetBSD: kcmd.c,v 1.2 1995/03/21 07:58:32 cgd Exp $ */ + +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +#if 0 +static char Xsccsid[] = "derived from @(#)rcmd.c 5.17 (Berkeley) 6/27/88"; +static char sccsid[] = "@(#)kcmd.c 8.2 (Berkeley) 8/19/93"; +#else +static char rcsid[] = "$NetBSD: kcmd.c,v 1.2 1995/03/21 07:58:32 cgd Exp $"; +#endif +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <sys/stat.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <kerberosIV/des.h> +#include <kerberosIV/krb.h> +#include <kerberosIV/kparse.h> + +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <pwd.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "krb.h" + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#define START_PORT 5120 /* arbitrary */ + +int getport __P((int *)); + +int +kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, ticket, service, realm, + cred, schedule, msg_data, laddr, faddr, authopts) + 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 s, timo = 1, pid; + long oldmask; + struct sockaddr_in sin, from; + char c; +#ifdef ATHENA_COMPAT + int lport = IPPORT_RESERVED - 1; +#else + int lport = START_PORT; +#endif + struct hostent *hp; + int rc; + char *host_save; + int status; + + pid = getpid(); + hp = gethostbyname(*ahost); + if (hp == NULL) { + /* 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; + +#ifdef KERBEROS + /* If realm is null, look up from table */ + if (realm == NULL || realm[0] == '\0') + realm = krb_realmofhost(host_save); +#endif /* KERBEROS */ + + oldmask = sigblock(sigmask(SIGURG)); + for (;;) { + s = getport(&lport); + if (s < 0) { + if (errno == EAGAIN) + fprintf(stderr, + "kcmd(socket): All ports in use\n"); + else + perror("kcmd: socket"); + sigsetmask(oldmask); + return (-1); + } + fcntl(s, F_SETOWN, pid); + sin.sin_family = hp->h_addrtype; +#if defined(ultrix) || defined(sun) + bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); +#else + bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length); +#endif + sin.sin_port = rport; + if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) + break; + (void) close(s); + if (errno == EADDRINUSE) { + lport--; + continue; + } + /* + * don't wait very long for Kerberos rcmd. + */ + if (errno == ECONNREFUSED && timo <= 4) { + /* sleep(timo); don't wait at all here */ + timo *= 2; + continue; + } +#if !(defined(ultrix) || defined(sun)) + if (hp->h_addr_list[1] != NULL) { + int oerrno = errno; + + fprintf(stderr, + "kcmd: connect to address %s: ", + inet_ntoa(sin.sin_addr)); + errno = oerrno; + perror(NULL); + hp->h_addr_list++; + bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, + hp->h_length); + fprintf(stderr, "Trying %s...\n", + inet_ntoa(sin.sin_addr)); + continue; + } +#endif /* !(defined(ultrix) || defined(sun)) */ + if (errno != ECONNREFUSED) + perror(hp->h_name); + sigsetmask(oldmask); + 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("kcmd(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("kcmd:accept"); + lport = 0; + status = -1; + goto bad; + } + *fd2p = s3; + from.sin_port = ntohs((u_short)from.sin_port); + if (from.sin_family != AF_INET || + from.sin_port >= IPPORT_RESERVED) { + fprintf(stderr, + "kcmd(socket): protocol failure in circuit setup.\n"); + status = -1; + goto bad2; + } + } + /* + * Kerberos-authenticated service. Don't have to send locuser, + * since its already in the ticket, and we'll extract it on + * the other side. + */ + /* (void) write(s, locuser, strlen(locuser)+1); */ + + /* set up the needed stuff for mutual auth, but only if necessary */ + if (authopts & KOPT_DO_MUTUAL) { + int sin_len; + *faddr = sin; + + sin_len = sizeof(struct sockaddr_in); + if (getsockname(s, (struct sockaddr *)laddr, &sin_len) < 0) { + perror("kcmd(getsockname)"); + status = -1; + goto bad2; + } + } +#ifdef KERBEROS + if ((status = krb_sendauth(authopts, s, ticket, service, *ahost, + realm, (unsigned long) getpid(), msg_data, + cred, schedule, + laddr, + faddr, + "KCMDV0.1")) != KSUCCESS) + goto bad2; +#endif /* KERBEROS */ + + (void) write(s, remuser, strlen(remuser)+1); + (void) write(s, cmd, strlen(cmd)+1); + + if ((rc = read(s, &c, 1)) != 1) { + if (rc == -1) + perror(*ahost); + else + fprintf(stderr,"kcmd: bad connection with remote host\n"); + status = -1; + goto bad2; + } + if (c != '\0') { + while (read(s, &c, 1) == 1) { + (void) write(2, &c, 1); + if (c == '\n') + break; + } + status = -1; + goto bad2; + } + sigsetmask(oldmask); + *sock = s; + return (KSUCCESS); +bad2: + if (lport) + (void) close(*fd2p); +bad: + (void) close(s); + sigsetmask(oldmask); + return (status); +} + +int +getport(alport) + int *alport; +{ + struct sockaddr_in sin; + int s; + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) + return (-1); + for (;;) { + sin.sin_port = htons((u_short)*alport); + if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) + return (s); + if (errno != EADDRINUSE) { + (void) close(s); + return (-1); + } + (*alport)--; +#ifdef ATHENA_COMPAT + if (*alport == IPPORT_RESERVED/2) { +#else + if (*alport == IPPORT_RESERVED) { +#endif + (void) close(s); + errno = EAGAIN; /* close */ + return (-1); + } + } +} diff --git a/usr.bin/rlogin/krb.h b/usr.bin/rlogin/krb.h new file mode 100644 index 00000000000..f40cdb6dd93 --- /dev/null +++ b/usr.bin/rlogin/krb.h @@ -0,0 +1,53 @@ +/* $NetBSD: krb.h,v 1.2 1995/03/21 07:58:34 cgd Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)krb.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * XXX + * These should be in a kerberos include file. + */ +void des_clear_key __P(()); +int des_read __P((int, char *, int)); +void des_set_key __P((C_Block, Key_schedule)); +int des_write __P((int, char *, int)); +int krb_net_read __P((int, char *, int)); +char *krb_realmofhost __P((char *)); +int krb_sendauth __P((long, int, KTEXT, char *, char *, char *, + u_long, MSG_DAT *, CREDENTIALS *, Key_schedule, + struct sockaddr_in *, struct sockaddr_in *, char *)); +int krcmd __P((char **, u_short, char *, char *, int *, char *)); +int krcmd_mutual __P((char **, u_short, char *, char *, int *, + char *, CREDENTIALS *, Key_schedule)); diff --git a/usr.bin/rlogin/krcmd.c b/usr.bin/rlogin/krcmd.c new file mode 100644 index 00000000000..5bcbb4c3312 --- /dev/null +++ b/usr.bin/rlogin/krcmd.c @@ -0,0 +1,164 @@ +/* $NetBSD: krcmd.c,v 1.2 1995/03/21 07:58:36 cgd Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)krcmd.c 8.1 (Berkeley) 6/6/93"; +#else +static char rcsid[] = "$NetBSD: krcmd.c,v 1.2 1995/03/21 07:58:36 cgd Exp $"; +#endif +#endif /* not lint */ + +/* + * $Source: /a/cvsroot/src/usr.bin/rlogin/krcmd.c,v + * $Header: /mit/kerberos/ucb/mit/kcmd/RCS/krcmd.c,v 5.1 + * 89/07/25 15:38:44 kfall Exp Locker: kfall + * static char *rcsid_kcmd_c = + * "$Header: /mit/kerberos/ucb/mit/kcmd/RCS/krcmd.c,v 5.1 89/07/25 15:38:44 + * kfall Exp Locker: kfall "; + */ + +#ifdef KERBEROS +#include <sys/types.h> +#ifdef CRYPT +#include <sys/socket.h> +#endif + +#include <netinet/in.h> + +#include <kerberosIV/des.h> +#include <kerberosIV/krb.h> + +#include <stdio.h> + +#define SERVICE_NAME "rcmd" + +int kcmd __P((int *, char **, u_short, char *, char *, char *, int *, + KTEXT, char *, char *, CREDENTIALS *, Key_schedule, MSG_DAT *, + struct sockaddr_in *, struct sockaddr_in *, long)); + +/* + * krcmd: simplified version of Athena's "kcmd" + * returns a socket attached to the destination, -1 or krb error on error + * if fd2p is non-NULL, another socket is filled in for it + */ + +int +krcmd(ahost, rport, remuser, cmd, fd2p, realm) + char **ahost; + u_short rport; + char *remuser, *cmd; + int *fd2p; + char *realm; +{ + int sock = -1, err = 0; + KTEXT_ST ticket; + long authopts = 0L; + + err = kcmd( + &sock, + ahost, + rport, + NULL, /* locuser not used */ + remuser, + cmd, + fd2p, + &ticket, + SERVICE_NAME, + realm, + (CREDENTIALS *) NULL, /* credentials not used */ + (bit_64 *) NULL, /* key schedule not used */ + (MSG_DAT *) NULL, /* MSG_DAT not used */ + (struct sockaddr_in *) NULL, /* local addr not used */ + (struct sockaddr_in *) NULL, /* foreign addr not used */ + authopts + ); + + if (err > KSUCCESS && err < MAX_KRB_ERRORS) { + fprintf(stderr, "krcmd: %s\n", krb_err_txt[err]); + return(-1); + } + if (err < 0) + return(-1); + return(sock); +} + +#ifdef CRYPT +int +krcmd_mutual(ahost, rport, remuser, cmd, fd2p, realm, cred, sched) + char **ahost; + u_short rport; + char *remuser, *cmd; + int *fd2p; + char *realm; + CREDENTIALS *cred; + Key_schedule sched; +{ + int sock, err; + KTEXT_ST ticket; + MSG_DAT msg_dat; + struct sockaddr_in laddr, faddr; + long authopts = KOPT_DO_MUTUAL; + + err = kcmd( + &sock, + ahost, + rport, + NULL, /* locuser not used */ + remuser, + cmd, + fd2p, + &ticket, + SERVICE_NAME, + realm, + cred, /* filled in */ + sched, /* filled in */ + &msg_dat, /* filled in */ + &laddr, /* filled in */ + &faddr, /* filled in */ + authopts + ); + + if (err > KSUCCESS && err < MAX_KRB_ERRORS) { + fprintf(stderr, "krcmd_mutual: %s\n", krb_err_txt[err]); + return(-1); + } + + if (err < 0) + return (-1); + return(sock); +} +#endif /* CRYPT */ +#endif /* KERBEROS */ diff --git a/usr.bin/rlogin/rlogin.1 b/usr.bin/rlogin/rlogin.1 new file mode 100644 index 00000000000..5a73e933f5d --- /dev/null +++ b/usr.bin/rlogin/rlogin.1 @@ -0,0 +1,185 @@ +.\" $NetBSD: rlogin.1,v 1.4 1995/08/18 15:07:35 pk Exp $ +.\" +.\" Copyright (c) 1983, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)rlogin.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt RLOGIN 1 +.Os BSD 4.2 +.Sh NAME +.Nm rlogin +.Nd remote login +.Sh SYNOPSIS +.Ar rlogin +.Op Fl 8EKLdx +.Op Fl e Ar char +.Op Fl k Ar realm +.Op Fl l Ar username +.Ar host +.Sh DESCRIPTION +.Nm Rlogin +starts a terminal session on a remote host +.Ar host . +.Pp +.Nm Rlogin +first attempts to use the Kerberos authorization mechanism, described below. +If the remote host does not supporting Kerberos the standard Berkeley +.Pa rhosts +authorization mechanism is used. +The options are as follows: +.Bl -tag -width flag +.It Fl 8 +The +.Fl 8 +option allows an eight-bit input data path at all times; otherwise +parity bits are stripped except when the remote side's stop and start +characters are other than +^S/^Q . +.It Fl E +The +.Fl E +option stops any character from being recognized as an escape character. +When used with the +.Fl 8 +option, this provides a completely transparent connection. +.It Fl K +The +.Fl K +option turns off all Kerberos authentication. +.It Fl L +The +.Fl L +option allows the rlogin session to be run in ``litout'' (see +.Xr tty 4 ) +mode. +.It Fl d +The +.Fl d +option turns on socket debugging (see +.Xr setsockopt 2 ) +on the TCP sockets used for communication with the remote host. +.It Fl e +The +.Fl e +option allows user specification of the escape character, which is +``~'' by default. +This specification may be as a literal character, or as an octal +value in the form \ennn. +.It Fl k +The +.Fl k +option requests rlogin to obtain tickets for the remote host +in realm +.Ar realm +instead of the remote host's realm as determined by +.Xr krb_realmofhost 3 . +.It Fl x +The +.Fl x +option turns on +.Tn DES +encryption for all data passed via the +rlogin session. +This may impact response time and +.Tn CPU +utilization, but provides +increased security. +.El +.Pp +A line of the form ``<escape char>.'' disconnects from the remote host. +Similarly, the line ``<escape char>^Z'' will suspend the +.Nm rlogin +session, and ``<escape char><delayed-suspend char>'' suspends the +send portion of the rlogin, but allows output from the remote system. +By default, the tilde (``~'') character is the escape character, and +normally control-Y (``^Y'') is the delayed-suspend character. +.Pp +All echoing takes place at the remote site, so that (except for delays) +the +.Nm rlogin +is transparent. +Flow control via ^S/^Q and flushing of input and output on interrupts +are handled properly. +.Sh KERBEROS AUTHENTICATION +Each user may have a private authorization list in the file +.Pa .klogin +in their home directory. +Each line in this file should contain a Kerberos principal name of the +form +.Ar principal.instance@realm . +If the originating user is authenticated to one of the principals named +in +.Pa .klogin , +access is granted to the account. +The principal +.Ar accountname.@localrealm +is granted access if +there is no +.Pa .klogin +file. +Otherwise a login and password will be prompted for on the remote machine +as in +.Xr login 1 . +To avoid certain security problems, the +.Pa .klogin +file must be owned by +the remote user. +.Pp +If Kerberos authentication fails, a warning message is printed and the +standard Berkeley +.Nm rlogin +is used instead. +.Sh ENVIRONMENT +The following environment variable is utilized by +.Nm rlogin : +.Bl -tag -width TERM +.It Ev TERM +Determines the user's terminal type. +.El +.Sh SEE ALSO +.Xr rsh 1 , +.Xr kerberos 3 , +.Xr krb_sendauth 3 , +.Xr krb_realmofhost 3 +.Sh HISTORY +The +.Nm rlogin +command appeared in +.Bx 4.2 . +.Sh BUGS +.Nm Rlogin +will be replaced by +.Xr telnet 1 +in the near future. +.Pp +More of the environment should be propagated. diff --git a/usr.bin/rlogin/rlogin.c b/usr.bin/rlogin/rlogin.c new file mode 100644 index 00000000000..8c93cd8f5c1 --- /dev/null +++ b/usr.bin/rlogin/rlogin.c @@ -0,0 +1,910 @@ +/* $NetBSD: rlogin.c,v 1.8 1995/10/05 09:07:22 mycroft Exp $ */ + +/* + * Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1990, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rlogin.c 8.1 (Berkeley) 6/6/93"; +#else +static char rcsid[] = "$NetBSD: rlogin.c,v 1.8 1995/10/05 09:07:22 mycroft Exp $"; +#endif +#endif /* not lint */ + +/* + * rlogin - remote login + */ +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/wait.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> + +#include <errno.h> +#include <fcntl.h> +#include <netdb.h> +#include <pwd.h> +#include <setjmp.h> +#include <termios.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifdef __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +#ifdef KERBEROS +#include <kerberosIV/des.h> +#include <kerberosIV/krb.h> + +#include "krb.h" + +CREDENTIALS cred; +Key_schedule schedule; +int use_kerberos = 1, doencrypt; +char dst_realm_buf[REALM_SZ], *dest_realm = NULL; +#endif + +#ifndef TIOCPKT_WINDOW +#define TIOCPKT_WINDOW 0x80 +#endif + +/* concession to Sun */ +#ifndef SIGUSR1 +#define SIGUSR1 30 +#endif + +#ifndef CCEQ +#define CCEQ(val, c) (c == val ? val != _POSIX_VDISABLE : 0) +#endif + +int eight, rem; +struct termios deftty; + +int noescape; +u_char escapechar = '~'; + +#ifdef OLDSUN +struct winsize { + unsigned short ws_row, ws_col; + unsigned short ws_xpixel, ws_ypixel; +}; +#else +#define get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp) +#endif +struct winsize winsize; + +void catch_child __P((int)); +void copytochild __P((int)); +__dead void doit __P((long)); +__dead void done __P((int)); +void echo __P((char)); +u_int getescape __P((char *)); +void lostpeer __P((int)); +void mode __P((int)); +void msg __P((char *)); +void oob __P((int)); +int reader __P((int)); +void sendwindow __P((void)); +void setsignal __P((int)); +void sigwinch __P((int)); +void stop __P((int)); +__dead void usage __P((void)); +void writer __P((void)); +void writeroob __P((int)); + +#ifdef KERBEROS +void warning __P((const char *, ...)); +#endif +#ifdef OLDSUN +int get_window_size __P((int, struct winsize *)); +#endif + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + extern int optind; + struct passwd *pw; + struct servent *sp; + struct termios tty; + long omask; + int argoff, ch, dflag, one, uid; + char *host, *p, *user, term[1024]; + + argoff = dflag = 0; + one = 1; + host = user = NULL; + + if (p = rindex(argv[0], '/')) + ++p; + else + p = argv[0]; + + if (strcmp(p, "rlogin")) + host = p; + + /* handle "rlogin host flags" */ + if (!host && argc > 2 && argv[1][0] != '-') { + host = argv[1]; + argoff = 1; + } + +#ifdef KERBEROS +#define OPTIONS "8EKLde:k:l:x" +#else +#define OPTIONS "8EKLde:l:" +#endif + while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF) + switch(ch) { + case '8': + eight = 1; + break; + case 'E': + noescape = 1; + break; + case 'K': +#ifdef KERBEROS + use_kerberos = 0; +#endif + break; + case 'd': + dflag = 1; + break; + case 'e': + noescape = 0; + escapechar = getescape(optarg); + break; +#ifdef KERBEROS + case 'k': + dest_realm = dst_realm_buf; + (void)strncpy(dest_realm, optarg, REALM_SZ); + break; +#endif + case 'l': + user = optarg; + break; +#ifdef CRYPT +#ifdef KERBEROS + case 'x': + doencrypt = 1; + des_set_key(cred.session, schedule); + break; +#endif +#endif + case '?': + default: + usage(); + } + optind += argoff; + argc -= optind; + argv += optind; + + /* if haven't gotten a host yet, do so */ + if (!host && !(host = *argv++)) + usage(); + + if (*argv) + usage(); + + if (!(pw = getpwuid(uid = getuid()))) { + (void)fprintf(stderr, "rlogin: unknown user id.\n"); + exit(1); + } + if (!user) + user = pw->pw_name; + + sp = NULL; +#ifdef KERBEROS + if (use_kerberos) { + sp = getservbyname((doencrypt ? "eklogin" : "klogin"), "tcp"); + if (sp == NULL) { + use_kerberos = 0; + warning("can't get entry for %s/tcp service", + doencrypt ? "eklogin" : "klogin"); + } + } +#endif + if (sp == NULL) + sp = getservbyname("login", "tcp"); + if (sp == NULL) { + (void)fprintf(stderr, "rlogin: login/tcp: unknown service.\n"); + exit(1); + } + + (void)strcpy(term, (p = getenv("TERM")) ? p : "network"); + if (tcgetattr(0, &tty) == 0) { + (void)strcat(term, "/"); + (void)sprintf(term + strlen(term), "%d", cfgetospeed(&tty)); + } + + (void)get_window_size(0, &winsize); + + (void)signal(SIGPIPE, lostpeer); + /* will use SIGUSR1 for window size hack, so hold it off */ + omask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1)); + /* + * We set SIGURG and SIGUSR1 below so that an + * incoming signal will be held pending rather than being + * discarded. Note that these routines will be ready to get + * a signal by the time that they are unblocked below. + */ + (void)signal(SIGURG, copytochild); + (void)signal(SIGUSR1, writeroob); + +#ifdef KERBEROS +try_connect: + if (use_kerberos) { + struct hostent *hp; + + /* Fully qualify hostname (needed for krb_realmofhost). */ + hp = gethostbyname(host); + if (hp != NULL && !(host = strdup(hp->h_name))) { + (void)fprintf(stderr, "rlogin: %s\n", + strerror(ENOMEM)); + exit(1); + } + + rem = KSUCCESS; + errno = 0; + if (dest_realm == NULL) + dest_realm = krb_realmofhost(host); + +#ifdef CRYPT + if (doencrypt) + rem = krcmd_mutual(&host, sp->s_port, user, term, 0, + dest_realm, &cred, schedule); + else +#endif /* CRYPT */ + rem = krcmd(&host, sp->s_port, user, term, 0, + dest_realm); + if (rem < 0) { + use_kerberos = 0; + sp = getservbyname("login", "tcp"); + if (sp == NULL) { + (void)fprintf(stderr, + "rlogin: unknown service login/tcp.\n"); + exit(1); + } + if (errno == ECONNREFUSED) + warning("remote host doesn't support Kerberos"); + if (errno == ENOENT) + warning("can't provide Kerberos auth data"); + goto try_connect; + } + } else { +#ifdef CRYPT + if (doencrypt) { + (void)fprintf(stderr, + "rlogin: the -x flag requires Kerberos authentication.\n"); + exit(1); + } +#endif /* CRYPT */ + rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0); + } +#else + rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0); +#endif /* KERBEROS */ + + if (rem < 0) + exit(1); + + if (dflag && + setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0) + (void)fprintf(stderr, "rlogin: setsockopt: %s.\n", + strerror(errno)); + one = IPTOS_LOWDELAY; + if (setsockopt(rem, IPPROTO_IP, IP_TOS, (char *)&one, sizeof(int)) < 0) + perror("rlogin: setsockopt TOS (ignored)"); + + (void)setuid(uid); + doit(omask); + /*NOTREACHED*/ +} + +int child; + +void +doit(omask) + long omask; +{ + + (void)signal(SIGINT, SIG_IGN); + setsignal(SIGHUP); + setsignal(SIGQUIT); + mode(1); + child = fork(); + if (child == -1) { + (void)fprintf(stderr, "rlogin: fork: %s.\n", strerror(errno)); + done(1); + } + if (child == 0) { + if (reader(omask) == 0) { + msg("connection closed."); + exit(0); + } + sleep(1); + msg("\aconnection closed."); + exit(1); + } + + /* + * We may still own the socket, and may have a pending SIGURG (or might + * receive one soon) that we really want to send to the reader. When + * one of these comes in, the trap copytochild simply copies such + * signals to the child. We can now unblock SIGURG and SIGUSR1 + * that were set above. + */ + (void)sigsetmask(omask); + (void)signal(SIGCHLD, catch_child); + writer(); + msg("closed connection."); + done(0); +} + +/* trap a signal, unless it is being ignored. */ +void +setsignal(sig) + int sig; +{ + int omask = sigblock(sigmask(sig)); + + if (signal(sig, exit) == SIG_IGN) + (void)signal(sig, SIG_IGN); + (void)sigsetmask(omask); +} + +__dead void +done(status) + int status; +{ + int w, wstatus; + + mode(0); + if (child > 0) { + /* make sure catch_child does not snap it up */ + (void)signal(SIGCHLD, SIG_DFL); + if (kill(child, SIGKILL) >= 0) + while ((w = wait(&wstatus)) > 0 && w != child); + } + exit(status); +} + +int dosigwinch; + +/* + * This is called when the reader process gets the out-of-band (urgent) + * request to turn on the window-changing protocol. + */ +void +writeroob(signo) + int signo; +{ + if (dosigwinch == 0) { + sendwindow(); + (void)signal(SIGWINCH, sigwinch); + } + dosigwinch = 1; +} + +void +catch_child(signo) + int signo; +{ + union wait status; + int pid; + + for (;;) { + pid = wait3((int *)&status, WNOHANG|WUNTRACED, NULL); + if (pid == 0) + return; + /* if the child (reader) dies, just quit */ + if (pid < 0 || (pid == child && !WIFSTOPPED(status))) + done((int)(status.w_termsig | status.w_retcode)); + } + /* NOTREACHED */ +} + +/* + * writer: write to remote: 0 -> line. + * ~. terminate + * ~^Z suspend rlogin process. + * ~<delayed-suspend char> suspend rlogin process, but leave reader alone. + */ +void +writer() +{ + register int bol, local, n; + char c; + + bol = 1; /* beginning of line */ + local = 0; + for (;;) { + n = read(STDIN_FILENO, &c, 1); + if (n <= 0) { + if (n < 0 && errno == EINTR) + continue; + break; + } + /* + * If we're at the beginning of the line and recognize a + * command character, then we echo locally. Otherwise, + * characters are echo'd remotely. If the command character + * is doubled, this acts as a force and local echo is + * suppressed. + */ + if (bol) { + bol = 0; + if (!noescape && c == escapechar) { + local = 1; + continue; + } + } else if (local) { + local = 0; + if (c == '.' || CCEQ(deftty.c_cc[VEOF], c)) { + echo(c); + break; + } + if (CCEQ(deftty.c_cc[VSUSP], c)) { + bol = 1; + echo(c); + stop(1); + continue; + } + if (CCEQ(deftty.c_cc[VDSUSP], c)) { + bol = 1; + echo(c); + stop(0); + continue; + } + if (c != escapechar) +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt) + (void)des_write(rem, + (char *)&escapechar, 1); + else +#endif +#endif + (void)write(rem, &escapechar, 1); + } + +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt) { + if (des_write(rem, &c, 1) == 0) { + msg("line gone"); + break; + } + } else +#endif +#endif + if (write(rem, &c, 1) == 0) { + msg("line gone"); + break; + } + bol = CCEQ(deftty.c_cc[VKILL], c) || + CCEQ(deftty.c_cc[VEOF], c) || + CCEQ(deftty.c_cc[VINTR], c) || + CCEQ(deftty.c_cc[VSUSP], c) || + c == '\r' || c == '\n'; + } +} + +void +#if __STDC__ +echo(register char c) +#else +echo(c) + register char c; +#endif +{ + register char *p; + char buf[8]; + + p = buf; + c &= 0177; + *p++ = escapechar; + if (c < ' ') { + *p++ = '^'; + *p++ = c + '@'; + } else if (c == 0177) { + *p++ = '^'; + *p++ = '?'; + } else + *p++ = c; + *p++ = '\r'; + *p++ = '\n'; + (void)write(STDOUT_FILENO, buf, p - buf); +} + +void +stop(all) + int all; +{ + mode(0); + (void)signal(SIGCHLD, SIG_IGN); + (void)kill(all ? 0 : getpid(), SIGTSTP); + (void)signal(SIGCHLD, catch_child); + mode(1); + sigwinch(0); /* check for size changes */ +} + +void +sigwinch(signo) + int signo; +{ + struct winsize ws; + + if (dosigwinch && get_window_size(0, &ws) == 0 && + bcmp(&ws, &winsize, sizeof(ws))) { + winsize = ws; + sendwindow(); + } +} + +/* + * Send the window size to the server via the magic escape + */ +void +sendwindow() +{ + struct winsize *wp; + char obuf[4 + sizeof (struct winsize)]; + + wp = (struct winsize *)(obuf+4); + obuf[0] = 0377; + obuf[1] = 0377; + obuf[2] = 's'; + obuf[3] = 's'; + wp->ws_row = htons(winsize.ws_row); + wp->ws_col = htons(winsize.ws_col); + wp->ws_xpixel = htons(winsize.ws_xpixel); + wp->ws_ypixel = htons(winsize.ws_ypixel); + +#ifdef CRYPT +#ifdef KERBEROS + if(doencrypt) + (void)des_write(rem, obuf, sizeof(obuf)); + else +#endif +#endif + (void)write(rem, obuf, sizeof(obuf)); +} + +/* + * reader: read from remote: line -> 1 + */ +#define READING 1 +#define WRITING 2 + +jmp_buf rcvtop; +int ppid, rcvcnt, rcvstate; +char rcvbuf[8 * 1024]; + +void +oob(signo) + int signo; +{ + struct termios tty; + int atmark, n, rcvd; + char waste[BUFSIZ], mark; + + rcvd = 0; + while (recv(rem, &mark, 1, MSG_OOB) < 0) { + switch (errno) { + case EWOULDBLOCK: + /* + * Urgent data not here yet. It may not be possible + * to send it yet if we are blocked for output and + * our input buffer is full. + */ + if (rcvcnt < sizeof(rcvbuf)) { + n = read(rem, rcvbuf + rcvcnt, + sizeof(rcvbuf) - rcvcnt); + if (n <= 0) + return; + rcvd += n; + } else { + n = read(rem, waste, sizeof(waste)); + if (n <= 0) + return; + } + continue; + default: + return; + } + } + if (mark & TIOCPKT_WINDOW) { + /* Let server know about window size changes */ + (void)kill(ppid, SIGUSR1); + } + if (!eight && (mark & TIOCPKT_NOSTOP)) { + (void)tcgetattr(0, &tty); + tty.c_iflag &= ~IXON; + (void)tcsetattr(0, TCSANOW, &tty); + } + if (!eight && (mark & TIOCPKT_DOSTOP)) { + (void)tcgetattr(0, &tty); + tty.c_iflag |= (deftty.c_iflag & IXON); + (void)tcsetattr(0, TCSANOW, &tty); + } + if (mark & TIOCPKT_FLUSHWRITE) { + (void)tcflush(1, TCIOFLUSH); + for (;;) { + if (ioctl(rem, SIOCATMARK, &atmark) < 0) { + (void)fprintf(stderr, "rlogin: ioctl: %s.\n", + strerror(errno)); + break; + } + if (atmark) + break; + n = read(rem, waste, sizeof (waste)); + if (n <= 0) + break; + } + /* + * Don't want any pending data to be output, so clear the recv + * buffer. If we were hanging on a write when interrupted, + * don't want it to restart. If we were reading, restart + * anyway. + */ + rcvcnt = 0; + longjmp(rcvtop, 1); + } + + /* oob does not do FLUSHREAD (alas!) */ + + /* + * If we filled the receive buffer while a read was pending, longjmp + * to the top to restart appropriately. Don't abort a pending write, + * however, or we won't know how much was written. + */ + if (rcvd && rcvstate == READING) + longjmp(rcvtop, 1); +} + +/* reader: read from remote: line -> 1 */ +int +reader(omask) + int omask; +{ + int pid, n, remaining; + char *bufp; + +#if BSD >= 43 || defined(SUNOS4) + pid = getpid(); /* modern systems use positives for pid */ +#else + pid = -getpid(); /* old broken systems use negatives */ +#endif + (void)signal(SIGTTOU, SIG_IGN); + (void)signal(SIGURG, oob); + ppid = getppid(); + (void)fcntl(rem, F_SETOWN, pid); + (void)setjmp(rcvtop); + (void)sigsetmask(omask); + bufp = rcvbuf; + for (;;) { + while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) { + rcvstate = WRITING; + n = write(STDOUT_FILENO, bufp, remaining); + if (n < 0) { + if (errno != EINTR) + return (-1); + continue; + } + bufp += n; + } + bufp = rcvbuf; + rcvcnt = 0; + rcvstate = READING; + +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt) + rcvcnt = des_read(rem, rcvbuf, sizeof(rcvbuf)); + else +#endif +#endif + rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf)); + if (rcvcnt == 0) + return (0); + if (rcvcnt < 0) { + if (errno == EINTR) + continue; + (void)fprintf(stderr, "rlogin: read: %s.\n", + strerror(errno)); + return (-1); + } + } +} + +void +mode(f) + int f; +{ + struct termios tty; + + switch (f) { + case 0: + (void)tcsetattr(0, TCSANOW, &deftty); + break; + case 1: + (void)tcgetattr(0, &deftty); + tty = deftty; + /* This is loosely derived from sys/compat/tty_compat.c. */ + tty.c_lflag &= ~(ECHO|ICANON|ISIG|IEXTEN); + tty.c_iflag &= ~ICRNL; + tty.c_oflag &= ~OPOST; + if (eight) { + tty.c_iflag &= IXOFF; + tty.c_cflag &= ~(CSIZE|PARENB); + tty.c_cflag |= CS8; + } + (void)tcsetattr(0, TCSANOW, &tty); + break; + default: + return; + } +} + +void +lostpeer(signo) + int signo; +{ + (void)signal(SIGPIPE, SIG_IGN); + msg("\aconnection closed."); + done(1); +} + +/* copy SIGURGs to the child process. */ +void +copytochild(signo) + int signo; +{ + (void)kill(child, SIGURG); +} + +void +msg(str) + char *str; +{ + (void)fprintf(stderr, "rlogin: %s\r\n", str); +} + +#ifdef KERBEROS +/* VARARGS */ +void +#if __STDC__ +warning(const char *fmt, ...) +#else +warning(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; + + (void)fprintf(stderr, "rlogin: warning, using standard rlogin: "); +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, ".\n"); +} +#endif + +__dead void +usage() +{ + (void)fprintf(stderr, + "usage: rlogin [ -%s]%s[-e char] [ -l username ] host\n", +#ifdef KERBEROS +#ifdef CRYPT + "8EKLx", " [-k realm] "); +#else + "8EKL", " [-k realm] "); +#endif +#else + "8EL", " "); +#endif + exit(1); +} + +/* + * The following routine provides compatibility (such as it is) between older + * Suns and others. Suns have only a `ttysize', so we convert it to a winsize. + */ +#ifdef OLDSUN +int +get_window_size(fd, wp) + int fd; + struct winsize *wp; +{ + struct ttysize ts; + int error; + + if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0) + return (error); + wp->ws_row = ts.ts_lines; + wp->ws_col = ts.ts_cols; + wp->ws_xpixel = 0; + wp->ws_ypixel = 0; + return (0); +} +#endif + +u_int +getescape(p) + register char *p; +{ + long val; + int len; + + if ((len = strlen(p)) == 1) /* use any single char, including '\' */ + return ((u_int)*p); + /* otherwise, \nnn */ + if (*p == '\\' && len >= 2 && len <= 4) { + val = strtol(++p, NULL, 8); + for (;;) { + if (!*++p) + return ((u_int)val); + if (*p < '0' || *p > '8') + break; + } + } + msg("illegal option value -- e"); + usage(); + /* NOTREACHED */ +} |