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 + -
显示快捷键?