rlogind.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 501 行
C
501 行
#ifndef lintstatic char *sccsid = "@(#)rlogind.c 4.1 (ULTRIX) 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1987-1990 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//*static char sccsid[] = "@(#)rlogind.c 5.11 (Berkeley) 5/23/86";*//* * Modification History: * * 07-Feb-90 sue * Added Berkeley fix to check IP address after gethostbyaddr * with a gethostbyname and comparison. * * 09-Sep-89 lp * Fix for wtmp cleanup (add locking mechanism) * * 09-Jun-88 map * Changed signal handlers to void. * * 25-Jul-87 melvin * Removed the O_APPEND flag to opens of /etc/utmp. * * 18-May-87 lp * Bump pty search from p-s to p-z (giving more pty's). * * Added a few omission back to rlogind.c which were left out in the * previous submission *//* * remote login server: * remuser\0 * locuser\0 * terminal info\0 * data */#include <stdio.h>#include <sys/param.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#include <sys/wait.h>#include <sys/file.h>#include <sys/svcinfo.h>#include <netinet/in.h>#include <errno.h>#include <pwd.h>#include <signal.h>#include <sgtty.h>#include <stdio.h>#include <netdb.h>#include <syslog.h>#include <strings.h># ifndef TIOCPKT_WINDOW# define TIOCPKT_WINDOW 0x80# endif TIOCPKT_WINDOW#define TTY_DEBUG /* report to syslog if tty not found */extern errno;int reapchild();char *malloc();int Pfd;main(argc, argv) int argc; char **argv;{ int on = 1, fromlen; struct sockaddr_in from; fromlen = sizeof (from); if (getpeername(0, &from, &fromlen) < 0) { fprintf(stderr, "%s: ", argv[0]); perror("getpeername"); _exit(1); } if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) { openlog(argv[0], LOG_PID); syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); closelog(); } openlog(argv[0], LOG_PID); doit(0, &from); closelog();}void cleanup();int netf;extern errno;char *line;int didcleanup = 0;extern char *inet_ntoa();struct winsize win = { 0, 0, 0, 0 };doit(f, fromp) int f; struct sockaddr_in *fromp;{ int i, p, t, pid, on = 1; struct hostent hostent; int hostok = 0; char remotehost[2 * MAXHOSTNAMELEN + 1]; char c; struct hostent *hp; alarm(60); read(f, &c, 1); if (c != 0) exit(1); alarm(0); fromp->sin_port = ntohs((u_short)fromp->sin_port); hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), fromp->sin_family); if (hp == 0) { /* * Only the name is used below. */ hp = &hostent; hp->h_name = inet_ntoa(fromp->sin_addr); hostok++; } else if (svc_lastlookup == SVC_BIND) { /* * Attempt to verify that we haven't been fooled by * someone on the net; look up the name and check * that this address corresponds to the name. */ strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1); remotehost[sizeof(remotehost) - 1] = 0; hp = gethostbyname(remotehost); if (hp) for (; hp->h_addr_list[0]; hp->h_addr_list++) if (!bcmp(hp->h_addr_list[0], (caddr_t)&fromp->sin_addr, sizeof(fromp->sin_addr))) { hostok++; break; } } else hostok++; if (fromp->sin_family != AF_INET || fromp->sin_port >= IPPORT_RESERVED || fromp->sin_port < IPPORT_RESERVED/2) fatal(f, "Permission denied"); write(f, "", 1); if (hostok == 0) fatal(f, "Host address mismatch. Permission denied"); for (c = 'p'; c <= 'z'; c++) { struct stat stb; line = "/dev/ptyXX"; line[strlen("/dev/pty")] = c; line[strlen("/dev/ptyp")] = '0'; if (stat(line, &stb) < 0) break; for (i = 0; i < 16; i++) { line[strlen("/dev/ptyp")] = "0123456789abcdef"[i]; p = open(line, 2); if (p > 0) goto gotpty; } } fatal(f, "Out of ptys"); /*NOTREACHED*/gotpty: Pfd = p; (void) ioctl(p, TIOCSWINSZ, &win); netf = f; line[strlen("/dev/")] = 't';#ifdef DEBUG { int tt = open("/dev/tty", 2); if (tt > 0) { ioctl(tt, TIOCNOTTY, 0); close(tt); } }#endif t = open(line, 2); if (t < 0) fatalperror(f, line, errno); { struct sgttyb b; gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b); } pid = fork(); if (pid < 0) fatalperror(f, "", errno); if (pid == 0) { 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*/ } close(t); ioctl(f, FIONBIO, &on); ioctl(p, FIONBIO, &on); ioctl(p, TIOCPKT, &on); signal(SIGTSTP, SIG_IGN); signal(SIGCHLD, cleanup); signal(SIGTERM, cleanup); signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); setpgrp(0, 0); protocol(f, p); 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); sleep(1); send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ for (;;) { int ibits, obits, ebits; ibits = 0; obits = 0; if (fcc) obits |= (1<<p); else ibits |= (1<<f); if (pcc >= 0) if (pcc) obits |= (1<<f); else ibits |= (1<<p); ebits = (1<<p); if (select(16, &ibits, &obits, &ebits, 0) < 0) { if (errno == EINTR) continue; fatalperror(f, "select", errno); } if (ibits == 0 && obits == 0 && ebits == 0) { /* shouldn't happen... */ sleep(5); continue; }#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) if (ebits & (1<<p)) { cc = read(p, &cntl, 1); if (cc == 1 && pkcontrol(cntl)) { cntl |= oobdata[0]; send(f, &cntl, 1, MSG_OOB); if (cntl & TIOCPKT_FLUSHWRITE) { pcc = 0; ibits &= ~(1<<p); } } } if (ibits & (1<<f)) { fcc = read(f, fibuf, sizeof (fibuf)); if (fcc < 0 && errno == EWOULDBLOCK) fcc = 0; else { register char *cp; int left, n; if (fcc <= 0) break; fbp = fibuf; top: for (cp = fibuf; cp < fibuf+fcc-1; cp++) if (cp[0] == magic[0] && cp[1] == magic[1]) { left = fcc - (cp-fibuf); n = control(p, cp, left); if (n) { left -= n; if (left > 0) bcopy(cp+n, cp, left); fcc -= n; goto top; /* n^2 */ } } } } if ((obits & (1<<p)) && fcc > 0) { cc = write(p, fbp, fcc); if (cc > 0) { fcc -= cc; fbp += cc; } } if (ibits & (1<<p)) { pcc = read(p, pibuf, sizeof (pibuf)); pbp = pibuf; if (pcc < 0 && errno == EWOULDBLOCK) pcc = 0; else if (pcc <= 0) break; else if (pibuf[0] == 0) pbp++, pcc--; else { if (pkcontrol(pibuf[0])) { pibuf[0] |= oobdata[0]; send(f, &pibuf[0], 1, MSG_OOB); } pcc = 0; } } if ((obits & (1<<f)) && pcc > 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; } } }}voidcleanup(){ signal(SIGCHLD, SIG_IGN); if(!didcleanup++) { rmut(); signal(SIGHUP, SIG_IGN); close(Pfd); vhangup(); /* XXX */ shutdown(netf, 2); (void) kill(0, SIGKILL); exit(1); }}fatal(f, msg) int f; char *msg;{ char buf[BUFSIZ]; buf[0] = '\01'; /* error indicator */ (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg); (void) write(f, buf, strlen(buf)); exit(1);}fatalperror(f, msg, errno) int f; char *msg; int errno;{ char buf[BUFSIZ]; extern int sys_nerr; extern char *sys_errlist[]; 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);}#include <utmp.h>struct utmp wtmp;char wtmpf[] = "/usr/adm/wtmp";char utmpf[] = "/etc/utmp";#define SCPYN(a, b) strncpy(a, b, sizeof(a))#define SCMPN(a, b) strncmp(a, b, sizeof(a))rmut(){ register f; int found = 0; struct utmp *u, *utmp; int nutmp; struct stat statbf; f = open(utmpf, O_RDWR); if (f >= 0) { 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++; }#ifdef TTY_DEBUGif(!found)syslog(LOG_ERR, "notfound %10s %d", line, nutmp);#endif TTY_DEBUG } close(f); } if (found) { 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); write(f, (char *)&wtmp, sizeof(wtmp)); close(f); } } chmod(line, 0666); chown(line, 0, 0); line[strlen("/dev/")] = 'p'; chmod(line, 0666); chown(line, 0, 0);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?