date and time created 82/04/02 10:29:04 by wnj
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Sat, 3 Apr 1982 01:29:04 +0000 (17:29 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Sat, 3 Apr 1982 01:29:04 +0000 (17:29 -0800)
SCCS-vsn: libexec/rshd/rshd.c 4.1

usr/src/libexec/rshd/rshd.c [new file with mode: 0644]

diff --git a/usr/src/libexec/rshd/rshd.c b/usr/src/libexec/rshd/rshd.c
new file mode 100644 (file)
index 0000000..40eac9c
--- /dev/null
@@ -0,0 +1,262 @@
+#ifndef lint
+static char sccsid[] = "@(#)rshd.c     4.1 82/04/02";
+#endif
+
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/in.h>
+#include <errno.h>
+#include <pwd.h>
+#include <wait.h>
+#include <signal.h>
+
+int    errno;
+struct sockaddr_in sin = { AF_INET, IPPORT_CMDSERVER };
+struct passwd *getpwnam();
+char   *index(), *rindex(), *raddr(), *sprintf();
+int    options = SO_ACCEPTCONN|SO_KEEPALIVE;
+/* VARARGS 1 */
+int    error();
+/*
+ * remote execute server:
+ *     remuser\0
+ *     locuser\0
+ *     command\0
+ *     data
+ */
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       union wait status;
+       int f;
+       struct sockaddr_in from;
+
+#ifndef DEBUG
+       if (fork())
+               exit(0);
+       for (f = 0; f < 10; f++)
+               (void) close(f);
+       (void) open("/", 0);
+       (void) dup2(0, 1);
+       (void) dup2(0, 2);
+       { int t = open("/dev/tty", 2);
+         if (t >= 0) {
+               ioctl(t, TIOCNOTTY, (char *)0);
+               (void) close(t);
+         }
+       }
+#endif
+#if vax
+       sin.sin_port = htons(sin.sin_port);
+#endif
+       argc--, argv++;
+       if (argc > 0 && !strcmp(argv[0], "-d"))
+               options |= SO_DEBUG;
+       for (;;) {
+               errno = 0;
+               f = socket(SOCK_STREAM, 0, &sin, options);
+               if (f < 0) {
+                       perror("socket");
+                       sleep(5);
+                       continue;
+               }
+               if (accept(f, &from) < 0) {
+                       perror("accept");
+                       (void) close(f);
+                       sleep(1);
+                       continue;
+               }
+               if (fork() == 0)
+                       doit(f, &from);
+               (void) close(f);
+               while(wait3(status, WNOHANG, 0) > 0)
+                       continue;
+       }
+}
+
+char   username[20] = "USER=";
+char   homedir[64] = "HOME=";
+char   shell[64] = "SHELL=";
+char   *envinit[] =
+           {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", username, 0};
+char   **environ;
+
+doit(f, fromp)
+       int f;
+       struct sockaddr_in *fromp;
+{
+       char cmdbuf[NCARGS+1], *cp;
+       char locuser[16], remuser[16];
+       struct passwd *pwd;
+       char *rhost;
+       int s;
+       short port;
+       int pv[2], pid, ready, readfrom, cc;
+       char buf[BUFSIZ], sig;
+       int one = 1;
+
+       (void) signal(SIGINT, SIG_DFL);
+       (void) signal(SIGQUIT, SIG_DFL);
+       (void) signal(SIGTERM, SIG_DFL);
+#ifdef DEBUG
+       { int t = open("/dev/tty", 2);
+         if (t >= 0) {
+               ioctl(t, TIOCNOTTY, (char *)0);
+               (void) close(t);
+         }
+       }
+#endif
+       dup2(f, 0);
+       dup2(f, 1);
+       dup2(f, 2);
+#if vax
+       fromp->sin_port = ntohs((u_short)fromp->sin_port);
+#endif
+       if (fromp->sin_family != AF_INET ||
+           fromp->sin_port >= IPPORT_RESERVED)
+               exit(1);
+       (void) alarm(60);
+       port = 0;
+       for (;;) {
+               char c;
+               if (read(f, &c, 1) != 1)
+                       exit(1);
+               if (c == 0)
+                       break;
+               port = port * 10 + c - '0';
+       }
+       (void) alarm(0);
+       if (port != 0) {
+               s = rresvport(0);
+               if (s < 0)
+                       exit(1);
+               if (port >= IPPORT_RESERVED)
+                       goto protofail;
+               (void) alarm(60);
+               fromp->sin_port = port;
+#if vax
+               fromp->sin_port = ntohs(fromp->sin_port);
+#endif
+               if (connect(s, fromp) < 0)
+                       exit(1);
+               (void) alarm(0);
+       }
+       rhost = raddr(fromp->sin_addr.s_addr);
+       if (rhost == 0) {
+               error("Host name for your address unknown\n");
+               exit(1);
+       }
+       getstr(remuser, sizeof(remuser), "remuser");
+       getstr(locuser, sizeof(locuser), "locuser");
+       getstr(cmdbuf, sizeof(cmdbuf), "command");
+       setpwent();
+       pwd = getpwnam(locuser);
+       if (pwd == NULL) {
+               error("Login incorrect.\n");
+               exit(1);
+       }
+       endpwent();
+       if (chdir(pwd->pw_dir) < 0) {
+               error("No remote directory.\n");
+               exit(1);
+       }
+       if (ruserok(rhost, remuser, locuser) < 0) {
+               error("Permission denied.\n");
+               exit(1);
+       }
+       (void) write(2, "\0", 1);
+       if (port) {
+               if (pipe(pv) < 0) {
+                       error("Can't make pipe.\n");
+                       exit(1);
+               }
+               pid = fork();
+               if (pid == -1)  {
+                       error("Try again.\n");
+                       exit(1);
+               }
+               if (pid) {
+                       (void) close(0); (void) close(1); (void) close(2);
+                       (void) close(f); (void) close(pv[1]);
+                       readfrom = (1<<s) | (1<<pv[0]);
+                       ioctl(pv[1], FIONBIO, (char *)&one);
+                       /* should set s nbio! */
+                       do {
+                               ready = readfrom;
+                               (void) select(32, &ready, 0, 1000000);
+                               if (ready & (1<<s)) {
+                                       if (read(s, &sig, 1) <= 0)
+                                               readfrom &= ~(1<<s);
+                                       else
+                                               killpg(pid, sig);
+                               }
+                               if (ready & (1<<pv[0])) {
+                                       cc = read(pv[0], buf, sizeof (buf));
+                                       if (cc <= 0) {
+                                               int done = 1+1;
+                                               ioctl(s, SIOCDONE, (char *)&done);
+                                               readfrom &= ~(1<<pv[0]);
+                                       } else
+                                               (void) write(s, buf, cc);
+                               }
+                       } while (readfrom);
+                       exit(0);
+               }
+               setpgrp(0, getpid());
+               (void) close(s); (void) close(pv[0]);
+               dup2(pv[1], 2);
+       }
+       if (*pwd->pw_shell == '\0')
+               pwd->pw_shell = "/bin/sh";
+       (void) close(f);
+       inigrp(pwd->pw_name, pwd->pw_gid);
+       (void) setuid(pwd->pw_uid);
+       (void) setgid(pwd->pw_gid);
+       environ = envinit;
+       strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
+       strncat(shell, pwd->pw_shell, sizeof(shell)-7);
+       strncat(username, pwd->pw_name, sizeof(username)-6);
+       cp = rindex(pwd->pw_shell, '/');
+       if (cp)
+               cp++;
+       else
+               cp = pwd->pw_shell;
+       execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
+       perror(pwd->pw_shell);
+       exit(1);
+protofail:
+       error("rsh: protocol failure detected by remote\n");
+       exit(1);
+}
+
+/* VARARGS 1 */
+error(fmt)
+       char *fmt;
+{
+       char buf[BUFSIZ];
+
+       buf[0] = 1;
+       (void) sprintf(buf+1, fmt);
+       (void) write(2, buf, strlen(buf));
+}
+
+getstr(buf, cnt, err)
+       char *buf;
+       int cnt;
+       char *err;
+{
+       char c;
+
+       do {
+               if (read(0, &c, 1) != 1)
+                       exit(1);
+               *buf++ = c;
+               if (--cnt == 0) {
+                       error("%s too long\n", err);
+                       exit(1);
+               }
+       } while (c != 0);
+}