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