xref: /csrg-svn/libexec/uucpd/uucpd.c (revision 42673)
136093Sbostic /*
236093Sbostic  * Copyright (c) 1985 The Regents of the University of California.
336093Sbostic  * All rights reserved.
436093Sbostic  *
536093Sbostic  * This code is derived from software contributed to Berkeley by
636093Sbostic  * Rick Adams.
736093Sbostic  *
8*42673Sbostic  * %sccs.include.redist.c%
936093Sbostic  */
1036093Sbostic 
1117144Sralph #ifndef lint
1236093Sbostic char copyright[] =
1336093Sbostic "@(#) Copyright (c) 1985 The Regents of the University of California.\n\
1436093Sbostic  All rights reserved.\n";
1536093Sbostic #endif /* not lint */
1617144Sralph 
1736093Sbostic #ifndef lint
18*42673Sbostic static char sccsid[] = "@(#)uucpd.c	5.9 (Berkeley) 06/01/90";
1936093Sbostic #endif /* not lint */
2036093Sbostic 
2117144Sralph /*
2233974Srick  * 4.2BSD TCP/IP server for uucico
2317843Sralph  * uucico's TCP channel causes this server to be run at the remote end.
2417144Sralph  */
2517144Sralph 
2638030Sbostic #include <sys/types.h>
2738030Sbostic #include <sys/socket.h>
2838030Sbostic #include <sys/wait.h>
2938030Sbostic #include <sys/ioctl.h>
3038030Sbostic #include <sys/file.h>
3138030Sbostic #include <netinet/in.h>
3223682Sbloom #include <netdb.h>
3317843Sralph #include <signal.h>
3417144Sralph #include <errno.h>
3517843Sralph #include <pwd.h>
3638030Sbostic #include <stdio.h>
3737931Sbostic #include "pathnames.h"
3817144Sralph 
3917843Sralph struct	sockaddr_in hisctladdr;
4017843Sralph int hisaddrlen = sizeof hisctladdr;
4117843Sralph struct	sockaddr_in myctladdr;
4217843Sralph int mypid;
4317144Sralph 
4423682Sbloom char Username[64];
4523682Sbloom char *nenv[] = {
4623682Sbloom 	Username,
4723682Sbloom 	NULL,
4823682Sbloom };
4923682Sbloom extern char **environ;
5023682Sbloom 
5117144Sralph main(argc, argv)
5217843Sralph int argc;
5317843Sralph char **argv;
5417144Sralph {
5518625Sralph #ifndef BSDINETD
5617843Sralph 	register int s, tcp_socket;
5717843Sralph 	struct servent *sp;
5818625Sralph #endif !BSDINETD
5917843Sralph 	extern int errno;
6017843Sralph 	int dologout();
6117144Sralph 
6223682Sbloom 	environ = nenv;
6317843Sralph #ifdef BSDINETD
6417843Sralph 	close(1); close(2);
6517843Sralph 	dup(0); dup(0);
6617843Sralph 	hisaddrlen = sizeof (hisctladdr);
6717843Sralph 	if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) {
6817144Sralph 		fprintf(stderr, "%s: ", argv[0]);
6917144Sralph 		perror("getpeername");
7017144Sralph 		_exit(1);
7117144Sralph 	}
7217843Sralph 	if (fork() == 0)
7317843Sralph 		doit(&hisctladdr);
7417843Sralph 	dologout();
7517843Sralph 	exit(1);
7617843Sralph #else !BSDINETD
7717843Sralph 	sp = getservbyname("uucp", "tcp");
7817843Sralph 	if (sp == NULL){
7917843Sralph 		perror("uucpd: getservbyname");
8017843Sralph 		exit(1);
8117843Sralph 	}
8223682Sbloom 	if (fork())
8323682Sbloom 		exit(0);
8437931Sbostic 	if ((s=open(_PATH_TTY, 2)) >= 0){
8517843Sralph 		ioctl(s, TIOCNOTTY, (char *)0);
8617843Sralph 		close(s);
8717843Sralph 	}
8817144Sralph 
8917843Sralph 	bzero((char *)&myctladdr, sizeof (myctladdr));
9023682Sbloom 	myctladdr.sin_family = AF_INET;
9123682Sbloom 	myctladdr.sin_port = sp->s_port;
9223682Sbloom #ifdef BSD4_2
9323682Sbloom 	tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
9423682Sbloom 	if (tcp_socket < 0) {
9517843Sralph 		perror("uucpd: socket");
9617843Sralph 		exit(1);
9717843Sralph 	}
9823682Sbloom 	if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) {
9917843Sralph 		perror("uucpd: bind");
10017843Sralph 		exit(1);
10117843Sralph 	}
10223682Sbloom 	listen(tcp_socket, 3);	/* at most 3 simultaneuos uucp connections */
10317843Sralph 	signal(SIGCHLD, dologout);
10417843Sralph 
10517843Sralph 	for(;;) {
10617843Sralph 		s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
10717843Sralph 		if (s < 0){
10823682Sbloom 			if (errno == EINTR)
10917843Sralph 				continue;
11017843Sralph 			perror("uucpd: accept");
11117843Sralph 			exit(1);
11217843Sralph 		}
11323682Sbloom 		if (fork() == 0) {
11417843Sralph 			close(0); close(1); close(2);
11517843Sralph 			dup(s); dup(s); dup(s);
11623682Sbloom 			close(tcp_socket); close(s);
11717843Sralph 			doit(&hisctladdr);
11817843Sralph 			exit(1);
11917843Sralph 		}
12017843Sralph 		close(s);
12117843Sralph 	}
12223682Sbloom #endif BSD4_2
12323682Sbloom 
12423682Sbloom #endif	!BSDINETD
12517144Sralph }
12617843Sralph 
12717843Sralph doit(sinp)
12817843Sralph struct sockaddr_in *sinp;
12917843Sralph {
13023682Sbloom 	char user[64], passwd[64];
13117843Sralph 	char *xpasswd, *crypt();
13217843Sralph 	struct passwd *pw, *getpwnam();
13317843Sralph 
13417843Sralph 	alarm(60);
13518625Sralph 	printf("login: "); fflush(stdout);
13617843Sralph 	if (readline(user, sizeof user) < 0) {
13717843Sralph 		fprintf(stderr, "user read\n");
13817843Sralph 		return;
13917843Sralph 	}
14017843Sralph 	/* truncate username to 8 characters */
14117843Sralph 	user[8] = '\0';
14217843Sralph 	pw = getpwnam(user);
14317843Sralph 	if (pw == NULL) {
14417843Sralph 		fprintf(stderr, "user unknown\n");
14517843Sralph 		return;
14617843Sralph 	}
14738030Sbostic 	if (strcmp(pw->pw_shell, _PATH_UUCICO)) {
14817843Sralph 		fprintf(stderr, "Login incorrect.");
14917843Sralph 		return;
15017843Sralph 	}
15117843Sralph 	if (pw->pw_passwd && *pw->pw_passwd != '\0') {
15218625Sralph 		printf("Password: "); fflush(stdout);
15317843Sralph 		if (readline(passwd, sizeof passwd) < 0) {
15417843Sralph 			fprintf(stderr, "passwd read\n");
15517843Sralph 			return;
15617843Sralph 		}
15717843Sralph 		xpasswd = crypt(passwd, pw->pw_passwd);
15817843Sralph 		if (strcmp(xpasswd, pw->pw_passwd)) {
15917843Sralph 			fprintf(stderr, "Login incorrect.");
16017843Sralph 			return;
16117843Sralph 		}
16217843Sralph 	}
16317843Sralph 	alarm(0);
16423682Sbloom 	sprintf(Username, "USER=%s", user);
16517843Sralph 	dologin(pw, sinp);
16623682Sbloom 	setgid(pw->pw_gid);
16723682Sbloom #ifdef BSD4_2
16817843Sralph 	initgroups(pw->pw_name, pw->pw_gid);
16923682Sbloom #endif BSD4_2
17017843Sralph 	chdir(pw->pw_dir);
17123682Sbloom 	setuid(pw->pw_uid);
17223682Sbloom #ifdef BSD4_2
17317843Sralph 	execl(UUCICO, "uucico", (char *)0);
17423682Sbloom #endif BSD4_2
17517843Sralph 	perror("uucico server: execl");
17617843Sralph }
17717843Sralph 
17817843Sralph readline(p, n)
17918625Sralph register char *p;
18018625Sralph register int n;
18117843Sralph {
18217843Sralph 	char c;
18317843Sralph 
18417843Sralph 	while (n-- > 0) {
18517843Sralph 		if (read(0, &c, 1) <= 0)
18617843Sralph 			return(-1);
18717843Sralph 		c &= 0177;
18817843Sralph 		if (c == '\n' || c == '\r') {
18917843Sralph 			*p = '\0';
19017843Sralph 			return(0);
19117843Sralph 		}
19217843Sralph 		*p++ = c;
19317843Sralph 	}
19417843Sralph 	return(-1);
19517843Sralph }
19617843Sralph 
19717843Sralph #include <utmp.h>
19823682Sbloom #ifdef BSD4_2
19917843Sralph #include <fcntl.h>
20023682Sbloom #endif BSD4_2
20117843Sralph 
20217843Sralph #define	SCPYN(a, b)	strncpy(a, b, sizeof (a))
20317843Sralph 
20417843Sralph struct	utmp utmp;
20517843Sralph 
20617843Sralph dologout()
20717843Sralph {
20817843Sralph 	union wait status;
20917843Sralph 	int pid, wtmp;
21017843Sralph 
21117843Sralph #ifdef BSDINETD
21223682Sbloom 	while ((pid=wait(&status)) > 0) {
21317843Sralph #else  !BSDINETD
21423682Sbloom 	while ((pid=wait3(&status,WNOHANG,0)) > 0) {
21517843Sralph #endif !BSDINETD
21637931Sbostic 		wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND);
21717843Sralph 		if (wtmp >= 0) {
21817843Sralph 			sprintf(utmp.ut_line, "uucp%.4d", pid);
21917843Sralph 			SCPYN(utmp.ut_name, "");
22017843Sralph 			SCPYN(utmp.ut_host, "");
22123682Sbloom 			(void) time(&utmp.ut_time);
22217843Sralph 			(void) write(wtmp, (char *)&utmp, sizeof (utmp));
22317843Sralph 			(void) close(wtmp);
22417843Sralph 		}
22517843Sralph 	}
22617843Sralph }
22717843Sralph 
22817843Sralph /*
22917843Sralph  * Record login in wtmp file.
23017843Sralph  */
23117843Sralph dologin(pw, sin)
23217843Sralph struct passwd *pw;
23317843Sralph struct sockaddr_in *sin;
23417843Sralph {
23517843Sralph 	char line[32];
23617843Sralph 	char remotehost[32];
23717843Sralph 	int wtmp, f;
23817843Sralph 	struct hostent *hp = gethostbyaddr(&sin->sin_addr,
23917843Sralph 		sizeof (struct in_addr), AF_INET);
24017843Sralph 
24117843Sralph 	if (hp) {
24217843Sralph 		strncpy(remotehost, hp->h_name, sizeof (remotehost));
24317843Sralph 		endhostent();
24417843Sralph 	} else
24517843Sralph 		strncpy(remotehost, inet_ntoa(sin->sin_addr),
24617843Sralph 		    sizeof (remotehost));
24737931Sbostic 	wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND);
24817843Sralph 	if (wtmp >= 0) {
24917843Sralph 		/* hack, but must be unique and no tty line */
25017843Sralph 		sprintf(line, "uucp%.4d", getpid());
25117843Sralph 		SCPYN(utmp.ut_line, line);
25217843Sralph 		SCPYN(utmp.ut_name, pw->pw_name);
25317843Sralph 		SCPYN(utmp.ut_host, remotehost);
25423682Sbloom 		time(&utmp.ut_time);
25517843Sralph 		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
25617843Sralph 		(void) close(wtmp);
25717843Sralph 	}
25837931Sbostic 	if ((f = open(_PATH_LASTLOG, O_RDWR)) >= 0) {
25917843Sralph 		struct lastlog ll;
26017843Sralph 
26117843Sralph 		time(&ll.ll_time);
26217843Sralph 		lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0);
26317843Sralph 		strcpy(line, remotehost);
26417843Sralph 		SCPYN(ll.ll_line, line);
26517843Sralph 		SCPYN(ll.ll_host, remotehost);
26617843Sralph 		(void) write(f, (char *) &ll, sizeof ll);
26717843Sralph 		(void) close(f);
26817843Sralph 	}
26917843Sralph }
270