xref: /csrg-svn/libexec/uucpd/uucpd.c (revision 37931)
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*37931Sbostic static char sccsid[] = "@(#)uucpd.c	5.7 (Berkeley) 05/11/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 
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>
45*37931Sbostic #include "pathnames.h"
4617144Sralph 
4717843Sralph struct	sockaddr_in hisctladdr;
4817843Sralph int hisaddrlen = sizeof hisctladdr;
4917843Sralph struct	sockaddr_in myctladdr;
5017843Sralph int mypid;
5117144Sralph 
5223682Sbloom char Username[64];
5323682Sbloom char *nenv[] = {
5423682Sbloom 	Username,
5523682Sbloom 	NULL,
5623682Sbloom };
5723682Sbloom extern char **environ;
5823682Sbloom 
5917144Sralph main(argc, argv)
6017843Sralph int argc;
6117843Sralph char **argv;
6217144Sralph {
6318625Sralph #ifndef BSDINETD
6417843Sralph 	register int s, tcp_socket;
6517843Sralph 	struct servent *sp;
6618625Sralph #endif !BSDINETD
6717843Sralph 	extern int errno;
6817843Sralph 	int dologout();
6917144Sralph 
7023682Sbloom 	environ = nenv;
7117843Sralph #ifdef BSDINETD
7217843Sralph 	close(1); close(2);
7317843Sralph 	dup(0); dup(0);
7417843Sralph 	hisaddrlen = sizeof (hisctladdr);
7517843Sralph 	if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) {
7617144Sralph 		fprintf(stderr, "%s: ", argv[0]);
7717144Sralph 		perror("getpeername");
7817144Sralph 		_exit(1);
7917144Sralph 	}
8017843Sralph 	if (fork() == 0)
8117843Sralph 		doit(&hisctladdr);
8217843Sralph 	dologout();
8317843Sralph 	exit(1);
8417843Sralph #else !BSDINETD
8517843Sralph 	sp = getservbyname("uucp", "tcp");
8617843Sralph 	if (sp == NULL){
8717843Sralph 		perror("uucpd: getservbyname");
8817843Sralph 		exit(1);
8917843Sralph 	}
9023682Sbloom 	if (fork())
9123682Sbloom 		exit(0);
92*37931Sbostic 	if ((s=open(_PATH_TTY, 2)) >= 0){
9317843Sralph 		ioctl(s, TIOCNOTTY, (char *)0);
9417843Sralph 		close(s);
9517843Sralph 	}
9617144Sralph 
9717843Sralph 	bzero((char *)&myctladdr, sizeof (myctladdr));
9823682Sbloom 	myctladdr.sin_family = AF_INET;
9923682Sbloom 	myctladdr.sin_port = sp->s_port;
10023682Sbloom #ifdef BSD4_2
10123682Sbloom 	tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
10223682Sbloom 	if (tcp_socket < 0) {
10317843Sralph 		perror("uucpd: socket");
10417843Sralph 		exit(1);
10517843Sralph 	}
10623682Sbloom 	if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) {
10717843Sralph 		perror("uucpd: bind");
10817843Sralph 		exit(1);
10917843Sralph 	}
11023682Sbloom 	listen(tcp_socket, 3);	/* at most 3 simultaneuos uucp connections */
11117843Sralph 	signal(SIGCHLD, dologout);
11217843Sralph 
11317843Sralph 	for(;;) {
11417843Sralph 		s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
11517843Sralph 		if (s < 0){
11623682Sbloom 			if (errno == EINTR)
11717843Sralph 				continue;
11817843Sralph 			perror("uucpd: accept");
11917843Sralph 			exit(1);
12017843Sralph 		}
12123682Sbloom 		if (fork() == 0) {
12217843Sralph 			close(0); close(1); close(2);
12317843Sralph 			dup(s); dup(s); dup(s);
12423682Sbloom 			close(tcp_socket); close(s);
12517843Sralph 			doit(&hisctladdr);
12617843Sralph 			exit(1);
12717843Sralph 		}
12817843Sralph 		close(s);
12917843Sralph 	}
13023682Sbloom #endif BSD4_2
13123682Sbloom 
13223682Sbloom #endif	!BSDINETD
13317144Sralph }
13417843Sralph 
13517843Sralph doit(sinp)
13617843Sralph struct sockaddr_in *sinp;
13717843Sralph {
13823682Sbloom 	char user[64], passwd[64];
13917843Sralph 	char *xpasswd, *crypt();
14017843Sralph 	struct passwd *pw, *getpwnam();
14117843Sralph 
14217843Sralph 	alarm(60);
14318625Sralph 	printf("login: "); fflush(stdout);
14417843Sralph 	if (readline(user, sizeof user) < 0) {
14517843Sralph 		fprintf(stderr, "user read\n");
14617843Sralph 		return;
14717843Sralph 	}
14817843Sralph 	/* truncate username to 8 characters */
14917843Sralph 	user[8] = '\0';
15017843Sralph 	pw = getpwnam(user);
15117843Sralph 	if (pw == NULL) {
15217843Sralph 		fprintf(stderr, "user unknown\n");
15317843Sralph 		return;
15417843Sralph 	}
15517843Sralph 	if (strcmp(pw->pw_shell, UUCICO)) {
15617843Sralph 		fprintf(stderr, "Login incorrect.");
15717843Sralph 		return;
15817843Sralph 	}
15917843Sralph 	if (pw->pw_passwd && *pw->pw_passwd != '\0') {
16018625Sralph 		printf("Password: "); fflush(stdout);
16117843Sralph 		if (readline(passwd, sizeof passwd) < 0) {
16217843Sralph 			fprintf(stderr, "passwd read\n");
16317843Sralph 			return;
16417843Sralph 		}
16517843Sralph 		xpasswd = crypt(passwd, pw->pw_passwd);
16617843Sralph 		if (strcmp(xpasswd, pw->pw_passwd)) {
16717843Sralph 			fprintf(stderr, "Login incorrect.");
16817843Sralph 			return;
16917843Sralph 		}
17017843Sralph 	}
17117843Sralph 	alarm(0);
17223682Sbloom 	sprintf(Username, "USER=%s", user);
17317843Sralph 	dologin(pw, sinp);
17423682Sbloom 	setgid(pw->pw_gid);
17523682Sbloom #ifdef BSD4_2
17617843Sralph 	initgroups(pw->pw_name, pw->pw_gid);
17723682Sbloom #endif BSD4_2
17817843Sralph 	chdir(pw->pw_dir);
17923682Sbloom 	setuid(pw->pw_uid);
18023682Sbloom #ifdef BSD4_2
18117843Sralph 	execl(UUCICO, "uucico", (char *)0);
18223682Sbloom #endif BSD4_2
18317843Sralph 	perror("uucico server: execl");
18417843Sralph }
18517843Sralph 
18617843Sralph readline(p, n)
18718625Sralph register char *p;
18818625Sralph register int n;
18917843Sralph {
19017843Sralph 	char c;
19117843Sralph 
19217843Sralph 	while (n-- > 0) {
19317843Sralph 		if (read(0, &c, 1) <= 0)
19417843Sralph 			return(-1);
19517843Sralph 		c &= 0177;
19617843Sralph 		if (c == '\n' || c == '\r') {
19717843Sralph 			*p = '\0';
19817843Sralph 			return(0);
19917843Sralph 		}
20017843Sralph 		*p++ = c;
20117843Sralph 	}
20217843Sralph 	return(-1);
20317843Sralph }
20417843Sralph 
20517843Sralph #include <utmp.h>
20623682Sbloom #ifdef BSD4_2
20717843Sralph #include <fcntl.h>
20823682Sbloom #endif BSD4_2
20917843Sralph 
21017843Sralph #define	SCPYN(a, b)	strncpy(a, b, sizeof (a))
21117843Sralph 
21217843Sralph struct	utmp utmp;
21317843Sralph 
21417843Sralph dologout()
21517843Sralph {
21617843Sralph 	union wait status;
21717843Sralph 	int pid, wtmp;
21817843Sralph 
21917843Sralph #ifdef BSDINETD
22023682Sbloom 	while ((pid=wait(&status)) > 0) {
22117843Sralph #else  !BSDINETD
22223682Sbloom 	while ((pid=wait3(&status,WNOHANG,0)) > 0) {
22317843Sralph #endif !BSDINETD
224*37931Sbostic 		wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND);
22517843Sralph 		if (wtmp >= 0) {
22617843Sralph 			sprintf(utmp.ut_line, "uucp%.4d", pid);
22717843Sralph 			SCPYN(utmp.ut_name, "");
22817843Sralph 			SCPYN(utmp.ut_host, "");
22923682Sbloom 			(void) time(&utmp.ut_time);
23017843Sralph 			(void) write(wtmp, (char *)&utmp, sizeof (utmp));
23117843Sralph 			(void) close(wtmp);
23217843Sralph 		}
23317843Sralph 	}
23417843Sralph }
23517843Sralph 
23617843Sralph /*
23717843Sralph  * Record login in wtmp file.
23817843Sralph  */
23917843Sralph dologin(pw, sin)
24017843Sralph struct passwd *pw;
24117843Sralph struct sockaddr_in *sin;
24217843Sralph {
24317843Sralph 	char line[32];
24417843Sralph 	char remotehost[32];
24517843Sralph 	int wtmp, f;
24617843Sralph 	struct hostent *hp = gethostbyaddr(&sin->sin_addr,
24717843Sralph 		sizeof (struct in_addr), AF_INET);
24817843Sralph 
24917843Sralph 	if (hp) {
25017843Sralph 		strncpy(remotehost, hp->h_name, sizeof (remotehost));
25117843Sralph 		endhostent();
25217843Sralph 	} else
25317843Sralph 		strncpy(remotehost, inet_ntoa(sin->sin_addr),
25417843Sralph 		    sizeof (remotehost));
255*37931Sbostic 	wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND);
25617843Sralph 	if (wtmp >= 0) {
25717843Sralph 		/* hack, but must be unique and no tty line */
25817843Sralph 		sprintf(line, "uucp%.4d", getpid());
25917843Sralph 		SCPYN(utmp.ut_line, line);
26017843Sralph 		SCPYN(utmp.ut_name, pw->pw_name);
26117843Sralph 		SCPYN(utmp.ut_host, remotehost);
26223682Sbloom 		time(&utmp.ut_time);
26317843Sralph 		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
26417843Sralph 		(void) close(wtmp);
26517843Sralph 	}
266*37931Sbostic 	if ((f = open(_PATH_LASTLOG, O_RDWR)) >= 0) {
26717843Sralph 		struct lastlog ll;
26817843Sralph 
26917843Sralph 		time(&ll.ll_time);
27017843Sralph 		lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0);
27117843Sralph 		strcpy(line, remotehost);
27217843Sralph 		SCPYN(ll.ll_line, line);
27317843Sralph 		SCPYN(ll.ll_host, remotehost);
27417843Sralph 		(void) write(f, (char *) &ll, sizeof ll);
27517843Sralph 		(void) close(f);
27617843Sralph 	}
27717843Sralph }
278