xref: /csrg-svn/libexec/uucpd/uucpd.c (revision 38030)
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  *
836093Sbostic  * Redistribution and use in source and binary forms are permitted
936093Sbostic  * provided that the above copyright notice and this paragraph are
1036093Sbostic  * duplicated in all such forms and that any documentation,
1136093Sbostic  * advertising materials, and other materials related to such
1236093Sbostic  * distribution and use acknowledge that the software was developed
1336093Sbostic  * by the University of California, Berkeley.  The name of the
1436093Sbostic  * University may not be used to endorse or promote products derived
1536093Sbostic  * from this software without specific prior written permission.
1636093Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1736093Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1836093Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1936093Sbostic  */
2036093Sbostic 
2117144Sralph #ifndef lint
2236093Sbostic char copyright[] =
2336093Sbostic "@(#) Copyright (c) 1985 The Regents of the University of California.\n\
2436093Sbostic  All rights reserved.\n";
2536093Sbostic #endif /* not lint */
2617144Sralph 
2736093Sbostic #ifndef lint
28*38030Sbostic static char sccsid[] = "@(#)uucpd.c	5.8 (Berkeley) 05/17/89";
2936093Sbostic #endif /* not lint */
3036093Sbostic 
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 
36*38030Sbostic #include <sys/types.h>
37*38030Sbostic #include <sys/socket.h>
38*38030Sbostic #include <sys/wait.h>
39*38030Sbostic #include <sys/ioctl.h>
40*38030Sbostic #include <sys/file.h>
41*38030Sbostic #include <netinet/in.h>
4223682Sbloom #include <netdb.h>
4317843Sralph #include <signal.h>
4417144Sralph #include <errno.h>
4517843Sralph #include <pwd.h>
46*38030Sbostic #include <stdio.h>
4737931Sbostic #include "pathnames.h"
4817144Sralph 
4917843Sralph struct	sockaddr_in hisctladdr;
5017843Sralph int hisaddrlen = sizeof hisctladdr;
5117843Sralph struct	sockaddr_in myctladdr;
5217843Sralph int mypid;
5317144Sralph 
5423682Sbloom char Username[64];
5523682Sbloom char *nenv[] = {
5623682Sbloom 	Username,
5723682Sbloom 	NULL,
5823682Sbloom };
5923682Sbloom extern char **environ;
6023682Sbloom 
6117144Sralph main(argc, argv)
6217843Sralph int argc;
6317843Sralph char **argv;
6417144Sralph {
6518625Sralph #ifndef BSDINETD
6617843Sralph 	register int s, tcp_socket;
6717843Sralph 	struct servent *sp;
6818625Sralph #endif !BSDINETD
6917843Sralph 	extern int errno;
7017843Sralph 	int dologout();
7117144Sralph 
7223682Sbloom 	environ = nenv;
7317843Sralph #ifdef BSDINETD
7417843Sralph 	close(1); close(2);
7517843Sralph 	dup(0); dup(0);
7617843Sralph 	hisaddrlen = sizeof (hisctladdr);
7717843Sralph 	if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) {
7817144Sralph 		fprintf(stderr, "%s: ", argv[0]);
7917144Sralph 		perror("getpeername");
8017144Sralph 		_exit(1);
8117144Sralph 	}
8217843Sralph 	if (fork() == 0)
8317843Sralph 		doit(&hisctladdr);
8417843Sralph 	dologout();
8517843Sralph 	exit(1);
8617843Sralph #else !BSDINETD
8717843Sralph 	sp = getservbyname("uucp", "tcp");
8817843Sralph 	if (sp == NULL){
8917843Sralph 		perror("uucpd: getservbyname");
9017843Sralph 		exit(1);
9117843Sralph 	}
9223682Sbloom 	if (fork())
9323682Sbloom 		exit(0);
9437931Sbostic 	if ((s=open(_PATH_TTY, 2)) >= 0){
9517843Sralph 		ioctl(s, TIOCNOTTY, (char *)0);
9617843Sralph 		close(s);
9717843Sralph 	}
9817144Sralph 
9917843Sralph 	bzero((char *)&myctladdr, sizeof (myctladdr));
10023682Sbloom 	myctladdr.sin_family = AF_INET;
10123682Sbloom 	myctladdr.sin_port = sp->s_port;
10223682Sbloom #ifdef BSD4_2
10323682Sbloom 	tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
10423682Sbloom 	if (tcp_socket < 0) {
10517843Sralph 		perror("uucpd: socket");
10617843Sralph 		exit(1);
10717843Sralph 	}
10823682Sbloom 	if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) {
10917843Sralph 		perror("uucpd: bind");
11017843Sralph 		exit(1);
11117843Sralph 	}
11223682Sbloom 	listen(tcp_socket, 3);	/* at most 3 simultaneuos uucp connections */
11317843Sralph 	signal(SIGCHLD, dologout);
11417843Sralph 
11517843Sralph 	for(;;) {
11617843Sralph 		s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
11717843Sralph 		if (s < 0){
11823682Sbloom 			if (errno == EINTR)
11917843Sralph 				continue;
12017843Sralph 			perror("uucpd: accept");
12117843Sralph 			exit(1);
12217843Sralph 		}
12323682Sbloom 		if (fork() == 0) {
12417843Sralph 			close(0); close(1); close(2);
12517843Sralph 			dup(s); dup(s); dup(s);
12623682Sbloom 			close(tcp_socket); close(s);
12717843Sralph 			doit(&hisctladdr);
12817843Sralph 			exit(1);
12917843Sralph 		}
13017843Sralph 		close(s);
13117843Sralph 	}
13223682Sbloom #endif BSD4_2
13323682Sbloom 
13423682Sbloom #endif	!BSDINETD
13517144Sralph }
13617843Sralph 
13717843Sralph doit(sinp)
13817843Sralph struct sockaddr_in *sinp;
13917843Sralph {
14023682Sbloom 	char user[64], passwd[64];
14117843Sralph 	char *xpasswd, *crypt();
14217843Sralph 	struct passwd *pw, *getpwnam();
14317843Sralph 
14417843Sralph 	alarm(60);
14518625Sralph 	printf("login: "); fflush(stdout);
14617843Sralph 	if (readline(user, sizeof user) < 0) {
14717843Sralph 		fprintf(stderr, "user read\n");
14817843Sralph 		return;
14917843Sralph 	}
15017843Sralph 	/* truncate username to 8 characters */
15117843Sralph 	user[8] = '\0';
15217843Sralph 	pw = getpwnam(user);
15317843Sralph 	if (pw == NULL) {
15417843Sralph 		fprintf(stderr, "user unknown\n");
15517843Sralph 		return;
15617843Sralph 	}
157*38030Sbostic 	if (strcmp(pw->pw_shell, _PATH_UUCICO)) {
15817843Sralph 		fprintf(stderr, "Login incorrect.");
15917843Sralph 		return;
16017843Sralph 	}
16117843Sralph 	if (pw->pw_passwd && *pw->pw_passwd != '\0') {
16218625Sralph 		printf("Password: "); fflush(stdout);
16317843Sralph 		if (readline(passwd, sizeof passwd) < 0) {
16417843Sralph 			fprintf(stderr, "passwd read\n");
16517843Sralph 			return;
16617843Sralph 		}
16717843Sralph 		xpasswd = crypt(passwd, pw->pw_passwd);
16817843Sralph 		if (strcmp(xpasswd, pw->pw_passwd)) {
16917843Sralph 			fprintf(stderr, "Login incorrect.");
17017843Sralph 			return;
17117843Sralph 		}
17217843Sralph 	}
17317843Sralph 	alarm(0);
17423682Sbloom 	sprintf(Username, "USER=%s", user);
17517843Sralph 	dologin(pw, sinp);
17623682Sbloom 	setgid(pw->pw_gid);
17723682Sbloom #ifdef BSD4_2
17817843Sralph 	initgroups(pw->pw_name, pw->pw_gid);
17923682Sbloom #endif BSD4_2
18017843Sralph 	chdir(pw->pw_dir);
18123682Sbloom 	setuid(pw->pw_uid);
18223682Sbloom #ifdef BSD4_2
18317843Sralph 	execl(UUCICO, "uucico", (char *)0);
18423682Sbloom #endif BSD4_2
18517843Sralph 	perror("uucico server: execl");
18617843Sralph }
18717843Sralph 
18817843Sralph readline(p, n)
18918625Sralph register char *p;
19018625Sralph register int n;
19117843Sralph {
19217843Sralph 	char c;
19317843Sralph 
19417843Sralph 	while (n-- > 0) {
19517843Sralph 		if (read(0, &c, 1) <= 0)
19617843Sralph 			return(-1);
19717843Sralph 		c &= 0177;
19817843Sralph 		if (c == '\n' || c == '\r') {
19917843Sralph 			*p = '\0';
20017843Sralph 			return(0);
20117843Sralph 		}
20217843Sralph 		*p++ = c;
20317843Sralph 	}
20417843Sralph 	return(-1);
20517843Sralph }
20617843Sralph 
20717843Sralph #include <utmp.h>
20823682Sbloom #ifdef BSD4_2
20917843Sralph #include <fcntl.h>
21023682Sbloom #endif BSD4_2
21117843Sralph 
21217843Sralph #define	SCPYN(a, b)	strncpy(a, b, sizeof (a))
21317843Sralph 
21417843Sralph struct	utmp utmp;
21517843Sralph 
21617843Sralph dologout()
21717843Sralph {
21817843Sralph 	union wait status;
21917843Sralph 	int pid, wtmp;
22017843Sralph 
22117843Sralph #ifdef BSDINETD
22223682Sbloom 	while ((pid=wait(&status)) > 0) {
22317843Sralph #else  !BSDINETD
22423682Sbloom 	while ((pid=wait3(&status,WNOHANG,0)) > 0) {
22517843Sralph #endif !BSDINETD
22637931Sbostic 		wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND);
22717843Sralph 		if (wtmp >= 0) {
22817843Sralph 			sprintf(utmp.ut_line, "uucp%.4d", pid);
22917843Sralph 			SCPYN(utmp.ut_name, "");
23017843Sralph 			SCPYN(utmp.ut_host, "");
23123682Sbloom 			(void) time(&utmp.ut_time);
23217843Sralph 			(void) write(wtmp, (char *)&utmp, sizeof (utmp));
23317843Sralph 			(void) close(wtmp);
23417843Sralph 		}
23517843Sralph 	}
23617843Sralph }
23717843Sralph 
23817843Sralph /*
23917843Sralph  * Record login in wtmp file.
24017843Sralph  */
24117843Sralph dologin(pw, sin)
24217843Sralph struct passwd *pw;
24317843Sralph struct sockaddr_in *sin;
24417843Sralph {
24517843Sralph 	char line[32];
24617843Sralph 	char remotehost[32];
24717843Sralph 	int wtmp, f;
24817843Sralph 	struct hostent *hp = gethostbyaddr(&sin->sin_addr,
24917843Sralph 		sizeof (struct in_addr), AF_INET);
25017843Sralph 
25117843Sralph 	if (hp) {
25217843Sralph 		strncpy(remotehost, hp->h_name, sizeof (remotehost));
25317843Sralph 		endhostent();
25417843Sralph 	} else
25517843Sralph 		strncpy(remotehost, inet_ntoa(sin->sin_addr),
25617843Sralph 		    sizeof (remotehost));
25737931Sbostic 	wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND);
25817843Sralph 	if (wtmp >= 0) {
25917843Sralph 		/* hack, but must be unique and no tty line */
26017843Sralph 		sprintf(line, "uucp%.4d", getpid());
26117843Sralph 		SCPYN(utmp.ut_line, line);
26217843Sralph 		SCPYN(utmp.ut_name, pw->pw_name);
26317843Sralph 		SCPYN(utmp.ut_host, remotehost);
26423682Sbloom 		time(&utmp.ut_time);
26517843Sralph 		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
26617843Sralph 		(void) close(wtmp);
26717843Sralph 	}
26837931Sbostic 	if ((f = open(_PATH_LASTLOG, O_RDWR)) >= 0) {
26917843Sralph 		struct lastlog ll;
27017843Sralph 
27117843Sralph 		time(&ll.ll_time);
27217843Sralph 		lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0);
27317843Sralph 		strcpy(line, remotehost);
27417843Sralph 		SCPYN(ll.ll_line, line);
27517843Sralph 		SCPYN(ll.ll_host, remotehost);
27617843Sralph 		(void) write(f, (char *) &ll, sizeof ll);
27717843Sralph 		(void) close(f);
27817843Sralph 	}
27917843Sralph }
280