X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/36386d084a94788b4ada4439c8f34672c84972f6..fdc1cc8bb0b663a25e1902b6a0ac670af0f03b4d:/usr/src/libexec/rlogind/rlogind.c diff --git a/usr/src/libexec/rlogind/rlogind.c b/usr/src/libexec/rlogind/rlogind.c index e5e0c8015f..eec0cb327e 100644 --- a/usr/src/libexec/rlogind/rlogind.c +++ b/usr/src/libexec/rlogind/rlogind.c @@ -1,155 +1,111 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + #ifndef lint -static char sccsid[] = "@(#)rlogind.c 4.17 83/06/24"; -#endif +char copyright[] = +"@(#) Copyright (c) 1983 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif not lint + +#ifndef lint +static char sccsid[] = "@(#)rlogind.c 5.13 (Berkeley) %G%"; +#endif not lint + +/* + * remote login server: + * remuser\0 + * locuser\0 + * terminal info\0 + * data + */ #include #include #include #include +#include +#include #include #include #include -#include #include #include #include #include +#include +#include + +# ifndef TIOCPKT_WINDOW +# define TIOCPKT_WINDOW 0x80 +# endif TIOCPKT_WINDOW extern errno; int reapchild(); struct passwd *getpwnam(); -char *crypt(), *rindex(), *index(), *malloc(), *ntoa(); -struct sockaddr_in sin = { AF_INET }; -/* - * remote login server: - * remuser\0 - * locuser\0 - * terminal type\0 - * data - */ +char *malloc(); + main(argc, argv) int argc; char **argv; { - int f, options = 0; + int on = 1, options = 0, fromlen; struct sockaddr_in from; - struct servent *sp; - sp = getservbyname("login", "tcp"); - if (sp == 0) { - fprintf(stderr, "rlogind: tcp/rlogin: unknown service\n"); - exit(1); + openlog("rlogind", LOG_PID | LOG_AUTH, LOG_AUTH); + fromlen = sizeof (from); + if (getpeername(0, &from, &fromlen) < 0) { + fprintf(stderr, "%s: ", argv[0]); + perror("getpeername"); + _exit(1); } -#ifndef DEBUG - if (fork()) - exit(0); - for (f = 0; f < 10; f++) - (void) close(f); - (void) open("/", 0); - (void) dup2(0, 1); - (void) dup2(0, 2); - { int tt = open("/dev/tty", 2); - if (tt > 0) { - ioctl(tt, TIOCNOTTY, 0); - close(tt); - } + if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) { + syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); } -#endif - sin.sin_port = sp->s_port; - argc--, argv++; - if (argc > 0 && !strcmp(argv[0], "-d")) { - options |= SO_DEBUG; - argc--, argv++; - } - if (argc > 0) { - int port = atoi(argv[0]); - - if (port < 0) { - fprintf(stderr, "%s: bad port #\n", argv[0]); - exit(1); - } - sin.sin_port = htons((u_short)port); - argv++, argc--; - } - f = socket(AF_INET, SOCK_STREAM, 0, 0); - if (f < 0) { - perror("rlogind: socket"); - exit(1); - } - if (options & SO_DEBUG) - if (setsockopt(f, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) - perror("rlogind: setsockopt (SO_DEBUG)"); - if (setsockopt(f, SOL_SOCKET, SO_KEEPALIVE, 0, 0) < 0) - perror("rlogind: setsockopt (SO_KEEPALIVE)"); - if (bind(f, &sin, sizeof (sin), 0) < 0) { - perror("rlogind: bind"); - exit(1); - } - signal(SIGCHLD, reapchild); - listen(f, 10); - for (;;) { - int s, len = sizeof (from); - - s = accept(f, &from, &len, 0); - if (s < 0) { - if (errno == EINTR) - continue; - perror("rlogind: accept"); - continue; - } - if (fork() == 0) { - signal(SIGCHLD, SIG_IGN); - close(f); - doit(s, &from); - } - close(s); - } -} - -reapchild() -{ - union wait status; - - while (wait3(&status, WNOHANG, 0) > 0) - ; + doit(0, &from); } -char locuser[32], remuser[32]; -char buf[BUFSIZ]; int child; int cleanup(); int netf; extern errno; char *line; +extern char *inet_ntoa(); + +struct winsize win = { 0, 0, 0, 0 }; + doit(f, fromp) int f; struct sockaddr_in *fromp; { - char c; - int i, p, cc, t, pid; - int stop = TIOCPKT_DOSTOP; + int i, p, t, pid, on = 1; register struct hostent *hp; + struct hostent hostent; + char c; alarm(60); read(f, &c, 1); if (c != 0) exit(1); alarm(0); - fromp->sin_port = htons((u_short)fromp->sin_port); + fromp->sin_port = ntohs((u_short)fromp->sin_port); hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), fromp->sin_family); if (hp == 0) { - char buf[BUFSIZ], *cp = (char *)&fromp->sin_addr; - - fatal(f, sprintf(buf, "Host name for your address (%s) unknown", - ntoa(fromp->sin_addr))); + /* + * Only the name is used below. + */ + hp = &hostent; + hp->h_name = inet_ntoa(fromp->sin_addr); } if (fromp->sin_family != AF_INET || fromp->sin_port >= IPPORT_RESERVED || - hp == 0) + fromp->sin_port < IPPORT_RESERVED/2) fatal(f, "Permission denied"); write(f, "", 1); for (c = 'p'; c <= 's'; c++) { @@ -166,10 +122,11 @@ doit(f, fromp) goto gotpty; } } - fatal(f, "All network ports in use"); + fatal(f, "Out of ptys"); /*NOTREACHED*/ gotpty: - dup2(f, 0); + (void) ioctl(p, TIOCSWINSZ, &win); + netf = f; line[strlen("/dev/")] = 't'; #ifdef DEBUG { int tt = open("/dev/tty", 2); @@ -188,103 +145,175 @@ gotpty: pid = fork(); if (pid < 0) fatalperror(f, "", errno); - if (pid) { - char pibuf[1024], fibuf[1024], *pbp, *fbp; - int pcc = 0, fcc = 0, on = 1; -/* FILE *console = fopen("/dev/console", "w"); */ -/* setbuf(console, 0); */ - -/* fprintf(console, "f %d p %d\r\n", f, p); */ - ioctl(f, FIONBIO, &on); - ioctl(p, FIONBIO, &on); - ioctl(p, TIOCPKT, &on); - signal(SIGTSTP, SIG_IGN); - signal(SIGCHLD, cleanup); - for (;;) { - int ibits = 0, obits = 0; - - if (fcc) - obits |= (1<h_name, 0); + fatalperror(2, "/bin/login", errno); + /*NOTREACHED*/ + } + close(t); + ioctl(f, FIONBIO, &on); + ioctl(p, FIONBIO, &on); + ioctl(p, TIOCPKT, &on); + signal(SIGTSTP, SIG_IGN); + signal(SIGCHLD, cleanup); + setpgrp(0, 0); + protocol(f, p); + signal(SIGCHLD, SIG_IGN); + cleanup(); +} + +char magic[2] = { 0377, 0377 }; +char oobdata[] = {TIOCPKT_WINDOW}; + +/* + * Handle a "control" request (signaled by magic being present) + * in the data stream. For now, we are only willing to handle + * window size changes. + */ +control(pty, cp, n) + int pty; + char *cp; + int n; +{ + struct winsize w; + + if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') + return (0); + oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ + bcopy(cp+4, (char *)&w, sizeof(w)); + w.ws_row = ntohs(w.ws_row); + w.ws_col = ntohs(w.ws_col); + w.ws_xpixel = ntohs(w.ws_xpixel); + w.ws_ypixel = ntohs(w.ws_ypixel); + (void)ioctl(pty, TIOCSWINSZ, &w); + return (4+sizeof (w)); +} + +/* + * rlogin "protocol" machine. + */ +protocol(f, p) + int f, p; +{ + char pibuf[1024], fibuf[1024], *pbp, *fbp; + register pcc = 0, fcc = 0; + int cc; + char cntl; + + /* + * Must ignore SIGTTOU, otherwise we'll stop + * when we try and set slave pty's window shape + * (our controlling tty is the master pty). + */ + (void) signal(SIGTTOU, SIG_IGN); + send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ + for (;;) { + int ibits, obits, ebits; + + ibits = 0; + obits = 0; + if (fcc) + obits |= (1<= 0) + if (pcc) + obits |= (1<= 0) - if (pcc) - obits |= (1< 0) + bcopy(cp+n, cp, left); + fcc -= n; + goto top; /* n^2 */ + } } - pcc = 0; - } } - if ((obits & (1< 0) { - cc = write(f, pbp, pcc); -/* fprintf(console, "%d of %d to f\r\n", cc, pcc); */ - if (cc > 0) { - pcc -= cc; - pbp += cc; - } + } + + if ((obits & (1< 0) { + cc = write(p, fbp, fcc); + if (cc > 0) { + fcc -= cc; + fbp += cc; } - if ((obits & (1< 0) { - cc = write(p, fbp, fcc); -/* fprintf(console, "%d of %d to p\r\n", cc, fcc); */ - if (cc > 0) { - fcc -= cc; - fbp += cc; + } + + if (ibits & (1< 0) { + cc = write(f, pbp, pcc); + if (cc < 0 && errno == EWOULDBLOCK) { + /* also shouldn't happen */ + sleep(5); + continue; + } + if (cc > 0) { + pcc -= cc; + pbp += cc; } } - cleanup(); } - close(f); - close(p); - dup2(t, 0); - dup2(t, 1); - dup2(t, 2); - close(t); - execl("/bin/login", "login", "-r", hp->h_name, 0); - fatalperror(2, "/bin/login", errno); - /*NOTREACHED*/ } cleanup() @@ -293,7 +322,6 @@ cleanup() rmut(); vhangup(); /* XXX */ shutdown(netf, 2); - kill(0, SIGKILL); exit(1); } @@ -304,7 +332,7 @@ fatal(f, msg) char buf[BUFSIZ]; buf[0] = '\01'; /* error indicator */ - (void) sprintf(buf + 1, "rlogind: %s.\n", msg); + (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg); (void) write(f, buf, strlen(buf)); exit(1); } @@ -315,9 +343,13 @@ fatalperror(f, msg, errno) int errno; { char buf[BUFSIZ]; + extern int sys_nerr; extern char *sys_errlist[]; - (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); + if ((unsigned)errno < sys_nerr) + (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); + else + (void) sprintf(buf, "%s: Error %d", msg, errno); fatal(f, buf); } @@ -325,7 +357,7 @@ fatalperror(f, msg, errno) struct utmp wtmp; char wtmpf[] = "/usr/adm/wtmp"; -char utmp[] = "/etc/utmp"; +char utmpf[] = "/etc/utmp"; #define SCPYN(a, b) strncpy(a, b, sizeof(a)) #define SCMPN(a, b) strncmp(a, b, sizeof(a)) @@ -333,29 +365,41 @@ rmut() { register f; int found = 0; + struct utmp *u, *utmp; + int nutmp; + struct stat statbf; - f = open(utmp, 2); + f = open(utmpf, O_RDWR); if (f >= 0) { - while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { - if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0) - continue; - lseek(f, -(long)sizeof(wtmp), 1); - SCPYN(wtmp.ut_name, ""); - SCPYN(wtmp.ut_host, ""); - time(&wtmp.ut_time); - write(f, (char *)&wtmp, sizeof(wtmp)); - found++; + fstat(f, &statbf); + utmp = (struct utmp *)malloc(statbf.st_size); + if (!utmp) + syslog(LOG_ERR, "utmp malloc failed"); + if (statbf.st_size && utmp) { + nutmp = read(f, utmp, statbf.st_size); + nutmp /= sizeof(struct utmp); + + for (u = utmp ; u < &utmp[nutmp] ; u++) { + if (SCMPN(u->ut_line, line+5) || + u->ut_name[0]==0) + continue; + lseek(f, ((long)u)-((long)utmp), L_SET); + SCPYN(u->ut_name, ""); + SCPYN(u->ut_host, ""); + time(&u->ut_time); + write(f, (char *)u, sizeof(wtmp)); + found++; + } } close(f); } if (found) { - f = open(wtmpf, 1); + f = open(wtmpf, O_WRONLY|O_APPEND); if (f >= 0) { SCPYN(wtmp.ut_line, line+5); SCPYN(wtmp.ut_name, ""); SCPYN(wtmp.ut_host, ""); time(&wtmp.ut_time); - lseek(f, (long)0, 2); write(f, (char *)&wtmp, sizeof(wtmp)); close(f); } @@ -366,20 +410,3 @@ rmut() chmod(line, 0666); chown(line, 0, 0); } - -/* - * Convert network-format internet address - * to base 256 d.d.d.d representation. - */ -char * -ntoa(in) - struct in_addr in; -{ - static char b[18]; - register char *p; - - p = (char *)∈ -#define UC(b) (((int)b)&0xff) - sprintf(b, "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); - return (b); -}