16446Swnj #ifndef lint 2*17187Sralph static char sccsid[] = "@(#)rlogind.c 4.22 (Berkeley) 09/13/84"; 36446Swnj #endif 46446Swnj 516369Skarels /* 616369Skarels * remote login server: 716369Skarels * remuser\0 816369Skarels * locuser\0 916369Skarels * terminal type\0 1016369Skarels * data 1116369Skarels */ 1216369Skarels 136446Swnj #include <stdio.h> 146446Swnj #include <sys/types.h> 156446Swnj #include <sys/stat.h> 166446Swnj #include <sys/socket.h> 1713554Ssam #include <sys/wait.h> 189208Ssam 199208Ssam #include <netinet/in.h> 209208Ssam 216446Swnj #include <errno.h> 226446Swnj #include <pwd.h> 236446Swnj #include <signal.h> 246446Swnj #include <sgtty.h> 256446Swnj #include <stdio.h> 268380Ssam #include <netdb.h> 27*17187Sralph #include <syslog.h> 286446Swnj 296446Swnj extern errno; 3010417Ssam int reapchild(); 316446Swnj struct passwd *getpwnam(); 3211345Ssam char *crypt(), *rindex(), *index(), *malloc(), *ntoa(); 3316369Skarels 346446Swnj main(argc, argv) 356446Swnj int argc; 366446Swnj char **argv; 376446Swnj { 3817156Ssam int on = 1, options = 0, fromlen; 396446Swnj struct sockaddr_in from; 406446Swnj 4116369Skarels fromlen = sizeof (from); 4216369Skarels if (getpeername(0, &from, &fromlen) < 0) { 4316369Skarels fprintf(stderr, "%s: ", argv[0]); 4416369Skarels perror("getpeername"); 4516369Skarels _exit(1); 468380Ssam } 4717156Ssam if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) { 48*17187Sralph openlog(argv[0], LOG_PID, 0); 49*17187Sralph syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 506446Swnj } 5116369Skarels doit(0, &from); 526446Swnj } 536446Swnj 546446Swnj char locuser[32], remuser[32]; 556446Swnj char buf[BUFSIZ]; 566446Swnj int child; 576446Swnj int cleanup(); 586446Swnj int netf; 596446Swnj extern errno; 606446Swnj char *line; 616446Swnj 626446Swnj doit(f, fromp) 636446Swnj int f; 646446Swnj struct sockaddr_in *fromp; 656446Swnj { 668380Ssam char c; 679242Ssam int i, p, cc, t, pid; 686446Swnj int stop = TIOCPKT_DOSTOP; 698380Ssam register struct hostent *hp; 706446Swnj 716446Swnj alarm(60); 726446Swnj read(f, &c, 1); 736446Swnj if (c != 0) 746446Swnj exit(1); 756446Swnj alarm(0); 7616227Skarels fromp->sin_port = ntohs((u_short)fromp->sin_port); 778380Ssam hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), 788380Ssam fromp->sin_family); 7911345Ssam if (hp == 0) { 8016227Skarels char buf[BUFSIZ]; 8111345Ssam 8211345Ssam fatal(f, sprintf(buf, "Host name for your address (%s) unknown", 8311345Ssam ntoa(fromp->sin_addr))); 8411345Ssam } 856446Swnj if (fromp->sin_family != AF_INET || 8616227Skarels fromp->sin_port >= IPPORT_RESERVED) 879242Ssam fatal(f, "Permission denied"); 886446Swnj write(f, "", 1); 896446Swnj for (c = 'p'; c <= 's'; c++) { 906446Swnj struct stat stb; 916446Swnj line = "/dev/ptyXX"; 926446Swnj line[strlen("/dev/pty")] = c; 936446Swnj line[strlen("/dev/ptyp")] = '0'; 946446Swnj if (stat(line, &stb) < 0) 956446Swnj break; 966446Swnj for (i = 0; i < 16; i++) { 976446Swnj line[strlen("/dev/ptyp")] = "0123456789abcdef"[i]; 986446Swnj p = open(line, 2); 996446Swnj if (p > 0) 1006446Swnj goto gotpty; 1016446Swnj } 1026446Swnj } 1039242Ssam fatal(f, "All network ports in use"); 1049242Ssam /*NOTREACHED*/ 1056446Swnj gotpty: 10616227Skarels netf = f; 1076446Swnj line[strlen("/dev/")] = 't'; 1086446Swnj #ifdef DEBUG 1096446Swnj { int tt = open("/dev/tty", 2); 1106446Swnj if (tt > 0) { 1116446Swnj ioctl(tt, TIOCNOTTY, 0); 1126446Swnj close(tt); 1136446Swnj } 1146446Swnj } 1156446Swnj #endif 1166446Swnj t = open(line, 2); 1179242Ssam if (t < 0) 1189242Ssam fatalperror(f, line, errno); 1196446Swnj { struct sgttyb b; 1206446Swnj gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b); 1216446Swnj } 1229242Ssam pid = fork(); 1239242Ssam if (pid < 0) 1249242Ssam fatalperror(f, "", errno); 1259242Ssam if (pid) { 1266446Swnj char pibuf[1024], fibuf[1024], *pbp, *fbp; 12716227Skarels register pcc = 0, fcc = 0; 12816227Skarels int on = 1; 1296446Swnj /* FILE *console = fopen("/dev/console", "w"); */ 1306446Swnj /* setbuf(console, 0); */ 1316446Swnj 1326446Swnj /* fprintf(console, "f %d p %d\r\n", f, p); */ 13316227Skarels close(t); 1346446Swnj ioctl(f, FIONBIO, &on); 1356446Swnj ioctl(p, FIONBIO, &on); 1366446Swnj ioctl(p, TIOCPKT, &on); 1376446Swnj signal(SIGTSTP, SIG_IGN); 13813024Ssam signal(SIGCHLD, cleanup); 1396446Swnj for (;;) { 1406446Swnj int ibits = 0, obits = 0; 1419242Ssam 1429242Ssam if (fcc) 1439242Ssam obits |= (1<<p); 1449242Ssam else 1459242Ssam ibits |= (1<<f); 1466446Swnj if (pcc >= 0) 1479242Ssam if (pcc) 1489242Ssam obits |= (1<<f); 1499242Ssam else 1509242Ssam ibits |= (1<<p); 1516446Swnj /* fprintf(console, "ibits from %d obits from %d\r\n", ibits, obits); */ 15216227Skarels if (select(16, &ibits, &obits, 0, 0) < 0) { 15316227Skarels if (errno == EINTR) 15416227Skarels continue; 15516227Skarels fatalperror(f, "select", errno); 15616227Skarels } 1576446Swnj /* fprintf(console, "ibits %d obits %d\r\n", ibits, obits); */ 1586446Swnj if (ibits == 0 && obits == 0) { 15916227Skarels /* shouldn't happen... */ 1606446Swnj sleep(5); 1616446Swnj continue; 1626446Swnj } 1636446Swnj if (ibits & (1<<f)) { 1646446Swnj fcc = read(f, fibuf, sizeof (fibuf)); 1656446Swnj /* fprintf(console, "%d from f\r\n", fcc); */ 1666446Swnj if (fcc < 0 && errno == EWOULDBLOCK) 1676446Swnj fcc = 0; 1686446Swnj else { 1696446Swnj if (fcc <= 0) 1706446Swnj break; 1716446Swnj fbp = fibuf; 1726446Swnj } 1736446Swnj } 1746446Swnj if (ibits & (1<<p)) { 1756446Swnj pcc = read(p, pibuf, sizeof (pibuf)); 1766446Swnj /* fprintf(console, "%d from p, buf[0] %x, errno %d\r\n", pcc, buf[0], errno); */ 1776446Swnj pbp = pibuf; 1786446Swnj if (pcc < 0 && errno == EWOULDBLOCK) 1796446Swnj pcc = 0; 1806446Swnj else if (pcc <= 0) 18116227Skarels break; 1826446Swnj else if (pibuf[0] == 0) 1836446Swnj pbp++, pcc--; 1846446Swnj else { 1856446Swnj if (pibuf[0]&(TIOCPKT_FLUSHWRITE| 1866446Swnj TIOCPKT_NOSTOP| 1876446Swnj TIOCPKT_DOSTOP)) { 18816227Skarels /* The following 3 lines do nothing. */ 1896446Swnj int nstop = pibuf[0] & 1906446Swnj (TIOCPKT_NOSTOP| 1916446Swnj TIOCPKT_DOSTOP); 1926446Swnj if (nstop) 1936446Swnj stop = nstop; 1946446Swnj pibuf[0] |= nstop; 19512898Ssam send(f,&pibuf[0],1,MSG_OOB); 1966446Swnj } 1976446Swnj pcc = 0; 1986446Swnj } 1996446Swnj } 2006446Swnj if ((obits & (1<<f)) && pcc > 0) { 2016446Swnj cc = write(f, pbp, pcc); 20216227Skarels if (cc < 0 && errno == EWOULDBLOCK) { 20316227Skarels /* also shouldn't happen */ 20416227Skarels sleep(5); 20516227Skarels continue; 20616227Skarels } 2076446Swnj /* fprintf(console, "%d of %d to f\r\n", cc, pcc); */ 2086446Swnj if (cc > 0) { 2096446Swnj pcc -= cc; 2106446Swnj pbp += cc; 2116446Swnj } 2126446Swnj } 2136446Swnj if ((obits & (1<<p)) && fcc > 0) { 2146446Swnj cc = write(p, fbp, fcc); 2156446Swnj /* fprintf(console, "%d of %d to p\r\n", cc, fcc); */ 2166446Swnj if (cc > 0) { 2176446Swnj fcc -= cc; 2186446Swnj fbp += cc; 2196446Swnj } 2206446Swnj } 2216446Swnj } 2226446Swnj cleanup(); 2236446Swnj } 2246446Swnj close(f); 2256446Swnj close(p); 2266446Swnj dup2(t, 0); 2276446Swnj dup2(t, 1); 2286446Swnj dup2(t, 2); 2296446Swnj close(t); 2308380Ssam execl("/bin/login", "login", "-r", hp->h_name, 0); 2319242Ssam fatalperror(2, "/bin/login", errno); 2329242Ssam /*NOTREACHED*/ 2336446Swnj } 2346446Swnj 2356446Swnj cleanup() 2366446Swnj { 2376446Swnj 2386446Swnj rmut(); 23910009Ssam vhangup(); /* XXX */ 24010192Ssam shutdown(netf, 2); 2416446Swnj kill(0, SIGKILL); 2426446Swnj exit(1); 2436446Swnj } 2446446Swnj 2459242Ssam fatal(f, msg) 2469242Ssam int f; 2479242Ssam char *msg; 2489242Ssam { 2499242Ssam char buf[BUFSIZ]; 2509242Ssam 2519242Ssam buf[0] = '\01'; /* error indicator */ 25213554Ssam (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg); 2539242Ssam (void) write(f, buf, strlen(buf)); 2549242Ssam exit(1); 2559242Ssam } 2569242Ssam 2579242Ssam fatalperror(f, msg, errno) 2589242Ssam int f; 2599242Ssam char *msg; 2609242Ssam int errno; 2619242Ssam { 2629242Ssam char buf[BUFSIZ]; 26316227Skarels extern int sys_nerr; 2649242Ssam extern char *sys_errlist[]; 2659242Ssam 26616227Skarels if ((unsigned) errno < sys_nerr) 26716227Skarels (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); 26816227Skarels else 26916227Skarels (void) sprintf(buf, "%s: Error %d", msg, errno); 2709242Ssam fatal(f, buf); 2719242Ssam } 2729242Ssam 2736446Swnj #include <utmp.h> 2746446Swnj 2756446Swnj struct utmp wtmp; 2766446Swnj char wtmpf[] = "/usr/adm/wtmp"; 2776446Swnj char utmp[] = "/etc/utmp"; 2786446Swnj #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 2796446Swnj #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 2806446Swnj 2816446Swnj rmut() 2826446Swnj { 2836446Swnj register f; 2846446Swnj int found = 0; 2856446Swnj 2866446Swnj f = open(utmp, 2); 2876446Swnj if (f >= 0) { 2886446Swnj while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { 2896446Swnj if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0) 2906446Swnj continue; 2916446Swnj lseek(f, -(long)sizeof(wtmp), 1); 2926446Swnj SCPYN(wtmp.ut_name, ""); 29312681Ssam SCPYN(wtmp.ut_host, ""); 2946446Swnj time(&wtmp.ut_time); 2956446Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 2966446Swnj found++; 2976446Swnj } 2986446Swnj close(f); 2996446Swnj } 3006446Swnj if (found) { 3016446Swnj f = open(wtmpf, 1); 3026446Swnj if (f >= 0) { 3036446Swnj SCPYN(wtmp.ut_line, line+5); 3046446Swnj SCPYN(wtmp.ut_name, ""); 30512681Ssam SCPYN(wtmp.ut_host, ""); 3066446Swnj time(&wtmp.ut_time); 3076446Swnj lseek(f, (long)0, 2); 3086446Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 3096446Swnj close(f); 3106446Swnj } 3116446Swnj } 3126446Swnj chmod(line, 0666); 3136446Swnj chown(line, 0, 0); 3146446Swnj line[strlen("/dev/")] = 'p'; 3156446Swnj chmod(line, 0666); 3166446Swnj chown(line, 0, 0); 3176446Swnj } 31811345Ssam 31911345Ssam /* 32011345Ssam * Convert network-format internet address 32111345Ssam * to base 256 d.d.d.d representation. 32211345Ssam */ 32311345Ssam char * 32411345Ssam ntoa(in) 32511345Ssam struct in_addr in; 32611345Ssam { 32711345Ssam static char b[18]; 32811345Ssam register char *p; 32911345Ssam 33011345Ssam p = (char *)∈ 33111345Ssam #define UC(b) (((int)b)&0xff) 33211345Ssam sprintf(b, "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); 33311345Ssam return (b); 33411345Ssam } 335