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