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
main(argc,argv)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
readline(p,n)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
dologout()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