|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: char copyright[] = ! 9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\ ! 10: All rights reserved.\n"; ! 11: #endif not lint ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)rshd.c 5.7 (Berkeley) 5/9/86"; ! 15: #endif not lint ! 16: ! 17: /* ! 18: * remote shell server: ! 19: * remuser\0 ! 20: * locuser\0 ! 21: * command\0 ! 22: * data ! 23: */ ! 24: #include <sys/ioctl.h> ! 25: #include <sys/param.h> ! 26: #include <sys/socket.h> ! 27: #include <sys/time.h> ! 28: ! 29: #include <netinet/in.h> ! 30: ! 31: #include <arpa/inet.h> ! 32: ! 33: #include <stdio.h> ! 34: #include <errno.h> ! 35: #include <pwd.h> ! 36: #include <signal.h> ! 37: #include <netdb.h> ! 38: #include <syslog.h> ! 39: ! 40: int errno; ! 41: char *index(), *rindex(), *strncat(); ! 42: /*VARARGS1*/ ! 43: int error(); ! 44: ! 45: /*ARGSUSED*/ ! 46: main(argc, argv) ! 47: int argc; ! 48: char **argv; ! 49: { ! 50: struct linger linger; ! 51: int on = 1, fromlen; ! 52: struct sockaddr_in from; ! 53: ! 54: openlog("rsh", LOG_PID | LOG_ODELAY, LOG_DAEMON); ! 55: fromlen = sizeof (from); ! 56: if (getpeername(0, &from, &fromlen) < 0) { ! 57: fprintf(stderr, "%s: ", argv[0]); ! 58: perror("getpeername"); ! 59: _exit(1); ! 60: } ! 61: if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, ! 62: sizeof (on)) < 0) ! 63: syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); ! 64: linger.l_onoff = 1; ! 65: linger.l_linger = 60; /* XXX */ ! 66: if (setsockopt(0, SOL_SOCKET, SO_LINGER, (char *)&linger, ! 67: sizeof (linger)) < 0) ! 68: syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m"); ! 69: doit(dup(0), &from); ! 70: } ! 71: ! 72: char username[20] = "USER="; ! 73: char homedir[64] = "HOME="; ! 74: char shell[64] = "SHELL="; ! 75: char *envinit[] = ! 76: {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", username, 0}; ! 77: char **environ; ! 78: ! 79: doit(f, fromp) ! 80: int f; ! 81: struct sockaddr_in *fromp; ! 82: { ! 83: char cmdbuf[NCARGS+1], *cp; ! 84: char locuser[16], remuser[16]; ! 85: struct passwd *pwd; ! 86: int s; ! 87: struct hostent *hp; ! 88: char *hostname; ! 89: short port; ! 90: int pv[2], pid, ready, readfrom, cc; ! 91: char buf[BUFSIZ], sig; ! 92: int one = 1; ! 93: ! 94: (void) signal(SIGINT, SIG_DFL); ! 95: (void) signal(SIGQUIT, SIG_DFL); ! 96: (void) signal(SIGTERM, SIG_DFL); ! 97: #ifdef DEBUG ! 98: { int t = open("/dev/tty", 2); ! 99: if (t >= 0) { ! 100: ioctl(t, TIOCNOTTY, (char *)0); ! 101: (void) close(t); ! 102: } ! 103: } ! 104: #endif ! 105: fromp->sin_port = ntohs((u_short)fromp->sin_port); ! 106: if (fromp->sin_family != AF_INET || ! 107: fromp->sin_port >= IPPORT_RESERVED) { ! 108: syslog(LOG_ERR, "malformed from address\n"); ! 109: exit(1); ! 110: } ! 111: (void) alarm(60); ! 112: port = 0; ! 113: for (;;) { ! 114: char c; ! 115: if (read(f, &c, 1) != 1) { ! 116: syslog(LOG_ERR, "read: %m"); ! 117: shutdown(f, 1+1); ! 118: exit(1); ! 119: } ! 120: if (c == 0) ! 121: break; ! 122: port = port * 10 + c - '0'; ! 123: } ! 124: (void) alarm(0); ! 125: if (port != 0) { ! 126: int lport = IPPORT_RESERVED - 1; ! 127: s = rresvport(&lport); ! 128: if (s < 0) { ! 129: syslog(LOG_ERR, "can't get stderr port: %m"); ! 130: exit(1); ! 131: } ! 132: if (port >= IPPORT_RESERVED) { ! 133: syslog(LOG_ERR, "2nd port not reserved\n"); ! 134: exit(1); ! 135: } ! 136: fromp->sin_port = htons((u_short)port); ! 137: if (connect(s, fromp, sizeof (*fromp)) < 0) { ! 138: syslog(LOG_INFO, "connect second port: %m"); ! 139: exit(1); ! 140: } ! 141: } ! 142: dup2(f, 0); ! 143: dup2(f, 1); ! 144: dup2(f, 2); ! 145: hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr), ! 146: fromp->sin_family); ! 147: if (hp) ! 148: hostname = hp->h_name; ! 149: else ! 150: hostname = inet_ntoa(fromp->sin_addr); ! 151: getstr(remuser, sizeof(remuser), "remuser"); ! 152: getstr(locuser, sizeof(locuser), "locuser"); ! 153: getstr(cmdbuf, sizeof(cmdbuf), "command"); ! 154: setpwent(); ! 155: pwd = getpwnam(locuser); ! 156: if (pwd == NULL) { ! 157: error("Login incorrect.\n"); ! 158: exit(1); ! 159: } ! 160: endpwent(); ! 161: if (chdir(pwd->pw_dir) < 0) { ! 162: (void) chdir("/"); ! 163: #ifdef notdef ! 164: error("No remote directory.\n"); ! 165: exit(1); ! 166: #endif ! 167: } ! 168: if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' && ! 169: ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) { ! 170: error("Permission denied.\n"); ! 171: exit(1); ! 172: } ! 173: (void) write(2, "\0", 1); ! 174: if (port) { ! 175: if (pipe(pv) < 0) { ! 176: error("Can't make pipe.\n"); ! 177: exit(1); ! 178: } ! 179: pid = fork(); ! 180: if (pid == -1) { ! 181: error("Try again.\n"); ! 182: exit(1); ! 183: } ! 184: if (pid) { ! 185: (void) close(0); (void) close(1); (void) close(2); ! 186: (void) close(f); (void) close(pv[1]); ! 187: readfrom = (1<<s) | (1<<pv[0]); ! 188: ioctl(pv[1], FIONBIO, (char *)&one); ! 189: /* should set s nbio! */ ! 190: do { ! 191: ready = readfrom; ! 192: if (select(16, &ready, (fd_set *)0, ! 193: (fd_set *)0, (struct timeval *)0) < 0) ! 194: break; ! 195: if (ready & (1<<s)) { ! 196: if (read(s, &sig, 1) <= 0) ! 197: readfrom &= ~(1<<s); ! 198: else ! 199: killpg(pid, sig); ! 200: } ! 201: if (ready & (1<<pv[0])) { ! 202: errno = 0; ! 203: cc = read(pv[0], buf, sizeof (buf)); ! 204: if (cc <= 0) { ! 205: shutdown(s, 1+1); ! 206: readfrom &= ~(1<<pv[0]); ! 207: } else ! 208: (void) write(s, buf, cc); ! 209: } ! 210: } while (readfrom); ! 211: exit(0); ! 212: } ! 213: setpgrp(0, getpid()); ! 214: (void) close(s); (void) close(pv[0]); ! 215: dup2(pv[1], 2); ! 216: } ! 217: if (*pwd->pw_shell == '\0') ! 218: pwd->pw_shell = "/bin/sh"; ! 219: (void) close(f); ! 220: (void) setgid((gid_t)pwd->pw_gid); ! 221: initgroups(pwd->pw_name, pwd->pw_gid); ! 222: (void) setuid((uid_t)pwd->pw_uid); ! 223: environ = envinit; ! 224: strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); ! 225: strncat(shell, pwd->pw_shell, sizeof(shell)-7); ! 226: strncat(username, pwd->pw_name, sizeof(username)-6); ! 227: cp = rindex(pwd->pw_shell, '/'); ! 228: if (cp) ! 229: cp++; ! 230: else ! 231: cp = pwd->pw_shell; ! 232: execl(pwd->pw_shell, cp, "-c", cmdbuf, 0); ! 233: perror(pwd->pw_shell); ! 234: exit(1); ! 235: } ! 236: ! 237: /*VARARGS1*/ ! 238: error(fmt, a1, a2, a3) ! 239: char *fmt; ! 240: int a1, a2, a3; ! 241: { ! 242: char buf[BUFSIZ]; ! 243: ! 244: buf[0] = 1; ! 245: (void) sprintf(buf+1, fmt, a1, a2, a3); ! 246: (void) write(2, buf, strlen(buf)); ! 247: } ! 248: ! 249: getstr(buf, cnt, err) ! 250: char *buf; ! 251: int cnt; ! 252: char *err; ! 253: { ! 254: char c; ! 255: ! 256: do { ! 257: if (read(0, &c, 1) != 1) ! 258: exit(1); ! 259: *buf++ = c; ! 260: if (--cnt == 0) { ! 261: error("%s too long\n", err); ! 262: exit(1); ! 263: } ! 264: } while (c != 0); ! 265: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.