xref: /original-bsd/libexec/uucpd/uucpd.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1985, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Adams.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char copyright[] =
13 "@(#) Copyright (c) 1985, 1993\n\
14 	The Regents of the University of California.  All rights reserved.\n";
15 #endif /* not lint */
16 
17 #ifndef lint
18 static char sccsid[] = "@(#)uucpd.c	8.1 (Berkeley) 06/04/93";
19 #endif /* not lint */
20 
21 /*
22  * 4.2BSD TCP/IP server for uucico
23  * uucico's TCP channel causes this server to be run at the remote end.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <sys/ioctl.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #include <netdb.h>
33 #include <signal.h>
34 #include <fcntl.h>
35 #include <time.h>
36 #include <pwd.h>
37 #include <unistd.h>
38 #include <errno.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include "pathnames.h"
43 
44 struct	sockaddr_in hisctladdr;
45 int hisaddrlen = sizeof hisctladdr;
46 struct	sockaddr_in myctladdr;
47 int mypid;
48 
49 char Username[64];
50 char *nenv[] = {
51 	Username,
52 	NULL,
53 };
54 extern char **environ;
55 
56 main(argc, argv)
57 int argc;
58 char **argv;
59 {
60 #ifndef BSDINETD
61 	register int s, tcp_socket;
62 	struct servent *sp;
63 #endif !BSDINETD
64 	extern int errno;
65 	int dologout();
66 
67 	environ = nenv;
68 #ifdef BSDINETD
69 	close(1); close(2);
70 	dup(0); dup(0);
71 	hisaddrlen = sizeof (hisctladdr);
72 	if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) {
73 		fprintf(stderr, "%s: ", argv[0]);
74 		perror("getpeername");
75 		_exit(1);
76 	}
77 	if (fork() == 0)
78 		doit(&hisctladdr);
79 	dologout();
80 	exit(1);
81 #else !BSDINETD
82 	sp = getservbyname("uucp", "tcp");
83 	if (sp == NULL){
84 		perror("uucpd: getservbyname");
85 		exit(1);
86 	}
87 	if (fork())
88 		exit(0);
89 	if ((s=open(_PATH_TTY, 2)) >= 0){
90 		ioctl(s, TIOCNOTTY, (char *)0);
91 		close(s);
92 	}
93 
94 	bzero((char *)&myctladdr, sizeof (myctladdr));
95 	myctladdr.sin_family = AF_INET;
96 	myctladdr.sin_port = sp->s_port;
97 #ifdef BSD4_2
98 	tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
99 	if (tcp_socket < 0) {
100 		perror("uucpd: socket");
101 		exit(1);
102 	}
103 	if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) {
104 		perror("uucpd: bind");
105 		exit(1);
106 	}
107 	listen(tcp_socket, 3);	/* at most 3 simultaneuos uucp connections */
108 	signal(SIGCHLD, dologout);
109 
110 	for(;;) {
111 		s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
112 		if (s < 0){
113 			if (errno == EINTR)
114 				continue;
115 			perror("uucpd: accept");
116 			exit(1);
117 		}
118 		if (fork() == 0) {
119 			close(0); close(1); close(2);
120 			dup(s); dup(s); dup(s);
121 			close(tcp_socket); close(s);
122 			doit(&hisctladdr);
123 			exit(1);
124 		}
125 		close(s);
126 	}
127 #endif BSD4_2
128 
129 #endif	!BSDINETD
130 }
131 
132 doit(sinp)
133 struct sockaddr_in *sinp;
134 {
135 	char user[64], passwd[64];
136 	char *xpasswd, *crypt();
137 	struct passwd *pw, *getpwnam();
138 
139 	alarm(60);
140 	printf("login: "); fflush(stdout);
141 	if (readline(user, sizeof user) < 0) {
142 		fprintf(stderr, "user read\n");
143 		return;
144 	}
145 	/* truncate username to 8 characters */
146 	user[8] = '\0';
147 	pw = getpwnam(user);
148 	if (pw == NULL) {
149 		fprintf(stderr, "user unknown\n");
150 		return;
151 	}
152 	if (strcmp(pw->pw_shell, _PATH_UUCICO)) {
153 		fprintf(stderr, "Login incorrect.");
154 		return;
155 	}
156 	if (pw->pw_passwd && *pw->pw_passwd != '\0') {
157 		printf("Password: "); fflush(stdout);
158 		if (readline(passwd, sizeof passwd) < 0) {
159 			fprintf(stderr, "passwd read\n");
160 			return;
161 		}
162 		xpasswd = crypt(passwd, pw->pw_passwd);
163 		if (strcmp(xpasswd, pw->pw_passwd)) {
164 			fprintf(stderr, "Login incorrect.");
165 			return;
166 		}
167 	}
168 	alarm(0);
169 	sprintf(Username, "USER=%s", user);
170 	dologin(pw, sinp);
171 	setgid(pw->pw_gid);
172 #ifdef BSD4_2
173 	initgroups(pw->pw_name, pw->pw_gid);
174 #endif BSD4_2
175 	chdir(pw->pw_dir);
176 	setuid(pw->pw_uid);
177 #ifdef BSD4_2
178 	execl(UUCICO, "uucico", (char *)0);
179 #endif BSD4_2
180 	perror("uucico server: execl");
181 }
182 
183 readline(p, n)
184 register char *p;
185 register int n;
186 {
187 	char c;
188 
189 	while (n-- > 0) {
190 		if (read(0, &c, 1) <= 0)
191 			return(-1);
192 		c &= 0177;
193 		if (c == '\n' || c == '\r') {
194 			*p = '\0';
195 			return(0);
196 		}
197 		*p++ = c;
198 	}
199 	return(-1);
200 }
201 
202 #include <utmp.h>
203 #ifdef BSD4_2
204 #include <fcntl.h>
205 #endif BSD4_2
206 
207 #define	SCPYN(a, b)	strncpy(a, b, sizeof (a))
208 
209 struct	utmp utmp;
210 
211 dologout()
212 {
213 	union wait status;
214 	int pid, wtmp;
215 
216 #ifdef BSDINETD
217 	while ((pid=wait((int *)&status)) > 0) {
218 #else  !BSDINETD
219 	while ((pid=wait3((int *)&status,WNOHANG,0)) > 0) {
220 #endif !BSDINETD
221 		wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND);
222 		if (wtmp >= 0) {
223 			sprintf(utmp.ut_line, "uucp%.4d", pid);
224 			SCPYN(utmp.ut_name, "");
225 			SCPYN(utmp.ut_host, "");
226 			(void) time(&utmp.ut_time);
227 			(void) write(wtmp, (char *)&utmp, sizeof (utmp));
228 			(void) close(wtmp);
229 		}
230 	}
231 }
232 
233 /*
234  * Record login in wtmp file.
235  */
236 dologin(pw, sin)
237 struct passwd *pw;
238 struct sockaddr_in *sin;
239 {
240 	char line[32];
241 	char remotehost[32];
242 	int wtmp, f;
243 	struct hostent *hp = gethostbyaddr((char *)&sin->sin_addr,
244 		sizeof (struct in_addr), AF_INET);
245 
246 	if (hp) {
247 		strncpy(remotehost, hp->h_name, sizeof (remotehost));
248 		endhostent();
249 	} else
250 		strncpy(remotehost, inet_ntoa(sin->sin_addr),
251 		    sizeof (remotehost));
252 	wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND);
253 	if (wtmp >= 0) {
254 		/* hack, but must be unique and no tty line */
255 		sprintf(line, "uucp%.4d", getpid());
256 		SCPYN(utmp.ut_line, line);
257 		SCPYN(utmp.ut_name, pw->pw_name);
258 		SCPYN(utmp.ut_host, remotehost);
259 		time(&utmp.ut_time);
260 		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
261 		(void) close(wtmp);
262 	}
263 	if ((f = open(_PATH_LASTLOG, O_RDWR)) >= 0) {
264 		struct lastlog ll;
265 
266 		time(&ll.ll_time);
267 		lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0);
268 		strcpy(line, remotehost);
269 		SCPYN(ll.ll_line, line);
270 		SCPYN(ll.ll_host, remotehost);
271 		(void) write(f, (char *) &ll, sizeof ll);
272 		(void) close(f);
273 	}
274 }
275