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