xref: /csrg-svn/libexec/uucpd/uucpd.c (revision 33974)
117144Sralph #ifndef lint
2*33974Srick static char sccsid[] = "@(#)uucpd.c	5.5	(Berkeley) 04/05/88";
317144Sralph #endif
417144Sralph 
517144Sralph /*
6*33974Srick  * 4.2BSD 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"
1123682Sbloom #include <netdb.h>
1217843Sralph #include <signal.h>
1317144Sralph #include <errno.h>
1417144Sralph #include <sys/socket.h>
1517144Sralph #include <netinet/in.h>
1617843Sralph #include <sys/wait.h>
1723682Sbloom #include <sys/ioctl.h>
1817843Sralph #include <pwd.h>
1917843Sralph #include <lastlog.h>
2017144Sralph 
2117843Sralph char lastlog[] = "/usr/adm/lastlog";
2217843Sralph struct	sockaddr_in hisctladdr;
2317843Sralph int hisaddrlen = sizeof hisctladdr;
2417843Sralph struct	sockaddr_in myctladdr;
2517843Sralph int mypid;
2617144Sralph 
2723682Sbloom char Username[64];
2823682Sbloom char *nenv[] = {
2923682Sbloom 	Username,
3023682Sbloom 	NULL,
3123682Sbloom };
3223682Sbloom extern char **environ;
3323682Sbloom 
3417144Sralph main(argc, argv)
3517843Sralph int argc;
3617843Sralph char **argv;
3717144Sralph {
3818625Sralph #ifndef BSDINETD
3917843Sralph 	register int s, tcp_socket;
4017843Sralph 	struct servent *sp;
4118625Sralph #endif !BSDINETD
4217843Sralph 	extern int errno;
4317843Sralph 	int dologout();
4417144Sralph 
4523682Sbloom 	environ = nenv;
4617843Sralph #ifdef BSDINETD
4717843Sralph 	close(1); close(2);
4817843Sralph 	dup(0); dup(0);
4917843Sralph 	hisaddrlen = sizeof (hisctladdr);
5017843Sralph 	if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) {
5117144Sralph 		fprintf(stderr, "%s: ", argv[0]);
5217144Sralph 		perror("getpeername");
5317144Sralph 		_exit(1);
5417144Sralph 	}
5517843Sralph 	if (fork() == 0)
5617843Sralph 		doit(&hisctladdr);
5717843Sralph 	dologout();
5817843Sralph 	exit(1);
5917843Sralph #else !BSDINETD
6017843Sralph 	sp = getservbyname("uucp", "tcp");
6117843Sralph 	if (sp == NULL){
6217843Sralph 		perror("uucpd: getservbyname");
6317843Sralph 		exit(1);
6417843Sralph 	}
6523682Sbloom 	if (fork())
6623682Sbloom 		exit(0);
6717843Sralph 	if ((s=open("/dev/tty", 2)) >= 0){
6817843Sralph 		ioctl(s, TIOCNOTTY, (char *)0);
6917843Sralph 		close(s);
7017843Sralph 	}
7117144Sralph 
7217843Sralph 	bzero((char *)&myctladdr, sizeof (myctladdr));
7323682Sbloom 	myctladdr.sin_family = AF_INET;
7423682Sbloom 	myctladdr.sin_port = sp->s_port;
7523682Sbloom #ifdef BSD4_2
7623682Sbloom 	tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
7723682Sbloom 	if (tcp_socket < 0) {
7817843Sralph 		perror("uucpd: socket");
7917843Sralph 		exit(1);
8017843Sralph 	}
8123682Sbloom 	if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) {
8217843Sralph 		perror("uucpd: bind");
8317843Sralph 		exit(1);
8417843Sralph 	}
8523682Sbloom 	listen(tcp_socket, 3);	/* at most 3 simultaneuos uucp connections */
8617843Sralph 	signal(SIGCHLD, dologout);
8717843Sralph 
8817843Sralph 	for(;;) {
8917843Sralph 		s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
9017843Sralph 		if (s < 0){
9123682Sbloom 			if (errno == EINTR)
9217843Sralph 				continue;
9317843Sralph 			perror("uucpd: accept");
9417843Sralph 			exit(1);
9517843Sralph 		}
9623682Sbloom 		if (fork() == 0) {
9717843Sralph 			close(0); close(1); close(2);
9817843Sralph 			dup(s); dup(s); dup(s);
9923682Sbloom 			close(tcp_socket); close(s);
10017843Sralph 			doit(&hisctladdr);
10117843Sralph 			exit(1);
10217843Sralph 		}
10317843Sralph 		close(s);
10417843Sralph 	}
10523682Sbloom #endif BSD4_2
10623682Sbloom 
10723682Sbloom #endif	!BSDINETD
10817144Sralph }
10917843Sralph 
11017843Sralph doit(sinp)
11117843Sralph struct sockaddr_in *sinp;
11217843Sralph {
11323682Sbloom 	char user[64], passwd[64];
11417843Sralph 	char *xpasswd, *crypt();
11517843Sralph 	struct passwd *pw, *getpwnam();
11617843Sralph 
11717843Sralph 	alarm(60);
11818625Sralph 	printf("login: "); fflush(stdout);
11917843Sralph 	if (readline(user, sizeof user) < 0) {
12017843Sralph 		fprintf(stderr, "user read\n");
12117843Sralph 		return;
12217843Sralph 	}
12317843Sralph 	/* truncate username to 8 characters */
12417843Sralph 	user[8] = '\0';
12517843Sralph 	pw = getpwnam(user);
12617843Sralph 	if (pw == NULL) {
12717843Sralph 		fprintf(stderr, "user unknown\n");
12817843Sralph 		return;
12917843Sralph 	}
13017843Sralph 	if (strcmp(pw->pw_shell, UUCICO)) {
13117843Sralph 		fprintf(stderr, "Login incorrect.");
13217843Sralph 		return;
13317843Sralph 	}
13417843Sralph 	if (pw->pw_passwd && *pw->pw_passwd != '\0') {
13518625Sralph 		printf("Password: "); fflush(stdout);
13617843Sralph 		if (readline(passwd, sizeof passwd) < 0) {
13717843Sralph 			fprintf(stderr, "passwd read\n");
13817843Sralph 			return;
13917843Sralph 		}
14017843Sralph 		xpasswd = crypt(passwd, pw->pw_passwd);
14117843Sralph 		if (strcmp(xpasswd, pw->pw_passwd)) {
14217843Sralph 			fprintf(stderr, "Login incorrect.");
14317843Sralph 			return;
14417843Sralph 		}
14517843Sralph 	}
14617843Sralph 	alarm(0);
14723682Sbloom 	sprintf(Username, "USER=%s", user);
14817843Sralph 	dologin(pw, sinp);
14923682Sbloom 	setgid(pw->pw_gid);
15023682Sbloom #ifdef BSD4_2
15117843Sralph 	initgroups(pw->pw_name, pw->pw_gid);
15223682Sbloom #endif BSD4_2
15317843Sralph 	chdir(pw->pw_dir);
15423682Sbloom 	setuid(pw->pw_uid);
15523682Sbloom #ifdef BSD4_2
15617843Sralph 	execl(UUCICO, "uucico", (char *)0);
15723682Sbloom #endif BSD4_2
15817843Sralph 	perror("uucico server: execl");
15917843Sralph }
16017843Sralph 
16117843Sralph readline(p, n)
16218625Sralph register char *p;
16318625Sralph register int n;
16417843Sralph {
16517843Sralph 	char c;
16617843Sralph 
16717843Sralph 	while (n-- > 0) {
16817843Sralph 		if (read(0, &c, 1) <= 0)
16917843Sralph 			return(-1);
17017843Sralph 		c &= 0177;
17117843Sralph 		if (c == '\n' || c == '\r') {
17217843Sralph 			*p = '\0';
17317843Sralph 			return(0);
17417843Sralph 		}
17517843Sralph 		*p++ = c;
17617843Sralph 	}
17717843Sralph 	return(-1);
17817843Sralph }
17917843Sralph 
18017843Sralph #include <utmp.h>
18123682Sbloom #ifdef BSD4_2
18217843Sralph #include <fcntl.h>
18323682Sbloom #endif BSD4_2
18417843Sralph 
18517843Sralph #define	SCPYN(a, b)	strncpy(a, b, sizeof (a))
18617843Sralph 
18717843Sralph struct	utmp utmp;
18817843Sralph 
18917843Sralph dologout()
19017843Sralph {
19117843Sralph 	union wait status;
19217843Sralph 	int pid, wtmp;
19317843Sralph 
19417843Sralph #ifdef BSDINETD
19523682Sbloom 	while ((pid=wait(&status)) > 0) {
19617843Sralph #else  !BSDINETD
19723682Sbloom 	while ((pid=wait3(&status,WNOHANG,0)) > 0) {
19817843Sralph #endif !BSDINETD
19917843Sralph 		wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
20017843Sralph 		if (wtmp >= 0) {
20117843Sralph 			sprintf(utmp.ut_line, "uucp%.4d", pid);
20217843Sralph 			SCPYN(utmp.ut_name, "");
20317843Sralph 			SCPYN(utmp.ut_host, "");
20423682Sbloom 			(void) time(&utmp.ut_time);
20517843Sralph 			(void) write(wtmp, (char *)&utmp, sizeof (utmp));
20617843Sralph 			(void) close(wtmp);
20717843Sralph 		}
20817843Sralph 	}
20917843Sralph }
21017843Sralph 
21117843Sralph /*
21217843Sralph  * Record login in wtmp file.
21317843Sralph  */
21417843Sralph dologin(pw, sin)
21517843Sralph struct passwd *pw;
21617843Sralph struct sockaddr_in *sin;
21717843Sralph {
21817843Sralph 	char line[32];
21917843Sralph 	char remotehost[32];
22017843Sralph 	int wtmp, f;
22117843Sralph 	struct hostent *hp = gethostbyaddr(&sin->sin_addr,
22217843Sralph 		sizeof (struct in_addr), AF_INET);
22317843Sralph 
22417843Sralph 	if (hp) {
22517843Sralph 		strncpy(remotehost, hp->h_name, sizeof (remotehost));
22617843Sralph 		endhostent();
22717843Sralph 	} else
22817843Sralph 		strncpy(remotehost, inet_ntoa(sin->sin_addr),
22917843Sralph 		    sizeof (remotehost));
23017843Sralph 	wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
23117843Sralph 	if (wtmp >= 0) {
23217843Sralph 		/* hack, but must be unique and no tty line */
23317843Sralph 		sprintf(line, "uucp%.4d", getpid());
23417843Sralph 		SCPYN(utmp.ut_line, line);
23517843Sralph 		SCPYN(utmp.ut_name, pw->pw_name);
23617843Sralph 		SCPYN(utmp.ut_host, remotehost);
23723682Sbloom 		time(&utmp.ut_time);
23817843Sralph 		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
23917843Sralph 		(void) close(wtmp);
24017843Sralph 	}
24117843Sralph 	if ((f = open(lastlog, 2)) >= 0) {
24217843Sralph 		struct lastlog ll;
24317843Sralph 
24417843Sralph 		time(&ll.ll_time);
24517843Sralph 		lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0);
24617843Sralph 		strcpy(line, remotehost);
24717843Sralph 		SCPYN(ll.ll_line, line);
24817843Sralph 		SCPYN(ll.ll_host, remotehost);
24917843Sralph 		(void) write(f, (char *) &ll, sizeof ll);
25017843Sralph 		(void) close(f);
25117843Sralph 	}
25217843Sralph }
253