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