1 #ifndef lint 2 static char sccsid[] = "@(#)rshd.c 4.5 82/11/15"; 3 #endif 4 5 #include <sys/ioctl.h> 6 #include <sys/param.h> 7 #include <sys/socket.h> 8 9 #include <netinet/in.h> 10 11 #include <stdio.h> 12 #include <errno.h> 13 #include <pwd.h> 14 #include <wait.h> 15 #include <signal.h> 16 #include <netdb.h> 17 18 int errno; 19 struct sockaddr_in sin = { AF_INET }; 20 struct passwd *getpwnam(); 21 char *index(), *rindex(), *sprintf(); 22 int options = SO_ACCEPTCONN|SO_KEEPALIVE; 23 /* VARARGS 1 */ 24 int error(); 25 /* 26 * remote execute server: 27 * remuser\0 28 * locuser\0 29 * command\0 30 * data 31 */ 32 main(argc, argv) 33 int argc; 34 char **argv; 35 { 36 union wait status; 37 int f; 38 struct sockaddr_in from; 39 struct servent *sp; 40 41 sp = getservbyname("shell", "tcp"); 42 if (sp == 0) { 43 fprintf(stderr, "rshd: tcp/shell: 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 t = open("/dev/tty", 2); 55 if (t >= 0) { 56 ioctl(t, TIOCNOTTY, (char *)0); 57 (void) close(t); 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 argc--, argv++; 72 } 73 f = socket(AF_INET, SOCK_STREAM, 0, 0); 74 if (f < 0) { 75 perror("rshd: socket"); 76 exit(1); 77 } 78 if (bind(f, (caddr_t)&sin, sizeof (sin), 0) < 0) { 79 perror("rshd: bind"); 80 exit(1); 81 } 82 listen(f, 10); 83 for (;;) { 84 int g, len = sizeof (from); 85 86 g = accept(f, &from, &len, 0); 87 if (g < 0) { 88 perror("accept"); 89 sleep(1); 90 continue; 91 } 92 if (fork() == 0) { 93 close(f); 94 doit(g, &from); 95 } 96 close(g); 97 while (wait3(status, WNOHANG, 0) > 0) 98 continue; 99 } 100 } 101 102 char username[20] = "USER="; 103 char homedir[64] = "HOME="; 104 char shell[64] = "SHELL="; 105 char *envinit[] = 106 {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", username, 0}; 107 char **environ; 108 109 doit(f, fromp) 110 int f; 111 struct sockaddr_in *fromp; 112 { 113 char cmdbuf[NCARGS+1], *cp; 114 char locuser[16], remuser[16]; 115 struct passwd *pwd; 116 int s; 117 struct hostent *hp; 118 short port; 119 int pv[2], pid, ready, readfrom, cc; 120 char buf[BUFSIZ], sig; 121 int one = 1; 122 123 (void) signal(SIGINT, SIG_DFL); 124 (void) signal(SIGQUIT, SIG_DFL); 125 (void) signal(SIGTERM, SIG_DFL); 126 #ifdef DEBUG 127 { int t = open("/dev/tty", 2); 128 if (t >= 0) { 129 ioctl(t, TIOCNOTTY, (char *)0); 130 (void) close(t); 131 } 132 } 133 #endif 134 dup2(f, 0); 135 dup2(f, 1); 136 dup2(f, 2); 137 fromp->sin_port = ntohs((u_short)fromp->sin_port); 138 if (fromp->sin_family != AF_INET || 139 fromp->sin_port >= IPPORT_RESERVED) 140 exit(1); 141 (void) alarm(60); 142 port = 0; 143 for (;;) { 144 char c; 145 if (read(f, &c, 1) != 1) 146 exit(1); 147 if (c == 0) 148 break; 149 port = port * 10 + c - '0'; 150 } 151 (void) alarm(0); 152 if (port != 0) { 153 int lport = IPPORT_RESERVED - 1; 154 s = rresvport(0, &lport); 155 if (s < 0) 156 exit(1); 157 if (port >= IPPORT_RESERVED) 158 goto protofail; 159 (void) alarm(60); 160 fromp->sin_port = htons((u_short)port); 161 if (connect(s, fromp, sizeof (*fromp), 0) < 0) 162 exit(1); 163 (void) alarm(0); 164 } 165 hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), 166 fromp->sin_family); 167 if (hp == 0) { 168 error("Host name for your address unknown\n"); 169 exit(1); 170 } 171 getstr(remuser, sizeof(remuser), "remuser"); 172 getstr(locuser, sizeof(locuser), "locuser"); 173 getstr(cmdbuf, sizeof(cmdbuf), "command"); 174 setpwent(); 175 pwd = getpwnam(locuser); 176 if (pwd == NULL) { 177 error("Login incorrect.\n"); 178 exit(1); 179 } 180 endpwent(); 181 if (chdir(pwd->pw_dir) < 0) { 182 error("No remote directory.\n"); 183 exit(1); 184 } 185 if (ruserok(hp->h_name, remuser, locuser) < 0) { 186 error("Permission denied.\n"); 187 exit(1); 188 } 189 (void) write(2, "\0", 1); 190 if (port) { 191 if (pipe(pv) < 0) { 192 error("Can't make pipe.\n"); 193 exit(1); 194 } 195 pid = fork(); 196 if (pid == -1) { 197 error("Try again.\n"); 198 exit(1); 199 } 200 if (pid) { 201 (void) close(0); (void) close(1); (void) close(2); 202 (void) close(f); (void) close(pv[1]); 203 readfrom = (1<<s) | (1<<pv[0]); 204 ioctl(pv[1], FIONBIO, (char *)&one); 205 /* should set s nbio! */ 206 do { 207 ready = readfrom; 208 if (select(16, &ready, 0, 0, 0) < 0) 209 break; 210 if (ready & (1<<s)) { 211 if (read(s, &sig, 1) <= 0) 212 readfrom &= ~(1<<s); 213 else 214 killpg(pid, sig); 215 } 216 if (ready & (1<<pv[0])) { 217 cc = read(pv[0], buf, sizeof (buf)); 218 if (cc <= 0) { 219 int done = 1+1; 220 ioctl(s, SIOCDONE, (char *)&done); 221 readfrom &= ~(1<<pv[0]); 222 } else 223 (void) write(s, buf, cc); 224 } 225 } while (readfrom); 226 exit(0); 227 } 228 setpgrp(0, getpid()); 229 (void) close(s); (void) close(pv[0]); 230 dup2(pv[1], 2); 231 } 232 if (*pwd->pw_shell == '\0') 233 pwd->pw_shell = "/bin/sh"; 234 (void) close(f); 235 initgroups(pwd->pw_name, pwd->pw_gid); 236 (void) setuid(pwd->pw_uid); 237 (void) setgid(pwd->pw_gid); 238 environ = envinit; 239 strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); 240 strncat(shell, pwd->pw_shell, sizeof(shell)-7); 241 strncat(username, pwd->pw_name, sizeof(username)-6); 242 cp = rindex(pwd->pw_shell, '/'); 243 if (cp) 244 cp++; 245 else 246 cp = pwd->pw_shell; 247 execl(pwd->pw_shell, cp, "-c", cmdbuf, 0); 248 perror(pwd->pw_shell); 249 exit(1); 250 protofail: 251 error("rsh: protocol failure detected by remote\n"); 252 exit(1); 253 } 254 255 /* VARARGS 1 */ 256 error(fmt) 257 char *fmt; 258 { 259 char buf[BUFSIZ]; 260 261 buf[0] = 1; 262 (void) sprintf(buf+1, fmt); 263 (void) write(2, buf, strlen(buf)); 264 } 265 266 getstr(buf, cnt, err) 267 char *buf; 268 int cnt; 269 char *err; 270 { 271 char c; 272 273 do { 274 if (read(0, &c, 1) != 1) 275 exit(1); 276 *buf++ = c; 277 if (--cnt == 0) { 278 error("%s too long\n", err); 279 exit(1); 280 } 281 } while (c != 0); 282 } 283