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