diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /libexec/rexecd/rexecd.c |
initial import of NetBSD tree
Diffstat (limited to 'libexec/rexecd/rexecd.c')
-rw-r--r-- | libexec/rexecd/rexecd.c | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/libexec/rexecd/rexecd.c b/libexec/rexecd/rexecd.c new file mode 100644 index 00000000000..556587e8938 --- /dev/null +++ b/libexec/rexecd/rexecd.c @@ -0,0 +1,258 @@ +/* + * Copyright (c) 1983 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1983 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +/*static char sccsid[] = "from: @(#)rexecd.c 5.12 (Berkeley) 2/25/91";*/ +static char rcsid[] = "$Id: rexecd.c,v 1.1 1995/10/18 08:43:20 deraadt Exp $"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <signal.h> +#include <netdb.h> +#include <pwd.h> +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <paths.h> + +/*VARARGS1*/ +int error(); + +/* + * remote execute server: + * username\0 + * password\0 + * command\0 + * data + */ +/*ARGSUSED*/ +main(argc, argv) + int argc; + char **argv; +{ + struct sockaddr_in from; + int fromlen; + + fromlen = sizeof (from); + if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { + (void)fprintf(stderr, + "rexecd: getpeername: %s\n", strerror(errno)); + exit(1); + } + doit(0, &from); +} + +char username[20] = "USER="; +char homedir[64] = "HOME="; +char shell[64] = "SHELL="; +char path[sizeof(_PATH_DEFPATH) + sizeof("PATH=")] = "PATH="; +char *envinit[] = + {homedir, shell, path, username, 0}; +char **environ; + +struct sockaddr_in asin = { AF_INET }; + +doit(f, fromp) + int f; + struct sockaddr_in *fromp; +{ + char cmdbuf[NCARGS+1], *cp, *namep; + char user[16], pass[16]; + struct passwd *pwd; + int s; + u_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(_PATH_TTY, 2); + if (t >= 0) { + ioctl(t, TIOCNOTTY, (char *)0); + (void) close(t); + } + } +#endif + dup2(f, 0); + dup2(f, 1); + dup2(f, 2); + (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 = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) + exit(1); + if (bind(s, (struct sockaddr *)&asin, sizeof (asin)) < 0) + exit(1); + (void) alarm(60); + fromp->sin_port = htons(port); + if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) + exit(1); + (void) alarm(0); + } + getstr(user, sizeof(user), "username"); + getstr(pass, sizeof(pass), "password"); + getstr(cmdbuf, sizeof(cmdbuf), "command"); + setpwent(); + pwd = getpwnam(user); + if (pwd == NULL) { + error("Login incorrect.\n"); + exit(1); + } + endpwent(); + if (*pwd->pw_passwd != '\0') { + namep = crypt(pass, pwd->pw_passwd); + if (strcmp(namep, pwd->pw_passwd)) { + error("Password incorrect.\n"); + exit(1); + } + } + if (chdir(pwd->pw_dir) < 0) { + error("No remote directory.\n"); + exit(1); + } + (void) write(2, "\0", 1); + if (port) { + (void) pipe(pv); + 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(16, (fd_set *)&ready, + (fd_set *)NULL, (fd_set *)NULL, + (struct timeval *)NULL); + 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) { + shutdown(s, 1+1); + 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 = _PATH_BSHELL; + if (f > 2) + (void) close(f); + (void) setgid((gid_t)pwd->pw_gid); + initgroups(pwd->pw_name, pwd->pw_gid); + (void) setuid((uid_t)pwd->pw_uid); + (void)strcat(path, _PATH_DEFPATH); + 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); +} + +/*VARARGS1*/ +error(fmt, a1, a2, a3) + char *fmt; + int a1, a2, a3; +{ + char buf[BUFSIZ]; + + buf[0] = 1; + (void) sprintf(buf+1, fmt, a1, a2, a3); + (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); +} |