xref: /csrg-svn/libexec/uucpd/uucpd.c (revision 36093)
1*36093Sbostic /*
2*36093Sbostic  * Copyright (c) 1985 The Regents of the University of California.
3*36093Sbostic  * All rights reserved.
4*36093Sbostic  *
5*36093Sbostic  * This code is derived from software contributed to Berkeley by
6*36093Sbostic  * Rick Adams.
7*36093Sbostic  *
8*36093Sbostic  * Redistribution and use in source and binary forms are permitted
9*36093Sbostic  * provided that the above copyright notice and this paragraph are
10*36093Sbostic  * duplicated in all such forms and that any documentation,
11*36093Sbostic  * advertising materials, and other materials related to such
12*36093Sbostic  * distribution and use acknowledge that the software was developed
13*36093Sbostic  * by the University of California, Berkeley.  The name of the
14*36093Sbostic  * University may not be used to endorse or promote products derived
15*36093Sbostic  * from this software without specific prior written permission.
16*36093Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17*36093Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18*36093Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19*36093Sbostic  */
20*36093Sbostic 
2117144Sralph #ifndef lint
22*36093Sbostic char copyright[] =
23*36093Sbostic "@(#) Copyright (c) 1985 The Regents of the University of California.\n\
24*36093Sbostic  All rights reserved.\n";
25*36093Sbostic #endif /* not lint */
2617144Sralph 
27*36093Sbostic #ifndef lint
28*36093Sbostic static char sccsid[] = "@(#)uucpd.c	5.6 (Berkeley) 10/24/88";
29*36093Sbostic #endif /* not lint */
30*36093Sbostic 
3117144Sralph /*
3233974Srick  * 4.2BSD TCP/IP server for uucico
3317843Sralph  * uucico's TCP channel causes this server to be run at the remote end.
3417144Sralph  */
3517144Sralph 
3617843Sralph #include "uucp.h"
3723682Sbloom #include <netdb.h>
3817843Sralph #include <signal.h>
3917144Sralph #include <errno.h>
4017144Sralph #include <sys/socket.h>
4117144Sralph #include <netinet/in.h>
4217843Sralph #include <sys/wait.h>
4323682Sbloom #include <sys/ioctl.h>
4417843Sralph #include <pwd.h>
4517843Sralph #include <lastlog.h>
4617144Sralph 
4717843Sralph char lastlog[] = "/usr/adm/lastlog";
4817843Sralph struct	sockaddr_in hisctladdr;
4917843Sralph int hisaddrlen = sizeof hisctladdr;
5017843Sralph struct	sockaddr_in myctladdr;
5117843Sralph int mypid;
5217144Sralph 
5323682Sbloom char Username[64];
5423682Sbloom char *nenv[] = {
5523682Sbloom 	Username,
5623682Sbloom 	NULL,
5723682Sbloom };
5823682Sbloom extern char **environ;
5923682Sbloom 
6017144Sralph main(argc, argv)
6117843Sralph int argc;
6217843Sralph char **argv;
6317144Sralph {
6418625Sralph #ifndef BSDINETD
6517843Sralph 	register int s, tcp_socket;
6617843Sralph 	struct servent *sp;
6718625Sralph #endif !BSDINETD
6817843Sralph 	extern int errno;
6917843Sralph 	int dologout();
7017144Sralph 
7123682Sbloom 	environ = nenv;
7217843Sralph #ifdef BSDINETD
7317843Sralph 	close(1); close(2);
7417843Sralph 	dup(0); dup(0);
7517843Sralph 	hisaddrlen = sizeof (hisctladdr);
7617843Sralph 	if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) {
7717144Sralph 		fprintf(stderr, "%s: ", argv[0]);
7817144Sralph 		perror("getpeername");
7917144Sralph 		_exit(1);
8017144Sralph 	}
8117843Sralph 	if (fork() == 0)
8217843Sralph 		doit(&hisctladdr);
8317843Sralph 	dologout();
8417843Sralph 	exit(1);
8517843Sralph #else !BSDINETD
8617843Sralph 	sp = getservbyname("uucp", "tcp");
8717843Sralph 	if (sp == NULL){
8817843Sralph 		perror("uucpd: getservbyname");
8917843Sralph 		exit(1);
9017843Sralph 	}
9123682Sbloom 	if (fork())
9223682Sbloom 		exit(0);
9317843Sralph 	if ((s=open("/dev/tty", 2)) >= 0){
9417843Sralph 		ioctl(s, TIOCNOTTY, (char *)0);
9517843Sralph 		close(s);
9617843Sralph 	}
9717144Sralph 
9817843Sralph 	bzero((char *)&myctladdr, sizeof (myctladdr));
9923682Sbloom 	myctladdr.sin_family = AF_INET;
10023682Sbloom 	myctladdr.sin_port = sp->s_port;
10123682Sbloom #ifdef BSD4_2
10223682Sbloom 	tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
10323682Sbloom 	if (tcp_socket < 0) {
10417843Sralph 		perror("uucpd: socket");
10517843Sralph 		exit(1);
10617843Sralph 	}
10723682Sbloom 	if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) {
10817843Sralph 		perror("uucpd: bind");
10917843Sralph 		exit(1);
11017843Sralph 	}
11123682Sbloom 	listen(tcp_socket, 3);	/* at most 3 simultaneuos uucp connections */
11217843Sralph 	signal(SIGCHLD, dologout);
11317843Sralph 
11417843Sralph 	for(;;) {
11517843Sralph 		s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
11617843Sralph 		if (s < 0){
11723682Sbloom 			if (errno == EINTR)
11817843Sralph 				continue;
11917843Sralph 			perror("uucpd: accept");
12017843Sralph 			exit(1);
12117843Sralph 		}
12223682Sbloom 		if (fork() == 0) {
12317843Sralph 			close(0); close(1); close(2);
12417843Sralph 			dup(s); dup(s); dup(s);
12523682Sbloom 			close(tcp_socket); close(s);
12617843Sralph 			doit(&hisctladdr);
12717843Sralph 			exit(1);
12817843Sralph 		}
12917843Sralph 		close(s);
13017843Sralph 	}
13123682Sbloom #endif BSD4_2
13223682Sbloom 
13323682Sbloom #endif	!BSDINETD
13417144Sralph }
13517843Sralph 
13617843Sralph doit(sinp)
13717843Sralph struct sockaddr_in *sinp;
13817843Sralph {
13923682Sbloom 	char user[64], passwd[64];
14017843Sralph 	char *xpasswd, *crypt();
14117843Sralph 	struct passwd *pw, *getpwnam();
14217843Sralph 
14317843Sralph 	alarm(60);
14418625Sralph 	printf("login: "); fflush(stdout);
14517843Sralph 	if (readline(user, sizeof user) < 0) {
14617843Sralph 		fprintf(stderr, "user read\n");
14717843Sralph 		return;
14817843Sralph 	}
14917843Sralph 	/* truncate username to 8 characters */
15017843Sralph 	user[8] = '\0';
15117843Sralph 	pw = getpwnam(user);
15217843Sralph 	if (pw == NULL) {
15317843Sralph 		fprintf(stderr, "user unknown\n");
15417843Sralph 		return;
15517843Sralph 	}
15617843Sralph 	if (strcmp(pw->pw_shell, UUCICO)) {
15717843Sralph 		fprintf(stderr, "Login incorrect.");
15817843Sralph 		return;
15917843Sralph 	}
16017843Sralph 	if (pw->pw_passwd && *pw->pw_passwd != '\0') {
16118625Sralph 		printf("Password: "); fflush(stdout);
16217843Sralph 		if (readline(passwd, sizeof passwd) < 0) {
16317843Sralph 			fprintf(stderr, "passwd read\n");
16417843Sralph 			return;
16517843Sralph 		}
16617843Sralph 		xpasswd = crypt(passwd, pw->pw_passwd);
16717843Sralph 		if (strcmp(xpasswd, pw->pw_passwd)) {
16817843Sralph 			fprintf(stderr, "Login incorrect.");
16917843Sralph 			return;
17017843Sralph 		}
17117843Sralph 	}
17217843Sralph 	alarm(0);
17323682Sbloom 	sprintf(Username, "USER=%s", user);
17417843Sralph 	dologin(pw, sinp);
17523682Sbloom 	setgid(pw->pw_gid);
17623682Sbloom #ifdef BSD4_2
17717843Sralph 	initgroups(pw->pw_name, pw->pw_gid);
17823682Sbloom #endif BSD4_2
17917843Sralph 	chdir(pw->pw_dir);
18023682Sbloom 	setuid(pw->pw_uid);
18123682Sbloom #ifdef BSD4_2
18217843Sralph 	execl(UUCICO, "uucico", (char *)0);
18323682Sbloom #endif BSD4_2
18417843Sralph 	perror("uucico server: execl");
18517843Sralph }
18617843Sralph 
18717843Sralph readline(p, n)
18818625Sralph register char *p;
18918625Sralph register int n;
19017843Sralph {
19117843Sralph 	char c;
19217843Sralph 
19317843Sralph 	while (n-- > 0) {
19417843Sralph 		if (read(0, &c, 1) <= 0)
19517843Sralph 			return(-1);
19617843Sralph 		c &= 0177;
19717843Sralph 		if (c == '\n' || c == '\r') {
19817843Sralph 			*p = '\0';
19917843Sralph 			return(0);
20017843Sralph 		}
20117843Sralph 		*p++ = c;
20217843Sralph 	}
20317843Sralph 	return(-1);
20417843Sralph }
20517843Sralph 
20617843Sralph #include <utmp.h>
20723682Sbloom #ifdef BSD4_2
20817843Sralph #include <fcntl.h>
20923682Sbloom #endif BSD4_2
21017843Sralph 
21117843Sralph #define	SCPYN(a, b)	strncpy(a, b, sizeof (a))
21217843Sralph 
21317843Sralph struct	utmp utmp;
21417843Sralph 
21517843Sralph dologout()
21617843Sralph {
21717843Sralph 	union wait status;
21817843Sralph 	int pid, wtmp;
21917843Sralph 
22017843Sralph #ifdef BSDINETD
22123682Sbloom 	while ((pid=wait(&status)) > 0) {
22217843Sralph #else  !BSDINETD
22323682Sbloom 	while ((pid=wait3(&status,WNOHANG,0)) > 0) {
22417843Sralph #endif !BSDINETD
22517843Sralph 		wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
22617843Sralph 		if (wtmp >= 0) {
22717843Sralph 			sprintf(utmp.ut_line, "uucp%.4d", pid);
22817843Sralph 			SCPYN(utmp.ut_name, "");
22917843Sralph 			SCPYN(utmp.ut_host, "");
23023682Sbloom 			(void) time(&utmp.ut_time);
23117843Sralph 			(void) write(wtmp, (char *)&utmp, sizeof (utmp));
23217843Sralph 			(void) close(wtmp);
23317843Sralph 		}
23417843Sralph 	}
23517843Sralph }
23617843Sralph 
23717843Sralph /*
23817843Sralph  * Record login in wtmp file.
23917843Sralph  */
24017843Sralph dologin(pw, sin)
24117843Sralph struct passwd *pw;
24217843Sralph struct sockaddr_in *sin;
24317843Sralph {
24417843Sralph 	char line[32];
24517843Sralph 	char remotehost[32];
24617843Sralph 	int wtmp, f;
24717843Sralph 	struct hostent *hp = gethostbyaddr(&sin->sin_addr,
24817843Sralph 		sizeof (struct in_addr), AF_INET);
24917843Sralph 
25017843Sralph 	if (hp) {
25117843Sralph 		strncpy(remotehost, hp->h_name, sizeof (remotehost));
25217843Sralph 		endhostent();
25317843Sralph 	} else
25417843Sralph 		strncpy(remotehost, inet_ntoa(sin->sin_addr),
25517843Sralph 		    sizeof (remotehost));
25617843Sralph 	wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
25717843Sralph 	if (wtmp >= 0) {
25817843Sralph 		/* hack, but must be unique and no tty line */
25917843Sralph 		sprintf(line, "uucp%.4d", getpid());
26017843Sralph 		SCPYN(utmp.ut_line, line);
26117843Sralph 		SCPYN(utmp.ut_name, pw->pw_name);
26217843Sralph 		SCPYN(utmp.ut_host, remotehost);
26323682Sbloom 		time(&utmp.ut_time);
26417843Sralph 		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
26517843Sralph 		(void) close(wtmp);
26617843Sralph 	}
26717843Sralph 	if ((f = open(lastlog, 2)) >= 0) {
26817843Sralph 		struct lastlog ll;
26917843Sralph 
27017843Sralph 		time(&ll.ll_time);
27117843Sralph 		lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0);
27217843Sralph 		strcpy(line, remotehost);
27317843Sralph 		SCPYN(ll.ll_line, line);
27417843Sralph 		SCPYN(ll.ll_host, remotehost);
27517843Sralph 		(void) write(f, (char *) &ll, sizeof ll);
27617843Sralph 		(void) close(f);
27717843Sralph 	}
27817843Sralph }
279