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