Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 24 Aug 2000 20:30:03 -0700 (PDT)
From:      Warner Losh <imp@village.org>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: bin/15830: PATCH: rdump over ssh
Message-ID:  <200008250330.UAA87688@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/15830; it has been noted by GNATS.

From: Warner Losh <imp@village.org>
To: freebsd-gnats-submit@FreeBSD.org
Cc: naddy@mips.rhein-neckar.de
Subject: Re: bin/15830: PATCH: rdump over ssh
Date: Thu, 24 Aug 2000 21:29:59 -0600

 I don't like this at all.  It is too specific to dump.  Why not take a
 page from OpenBSD and do the following?
 
 Warner
 
 Index: net/Makefile.inc
 ===================================================================
 RCS file: /home/imp/FreeBSD/CVS/src/lib/libc/net/Makefile.inc,v
 retrieving revision 1.37
 diff -u -r1.37 Makefile.inc
 --- net/Makefile.inc	2000/07/05 02:13:14	1.37
 +++ net/Makefile.inc	2000/08/25 03:21:51
 @@ -16,7 +16,7 @@
  	inet_pton.c ip6opt.c linkaddr.c map_v4v6.c name6.c ns_addr.c \
  	ns_name.c ns_netint.c \
  	ns_ntoa.c ns_parse.c ns_print.c ns_ttl.c nsap_addr.c \
 -	rcmd.c recv.c res_comp.c res_data.c res_debug.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 
 Index: net/rcmd.c
 ===================================================================
 RCS file: /home/imp/FreeBSD/CVS/src/lib/libc/net/rcmd.c,v
 retrieving revision 1.29
 diff -u -r1.29 rcmd.c
 --- net/rcmd.c	2000/08/10 17:10:57	1.29
 +++ net/rcmd.c	2000/08/25 03:21:54
 @@ -47,6 +47,7 @@
  #include <signal.h>
  #include <fcntl.h>
  #include <netdb.h>
 +#include <stdlib.h>
  #include <unistd.h>
  #include <pwd.h>
  #include <errno.h>
 @@ -99,9 +100,27 @@
  	long oldmask;
  	pid_t pid;
  	int s, aport, lport, timo, error;
 -	char c;
 +	char c, *p;
  	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();
  
 Index: net/rcmdsh.3
 ===================================================================
 RCS file: rcmdsh.3
 diff -N rcmdsh.3
 --- /dev/null	Thu Aug 24 20:04:33 2000
 +++ rcmdsh.3	Thu Aug 24 20:21:54 2000
 @@ -0,0 +1,103 @@
 +.\"	$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.
 +.\"
 +.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 .
 Index: net/rcmdsh.c
 ===================================================================
 RCS file: rcmdsh.c
 diff -N rcmdsh.c
 --- /dev/null	Thu Aug 24 20:04:33 2000
 +++ rcmdsh.c	Thu Aug 24 20:21:54 2000
 @@ -0,0 +1,128 @@
 +/*	$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>.
 + */
 +
 +#if defined(LIBC_SCCS) && !defined(lint)
 +static char *rcsid = "$OpenBSD: rcmdsh.c,v 1.5 1998/04/25 16:23:58 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>
 +#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 */
 +}
 Index: net/res_query.c
 ===================================================================
 RCS file: /home/imp/FreeBSD/CVS/src/lib/libc/net/res_query.c,v
 retrieving revision 1.19
 diff -u -r1.19 res_query.c
 --- net/res_query.c	1999/11/04 04:30:44	1.19
 +++ net/res_query.c	2000/08/25 03:21:55
 @@ -76,6 +76,7 @@
  
  #include <sys/types.h>
  #include <sys/param.h>
 +#include <sys/stat.h>
  #include <netinet/in.h>
  #include <arpa/inet.h>
  #include <arpa/nameser.h>
 @@ -376,14 +377,23 @@
  	char *file;
  	char buf[BUFSIZ];
  	static char abuf[MAXDNAME];
 +	struct stat sb;
  
  	if (_res.options & RES_NOALIASES)
  		return (NULL);
 -	if (issetugid())
 -		return (NULL);
  	file = getenv("HOSTALIASES");
  	if (file == NULL || (fp = fopen(file, "r")) == NULL)
  		return (NULL);
 +	if (issetugid()) {
 +		if (fstat(fileno(fp), &sb)) {
 +			fclose(fp);
 +			return (NULL);
 +		}
 +		if ((sb.st_mode & 0444) != 0444) {
 +			fclose(fp);
 +			return (NULL);
 +		}
 +	}
  	setbuf(fp, NULL);
  	buf[sizeof(buf) - 1] = '\0';
  	while (fgets(buf, sizeof(buf), fp)) {
 


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200008250330.UAA87688>