16446Swnj #ifndef lint 2*9208Ssam static char sccsid[] = "@(#)rlogind.c 4.3 82/11/14"; 36446Swnj #endif 46446Swnj 56446Swnj #include <stdio.h> 66446Swnj #include <sys/types.h> 76446Swnj #include <sys/stat.h> 86446Swnj #include <sys/socket.h> 9*9208Ssam 10*9208Ssam #include <netinet/in.h> 11*9208Ssam 126446Swnj #include <errno.h> 136446Swnj #include <pwd.h> 146446Swnj #include <wait.h> 156446Swnj #include <signal.h> 166446Swnj #include <sgtty.h> 176446Swnj #include <stdio.h> 188380Ssam #include <netdb.h> 196446Swnj 206446Swnj extern errno; 216446Swnj struct passwd *getpwnam(); 228380Ssam char *crypt(), *rindex(), *index(), *malloc(); 236446Swnj int options = SO_ACCEPTCONN|SO_KEEPALIVE; 248380Ssam struct sockaddr_in sin = { AF_INET }; 256446Swnj /* 266446Swnj * remote login server: 276446Swnj * remuser\0 286446Swnj * locuser\0 296446Swnj * terminal type\0 306446Swnj * data 316446Swnj */ 326446Swnj main(argc, argv) 336446Swnj int argc; 346446Swnj char **argv; 356446Swnj { 366446Swnj union wait status; 376446Swnj int f, debug = 0; 386446Swnj struct sockaddr_in from; 398380Ssam struct servent *sp; 406446Swnj 418380Ssam sp = getservbyname("login", "tcp"); 428380Ssam if (sp == 0) { 438380Ssam fprintf(stderr, "rlogind: tcp/rlogin: unknown service\n"); 448380Ssam exit(1); 458380Ssam } 466446Swnj #ifndef DEBUG 476446Swnj if (fork()) 486446Swnj exit(0); 496446Swnj for (f = 0; f < 10; f++) 506446Swnj (void) close(f); 516446Swnj (void) open("/", 0); 526446Swnj (void) dup2(0, 1); 536446Swnj (void) dup2(0, 2); 546446Swnj { int tt = open("/dev/tty", 2); 556446Swnj if (tt > 0) { 566446Swnj ioctl(tt, TIOCNOTTY, 0); 576446Swnj close(tt); 586446Swnj } 596446Swnj } 606446Swnj #endif 618380Ssam sin.sin_port = htons(sp->s_port); 626446Swnj argc--, argv++; 63*9208Ssam if (argc > 0 && !strcmp(argv[0], "-d")) { 648380Ssam int port = atoi(argv[0]); 658380Ssam 668380Ssam if (port < 0) { 678380Ssam fprintf(stderr, "%s: bad port #\n", argv[0]); 688380Ssam exit(1); 698380Ssam } 708380Ssam sin.sin_port = htons(port); 718380Ssam argv++, argc--; 728380Ssam } 73*9208Ssam f = socket(0, SOCK_STREAM, 0, 0); 74*9208Ssam if (f < 0) { 75*9208Ssam perror("rlogind: socket"); 76*9208Ssam exit(1); 77*9208Ssam } 78*9208Ssam if (bind(f, &sin, sizeof (sin), 0) < 0) { 79*9208Ssam perror("rlogind: bind"); 80*9208Ssam exit(1); 81*9208Ssam } 82*9208Ssam listen(f, 10); 836446Swnj for (;;) { 84*9208Ssam int s, len = sizeof (from); 85*9208Ssam 86*9208Ssam s = accept(f, &from, &len, 0); 87*9208Ssam if (s < 0) { 886446Swnj perror("accept"); 896446Swnj sleep(1); 906446Swnj continue; 916446Swnj } 926446Swnj if (fork() == 0) 93*9208Ssam doit(s, &from); 94*9208Ssam close(s); 956446Swnj while (wait3(status, WNOHANG, 0) > 0) 966446Swnj continue; 976446Swnj } 986446Swnj } 996446Swnj 1006446Swnj char locuser[32], remuser[32]; 1016446Swnj char buf[BUFSIZ]; 1026446Swnj int child; 1036446Swnj int cleanup(); 1046446Swnj int netf; 1056446Swnj extern errno; 1066446Swnj char *line; 1076446Swnj 1086446Swnj doit(f, fromp) 1096446Swnj int f; 1106446Swnj struct sockaddr_in *fromp; 1116446Swnj { 1128380Ssam char c; 1136446Swnj int i, p, cc, t; 1146446Swnj int stop = TIOCPKT_DOSTOP; 1158380Ssam register struct hostent *hp; 1166446Swnj 1176446Swnj alarm(60); 1186446Swnj read(f, &c, 1); 1196446Swnj if (c != 0) 1206446Swnj exit(1); 1216446Swnj alarm(0); 1226446Swnj fromp->sin_port = htons(fromp->sin_port); 1238380Ssam hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), 1248380Ssam fromp->sin_family); 1256446Swnj if (fromp->sin_family != AF_INET || 1266446Swnj fromp->sin_port >= IPPORT_RESERVED || 1278380Ssam hp == 0) { 1286446Swnj write(f, "\01Permission denied.\n", 20); 1296446Swnj exit(1); 1306446Swnj } 1316446Swnj write(f, "", 1); 1326446Swnj for (c = 'p'; c <= 's'; c++) { 1336446Swnj struct stat stb; 1346446Swnj line = "/dev/ptyXX"; 1356446Swnj line[strlen("/dev/pty")] = c; 1366446Swnj line[strlen("/dev/ptyp")] = '0'; 1376446Swnj if (stat(line, &stb) < 0) 1386446Swnj break; 1396446Swnj for (i = 0; i < 16; i++) { 1406446Swnj line[strlen("/dev/ptyp")] = "0123456789abcdef"[i]; 1416446Swnj p = open(line, 2); 1426446Swnj if (p > 0) 1436446Swnj goto gotpty; 1446446Swnj } 1456446Swnj } 1466446Swnj dup2(f, 1); 1476446Swnj printf("All network ports in use.\r\n"); 1486446Swnj exit(1); 1496446Swnj gotpty: 1506446Swnj dup2(f, 0); 1516446Swnj line[strlen("/dev/")] = 't'; 1526446Swnj #ifdef DEBUG 1536446Swnj { int tt = open("/dev/tty", 2); 1546446Swnj if (tt > 0) { 1556446Swnj ioctl(tt, TIOCNOTTY, 0); 1566446Swnj close(tt); 1576446Swnj } 1586446Swnj } 1596446Swnj #endif 1606446Swnj t = open(line, 2); 1616446Swnj if (t < 0) { 1626446Swnj dup2(f, 2); 1636446Swnj perror(line); 1646446Swnj exit(1); 1656446Swnj } 1666446Swnj { struct sgttyb b; 1676446Swnj gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b); 1686446Swnj } 1696446Swnj if (fork()) { 1706446Swnj char pibuf[1024], fibuf[1024], *pbp, *fbp; 1716446Swnj int pcc = 0, fcc = 0, on = 1; 1726446Swnj /* FILE *console = fopen("/dev/console", "w"); */ 1736446Swnj /* setbuf(console, 0); */ 1746446Swnj 1756446Swnj /* fprintf(console, "f %d p %d\r\n", f, p); */ 1766446Swnj ioctl(f, FIONBIO, &on); 1776446Swnj ioctl(p, FIONBIO, &on); 1786446Swnj ioctl(p, TIOCPKT, &on); 1796446Swnj signal(SIGTSTP, SIG_IGN); 1806446Swnj sigset(SIGCHLD, cleanup); 1816446Swnj for (;;) { 1826446Swnj int ibits = 0, obits = 0; 1836446Swnj if (fcc) obits |= (1<<p); else ibits |= (1<<f); 1846446Swnj if (pcc >= 0) 1856446Swnj if (pcc) obits |= (1<<f); else ibits |= (1<<p); 1866446Swnj if (fcc < 0 && pcc < 0) break; 1876446Swnj /* fprintf(console, "ibits from %d obits from %d\r\n", ibits, obits); */ 188*9208Ssam select(16, &ibits, &obits, 0, 0, 0); 1896446Swnj /* fprintf(console, "ibits %d obits %d\r\n", ibits, obits); */ 1906446Swnj if (ibits == 0 && obits == 0) { 1916446Swnj sleep(5); 1926446Swnj continue; 1936446Swnj } 1946446Swnj if (ibits & (1<<f)) { 1956446Swnj fcc = read(f, fibuf, sizeof (fibuf)); 1966446Swnj /* fprintf(console, "%d from f\r\n", fcc); */ 1976446Swnj if (fcc < 0 && errno == EWOULDBLOCK) 1986446Swnj fcc = 0; 1996446Swnj else { 2006446Swnj if (fcc <= 0) 2016446Swnj break; 2026446Swnj fbp = fibuf; 2036446Swnj } 2046446Swnj } 2056446Swnj if (ibits & (1<<p)) { 2066446Swnj pcc = read(p, pibuf, sizeof (pibuf)); 2076446Swnj /* fprintf(console, "%d from p, buf[0] %x, errno %d\r\n", pcc, buf[0], errno); */ 2086446Swnj pbp = pibuf; 2096446Swnj if (pcc < 0 && errno == EWOULDBLOCK) 2106446Swnj pcc = 0; 2116446Swnj else if (pcc <= 0) 2126446Swnj pcc = -1; 2136446Swnj else if (pibuf[0] == 0) 2146446Swnj pbp++, pcc--; 2156446Swnj else { 2166446Swnj if (pibuf[0]&(TIOCPKT_FLUSHWRITE| 2176446Swnj TIOCPKT_NOSTOP| 2186446Swnj TIOCPKT_DOSTOP)) { 2196446Swnj int nstop = pibuf[0] & 2206446Swnj (TIOCPKT_NOSTOP| 2216446Swnj TIOCPKT_DOSTOP); 2226446Swnj if (nstop) 2236446Swnj stop = nstop; 2246446Swnj pibuf[0] |= nstop; 225*9208Ssam send(f,&pibuf[0],1,SOF_OOB); 2266446Swnj } 2276446Swnj pcc = 0; 2286446Swnj } 2296446Swnj } 2306446Swnj if ((obits & (1<<f)) && pcc > 0) { 2316446Swnj cc = write(f, pbp, pcc); 2326446Swnj /* fprintf(console, "%d of %d to f\r\n", cc, pcc); */ 2336446Swnj if (cc > 0) { 2346446Swnj pcc -= cc; 2356446Swnj pbp += cc; 2366446Swnj } 2376446Swnj } 2386446Swnj if ((obits & (1<<p)) && fcc > 0) { 2396446Swnj cc = write(p, fbp, fcc); 2406446Swnj /* fprintf(console, "%d of %d to p\r\n", cc, fcc); */ 2416446Swnj if (cc > 0) { 2426446Swnj fcc -= cc; 2436446Swnj fbp += cc; 2446446Swnj } 2456446Swnj } 2466446Swnj } 2476446Swnj cleanup(); 2486446Swnj } 2496446Swnj close(f); 2506446Swnj close(p); 2516446Swnj dup2(t, 0); 2526446Swnj dup2(t, 1); 2536446Swnj dup2(t, 2); 2546446Swnj close(t); 2558380Ssam execl("/bin/login", "login", "-r", hp->h_name, 0); 2566446Swnj perror("/bin/login"); 2576446Swnj exit(1); 2586446Swnj } 2596446Swnj 2606446Swnj cleanup() 2616446Swnj { 2626446Swnj int how = 2; 2636446Swnj 2646446Swnj rmut(); 2656446Swnj ioctl(netf, SIOCDONE, &how); 2666446Swnj kill(0, SIGKILL); 2676446Swnj exit(1); 2686446Swnj } 2696446Swnj 2706446Swnj #include <utmp.h> 2716446Swnj 2726446Swnj struct utmp wtmp; 2736446Swnj char wtmpf[] = "/usr/adm/wtmp"; 2746446Swnj char utmp[] = "/etc/utmp"; 2756446Swnj #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 2766446Swnj #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 2776446Swnj 2786446Swnj rmut() 2796446Swnj { 2806446Swnj register f; 2816446Swnj int found = 0; 2826446Swnj 2836446Swnj f = open(utmp, 2); 2846446Swnj if (f >= 0) { 2856446Swnj while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { 2866446Swnj if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0) 2876446Swnj continue; 2886446Swnj lseek(f, -(long)sizeof(wtmp), 1); 2896446Swnj SCPYN(wtmp.ut_name, ""); 2906446Swnj time(&wtmp.ut_time); 2916446Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 2926446Swnj found++; 2936446Swnj } 2946446Swnj close(f); 2956446Swnj } 2966446Swnj if (found) { 2976446Swnj f = open(wtmpf, 1); 2986446Swnj if (f >= 0) { 2996446Swnj SCPYN(wtmp.ut_line, line+5); 3006446Swnj SCPYN(wtmp.ut_name, ""); 3016446Swnj time(&wtmp.ut_time); 3026446Swnj lseek(f, (long)0, 2); 3036446Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 3046446Swnj close(f); 3056446Swnj } 3066446Swnj } 3076446Swnj chmod(line, 0666); 3086446Swnj chown(line, 0, 0); 3096446Swnj line[strlen("/dev/")] = 'p'; 3106446Swnj chmod(line, 0666); 3116446Swnj chown(line, 0, 0); 3126446Swnj } 313