1 #ifndef lint 2 static char sccsid[] = "@(#)rlogind.c 4.1 82/04/02"; 3 #endif 4 5 #include <stdio.h> 6 #include <sys/types.h> 7 #include <sys/stat.h> 8 #include <sys/socket.h> 9 #include <net/in.h> 10 #include <errno.h> 11 #include <pwd.h> 12 #include <wait.h> 13 #include <signal.h> 14 #include <sgtty.h> 15 #include <stdio.h> 16 17 extern errno; 18 struct passwd *getpwnam(); 19 char *crypt(), *rindex(), *index(), *malloc(), *raddr(); 20 int options = SO_ACCEPTCONN|SO_KEEPALIVE; 21 struct sockaddr_in sin = { AF_INET, IPPORT_LOGINSERVER }; 22 /* 23 * remote login server: 24 * remuser\0 25 * locuser\0 26 * terminal type\0 27 * data 28 */ 29 main(argc, argv) 30 int argc; 31 char **argv; 32 { 33 union wait status; 34 int f, debug = 0; 35 struct sockaddr_in from; 36 37 #ifndef DEBUG 38 if (fork()) 39 exit(0); 40 for (f = 0; f < 10; f++) 41 (void) close(f); 42 (void) open("/", 0); 43 (void) dup2(0, 1); 44 (void) dup2(0, 2); 45 { int tt = open("/dev/tty", 2); 46 if (tt > 0) { 47 ioctl(tt, TIOCNOTTY, 0); 48 close(tt); 49 } 50 } 51 #endif 52 #if vax 53 sin.sin_port = htons(sin.sin_port); 54 #endif 55 argc--, argv++; 56 if (argc > 0 && !strcmp(argv[0], "-d")) 57 options |= SO_DEBUG; 58 for (;;) { 59 f = socket(SOCK_STREAM, 0, &sin, options); 60 if (f < 0) { 61 perror("socket"); 62 sleep(5); 63 continue; 64 } 65 if (accept(f, &from) < 0) { 66 perror("accept"); 67 close(f); 68 sleep(1); 69 continue; 70 } 71 if (fork() == 0) 72 doit(f, &from); 73 close(f); 74 while (wait3(status, WNOHANG, 0) > 0) 75 continue; 76 } 77 } 78 79 char locuser[32], remuser[32]; 80 char buf[BUFSIZ]; 81 int child; 82 int cleanup(); 83 int netf; 84 extern errno; 85 char *line; 86 87 doit(f, fromp) 88 int f; 89 struct sockaddr_in *fromp; 90 { 91 char c, *rhost; 92 int i, p, cc, t; 93 int stop = TIOCPKT_DOSTOP; 94 95 alarm(60); 96 read(f, &c, 1); 97 if (c != 0) 98 exit(1); 99 alarm(0); 100 #if vax 101 fromp->sin_port = htons(fromp->sin_port); 102 #endif 103 rhost = raddr(fromp->sin_addr.s_addr); 104 if (fromp->sin_family != AF_INET || 105 fromp->sin_port >= IPPORT_RESERVED || 106 rhost == 0) { 107 write(f, "\01Permission denied.\n", 20); 108 exit(1); 109 } 110 write(f, "", 1); 111 for (c = 'p'; c <= 's'; c++) { 112 struct stat stb; 113 line = "/dev/ptyXX"; 114 line[strlen("/dev/pty")] = c; 115 line[strlen("/dev/ptyp")] = '0'; 116 if (stat(line, &stb) < 0) 117 break; 118 for (i = 0; i < 16; i++) { 119 line[strlen("/dev/ptyp")] = "0123456789abcdef"[i]; 120 p = open(line, 2); 121 if (p > 0) 122 goto gotpty; 123 } 124 } 125 dup2(f, 1); 126 printf("All network ports in use.\r\n"); 127 exit(1); 128 gotpty: 129 dup2(f, 0); 130 line[strlen("/dev/")] = 't'; 131 #ifdef DEBUG 132 { int tt = open("/dev/tty", 2); 133 if (tt > 0) { 134 ioctl(tt, TIOCNOTTY, 0); 135 close(tt); 136 } 137 } 138 #endif 139 t = open(line, 2); 140 if (t < 0) { 141 dup2(f, 2); 142 perror(line); 143 exit(1); 144 } 145 { struct sgttyb b; 146 gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b); 147 } 148 if (fork()) { 149 char pibuf[1024], fibuf[1024], *pbp, *fbp; 150 int pcc = 0, fcc = 0, on = 1; 151 /* FILE *console = fopen("/dev/console", "w"); */ 152 /* setbuf(console, 0); */ 153 154 /* fprintf(console, "f %d p %d\r\n", f, p); */ 155 ioctl(f, FIONBIO, &on); 156 ioctl(p, FIONBIO, &on); 157 ioctl(p, TIOCPKT, &on); 158 signal(SIGTSTP, SIG_IGN); 159 sigset(SIGCHLD, cleanup); 160 for (;;) { 161 int ibits = 0, obits = 0; 162 if (fcc) obits |= (1<<p); else ibits |= (1<<f); 163 if (pcc >= 0) 164 if (pcc) obits |= (1<<f); else ibits |= (1<<p); 165 if (fcc < 0 && pcc < 0) break; 166 /* fprintf(console, "ibits from %d obits from %d\r\n", ibits, obits); */ 167 select(32, &ibits, &obits, 10000000); 168 /* fprintf(console, "ibits %d obits %d\r\n", ibits, obits); */ 169 if (ibits == 0 && obits == 0) { 170 sleep(5); 171 continue; 172 } 173 if (ibits & (1<<f)) { 174 fcc = read(f, fibuf, sizeof (fibuf)); 175 /* fprintf(console, "%d from f\r\n", fcc); */ 176 if (fcc < 0 && errno == EWOULDBLOCK) 177 fcc = 0; 178 else { 179 if (fcc <= 0) 180 break; 181 fbp = fibuf; 182 } 183 } 184 if (ibits & (1<<p)) { 185 pcc = read(p, pibuf, sizeof (pibuf)); 186 /* fprintf(console, "%d from p, buf[0] %x, errno %d\r\n", pcc, buf[0], errno); */ 187 pbp = pibuf; 188 if (pcc < 0 && errno == EWOULDBLOCK) 189 pcc = 0; 190 else if (pcc <= 0) 191 pcc = -1; 192 else if (pibuf[0] == 0) 193 pbp++, pcc--; 194 else { 195 if (pibuf[0]&(TIOCPKT_FLUSHWRITE| 196 TIOCPKT_NOSTOP| 197 TIOCPKT_DOSTOP)) { 198 int nstop = pibuf[0] & 199 (TIOCPKT_NOSTOP| 200 TIOCPKT_DOSTOP); 201 if (nstop) 202 stop = nstop; 203 pibuf[0] |= nstop; 204 ioctl(f,SIOCSENDOOB,&pibuf[0]); 205 } 206 pcc = 0; 207 } 208 } 209 if ((obits & (1<<f)) && pcc > 0) { 210 cc = write(f, pbp, pcc); 211 /* fprintf(console, "%d of %d to f\r\n", cc, pcc); */ 212 if (cc > 0) { 213 pcc -= cc; 214 pbp += cc; 215 } 216 } 217 if ((obits & (1<<p)) && fcc > 0) { 218 cc = write(p, fbp, fcc); 219 /* fprintf(console, "%d of %d to p\r\n", cc, fcc); */ 220 if (cc > 0) { 221 fcc -= cc; 222 fbp += cc; 223 } 224 } 225 } 226 cleanup(); 227 } 228 close(f); 229 close(p); 230 dup2(t, 0); 231 dup2(t, 1); 232 dup2(t, 2); 233 close(t); 234 execl("/bin/login", "login", "-r", rhost, 0); 235 perror("/bin/login"); 236 exit(1); 237 } 238 239 cleanup() 240 { 241 int how = 2; 242 243 rmut(); 244 ioctl(netf, SIOCDONE, &how); 245 kill(0, SIGKILL); 246 exit(1); 247 } 248 249 #include <utmp.h> 250 251 struct utmp wtmp; 252 char wtmpf[] = "/usr/adm/wtmp"; 253 char utmp[] = "/etc/utmp"; 254 #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 255 #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 256 257 rmut() 258 { 259 register f; 260 int found = 0; 261 262 f = open(utmp, 2); 263 if (f >= 0) { 264 while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { 265 if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0) 266 continue; 267 lseek(f, -(long)sizeof(wtmp), 1); 268 SCPYN(wtmp.ut_name, ""); 269 time(&wtmp.ut_time); 270 write(f, (char *)&wtmp, sizeof(wtmp)); 271 found++; 272 } 273 close(f); 274 } 275 if (found) { 276 f = open(wtmpf, 1); 277 if (f >= 0) { 278 SCPYN(wtmp.ut_line, line+5); 279 SCPYN(wtmp.ut_name, ""); 280 time(&wtmp.ut_time); 281 lseek(f, (long)0, 2); 282 write(f, (char *)&wtmp, sizeof(wtmp)); 283 close(f); 284 } 285 } 286 chmod(line, 0666); 287 chown(line, 0, 0); 288 line[strlen("/dev/")] = 'p'; 289 chmod(line, 0666); 290 chown(line, 0, 0); 291 } 292