Commit | Line | Data |
---|---|---|
a10a364d | 1 | #ifndef lint |
ff24c640 | 2 | static char sccsid[] = "@(#)rlogind.c 4.8 83/01/07"; |
a10a364d BJ |
3 | #endif |
4 | ||
5 | #include <stdio.h> | |
6 | #include <sys/types.h> | |
7 | #include <sys/stat.h> | |
8 | #include <sys/socket.h> | |
c6c678f1 SL |
9 | |
10 | #include <netinet/in.h> | |
11 | ||
a10a364d BJ |
12 | #include <errno.h> |
13 | #include <pwd.h> | |
14 | #include <wait.h> | |
15 | #include <signal.h> | |
16 | #include <sgtty.h> | |
17 | #include <stdio.h> | |
3f5b52bc | 18 | #include <netdb.h> |
a10a364d BJ |
19 | |
20 | extern errno; | |
21 | struct passwd *getpwnam(); | |
3f5b52bc | 22 | char *crypt(), *rindex(), *index(), *malloc(); |
a10a364d | 23 | int options = SO_ACCEPTCONN|SO_KEEPALIVE; |
3f5b52bc | 24 | struct sockaddr_in sin = { AF_INET }; |
a10a364d BJ |
25 | /* |
26 | * remote login server: | |
27 | * remuser\0 | |
28 | * locuser\0 | |
29 | * terminal type\0 | |
30 | * data | |
31 | */ | |
32 | main(argc, argv) | |
33 | int argc; | |
34 | char **argv; | |
35 | { | |
36 | union wait status; | |
37 | int f, debug = 0; | |
38 | struct sockaddr_in from; | |
3f5b52bc | 39 | struct servent *sp; |
a10a364d | 40 | |
3f5b52bc SL |
41 | sp = getservbyname("login", "tcp"); |
42 | if (sp == 0) { | |
43 | fprintf(stderr, "rlogind: tcp/rlogin: unknown service\n"); | |
44 | exit(1); | |
45 | } | |
a10a364d BJ |
46 | #ifndef DEBUG |
47 | if (fork()) | |
48 | exit(0); | |
49 | for (f = 0; f < 10; f++) | |
50 | (void) close(f); | |
51 | (void) open("/", 0); | |
52 | (void) dup2(0, 1); | |
53 | (void) dup2(0, 2); | |
54 | { int tt = open("/dev/tty", 2); | |
55 | if (tt > 0) { | |
56 | ioctl(tt, TIOCNOTTY, 0); | |
57 | close(tt); | |
58 | } | |
59 | } | |
60 | #endif | |
cb2d476f | 61 | sin.sin_port = sp->s_port; |
a10a364d | 62 | argc--, argv++; |
c6c678f1 | 63 | if (argc > 0 && !strcmp(argv[0], "-d")) { |
3f5b52bc SL |
64 | int port = atoi(argv[0]); |
65 | ||
66 | if (port < 0) { | |
67 | fprintf(stderr, "%s: bad port #\n", argv[0]); | |
68 | exit(1); | |
69 | } | |
cb2d476f | 70 | sin.sin_port = htons((u_short)port); |
3f5b52bc SL |
71 | argv++, argc--; |
72 | } | |
85b11450 | 73 | f = socket(AF_INET, SOCK_STREAM, 0, 0); |
c6c678f1 SL |
74 | if (f < 0) { |
75 | perror("rlogind: socket"); | |
76 | exit(1); | |
77 | } | |
78 | if (bind(f, &sin, sizeof (sin), 0) < 0) { | |
79 | perror("rlogind: bind"); | |
80 | exit(1); | |
81 | } | |
82 | listen(f, 10); | |
a10a364d | 83 | for (;;) { |
c6c678f1 SL |
84 | int s, len = sizeof (from); |
85 | ||
86 | s = accept(f, &from, &len, 0); | |
87 | if (s < 0) { | |
82c973f2 | 88 | perror("rlogind: accept"); |
a10a364d BJ |
89 | sleep(1); |
90 | continue; | |
91 | } | |
92 | if (fork() == 0) | |
c6c678f1 SL |
93 | doit(s, &from); |
94 | close(s); | |
a10a364d BJ |
95 | while (wait3(status, WNOHANG, 0) > 0) |
96 | continue; | |
97 | } | |
98 | } | |
99 | ||
100 | char locuser[32], remuser[32]; | |
101 | char buf[BUFSIZ]; | |
102 | int child; | |
103 | int cleanup(); | |
104 | int netf; | |
105 | extern errno; | |
106 | char *line; | |
107 | ||
108 | doit(f, fromp) | |
109 | int f; | |
110 | struct sockaddr_in *fromp; | |
111 | { | |
3f5b52bc | 112 | char c; |
82c973f2 | 113 | int i, p, cc, t, pid; |
a10a364d | 114 | int stop = TIOCPKT_DOSTOP; |
3f5b52bc | 115 | register struct hostent *hp; |
a10a364d BJ |
116 | |
117 | alarm(60); | |
118 | read(f, &c, 1); | |
119 | if (c != 0) | |
120 | exit(1); | |
121 | alarm(0); | |
cb2d476f | 122 | fromp->sin_port = htons((u_short)fromp->sin_port); |
3f5b52bc SL |
123 | hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), |
124 | fromp->sin_family); | |
82c973f2 SL |
125 | if (hp == 0) |
126 | fatal(f, "Host name for your address unknown"); | |
a10a364d BJ |
127 | if (fromp->sin_family != AF_INET || |
128 | fromp->sin_port >= IPPORT_RESERVED || | |
82c973f2 SL |
129 | hp == 0) |
130 | fatal(f, "Permission denied"); | |
a10a364d BJ |
131 | write(f, "", 1); |
132 | for (c = 'p'; c <= 's'; c++) { | |
133 | struct stat stb; | |
134 | line = "/dev/ptyXX"; | |
135 | line[strlen("/dev/pty")] = c; | |
136 | line[strlen("/dev/ptyp")] = '0'; | |
137 | if (stat(line, &stb) < 0) | |
138 | break; | |
139 | for (i = 0; i < 16; i++) { | |
140 | line[strlen("/dev/ptyp")] = "0123456789abcdef"[i]; | |
141 | p = open(line, 2); | |
142 | if (p > 0) | |
143 | goto gotpty; | |
144 | } | |
145 | } | |
82c973f2 SL |
146 | fatal(f, "All network ports in use"); |
147 | /*NOTREACHED*/ | |
a10a364d BJ |
148 | gotpty: |
149 | dup2(f, 0); | |
150 | line[strlen("/dev/")] = 't'; | |
151 | #ifdef DEBUG | |
152 | { int tt = open("/dev/tty", 2); | |
153 | if (tt > 0) { | |
154 | ioctl(tt, TIOCNOTTY, 0); | |
155 | close(tt); | |
156 | } | |
157 | } | |
158 | #endif | |
159 | t = open(line, 2); | |
82c973f2 SL |
160 | if (t < 0) |
161 | fatalperror(f, line, errno); | |
a10a364d BJ |
162 | { struct sgttyb b; |
163 | gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b); | |
164 | } | |
82c973f2 SL |
165 | pid = fork(); |
166 | if (pid < 0) | |
167 | fatalperror(f, "", errno); | |
168 | if (pid) { | |
a10a364d BJ |
169 | char pibuf[1024], fibuf[1024], *pbp, *fbp; |
170 | int pcc = 0, fcc = 0, on = 1; | |
171 | /* FILE *console = fopen("/dev/console", "w"); */ | |
172 | /* setbuf(console, 0); */ | |
173 | ||
174 | /* fprintf(console, "f %d p %d\r\n", f, p); */ | |
175 | ioctl(f, FIONBIO, &on); | |
176 | ioctl(p, FIONBIO, &on); | |
177 | ioctl(p, TIOCPKT, &on); | |
178 | signal(SIGTSTP, SIG_IGN); | |
179 | sigset(SIGCHLD, cleanup); | |
180 | for (;;) { | |
181 | int ibits = 0, obits = 0; | |
82c973f2 SL |
182 | |
183 | if (fcc) | |
184 | obits |= (1<<p); | |
185 | else | |
186 | ibits |= (1<<f); | |
a10a364d | 187 | if (pcc >= 0) |
82c973f2 SL |
188 | if (pcc) |
189 | obits |= (1<<f); | |
190 | else | |
191 | ibits |= (1<<p); | |
192 | if (fcc < 0 && pcc < 0) | |
193 | break; | |
a10a364d | 194 | /* fprintf(console, "ibits from %d obits from %d\r\n", ibits, obits); */ |
c6c678f1 | 195 | select(16, &ibits, &obits, 0, 0, 0); |
a10a364d BJ |
196 | /* fprintf(console, "ibits %d obits %d\r\n", ibits, obits); */ |
197 | if (ibits == 0 && obits == 0) { | |
198 | sleep(5); | |
199 | continue; | |
200 | } | |
201 | if (ibits & (1<<f)) { | |
202 | fcc = read(f, fibuf, sizeof (fibuf)); | |
203 | /* fprintf(console, "%d from f\r\n", fcc); */ | |
204 | if (fcc < 0 && errno == EWOULDBLOCK) | |
205 | fcc = 0; | |
206 | else { | |
207 | if (fcc <= 0) | |
208 | break; | |
209 | fbp = fibuf; | |
210 | } | |
211 | } | |
212 | if (ibits & (1<<p)) { | |
213 | pcc = read(p, pibuf, sizeof (pibuf)); | |
214 | /* fprintf(console, "%d from p, buf[0] %x, errno %d\r\n", pcc, buf[0], errno); */ | |
215 | pbp = pibuf; | |
216 | if (pcc < 0 && errno == EWOULDBLOCK) | |
217 | pcc = 0; | |
218 | else if (pcc <= 0) | |
219 | pcc = -1; | |
220 | else if (pibuf[0] == 0) | |
221 | pbp++, pcc--; | |
222 | else { | |
223 | if (pibuf[0]&(TIOCPKT_FLUSHWRITE| | |
224 | TIOCPKT_NOSTOP| | |
225 | TIOCPKT_DOSTOP)) { | |
226 | int nstop = pibuf[0] & | |
227 | (TIOCPKT_NOSTOP| | |
228 | TIOCPKT_DOSTOP); | |
229 | if (nstop) | |
230 | stop = nstop; | |
231 | pibuf[0] |= nstop; | |
c6c678f1 | 232 | send(f,&pibuf[0],1,SOF_OOB); |
a10a364d BJ |
233 | } |
234 | pcc = 0; | |
235 | } | |
236 | } | |
237 | if ((obits & (1<<f)) && pcc > 0) { | |
238 | cc = write(f, pbp, pcc); | |
239 | /* fprintf(console, "%d of %d to f\r\n", cc, pcc); */ | |
240 | if (cc > 0) { | |
241 | pcc -= cc; | |
242 | pbp += cc; | |
243 | } | |
244 | } | |
245 | if ((obits & (1<<p)) && fcc > 0) { | |
246 | cc = write(p, fbp, fcc); | |
247 | /* fprintf(console, "%d of %d to p\r\n", cc, fcc); */ | |
248 | if (cc > 0) { | |
249 | fcc -= cc; | |
250 | fbp += cc; | |
251 | } | |
252 | } | |
253 | } | |
254 | cleanup(); | |
255 | } | |
256 | close(f); | |
257 | close(p); | |
258 | dup2(t, 0); | |
259 | dup2(t, 1); | |
260 | dup2(t, 2); | |
261 | close(t); | |
3f5b52bc | 262 | execl("/bin/login", "login", "-r", hp->h_name, 0); |
82c973f2 SL |
263 | fatalperror(2, "/bin/login", errno); |
264 | /*NOTREACHED*/ | |
a10a364d BJ |
265 | } |
266 | ||
267 | cleanup() | |
268 | { | |
a10a364d BJ |
269 | |
270 | rmut(); | |
dd83e8ac | 271 | vhangup(); /* XXX */ |
ff24c640 | 272 | shutdown(netf, 2); |
a10a364d BJ |
273 | kill(0, SIGKILL); |
274 | exit(1); | |
275 | } | |
276 | ||
82c973f2 SL |
277 | fatal(f, msg) |
278 | int f; | |
279 | char *msg; | |
280 | { | |
281 | char buf[BUFSIZ]; | |
282 | ||
283 | buf[0] = '\01'; /* error indicator */ | |
284 | (void) sprintf(buf + 1, "rlogind: %s.\n", msg); | |
285 | (void) write(f, buf, strlen(buf)); | |
286 | exit(1); | |
287 | } | |
288 | ||
289 | fatalperror(f, msg, errno) | |
290 | int f; | |
291 | char *msg; | |
292 | int errno; | |
293 | { | |
294 | char buf[BUFSIZ]; | |
295 | extern char *sys_errlist[]; | |
296 | ||
297 | (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); | |
298 | fatal(f, buf); | |
299 | } | |
300 | ||
a10a364d BJ |
301 | #include <utmp.h> |
302 | ||
303 | struct utmp wtmp; | |
304 | char wtmpf[] = "/usr/adm/wtmp"; | |
305 | char utmp[] = "/etc/utmp"; | |
306 | #define SCPYN(a, b) strncpy(a, b, sizeof(a)) | |
307 | #define SCMPN(a, b) strncmp(a, b, sizeof(a)) | |
308 | ||
309 | rmut() | |
310 | { | |
311 | register f; | |
312 | int found = 0; | |
313 | ||
314 | f = open(utmp, 2); | |
315 | if (f >= 0) { | |
316 | while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { | |
317 | if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0) | |
318 | continue; | |
319 | lseek(f, -(long)sizeof(wtmp), 1); | |
320 | SCPYN(wtmp.ut_name, ""); | |
321 | time(&wtmp.ut_time); | |
322 | write(f, (char *)&wtmp, sizeof(wtmp)); | |
323 | found++; | |
324 | } | |
325 | close(f); | |
326 | } | |
327 | if (found) { | |
328 | f = open(wtmpf, 1); | |
329 | if (f >= 0) { | |
330 | SCPYN(wtmp.ut_line, line+5); | |
331 | SCPYN(wtmp.ut_name, ""); | |
332 | time(&wtmp.ut_time); | |
333 | lseek(f, (long)0, 2); | |
334 | write(f, (char *)&wtmp, sizeof(wtmp)); | |
335 | close(f); | |
336 | } | |
337 | } | |
338 | chmod(line, 0666); | |
339 | chown(line, 0, 0); | |
340 | line[strlen("/dev/")] = 'p'; | |
341 | chmod(line, 0666); | |
342 | chown(line, 0, 0); | |
343 | } |