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