1 #ifndef lint 2 static char sccsid[] = "@(#)rlogind.c 4.13 83/05/03"; 3 #endif 4 5 #include <stdio.h> 6 #include <sys/types.h> 7 #include <sys/stat.h> 8 #include <sys/socket.h> 9 10 #include <netinet/in.h> 11 12 #include <errno.h> 13 #include <pwd.h> 14 #include <wait.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 sigset(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 doit(s, &from); 105 } 106 close(s); 107 } 108 } 109 110 reapchild() 111 { 112 union wait status; 113 114 while (wait3(&status, WNOHANG, 0) > 0) 115 ; 116 } 117 118 char locuser[32], remuser[32]; 119 char buf[BUFSIZ]; 120 int child; 121 int cleanup(); 122 int netf; 123 extern errno; 124 char *line; 125 126 doit(f, fromp) 127 int f; 128 struct sockaddr_in *fromp; 129 { 130 char c; 131 int i, p, cc, t, pid; 132 int stop = TIOCPKT_DOSTOP; 133 register struct hostent *hp; 134 135 alarm(60); 136 read(f, &c, 1); 137 if (c != 0) 138 exit(1); 139 alarm(0); 140 fromp->sin_port = htons((u_short)fromp->sin_port); 141 hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), 142 fromp->sin_family); 143 if (hp == 0) { 144 char buf[BUFSIZ], *cp = (char *)&fromp->sin_addr; 145 146 fatal(f, sprintf(buf, "Host name for your address (%s) unknown", 147 ntoa(fromp->sin_addr))); 148 } 149 if (fromp->sin_family != AF_INET || 150 fromp->sin_port >= IPPORT_RESERVED || 151 hp == 0) 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 dup2(f, 0); 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 int pcc = 0, fcc = 0, on = 1; 193 /* FILE *console = fopen("/dev/console", "w"); */ 194 /* setbuf(console, 0); */ 195 196 /* fprintf(console, "f %d p %d\r\n", f, p); */ 197 ioctl(f, FIONBIO, &on); 198 ioctl(p, FIONBIO, &on); 199 ioctl(p, TIOCPKT, &on); 200 signal(SIGTSTP, SIG_IGN); 201 sigset(SIGCHLD, cleanup); 202 for (;;) { 203 int ibits = 0, obits = 0; 204 205 if (fcc) 206 obits |= (1<<p); 207 else 208 ibits |= (1<<f); 209 if (pcc >= 0) 210 if (pcc) 211 obits |= (1<<f); 212 else 213 ibits |= (1<<p); 214 if (fcc < 0 && pcc < 0) 215 break; 216 /* fprintf(console, "ibits from %d obits from %d\r\n", ibits, obits); */ 217 select(16, &ibits, &obits, 0, 0, 0); 218 /* fprintf(console, "ibits %d obits %d\r\n", ibits, obits); */ 219 if (ibits == 0 && obits == 0) { 220 sleep(5); 221 continue; 222 } 223 if (ibits & (1<<f)) { 224 fcc = read(f, fibuf, sizeof (fibuf)); 225 /* fprintf(console, "%d from f\r\n", fcc); */ 226 if (fcc < 0 && errno == EWOULDBLOCK) 227 fcc = 0; 228 else { 229 if (fcc <= 0) 230 break; 231 fbp = fibuf; 232 } 233 } 234 if (ibits & (1<<p)) { 235 pcc = read(p, pibuf, sizeof (pibuf)); 236 /* fprintf(console, "%d from p, buf[0] %x, errno %d\r\n", pcc, buf[0], errno); */ 237 pbp = pibuf; 238 if (pcc < 0 && errno == EWOULDBLOCK) 239 pcc = 0; 240 else if (pcc <= 0) 241 pcc = -1; 242 else if (pibuf[0] == 0) 243 pbp++, pcc--; 244 else { 245 if (pibuf[0]&(TIOCPKT_FLUSHWRITE| 246 TIOCPKT_NOSTOP| 247 TIOCPKT_DOSTOP)) { 248 int nstop = pibuf[0] & 249 (TIOCPKT_NOSTOP| 250 TIOCPKT_DOSTOP); 251 if (nstop) 252 stop = nstop; 253 pibuf[0] |= nstop; 254 send(f,&pibuf[0],1,SOF_OOB); 255 } 256 pcc = 0; 257 } 258 } 259 if ((obits & (1<<f)) && pcc > 0) { 260 cc = write(f, pbp, pcc); 261 /* fprintf(console, "%d of %d to f\r\n", cc, pcc); */ 262 if (cc > 0) { 263 pcc -= cc; 264 pbp += cc; 265 } 266 } 267 if ((obits & (1<<p)) && fcc > 0) { 268 cc = write(p, fbp, fcc); 269 /* fprintf(console, "%d of %d to p\r\n", cc, fcc); */ 270 if (cc > 0) { 271 fcc -= cc; 272 fbp += cc; 273 } 274 } 275 } 276 cleanup(); 277 } 278 close(f); 279 close(p); 280 dup2(t, 0); 281 dup2(t, 1); 282 dup2(t, 2); 283 close(t); 284 execl("/bin/login", "login", "-r", hp->h_name, 0); 285 fatalperror(2, "/bin/login", errno); 286 /*NOTREACHED*/ 287 } 288 289 cleanup() 290 { 291 292 rmut(); 293 vhangup(); /* XXX */ 294 shutdown(netf, 2); 295 kill(0, SIGKILL); 296 exit(1); 297 } 298 299 fatal(f, msg) 300 int f; 301 char *msg; 302 { 303 char buf[BUFSIZ]; 304 305 buf[0] = '\01'; /* error indicator */ 306 (void) sprintf(buf + 1, "rlogind: %s.\n", msg); 307 (void) write(f, buf, strlen(buf)); 308 exit(1); 309 } 310 311 fatalperror(f, msg, errno) 312 int f; 313 char *msg; 314 int errno; 315 { 316 char buf[BUFSIZ]; 317 extern char *sys_errlist[]; 318 319 (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); 320 fatal(f, buf); 321 } 322 323 #include <utmp.h> 324 325 struct utmp wtmp; 326 char wtmpf[] = "/usr/adm/wtmp"; 327 char utmp[] = "/etc/utmp"; 328 #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 329 #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 330 331 rmut() 332 { 333 register f; 334 int found = 0; 335 336 f = open(utmp, 2); 337 if (f >= 0) { 338 while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { 339 if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0) 340 continue; 341 lseek(f, -(long)sizeof(wtmp), 1); 342 SCPYN(wtmp.ut_name, ""); 343 time(&wtmp.ut_time); 344 write(f, (char *)&wtmp, sizeof(wtmp)); 345 found++; 346 } 347 close(f); 348 } 349 if (found) { 350 f = open(wtmpf, 1); 351 if (f >= 0) { 352 SCPYN(wtmp.ut_line, line+5); 353 SCPYN(wtmp.ut_name, ""); 354 time(&wtmp.ut_time); 355 lseek(f, (long)0, 2); 356 write(f, (char *)&wtmp, sizeof(wtmp)); 357 close(f); 358 } 359 } 360 chmod(line, 0666); 361 chown(line, 0, 0); 362 line[strlen("/dev/")] = 'p'; 363 chmod(line, 0666); 364 chown(line, 0, 0); 365 } 366 367 /* 368 * Convert network-format internet address 369 * to base 256 d.d.d.d representation. 370 */ 371 char * 372 ntoa(in) 373 struct in_addr in; 374 { 375 static char b[18]; 376 register char *p; 377 378 p = (char *)∈ 379 #define UC(b) (((int)b)&0xff) 380 sprintf(b, "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); 381 return (b); 382 } 383