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