xref: /csrg-svn/libexec/uucpd/uucpd.c (revision 17843)
117144Sralph #ifndef lint
2*17843Sralph static char sccsid[] = "@(#)uucpd.c	5.2 (Berkeley) 01/22/85";
317144Sralph #endif
417144Sralph 
517144Sralph /*
6*17843Sralph  * 4.2BSD TCP/IP server for uucico
7*17843Sralph  * uucico's TCP channel causes this server to be run at the remote end.
817144Sralph  */
917144Sralph 
10*17843Sralph #include "uucp.h"
11*17843Sralph #include <signal.h>
1217144Sralph #include <errno.h>
13*17843Sralph #include <sys/param.h>
1417144Sralph #include <sys/socket.h>
15*17843Sralph #include <sys/ioctl.h>
1617144Sralph #include <netinet/in.h>
17*17843Sralph #include <netdb.h>
18*17843Sralph #include <sys/wait.h>
19*17843Sralph #include <pwd.h>
20*17843Sralph #include <lastlog.h>
2117144Sralph 
22*17843Sralph char lastlog[] = "/usr/adm/lastlog";
23*17843Sralph struct	sockaddr_in hisctladdr;
24*17843Sralph int hisaddrlen = sizeof hisctladdr;
25*17843Sralph struct	sockaddr_in myctladdr;
26*17843Sralph int mypid;
2717144Sralph 
2817144Sralph main(argc, argv)
29*17843Sralph int argc;
30*17843Sralph char **argv;
3117144Sralph {
32*17843Sralph 	register int s, tcp_socket;
33*17843Sralph 	struct servent *sp;
34*17843Sralph 	extern int errno;
35*17843Sralph 	int dologout();
3617144Sralph 
37*17843Sralph #ifdef BSDINETD
38*17843Sralph 	close(1); close(2);
39*17843Sralph 	dup(0); dup(0);
40*17843Sralph 	hisaddrlen = sizeof (hisctladdr);
41*17843Sralph 	if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) {
4217144Sralph 		fprintf(stderr, "%s: ", argv[0]);
4317144Sralph 		perror("getpeername");
4417144Sralph 		_exit(1);
4517144Sralph 	}
46*17843Sralph 	if (fork() == 0)
47*17843Sralph 		doit(&hisctladdr);
48*17843Sralph 	dologout();
49*17843Sralph 	exit(1);
50*17843Sralph #else !BSDINETD
51*17843Sralph 	sp = getservbyname("uucp", "tcp");
52*17843Sralph 	if (sp == NULL){
53*17843Sralph 		perror("uucpd: getservbyname");
54*17843Sralph 		exit(1);
55*17843Sralph 	}
56*17843Sralph 	if ((s=open("/dev/tty", 2)) >= 0){
57*17843Sralph 		ioctl(s, TIOCNOTTY, (char *)0);
58*17843Sralph 		close(s);
59*17843Sralph 	}
6017144Sralph 
61*17843Sralph 	bzero((char *)&myctladdr, sizeof (myctladdr));
62*17843Sralph 	tcp_socket = socket(AF_INET, SOCK_STREAM, 0, 0);
63*17843Sralph 	if ( tcp_socket<0 ) {
64*17843Sralph 		perror("uucpd: socket");
65*17843Sralph 		exit(1);
66*17843Sralph 	}
67*17843Sralph 	myctladdr.sin_port = sp->s_port;
68*17843Sralph 	if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr), 0) < 0) {
69*17843Sralph 		perror("uucpd: bind");
70*17843Sralph 		exit(1);
71*17843Sralph 	}
72*17843Sralph 	signal(SIGCHLD, dologout);
73*17843Sralph 	listen(tcp_socket, 5);	/* 5's as good as any */
74*17843Sralph 
75*17843Sralph 	for(;;) {
76*17843Sralph 		s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
77*17843Sralph 		if (s < 0){
78*17843Sralph 			if (errno == EINTR)
79*17843Sralph 				continue;
80*17843Sralph 			perror("uucpd: accept");
81*17843Sralph 			exit(1);
82*17843Sralph 		}
83*17843Sralph 		if (fork()== 0) {
84*17843Sralph 			close(0); close(1); close(2);
85*17843Sralph 			dup(s); dup(s); dup(s);
86*17843Sralph 			close(tcp_socket);close(s);
87*17843Sralph 			doit(&hisctladdr);
88*17843Sralph 			exit(1);
89*17843Sralph 		}
90*17843Sralph 		close(s);
91*17843Sralph 	}
92*17843Sralph #endif
9317144Sralph }
94*17843Sralph 
95*17843Sralph doit(sinp)
96*17843Sralph struct sockaddr_in *sinp;
97*17843Sralph {
98*17843Sralph 	char ebuf[32];
99*17843Sralph 	char user[64];
100*17843Sralph 	char passwd[64];
101*17843Sralph 	char *xpasswd, *crypt();
102*17843Sralph 	struct passwd *pw, *getpwnam();
103*17843Sralph 
104*17843Sralph 	alarm(60);
105*17843Sralph 	if (readline(user, sizeof user) < 0) {
106*17843Sralph 		fprintf(stderr, "user read\n");
107*17843Sralph 		return;
108*17843Sralph 	}
109*17843Sralph 	/* truncate username to 8 characters */
110*17843Sralph 	user[8] = '\0';
111*17843Sralph 	pw = getpwnam(user);
112*17843Sralph 	if (pw == NULL) {
113*17843Sralph 		fprintf(stderr, "user unknown\n");
114*17843Sralph 		return;
115*17843Sralph 	}
116*17843Sralph 	if (strcmp(pw->pw_shell, UUCICO)) {
117*17843Sralph 		fprintf(stderr, "Login incorrect.");
118*17843Sralph 		return;
119*17843Sralph 	}
120*17843Sralph 	if (pw->pw_passwd && *pw->pw_passwd != '\0') {
121*17843Sralph 		if (readline(passwd, sizeof passwd) < 0) {
122*17843Sralph 			fprintf(stderr, "passwd read\n");
123*17843Sralph 			return;
124*17843Sralph 		}
125*17843Sralph 		xpasswd = crypt(passwd, pw->pw_passwd);
126*17843Sralph 		if (strcmp(xpasswd, pw->pw_passwd)) {
127*17843Sralph 			fprintf(stderr, "Login incorrect.");
128*17843Sralph 			return;
129*17843Sralph 		}
130*17843Sralph 	}
131*17843Sralph 	alarm(0);
132*17843Sralph 	dologin(pw, sinp);
133*17843Sralph 	setegid(pw->pw_gid);
134*17843Sralph 	initgroups(pw->pw_name, pw->pw_gid);
135*17843Sralph 	chdir(pw->pw_dir);
136*17843Sralph 	seteuid(pw->pw_uid);
137*17843Sralph 	execl(UUCICO, "uucico", (char *)0);
138*17843Sralph 	perror("uucico server: execl");
139*17843Sralph }
140*17843Sralph 
141*17843Sralph readline(p, n)
142*17843Sralph 	register char *p;
143*17843Sralph 	register int n;
144*17843Sralph {
145*17843Sralph 	char c;
146*17843Sralph 
147*17843Sralph 	while (n-- > 0) {
148*17843Sralph 		if (read(0, &c, 1) <= 0)
149*17843Sralph 			return(-1);
150*17843Sralph 		c &= 0177;
151*17843Sralph 		if (c == '\n' || c == '\r') {
152*17843Sralph 			*p = '\0';
153*17843Sralph 			return(0);
154*17843Sralph 		}
155*17843Sralph 		*p++ = c;
156*17843Sralph 	}
157*17843Sralph 	return(-1);
158*17843Sralph }
159*17843Sralph 
160*17843Sralph #include <utmp.h>
161*17843Sralph #include <fcntl.h>
162*17843Sralph 
163*17843Sralph #define	SCPYN(a, b)	strncpy(a, b, sizeof (a))
164*17843Sralph 
165*17843Sralph struct	utmp utmp;
166*17843Sralph 
167*17843Sralph dologout()
168*17843Sralph {
169*17843Sralph 	union wait status;
170*17843Sralph 	int pid, wtmp;
171*17843Sralph 
172*17843Sralph #ifdef BSDINETD
173*17843Sralph 	while ((pid=wait(&status)) > 0 ) {
174*17843Sralph #else  !BSDINETD
175*17843Sralph 	while ((pid=wait3(&status,WNOHANG,0)) > 0 ) {
176*17843Sralph #endif !BSDINETD
177*17843Sralph 		wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
178*17843Sralph 		if (wtmp >= 0) {
179*17843Sralph 			sprintf(utmp.ut_line, "uucp%.4d", pid);
180*17843Sralph 			SCPYN(utmp.ut_name, "");
181*17843Sralph 			SCPYN(utmp.ut_host, "");
182*17843Sralph 			utmp.ut_time = time(0);
183*17843Sralph 			(void) write(wtmp, (char *)&utmp, sizeof (utmp));
184*17843Sralph 			(void) close(wtmp);
185*17843Sralph 		}
186*17843Sralph 	}
187*17843Sralph }
188*17843Sralph 
189*17843Sralph /*
190*17843Sralph  * Record login in wtmp file.
191*17843Sralph  */
192*17843Sralph dologin(pw, sin)
193*17843Sralph struct passwd *pw;
194*17843Sralph struct sockaddr_in *sin;
195*17843Sralph {
196*17843Sralph 	char line[32];
197*17843Sralph 	char remotehost[32];
198*17843Sralph 	int wtmp, f;
199*17843Sralph 	struct hostent *hp = gethostbyaddr(&sin->sin_addr,
200*17843Sralph 		sizeof (struct in_addr), AF_INET);
201*17843Sralph 
202*17843Sralph 	if (hp) {
203*17843Sralph 		strncpy(remotehost, hp->h_name, sizeof (remotehost));
204*17843Sralph 		endhostent();
205*17843Sralph 	} else
206*17843Sralph 		strncpy(remotehost, inet_ntoa(sin->sin_addr),
207*17843Sralph 		    sizeof (remotehost));
208*17843Sralph 	wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
209*17843Sralph 	if (wtmp >= 0) {
210*17843Sralph 		/* hack, but must be unique and no tty line */
211*17843Sralph 		sprintf(line, "uucp%.4d", getpid());
212*17843Sralph 		SCPYN(utmp.ut_line, line);
213*17843Sralph 		SCPYN(utmp.ut_name, pw->pw_name);
214*17843Sralph 		SCPYN(utmp.ut_host, remotehost);
215*17843Sralph 		utmp.ut_time = time(0);
216*17843Sralph 		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
217*17843Sralph 		(void) close(wtmp);
218*17843Sralph 	}
219*17843Sralph 	if ((f = open(lastlog, 2)) >= 0) {
220*17843Sralph 		struct lastlog ll;
221*17843Sralph 
222*17843Sralph 		time(&ll.ll_time);
223*17843Sralph 		lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0);
224*17843Sralph 		strcpy(line, remotehost);
225*17843Sralph 		SCPYN(ll.ll_line, line);
226*17843Sralph 		SCPYN(ll.ll_host, remotehost);
227*17843Sralph 		(void) write(f, (char *) &ll, sizeof ll);
228*17843Sralph 		(void) close(f);
229*17843Sralph 	}
230*17843Sralph }
231