xref: /csrg-svn/libexec/uucpd/uucpd.c (revision 23682)
117144Sralph #ifndef lint
2*23682Sbloom static char sccsid[] = "@(#)uucpd.c	5.4 (Berkeley) 06/23/85";
317144Sralph #endif
417144Sralph 
517144Sralph /*
6*23682Sbloom  * 4.2BSD or 2.9BSD TCP/IP server for uucico
717843Sralph  * uucico's TCP channel causes this server to be run at the remote end.
817144Sralph  */
917144Sralph 
1017843Sralph #include "uucp.h"
11*23682Sbloom #include <netdb.h>
12*23682Sbloom #ifdef BSD2_9
13*23682Sbloom #include <sys/localopts.h>
14*23682Sbloom #include <sys/file.h>
15*23682Sbloom #endif BSD2_9
1617843Sralph #include <signal.h>
1717144Sralph #include <errno.h>
1817144Sralph #include <sys/socket.h>
1917144Sralph #include <netinet/in.h>
2017843Sralph #include <sys/wait.h>
21*23682Sbloom #include <sys/ioctl.h>
2217843Sralph #include <pwd.h>
2317843Sralph #include <lastlog.h>
2417144Sralph 
25*23682Sbloom #if !defined(BSD4_2) && !defined(BSD2_9)
26*23682Sbloom --- You must have either BSD4_2 or BSD2_9 defined for this to work
27*23682Sbloom #endif !BSD4_2 && !BSD2_9
28*23682Sbloom #if defined(BSD4_2) && defined(BSD2_9)
29*23682Sbloom --- You may not have both BSD4_2 and BSD2_9 defined for this to work
30*23682Sbloom #endif	/* check for stupidity */
31*23682Sbloom 
3217843Sralph char lastlog[] = "/usr/adm/lastlog";
3317843Sralph struct	sockaddr_in hisctladdr;
3417843Sralph int hisaddrlen = sizeof hisctladdr;
3517843Sralph struct	sockaddr_in myctladdr;
3617843Sralph int mypid;
3717144Sralph 
38*23682Sbloom char Username[64];
39*23682Sbloom char *nenv[] = {
40*23682Sbloom 	Username,
41*23682Sbloom 	NULL,
42*23682Sbloom };
43*23682Sbloom extern char **environ;
44*23682Sbloom 
4517144Sralph main(argc, argv)
4617843Sralph int argc;
4717843Sralph char **argv;
4817144Sralph {
4918625Sralph #ifndef BSDINETD
5017843Sralph 	register int s, tcp_socket;
5117843Sralph 	struct servent *sp;
5218625Sralph #endif !BSDINETD
5317843Sralph 	extern int errno;
5417843Sralph 	int dologout();
5517144Sralph 
56*23682Sbloom 	environ = nenv;
5717843Sralph #ifdef BSDINETD
5817843Sralph 	close(1); close(2);
5917843Sralph 	dup(0); dup(0);
6017843Sralph 	hisaddrlen = sizeof (hisctladdr);
6117843Sralph 	if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) {
6217144Sralph 		fprintf(stderr, "%s: ", argv[0]);
6317144Sralph 		perror("getpeername");
6417144Sralph 		_exit(1);
6517144Sralph 	}
6617843Sralph 	if (fork() == 0)
6717843Sralph 		doit(&hisctladdr);
6817843Sralph 	dologout();
6917843Sralph 	exit(1);
7017843Sralph #else !BSDINETD
7117843Sralph 	sp = getservbyname("uucp", "tcp");
7217843Sralph 	if (sp == NULL){
7317843Sralph 		perror("uucpd: getservbyname");
7417843Sralph 		exit(1);
7517843Sralph 	}
76*23682Sbloom 	if (fork())
77*23682Sbloom 		exit(0);
7817843Sralph 	if ((s=open("/dev/tty", 2)) >= 0){
7917843Sralph 		ioctl(s, TIOCNOTTY, (char *)0);
8017843Sralph 		close(s);
8117843Sralph 	}
8217144Sralph 
8317843Sralph 	bzero((char *)&myctladdr, sizeof (myctladdr));
84*23682Sbloom 	myctladdr.sin_family = AF_INET;
85*23682Sbloom 	myctladdr.sin_port = sp->s_port;
86*23682Sbloom #ifdef BSD4_2
87*23682Sbloom 	tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
88*23682Sbloom 	if (tcp_socket < 0) {
8917843Sralph 		perror("uucpd: socket");
9017843Sralph 		exit(1);
9117843Sralph 	}
92*23682Sbloom 	if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) {
9317843Sralph 		perror("uucpd: bind");
9417843Sralph 		exit(1);
9517843Sralph 	}
96*23682Sbloom 	listen(tcp_socket, 3);	/* at most 3 simultaneuos uucp connections */
9717843Sralph 	signal(SIGCHLD, dologout);
9817843Sralph 
9917843Sralph 	for(;;) {
10017843Sralph 		s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
10117843Sralph 		if (s < 0){
102*23682Sbloom 			if (errno == EINTR)
10317843Sralph 				continue;
10417843Sralph 			perror("uucpd: accept");
10517843Sralph 			exit(1);
10617843Sralph 		}
107*23682Sbloom 		if (fork() == 0) {
10817843Sralph 			close(0); close(1); close(2);
10917843Sralph 			dup(s); dup(s); dup(s);
110*23682Sbloom 			close(tcp_socket); close(s);
11117843Sralph 			doit(&hisctladdr);
11217843Sralph 			exit(1);
11317843Sralph 		}
11417843Sralph 		close(s);
11517843Sralph 	}
116*23682Sbloom #endif BSD4_2
117*23682Sbloom 
118*23682Sbloom #ifdef BSD2_9
119*23682Sbloom 	for(;;) {
120*23682Sbloom 		signal(SIGCHLD, dologout);
121*23682Sbloom 		s = socket(SOCK_STREAM, 0,  &myctladdr,
122*23682Sbloom 			SO_ACCEPTCONN|SO_KEEPALIVE);
123*23682Sbloom 		if (s < 0) {
124*23682Sbloom 			perror("uucpd: socket");
125*23682Sbloom 			exit(1);
126*23682Sbloom 		}
127*23682Sbloom 		if (accept(s, &hisctladdr) < 0) {
128*23682Sbloom 			if (errno == EINTR) {
129*23682Sbloom 				close(s);
130*23682Sbloom 				continue;
131*23682Sbloom 			}
132*23682Sbloom 			perror("uucpd: accept");
133*23682Sbloom 			exit(1);
134*23682Sbloom 		}
135*23682Sbloom 		if (fork() == 0) {
136*23682Sbloom 			close(0); close(1); close(2);
137*23682Sbloom 			dup(s); dup(s); dup(s);
138*23682Sbloom 			close(s);
139*23682Sbloom 			doit(&hisctladdr);
140*23682Sbloom 			exit(1);
141*23682Sbloom 		}
142*23682Sbloom 	}
143*23682Sbloom #endif BSD2_9
144*23682Sbloom #endif	!BSDINETD
14517144Sralph }
14617843Sralph 
14717843Sralph doit(sinp)
14817843Sralph struct sockaddr_in *sinp;
14917843Sralph {
150*23682Sbloom 	char user[64], passwd[64];
15117843Sralph 	char *xpasswd, *crypt();
15217843Sralph 	struct passwd *pw, *getpwnam();
15317843Sralph 
15417843Sralph 	alarm(60);
15518625Sralph 	printf("login: "); fflush(stdout);
15617843Sralph 	if (readline(user, sizeof user) < 0) {
15717843Sralph 		fprintf(stderr, "user read\n");
15817843Sralph 		return;
15917843Sralph 	}
16017843Sralph 	/* truncate username to 8 characters */
16117843Sralph 	user[8] = '\0';
16217843Sralph 	pw = getpwnam(user);
16317843Sralph 	if (pw == NULL) {
16417843Sralph 		fprintf(stderr, "user unknown\n");
16517843Sralph 		return;
16617843Sralph 	}
16717843Sralph 	if (strcmp(pw->pw_shell, UUCICO)) {
16817843Sralph 		fprintf(stderr, "Login incorrect.");
16917843Sralph 		return;
17017843Sralph 	}
17117843Sralph 	if (pw->pw_passwd && *pw->pw_passwd != '\0') {
17218625Sralph 		printf("Password: "); fflush(stdout);
17317843Sralph 		if (readline(passwd, sizeof passwd) < 0) {
17417843Sralph 			fprintf(stderr, "passwd read\n");
17517843Sralph 			return;
17617843Sralph 		}
17717843Sralph 		xpasswd = crypt(passwd, pw->pw_passwd);
17817843Sralph 		if (strcmp(xpasswd, pw->pw_passwd)) {
17917843Sralph 			fprintf(stderr, "Login incorrect.");
18017843Sralph 			return;
18117843Sralph 		}
18217843Sralph 	}
18317843Sralph 	alarm(0);
184*23682Sbloom 	sprintf(Username, "USER=%s", user);
18517843Sralph 	dologin(pw, sinp);
186*23682Sbloom 	setgid(pw->pw_gid);
187*23682Sbloom #ifdef BSD4_2
18817843Sralph 	initgroups(pw->pw_name, pw->pw_gid);
189*23682Sbloom #endif BSD4_2
19017843Sralph 	chdir(pw->pw_dir);
191*23682Sbloom 	setuid(pw->pw_uid);
192*23682Sbloom #ifdef BSD4_2
19317843Sralph 	execl(UUCICO, "uucico", (char *)0);
194*23682Sbloom #endif BSD4_2
195*23682Sbloom #ifdef BSD2_9
196*23682Sbloom 	sprintf(passwd, "-h%s", inet_ntoa(sinp->sin_addr));
197*23682Sbloom 	execl(UUCICO, "uucico", passwd, (char *)0);
198*23682Sbloom #endif BSD2_9
19917843Sralph 	perror("uucico server: execl");
20017843Sralph }
20117843Sralph 
20217843Sralph readline(p, n)
20318625Sralph register char *p;
20418625Sralph register int n;
20517843Sralph {
20617843Sralph 	char c;
20717843Sralph 
20817843Sralph 	while (n-- > 0) {
20917843Sralph 		if (read(0, &c, 1) <= 0)
21017843Sralph 			return(-1);
21117843Sralph 		c &= 0177;
21217843Sralph 		if (c == '\n' || c == '\r') {
21317843Sralph 			*p = '\0';
21417843Sralph 			return(0);
21517843Sralph 		}
21617843Sralph 		*p++ = c;
21717843Sralph 	}
21817843Sralph 	return(-1);
21917843Sralph }
22017843Sralph 
22117843Sralph #include <utmp.h>
222*23682Sbloom #ifdef BSD4_2
22317843Sralph #include <fcntl.h>
224*23682Sbloom #endif BSD4_2
22517843Sralph 
226*23682Sbloom #ifdef BSD2_9
227*23682Sbloom #define O_APPEND	0 /* kludge */
228*23682Sbloom #define wait3(a,b,c)	wait2(a,b)
229*23682Sbloom #endif BSD2_9
230*23682Sbloom 
23117843Sralph #define	SCPYN(a, b)	strncpy(a, b, sizeof (a))
23217843Sralph 
23317843Sralph struct	utmp utmp;
23417843Sralph 
23517843Sralph dologout()
23617843Sralph {
23717843Sralph 	union wait status;
23817843Sralph 	int pid, wtmp;
23917843Sralph 
24017843Sralph #ifdef BSDINETD
241*23682Sbloom 	while ((pid=wait(&status)) > 0) {
24217843Sralph #else  !BSDINETD
243*23682Sbloom 	while ((pid=wait3(&status,WNOHANG,0)) > 0) {
24417843Sralph #endif !BSDINETD
24517843Sralph 		wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
24617843Sralph 		if (wtmp >= 0) {
24717843Sralph 			sprintf(utmp.ut_line, "uucp%.4d", pid);
24817843Sralph 			SCPYN(utmp.ut_name, "");
24917843Sralph 			SCPYN(utmp.ut_host, "");
250*23682Sbloom 			(void) time(&utmp.ut_time);
251*23682Sbloom #ifdef BSD2_9
252*23682Sbloom 			(void) lseek(wtmp, 0L, 2);
253*23682Sbloom #endif BSD2_9
25417843Sralph 			(void) write(wtmp, (char *)&utmp, sizeof (utmp));
25517843Sralph 			(void) close(wtmp);
25617843Sralph 		}
25717843Sralph 	}
25817843Sralph }
25917843Sralph 
26017843Sralph /*
26117843Sralph  * Record login in wtmp file.
26217843Sralph  */
26317843Sralph dologin(pw, sin)
26417843Sralph struct passwd *pw;
26517843Sralph struct sockaddr_in *sin;
26617843Sralph {
26717843Sralph 	char line[32];
26817843Sralph 	char remotehost[32];
26917843Sralph 	int wtmp, f;
27017843Sralph 	struct hostent *hp = gethostbyaddr(&sin->sin_addr,
27117843Sralph 		sizeof (struct in_addr), AF_INET);
27217843Sralph 
27317843Sralph 	if (hp) {
27417843Sralph 		strncpy(remotehost, hp->h_name, sizeof (remotehost));
27517843Sralph 		endhostent();
27617843Sralph 	} else
27717843Sralph 		strncpy(remotehost, inet_ntoa(sin->sin_addr),
27817843Sralph 		    sizeof (remotehost));
27917843Sralph 	wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
28017843Sralph 	if (wtmp >= 0) {
28117843Sralph 		/* hack, but must be unique and no tty line */
28217843Sralph 		sprintf(line, "uucp%.4d", getpid());
28317843Sralph 		SCPYN(utmp.ut_line, line);
28417843Sralph 		SCPYN(utmp.ut_name, pw->pw_name);
28517843Sralph 		SCPYN(utmp.ut_host, remotehost);
286*23682Sbloom 		time(&utmp.ut_time);
287*23682Sbloom #ifdef BSD2_9
288*23682Sbloom 		(void) lseek(wtmp, 0L, 2);
289*23682Sbloom #endif BSD2_9
29017843Sralph 		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
29117843Sralph 		(void) close(wtmp);
29217843Sralph 	}
29317843Sralph 	if ((f = open(lastlog, 2)) >= 0) {
29417843Sralph 		struct lastlog ll;
29517843Sralph 
29617843Sralph 		time(&ll.ll_time);
29717843Sralph 		lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0);
29817843Sralph 		strcpy(line, remotehost);
29917843Sralph 		SCPYN(ll.ll_line, line);
30017843Sralph 		SCPYN(ll.ll_host, remotehost);
30117843Sralph 		(void) write(f, (char *) &ll, sizeof ll);
30217843Sralph 		(void) close(f);
30317843Sralph 	}
30417843Sralph }
305