home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / k95source / rlogind.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  8KB  |  411 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #ifndef lint
  8. char copyright[] =
  9. "@(#) Copyright (c) 1983 Regents of the University of California.\n\
  10.  All rights reserved.\n";
  11. #endif not lint
  12.  
  13. #ifndef lint
  14. static char sccsid[] = "@(#)rlogind.c    5.11 (Berkeley) 5/23/86";
  15. #endif not lint
  16.  
  17. /*
  18.  * remote login server:
  19.  *    remuser\0
  20.  *    locuser\0
  21.  *    terminal info\0
  22.  *    data
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <sys/socket.h>
  29. #include <sys/wait.h>
  30. #include <sys/file.h>
  31.  
  32. #include <netinet/in.h>
  33.  
  34. #include <errno.h>
  35. #include <pwd.h>
  36. #include <signal.h>
  37. #include <sgtty.h>
  38. #include <stdio.h>
  39. #include <netdb.h>
  40. #include <syslog.h>
  41. #include <strings.h>
  42.  
  43. # ifndef TIOCPKT_WINDOW
  44. # define TIOCPKT_WINDOW 0x80
  45. # endif TIOCPKT_WINDOW
  46.  
  47. extern    errno;
  48. int    reapchild();
  49. struct    passwd *getpwnam();
  50. char    *malloc();
  51.  
  52. main(argc, argv)
  53.     int argc;
  54.     char **argv;
  55. {
  56.     int on = 1, options = 0, fromlen;
  57.     struct sockaddr_in from;
  58.  
  59.     openlog("rlogind", LOG_PID | LOG_AUTH, LOG_AUTH);
  60.     fromlen = sizeof (from);
  61.     if (getpeername(0, &from, &fromlen) < 0) {
  62.         fprintf(stderr, "%s: ", argv[0]);
  63.         perror("getpeername");
  64.         _exit(1);
  65.     }
  66.     if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
  67.         syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
  68.     }
  69.     doit(0, &from);
  70. }
  71.  
  72. int    child;
  73. int    cleanup();
  74. int    netf;
  75. extern    errno;
  76. char    *line;
  77. extern    char    *inet_ntoa();
  78.  
  79. struct winsize win = { 0, 0, 0, 0 };
  80.  
  81.  
  82. doit(f, fromp)
  83.     int f;
  84.     struct sockaddr_in *fromp;
  85. {
  86.     int i, p, t, pid, on = 1;
  87.     register struct hostent *hp;
  88.     struct hostent hostent;
  89.     char c;
  90.  
  91.     alarm(60);
  92.     read(f, &c, 1);
  93.     if (c != 0)
  94.         exit(1);
  95.     alarm(0);
  96.     fromp->sin_port = ntohs((u_short)fromp->sin_port);
  97.     hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr),
  98.         fromp->sin_family);
  99.     if (hp == 0) {
  100.         /*
  101.          * Only the name is used below.
  102.          */
  103.         hp = &hostent;
  104.         hp->h_name = inet_ntoa(fromp->sin_addr);
  105.     }
  106.     if (fromp->sin_family != AF_INET ||
  107.         fromp->sin_port >= IPPORT_RESERVED)
  108.         fatal(f, "Permission denied");
  109.     write(f, "", 1);
  110.     for (c = 'p'; c <= 's'; c++) {
  111.         struct stat stb;
  112.         line = "/dev/ptyXX";
  113.         line[strlen("/dev/pty")] = c;
  114.         line[strlen("/dev/ptyp")] = '0';
  115.         if (stat(line, &stb) < 0)
  116.             break;
  117.         for (i = 0; i < 16; i++) {
  118.             line[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
  119.             p = open(line, 2);
  120.             if (p > 0)
  121.                 goto gotpty;
  122.         }
  123.     }
  124.     fatal(f, "Out of ptys");
  125.     /*NOTREACHED*/
  126. gotpty:
  127.     (void) ioctl(p, TIOCSWINSZ, &win);
  128.     netf = f;
  129.     line[strlen("/dev/")] = 't';
  130. #ifdef DEBUG
  131.     { int tt = open("/dev/tty", 2);
  132.       if (tt > 0) {
  133.         ioctl(tt, TIOCNOTTY, 0);
  134.         close(tt);
  135.       }
  136.     }
  137. #endif
  138.     t = open(line, 2);
  139.     if (t < 0)
  140.         fatalperror(f, line, errno);
  141.     { struct sgttyb b;
  142.       gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b);
  143.     }
  144.     pid = fork();
  145.     if (pid < 0)
  146.         fatalperror(f, "", errno);
  147.     if (pid == 0) {
  148.         close(f), close(p);
  149.         dup2(t, 0), dup2(t, 1), dup2(t, 2);
  150.         close(t);
  151.         execl("/bin/login", "login", "-r", hp->h_name, 0);
  152.         fatalperror(2, "/bin/login", errno);
  153.         /*NOTREACHED*/
  154.     }
  155.     close(t);
  156.     ioctl(f, FIONBIO, &on);
  157.     ioctl(p, FIONBIO, &on);
  158.     ioctl(p, TIOCPKT, &on);
  159.     signal(SIGTSTP, SIG_IGN);
  160.     signal(SIGCHLD, cleanup);
  161.     setpgrp(0, 0);
  162.     protocol(f, p);
  163.     cleanup();
  164. }
  165.  
  166. char    magic[2] = { 0377, 0377 };
  167. char    oobdata[] = {TIOCPKT_WINDOW};
  168.  
  169. /*
  170.  * Handle a "control" request (signaled by magic being present)
  171.  * in the data stream.  For now, we are only willing to handle
  172.  * window size changes.
  173.  */
  174. control(pty, cp, n)
  175.     int pty;
  176.     char *cp;
  177.     int n;
  178. {
  179.     struct winsize w;
  180.  
  181.     if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's')
  182.         return (0);
  183.     oobdata[0] &= ~TIOCPKT_WINDOW;    /* we know he heard */
  184.     bcopy(cp+4, (char *)&w, sizeof(w));
  185.     w.ws_row = ntohs(w.ws_row);
  186.     w.ws_col = ntohs(w.ws_col);
  187.     w.ws_xpixel = ntohs(w.ws_xpixel);
  188.     w.ws_ypixel = ntohs(w.ws_ypixel);
  189.     (void)ioctl(pty, TIOCSWINSZ, &w);
  190.     return (4+sizeof (w));
  191. }
  192.  
  193. /*
  194.  * rlogin "protocol" machine.
  195.  */
  196. protocol(f, p)
  197.     int f, p;
  198. {
  199.     char pibuf[1024], fibuf[1024], *pbp, *fbp;
  200.     register pcc = 0, fcc = 0;
  201.     int cc;
  202.     char cntl;
  203.  
  204.     /*
  205.      * Must ignore SIGTTOU, otherwise we'll stop
  206.      * when we try and set slave pty's window shape
  207.      * (our controlling tty is the master pty).
  208.      */
  209.     (void) signal(SIGTTOU, SIG_IGN);
  210.     send(f, oobdata, 1, MSG_OOB);    /* indicate new rlogin */
  211.     for (;;) {
  212.         int ibits, obits, ebits;
  213.  
  214.         ibits = 0;
  215.         obits = 0;
  216.         if (fcc)
  217.             obits |= (1<<p);
  218.         else
  219.             ibits |= (1<<f);
  220.         if (pcc >= 0)
  221.             if (pcc)
  222.                 obits |= (1<<f);
  223.             else
  224.                 ibits |= (1<<p);
  225.         ebits = (1<<p);
  226.         if (select(16, &ibits, &obits, &ebits, 0) < 0) {
  227.             if (errno == EINTR)
  228.                 continue;
  229.             fatalperror(f, "select", errno);
  230.         }
  231.         if (ibits == 0 && obits == 0 && ebits == 0) {
  232.             /* shouldn't happen... */
  233.             sleep(5);
  234.             continue;
  235.         }
  236. #define    pkcontrol(c)    ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
  237.         if (ebits & (1<<p)) {
  238.             cc = read(p, &cntl, 1);
  239.             if (cc == 1 && pkcontrol(cntl)) {
  240.                 cntl |= oobdata[0];
  241.                 send(f, &cntl, 1, MSG_OOB);
  242.                 if (cntl & TIOCPKT_FLUSHWRITE) {
  243.                     pcc = 0;
  244.                     ibits &= ~(1<<p);
  245.                 }
  246.             }
  247.         }
  248.         if (ibits & (1<<f)) {
  249.             fcc = read(f, fibuf, sizeof (fibuf));
  250.             if (fcc < 0 && errno == EWOULDBLOCK)
  251.                 fcc = 0;
  252.             else {
  253.                 register char *cp;
  254.                 int left, n;
  255.  
  256.                 if (fcc <= 0)
  257.                     break;
  258.                 fbp = fibuf;
  259.  
  260.             top:
  261.                 for (cp = fibuf; cp < fibuf+fcc-1; cp++)
  262.                     if (cp[0] == magic[0] &&
  263.                         cp[1] == magic[1]) {
  264.                         left = fcc - (cp-fibuf);
  265.                         n = control(p, cp, left);
  266.                         if (n) {
  267.                             left -= n;
  268.                             if (left > 0)
  269.                                 bcopy(cp+n, cp, left);
  270.                             fcc -= n;
  271.                             goto top; /* n^2 */
  272.                         }
  273.                     }
  274.             }
  275.         }
  276.  
  277.         if ((obits & (1<<p)) && fcc > 0) {
  278.             cc = write(p, fbp, fcc);
  279.             if (cc > 0) {
  280.                 fcc -= cc;
  281.                 fbp += cc;
  282.             }
  283.         }
  284.  
  285.         if (ibits & (1<<p)) {
  286.             pcc = read(p, pibuf, sizeof (pibuf));
  287.             pbp = pibuf;
  288.             if (pcc < 0 && errno == EWOULDBLOCK)
  289.                 pcc = 0;
  290.             else if (pcc <= 0)
  291.                 break;
  292.             else if (pibuf[0] == 0)
  293.                 pbp++, pcc--;
  294.             else {
  295.                 if (pkcontrol(pibuf[0])) {
  296.                     pibuf[0] |= oobdata[0];
  297.                     send(f, &pibuf[0], 1, MSG_OOB);
  298.                 }
  299.                 pcc = 0;
  300.             }
  301.         }
  302.         if ((obits & (1<<f)) && pcc > 0) {
  303.             cc = write(f, pbp, pcc);
  304.             if (cc < 0 && errno == EWOULDBLOCK) {
  305.                 /* also shouldn't happen */
  306.                 sleep(5);
  307.                 continue;
  308.             }
  309.             if (cc > 0) {
  310.                 pcc -= cc;
  311.                 pbp += cc;
  312.             }
  313.         }
  314.     }
  315. }
  316.  
  317. cleanup()
  318. {
  319.  
  320.     rmut();
  321.     vhangup();        /* XXX */
  322.     shutdown(netf, 2);
  323.     exit(1);
  324. }
  325.  
  326. fatal(f, msg)
  327.     int f;
  328.     char *msg;
  329. {
  330.     char buf[BUFSIZ];
  331.  
  332.     buf[0] = '\01';        /* error indicator */
  333.     (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg);
  334.     (void) write(f, buf, strlen(buf));
  335.     exit(1);
  336. }
  337.  
  338. fatalperror(f, msg, errno)
  339.     int f;
  340.     char *msg;
  341.     int errno;
  342. {
  343.     char buf[BUFSIZ];
  344.     extern int sys_nerr;
  345.     extern char *sys_errlist[];
  346.  
  347.     if ((unsigned)errno < sys_nerr)
  348.         (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]);
  349.     else
  350.         (void) sprintf(buf, "%s: Error %d", msg, errno);
  351.     fatal(f, buf);
  352. }
  353.  
  354. #include <utmp.h>
  355.  
  356. struct    utmp wtmp;
  357. char    wtmpf[]    = "/usr/adm/wtmp";
  358. char    utmpf[] = "/etc/utmp";
  359. #define SCPYN(a, b)    strncpy(a, b, sizeof(a))
  360. #define SCMPN(a, b)    strncmp(a, b, sizeof(a))
  361.  
  362. rmut()
  363. {
  364.     register f;
  365.     int found = 0;
  366.     struct utmp *u, *utmp;
  367.     int nutmp;
  368.     struct stat statbf;
  369.  
  370.     f = open(utmpf, O_RDWR);
  371.     if (f >= 0) {
  372.         fstat(f, &statbf);
  373.         utmp = (struct utmp *)malloc(statbf.st_size);
  374.         if (!utmp)
  375.             syslog(LOG_ERR, "utmp malloc failed");
  376.         if (statbf.st_size && utmp) {
  377.             nutmp = read(f, utmp, statbf.st_size);
  378.             nutmp /= sizeof(struct utmp);
  379.         
  380.             for (u = utmp ; u < &utmp[nutmp] ; u++) {
  381.                 if (SCMPN(u->ut_line, line+5) ||
  382.                     u->ut_name[0]==0)
  383.                     continue;
  384.                 lseek(f, ((long)u)-((long)utmp), L_SET);
  385.                 SCPYN(u->ut_name, "");
  386.                 SCPYN(u->ut_host, "");
  387.                 time(&u->ut_time);
  388.                 write(f, (char *)u, sizeof(wtmp));
  389.                 found++;
  390.             }
  391.         }
  392.         close(f);
  393.     }
  394.     if (found) {
  395.         f = open(wtmpf, O_WRONLY|O_APPEND);
  396.         if (f >= 0) {
  397.             SCPYN(wtmp.ut_line, line+5);
  398.             SCPYN(wtmp.ut_name, "");
  399.             SCPYN(wtmp.ut_host, "");
  400.             time(&wtmp.ut_time);
  401.             write(f, (char *)&wtmp, sizeof(wtmp));
  402.             close(f);
  403.         }
  404.     }
  405.     chmod(line, 0666);
  406.     chown(line, 0, 0);
  407.     line[strlen("/dev/")] = 'p';
  408.     chmod(line, 0666);
  409.     chown(line, 0, 0);
  410. }
  411.