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