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: }

Defined functions

cleanup defined in line 317; used 3 times
control defined in line 174; used 1 times
doit defined in line 82; used 1 times
  • in line 69
fatal defined in line 326; used 3 times
fatalperror defined in line 338; used 4 times
main defined in line 52; never used
protocol defined in line 196; used 1 times
rmut defined in line 362; used 1 times

Defined variables

child defined in line 72; never used
copyright defined in line 8; never used
line defined in line 76; used 16 times
magic defined in line 166; used 2 times
netf defined in line 74; used 2 times
oobdata defined in line 167; used 4 times
sccsid defined in line 14; never used
utmpf defined in line 358; used 1 times
win defined in line 79; used 1 times
wtmp defined in line 356; used 7 times
wtmpf defined in line 357; used 1 times

Defined macros

SCMPN defined in line 360; used 1 times
SCPYN defined in line 359; used 5 times
TIOCPKT_WINDOW defined in line 44; used 3 times
pkcontrol defined in line 236; used 2 times
Last modified: 1986-05-23
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2012
Valid CSS Valid XHTML 1.0 Strict