From owner-freebsd-bugs Thu Aug 24 20:30:13 2000 Delivered-To: freebsd-bugs@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 14D8137B42C for ; Thu, 24 Aug 2000 20:30:03 -0700 (PDT) Received: (from gnats@localhost) by freefall.freebsd.org (8.9.3/8.9.2) id UAA87688; Thu, 24 Aug 2000 20:30:03 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Date: Thu, 24 Aug 2000 20:30:03 -0700 (PDT) Message-Id: <200008250330.UAA87688@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: Warner Losh Subject: Re: bin/15830: PATCH: rdump over ssh Reply-To: Warner Losh Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org The following reply was made to PR bin/15830; it has been noted by GNATS. From: Warner Losh 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 #include #include +#include #include #include #include @@ -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 +.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 . + */ + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 #include +#include #include #include #include @@ -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