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