Allow users to specify a command to use as remote command instead of
using rcmd directly. This has been in my tree for a long time, but we may need to sync with OpenBSD before MFC. Obtained from: openbsd PR: 15830 MFC after: 2 months
This commit is contained in:
parent
4f467cb8c1
commit
d45672120f
@ -17,7 +17,7 @@ SRCS+= addr2ascii.c ascii2addr.c base64.c ether_addr.c getaddrinfo.c \
|
||||
ns_name.c ns_netint.c \
|
||||
ns_ntoa.c ns_parse.c ns_print.c ns_ttl.c \
|
||||
nsdispatch.c nslexer.c nsparser.c \
|
||||
nsap_addr.c rcmd.c recv.c res_comp.c res_data.c res_debug.c \
|
||||
nsap_addr.c rcmd.c rcmdsh.c recv.c res_comp.c res_data.c res_debug.c \
|
||||
res_init.c res_mkquery.c res_mkupdate.c res_query.c res_send.c \
|
||||
res_update.c rthdr.c send.c vars.c
|
||||
# not supported: iso_addr.c
|
||||
@ -48,7 +48,7 @@ MAN+= addr2ascii.3 byteorder.3 ethers.3 getaddrinfo.3 gethostbyname.3 \
|
||||
if_indextoname.3 \
|
||||
inet.3 inet_net.3 \
|
||||
inet6_option_space.3 inet6_rthdr_space.3 linkaddr.3 \
|
||||
nsdispatch.3 rcmd.3 resolver.3
|
||||
nsdispatch.3 rcmd.3 rcmdsh.3 resolver.3
|
||||
# not installed: iso_addr.3 ns.3
|
||||
|
||||
MLINKS+=addr2ascii.3 ascii2addr.3
|
||||
|
@ -48,6 +48,7 @@ static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94";
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
@ -105,11 +106,29 @@ rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
|
||||
sigset_t oldmask, newmask;
|
||||
pid_t pid;
|
||||
int s, aport, lport, timo, error;
|
||||
char c;
|
||||
char c, *p;
|
||||
int refused, nres;
|
||||
char num[8];
|
||||
static char canonnamebuf[MAXDNAME]; /* is it proper here? */
|
||||
|
||||
/* call rcmdsh() with specified remote shell if appropriate. */
|
||||
if (!issetugid() && (p = getenv("RSH"))) {
|
||||
struct servent *sp = getservbyname("shell", "tcp");
|
||||
|
||||
if (sp && sp->s_port == rport)
|
||||
return (rcmdsh(ahost, rport, locuser, remuser,
|
||||
cmd, p));
|
||||
}
|
||||
|
||||
/* use rsh(1) if non-root and remote port is shell. */
|
||||
if (geteuid()) {
|
||||
struct servent *sp = getservbyname("shell", "tcp");
|
||||
|
||||
if (sp && sp->s_port == rport)
|
||||
return (rcmdsh(ahost, rport, locuser, remuser,
|
||||
cmd, NULL));
|
||||
}
|
||||
|
||||
pid = getpid();
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
@ -579,9 +598,6 @@ __ivaliduser_af(hostf, raddr, luser, ruser, af, len)
|
||||
return __ivaliduser_sa(hostf, sa, sa->sa_len, luser, ruser);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0 if ok, -1 if not ok.
|
||||
*/
|
||||
int
|
||||
__ivaliduser_sa(hostf, raddr, salen, luser, ruser)
|
||||
FILE *hostf;
|
||||
|
105
lib/libc/net/rcmdsh.3
Normal file
105
lib/libc/net/rcmdsh.3
Normal file
@ -0,0 +1,105 @@
|
||||
.\" $OpenBSD: rcmdsh.3,v 1.6 1999/07/05 04:41:00 aaron Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1983, 1991, 1993
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 1, 1996
|
||||
.Dt RCMDSH 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rcmdsh
|
||||
.Nd return a stream to a remote command without superuser
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <unistd.h>
|
||||
.Ft int
|
||||
.Fn rcmdsh "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "char *rshprog"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn rcmdsh
|
||||
function
|
||||
is used by normal users to execute a command on
|
||||
a remote machine using an authentication scheme based
|
||||
on reserved port numbers using
|
||||
.Xr rshd 8
|
||||
or the value of
|
||||
.Fa rshprog
|
||||
(if non-null).
|
||||
.Pp
|
||||
The
|
||||
.Fn rcmdsh
|
||||
function
|
||||
looks up the host
|
||||
.Fa *ahost
|
||||
using
|
||||
.Xr gethostbyname 3 ,
|
||||
returning \-1 if the host does not exist.
|
||||
Otherwise
|
||||
.Fa *ahost
|
||||
is set to the standard name of the host
|
||||
and a connection is established to a server
|
||||
residing at the well-known Internet port
|
||||
.Li shell/tcp
|
||||
(or whatever port is used by
|
||||
.Fa rshprog
|
||||
). The parameter
|
||||
.Fa inport
|
||||
is ignored; it is only included to provide an interface similar to
|
||||
.Xr rcmd 3 .
|
||||
.Pp
|
||||
If the connection succeeds,
|
||||
a socket in the
|
||||
.Tn UNIX
|
||||
domain of type
|
||||
.Dv SOCK_STREAM
|
||||
is returned to the caller, and given to the remote
|
||||
command as stdin and stdout, and stderr.
|
||||
.Sh DIAGNOSTICS
|
||||
The
|
||||
.Fn rcmdsh
|
||||
function
|
||||
returns a valid socket descriptor on success.
|
||||
It returns \-1 on error and prints a diagnostic message on the standard error.
|
||||
.Sh SEE ALSO
|
||||
.Xr rsh 1 ,
|
||||
.Xr socketpair 2 ,
|
||||
.Xr rcmd 3 ,
|
||||
.Xr rshd 8
|
||||
.Sh BUGS
|
||||
If
|
||||
.Xr rsh 1
|
||||
gets an error a file descriptor is still returned instead of \-1.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn rcmdsh
|
||||
function first appeared in
|
||||
.Ox 2.0 .
|
130
lib/libc/net/rcmdsh.c
Normal file
130
lib/libc/net/rcmdsh.c
Normal file
@ -0,0 +1,130 @@
|
||||
/* $OpenBSD: rcmdsh.c,v 1.5 1998/04/25 16:23:58 millert Exp $ */
|
||||
|
||||
/*
|
||||
* This is an rcmd() replacement originally by
|
||||
* Chris Siebenmann <cks@utcc.utoronto.ca>.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char *rcsid = "$FreeBSD$"
|
||||
#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>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef _PATH_RSH
|
||||
#define _PATH_RSH "/usr/bin/rsh"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
int
|
||||
rcmdsh(ahost, rport, locuser, remuser, cmd, rshprog)
|
||||
char **ahost;
|
||||
int rport;
|
||||
const 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 (strcmp(*ahost, "localhost") != 0) {
|
||||
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, PF_UNSPEC, 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) {
|
||||
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 {
|
||||
/* Parent. close sp[1], return sp[0]. */
|
||||
(void) close(sp[1]);
|
||||
/* Reap child. */
|
||||
(void) wait(NULL);
|
||||
return(sp[0]);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
Loading…
Reference in New Issue
Block a user