1 #ifndef lint 2 static char sccsid[] = "@(#)rlogind.c 4.5 82/11/15"; 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 struct passwd *getpwnam(); 22 char *crypt(), *rindex(), *index(), *malloc(); 23 int options = SO_ACCEPTCONN|SO_KEEPALIVE; 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 union wait status; 37 int f, debug = 0; 38 struct sockaddr_in from; 39 struct servent *sp; 40 41 sp = getservbyname("login", "tcp"); 42 if (sp == 0) { 43 fprintf(stderr, "rlogind: tcp/rlogin: unknown service\n"); 44 exit(1); 45 } 46 #ifndef DEBUG 47 if (fork()) 48 exit(0); 49 for (f = 0; f < 10; f++) 50 (void) close(f); 51 (void) open("/", 0); 52 (void) dup2(0, 1); 53 (void) dup2(0, 2); 54 { int tt = open("/dev/tty", 2); 55 if (tt > 0) { 56 ioctl(tt, TIOCNOTTY, 0); 57 close(tt); 58 } 59 } 60 #endif 61 sin.sin_port = htons(sp->s_port); 62 argc--, argv++; 63 if (argc > 0 && !strcmp(argv[0], "-d")) { 64 int port = atoi(argv[0]); 65 66 if (port < 0) { 67 fprintf(stderr, "%s: bad port #\n", argv[0]); 68 exit(1); 69 } 70 sin.sin_port = htons(port); 71 argv++, argc--; 72 } 73 f = socket(AF_INET, SOCK_STREAM, 0, 0); 74 if (f < 0) { 75 perror("rlogind: socket"); 76 exit(1); 77 } 78 if (bind(f, &sin, sizeof (sin), 0) < 0) { 79 perror("rlogind: bind"); 80 exit(1); 81 } 82 listen(f, 10); 83 for (;;) { 84 int s, len = sizeof (from); 85 86 s = accept(f, &from, &len, 0); 87 if (s < 0) { 88 perror("rlogind: accept"); 89 sleep(1); 90 continue; 91 } 92 if (fork() == 0) 93 doit(s, &from); 94 close(s); 95 while (wait3(status, WNOHANG, 0) > 0) 96 continue; 97 } 98 } 99 100 char locuser[32], remuser[32]; 101 char buf[BUFSIZ]; 102 int child; 103 int cleanup(); 104 int netf; 105 extern errno; 106 char *line; 107 108 doit(f, fromp) 109 int f; 110 struct sockaddr_in *fromp; 111 { 112 char c; 113 int i, p, cc, t, pid; 114 int stop = TIOCPKT_DOSTOP; 115 register struct hostent *hp; 116 117 alarm(60); 118 read(f, &c, 1); 119 if (c != 0) 120 exit(1); 121 alarm(0); 122 fromp->sin_port = htons(fromp->sin_port); 123 hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), 124 fromp->sin_family); 125 if (hp == 0) 126 fatal(f, "Host name for your address unknown"); 127 if (fromp->sin_family != AF_INET || 128 fromp->sin_port >= IPPORT_RESERVED || 129 hp == 0) 130 fatal(f, "Permission denied"); 131 write(f, "", 1); 132 for (c = 'p'; c <= 's'; c++) { 133 struct stat stb; 134 line = "/dev/ptyXX"; 135 line[strlen("/dev/pty")] = c; 136 line[strlen("/dev/ptyp")] = '0'; 137 if (stat(line, &stb) < 0) 138 break; 139 for (i = 0; i < 16; i++) { 140 line[strlen("/dev/ptyp")] = "0123456789abcdef"[i]; 141 p = open(line, 2); 142 if (p > 0) 143 goto gotpty; 144 } 145 } 146 fatal(f, "All network ports in use"); 147 /*NOTREACHED*/ 148 gotpty: 149 dup2(f, 0); 150 line[strlen("/dev/")] = 't'; 151 #ifdef DEBUG 152 { int tt = open("/dev/tty", 2); 153 if (tt > 0) { 154 ioctl(tt, TIOCNOTTY, 0); 155 close(tt); 156 } 157 } 158 #endif 159 t = open(line, 2); 160 if (t < 0) 161 fatalperror(f, line, errno); 162 { struct sgttyb b; 163 gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b); 164 } 165 pid = fork(); 166 if (pid < 0) 167 fatalperror(f, "", errno); 168 if (pid) { 169 char pibuf[1024], fibuf[1024], *pbp, *fbp; 170 int pcc = 0, fcc = 0, on = 1; 171 /* FILE *console = fopen("/dev/console", "w"); */ 172 /* setbuf(console, 0); */ 173 174 /* fprintf(console, "f %d p %d\r\n", f, p); */ 175 ioctl(f, FIONBIO, &on); 176 ioctl(p, FIONBIO, &on); 177 ioctl(p, TIOCPKT, &on); 178 signal(SIGTSTP, SIG_IGN); 179 sigset(SIGCHLD, cleanup); 180 for (;;) { 181 int ibits = 0, obits = 0; 182 183 if (fcc) 184 obits |= (1<<p); 185 else 186 ibits |= (1<<f); 187 if (pcc >= 0) 188 if (pcc) 189 obits |= (1<<f); 190 else 191 ibits |= (1<<p); 192 if (fcc < 0 && pcc < 0) 193 break; 194 /* fprintf(console, "ibits from %d obits from %d\r\n", ibits, obits); */ 195 select(16, &ibits, &obits, 0, 0, 0); 196 /* fprintf(console, "ibits %d obits %d\r\n", ibits, obits); */ 197 if (ibits == 0 && obits == 0) { 198 sleep(5); 199 continue; 200 } 201 if (ibits & (1<<f)) { 202 fcc = read(f, fibuf, sizeof (fibuf)); 203 /* fprintf(console, "%d from f\r\n", fcc); */ 204 if (fcc < 0 && errno == EWOULDBLOCK) 205 fcc = 0; 206 else { 207 if (fcc <= 0) 208 break; 209 fbp = fibuf; 210 } 211 } 212 if (ibits & (1<<p)) { 213 pcc = read(p, pibuf, sizeof (pibuf)); 214 /* fprintf(console, "%d from p, buf[0] %x, errno %d\r\n", pcc, buf[0], errno); */ 215 pbp = pibuf; 216 if (pcc < 0 && errno == EWOULDBLOCK) 217 pcc = 0; 218 else if (pcc <= 0) 219 pcc = -1; 220 else if (pibuf[0] == 0) 221 pbp++, pcc--; 222 else { 223 if (pibuf[0]&(TIOCPKT_FLUSHWRITE| 224 TIOCPKT_NOSTOP| 225 TIOCPKT_DOSTOP)) { 226 int nstop = pibuf[0] & 227 (TIOCPKT_NOSTOP| 228 TIOCPKT_DOSTOP); 229 if (nstop) 230 stop = nstop; 231 pibuf[0] |= nstop; 232 send(f,&pibuf[0],1,SOF_OOB); 233 } 234 pcc = 0; 235 } 236 } 237 if ((obits & (1<<f)) && pcc > 0) { 238 cc = write(f, pbp, pcc); 239 /* fprintf(console, "%d of %d to f\r\n", cc, pcc); */ 240 if (cc > 0) { 241 pcc -= cc; 242 pbp += cc; 243 } 244 } 245 if ((obits & (1<<p)) && fcc > 0) { 246 cc = write(p, fbp, fcc); 247 /* fprintf(console, "%d of %d to p\r\n", cc, fcc); */ 248 if (cc > 0) { 249 fcc -= cc; 250 fbp += cc; 251 } 252 } 253 } 254 cleanup(); 255 } 256 close(f); 257 close(p); 258 dup2(t, 0); 259 dup2(t, 1); 260 dup2(t, 2); 261 close(t); 262 execl("/bin/login", "login", "-r", hp->h_name, 0); 263 fatalperror(2, "/bin/login", errno); 264 /*NOTREACHED*/ 265 } 266 267 cleanup() 268 { 269 int how = 2; 270 271 rmut(); 272 ioctl(netf, SIOCDONE, &how); 273 kill(0, SIGKILL); 274 exit(1); 275 } 276 277 fatal(f, msg) 278 int f; 279 char *msg; 280 { 281 char buf[BUFSIZ]; 282 283 buf[0] = '\01'; /* error indicator */ 284 (void) sprintf(buf + 1, "rlogind: %s.\n", msg); 285 (void) write(f, buf, strlen(buf)); 286 exit(1); 287 } 288 289 fatalperror(f, msg, errno) 290 int f; 291 char *msg; 292 int errno; 293 { 294 char buf[BUFSIZ]; 295 extern char *sys_errlist[]; 296 297 (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); 298 fatal(f, buf); 299 } 300 301 #include <utmp.h> 302 303 struct utmp wtmp; 304 char wtmpf[] = "/usr/adm/wtmp"; 305 char utmp[] = "/etc/utmp"; 306 #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 307 #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 308 309 rmut() 310 { 311 register f; 312 int found = 0; 313 314 f = open(utmp, 2); 315 if (f >= 0) { 316 while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { 317 if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0) 318 continue; 319 lseek(f, -(long)sizeof(wtmp), 1); 320 SCPYN(wtmp.ut_name, ""); 321 time(&wtmp.ut_time); 322 write(f, (char *)&wtmp, sizeof(wtmp)); 323 found++; 324 } 325 close(f); 326 } 327 if (found) { 328 f = open(wtmpf, 1); 329 if (f >= 0) { 330 SCPYN(wtmp.ut_line, line+5); 331 SCPYN(wtmp.ut_name, ""); 332 time(&wtmp.ut_time); 333 lseek(f, (long)0, 2); 334 write(f, (char *)&wtmp, sizeof(wtmp)); 335 close(f); 336 } 337 } 338 chmod(line, 0666); 339 chown(line, 0, 0); 340 line[strlen("/dev/")] = 'p'; 341 chmod(line, 0666); 342 chown(line, 0, 0); 343 } 344