diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 1996-08-22 20:11:21 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 1996-08-22 20:11:21 +0000 |
commit | 83401538373dbe9ae9dc907fffe379a27ceed105 (patch) | |
tree | 8e736b346be052e4150f6830746fbc40f1d42274 /lib | |
parent | 4fd0ce9848c054a28ab996c0ee838875b475b5bd (diff) |
Adds rcmdsh() -- rcmd-alike using rsh (or specified shell).
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/net/Makefile.inc | 4 | ||||
-rw-r--r-- | lib/libc/net/rcmdsh.c | 120 |
2 files changed, 122 insertions, 2 deletions
diff --git a/lib/libc/net/Makefile.inc b/lib/libc/net/Makefile.inc index e71a0f99fe5..708684876ab 100644 --- a/lib/libc/net/Makefile.inc +++ b/lib/libc/net/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.6 1996/08/19 08:28:32 tholo Exp $ +# $OpenBSD: Makefile.inc,v 1.7 1996/08/22 20:11:19 millert Exp $ # net sources .PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/net ${.CURDIR}/net @@ -10,7 +10,7 @@ SRCS+= gethostnamadr.c getnetbyaddr.c getnetbyname.c getnetent.c \ ipx_addr.c ipx_ntoa.c \ iso_addr.c linkaddr.c ns_addr.c ns_ntoa.c nsap_addr.c rcmd.c recv.c \ res_comp.c res_debug.c res_init.c res_mkquery.c res_query.c \ - res_send.c send.c sethostent.c ethers.c + res_send.c send.c sethostent.c ethers.c rcmdsh.c # machine-dependent net sources # m-d Makefile.inc must include sources for: diff --git a/lib/libc/net/rcmdsh.c b/lib/libc/net/rcmdsh.c new file mode 100644 index 00000000000..47b200ed682 --- /dev/null +++ b/lib/libc/net/rcmdsh.c @@ -0,0 +1,120 @@ +/* $OpenBSD: rcmdsh.c,v 1.1 1996/08/22 20:11:20 millert Exp $ */ + +/* + * This is an rcmd() replacement originally by + * Chris Siebenmann <cks@utcc.utoronto.ca>. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: rcmdsh.c,v 1.1 1996/08/22 20:11:20 millert Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <signal.h> +#include <errno.h> +#include <netdb.h> +#include <stdio.h> +#include <string.h> +#include <pwd.h> +#include <paths.h> + +/* + * This is a replacement rcmd() function that uses the rsh(1) + * program in place of a direct rcmd(3) function call so as to + * avoid having to be root. Note that rport is ignored. + */ +int +rcmdsh(ahost, rport, locuser, remuser, cmd, rshprog) + char **ahost; + u_short rport; + char *locuser, *remuser, *cmd; + char *rshprog; +{ + struct hostent *hp; + int cpid, sp[2]; + char *p; + struct passwd *pw; + + /* What rsh/shell to use. */ + if (rshprog == NULL) + rshprog = _PATH_RSH; + + /* locuser must exist on this host. */ + if ((pw = getpwnam(locuser)) == NULL) { + (void) fprintf(stderr, "rcmdsh: unknown user: %s\n", locuser); + return(-1); + } + + /* Validate remote hostname. */ + if ((hp = gethostbyname(*ahost)) == NULL) { + herror(*ahost); + return(-1); + } + *ahost = hp->h_name; + + /* Get a socketpair we'll use for stdin and stdout. */ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) < 0) { + perror("rcmdsh: socketpair"); + return(-1); + } + + cpid = fork(); + if (cpid < 0) { + perror("rcmdsh: fork failed"); + return(-1); + } else if (cpid == 0) { + /* + * Child. We use sp[1] to be stdin/stdout, and close sp[0]. + */ + (void) close(sp[0]); + if (dup2(sp[1], 0) < 0 || dup2(0, 1) < 0 || dup2(0, 2) < 0) { + perror("rcmdsh: dup2 failed"); + _exit(255); + } + /* Fork again to lose parent. */ + cpid = fork(); + if (cpid < 0) { + perror("rcmdsh: fork to lose parent failed"); + _exit(255); + } + if (cpid > 0) + _exit(0); + + /* In grandchild here. Become local user for rshprog. */ + if (setuid(pw->pw_uid)) { + (void) fprintf(stderr, "rcmdsh: setuid(%u): %s\n", + pw->pw_uid, strerror(errno)); + _exit(255); + } + + /* + * If remote host is "localhost" and local and remote user + * are the same, avoid running remote shell for efficiency. + */ + if (!strcmp(*ahost, "localhost") && !strcmp(locuser, remuser)) { + if (pw->pw_shell[0] == '\0') + rshprog = _PATH_BSHELL; + else + rshprog = pw->pw_shell; + p = strrchr(rshprog, '/'); + execlp(rshprog, p ? p+1 : rshprog, "-c", cmd, + (char *) NULL); + } else { + p = strrchr(rshprog, '/'); + execlp(rshprog, p ? p+1 : rshprog, *ahost, "-l", + remuser, cmd, (char *) NULL); + } + (void) fprintf(stderr, "rcmdsh: execlp %s failed: %s\n", + rshprog, strerror(errno)); + _exit(255); + } else if (cpid > 0) { + /* Parent. close sp[1], return sp[0]. */ + (void) close(sp[1]); + /* Reap child. */ + (void) wait(NULL); + return(sp[0]); + } + /*NOTREACHED*/ +} |