NetBSD Problem Report #46703

From darrenr@netbsd.org  Sat Jul 14 09:49:24 2012
Return-Path: <darrenr@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	by www.NetBSD.org (Postfix) with ESMTP id 7E04863B85F
	for <gnats-bugs@gnats.NetBSD.org>; Sat, 14 Jul 2012 09:49:24 +0000 (UTC)
Message-Id: <20120714094924.7023814A5B8@mail.netbsd.org>
Date: Sat, 14 Jul 2012 09:49:24 +0000 (UTC)
From: darrenr@netbsd.org
Reply-To: darrenr@netbsd.org
To: gnats-bugs@gnats.NetBSD.org
Subject: BSD r-commands use wrong source address for stderr
X-Send-Pr-Version: 3.95

>Number:         46703
>Category:       bin
>Synopsis:       BSD r-commands use wrong source address for stderr
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Jul 14 09:50:00 +0000 2012
>Closed-Date:    Sat Jul 14 15:17:27 +0000 2012
>Last-Modified:  Sat Jul 14 15:17:27 +0000 2012
>Originator:     Darren Reed
>Release:        NetBSD 5.99.59
>Organization:
NetBSD
>Environment:

>Description:
The BSD r-commands, rsh, rlogin ,etc, do not use the same IP address
for the outgoing connection for stderr as the local server when running
ona a host with address aliases.

To explain this with an example...
Server A has IP addresses 1.2.3.4 and 1.3.4.5
Client B does "rsh 1.3.4.5 who"
Server A accepts the connection on port 514 for 1.3.4.5 and initiates a
connection back to Client B using IP address 1.2.3.4.

The outgoing connection should use the same IP address as was made for
the incoming TCP connection.

>How-To-Repeat:

>Fix:

--- usr/src/lib/libc/net/rcmd.c.DIST	2011-06-01 02:31:58.000000000 +0200
+++ usr/src/lib/libc/net/rcmd.c	2012-07-14 13:04:06.000000000 +0200
@@ -503,6 +503,12 @@
 int
 rresvport_af(int *alport, int family)
 {
+	return rresvport_af_addr(alport, family, NULL);
+}
+
+int
+rresvport_af_addr(int *alport, int family, void *addr)
+{
 	struct sockaddr_storage ss;
 	struct sockaddr *sa;
 	socklen_t salen;
@@ -519,6 +525,9 @@
 		sa->sa_len =
 #endif
 		salen = sizeof(struct sockaddr_in);
+		if (addr)
+			((struct sockaddr_in *)(void *)sa)->sin_addr =
+			    ((struct sockaddr_in *)addr)->sin_addr;
 		portp = &((struct sockaddr_in *)(void *)sa)->sin_port;
 		break;
 #ifdef INET6
@@ -527,6 +536,9 @@
 		sa->sa_len =
 #endif
 		salen = sizeof(struct sockaddr_in6);
+		if (addr)
+			((struct sockaddr_in6 *)(void *)sa)->sin6_addr =
+			    ((struct sockaddr_in6 *)addr)->sin6_addr;
 		portp = &((struct sockaddr_in6 *)(void *)sa)->sin6_port;
 		break;
 #endif
--- usr/src/include/unistd.h.DIST	2011-11-05 12:07:00.000000000 +0100
+++ usr/src/include/unistd.h	2012-07-14 13:04:34.000000000 +0200
@@ -371,6 +371,7 @@
 int	 rcmd_af(char **, int, const char *,
 	    const char *, const char *, int *, int);
 int	 rresvport_af(int *, int);
+int	 rresvport_af_addr(int *, int, void *);
 int	 iruserok_sa(const void *, int, int, const char *, const char *);
 #endif

--- usr/src/libexec/rshd/rshd.c.DIST	2011-10-31 04:44:29.000000000 +0100
+++ usr/src/libexec/rshd/rshd.c	2012-07-14 13:10:44.000000000 +0200
@@ -137,7 +137,7 @@
 static int	log_success;		/* If TRUE, log all successful accesses */
 static int	sent_null;

-__dead static void	 doit(struct sockaddr *);
+__dead static void	 doit(struct sockaddr *, struct sockaddr *);
 __dead static void	 rshd_errx(int, const char *, ...) __printflike(2, 3);
 static void	 getstr(char *, int, const char *);
 static int	 local_domain(char *);
@@ -155,7 +155,9 @@
 	struct linger linger;
 	int ch, on = 1;
 	socklen_t fromlen;
+	socklen_t locallen;
 	struct sockaddr_storage from;
+	struct sockaddr_storage local;
 	struct protoent *proto;

 	openlog("rshd", LOG_PID, LOG_DAEMON);
@@ -185,10 +187,16 @@
 	argv += optind;

 	fromlen = sizeof(from); /* xxx */
+	locallen = sizeof(local); /* xxx */
 	if (getpeername(STDIN_FILENO, (struct sockaddr *)&from, &fromlen) < 0) {
 		syslog(LOG_ERR, "getpeername: %m");
 		return EXIT_FAILURE;
 	}
+	if (getsockname(STDIN_FILENO, (struct sockaddr *)&local,
+	    &locallen) < 0) {
+		syslog(LOG_ERR, "getsockname: %m");
+		return EXIT_FAILURE;
+	}
 #if 0
 	if (((struct sockaddr *)&from)->sa_family == AF_INET6 &&
 	    IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&from)->sin6_addr) &&
@@ -232,13 +240,13 @@
 	proto = getprotobyname("tcp");
 	(void)setsockopt(STDIN_FILENO, proto->p_proto, TCP_NODELAY, &on,
 	    sizeof(on));
-	doit((struct sockaddr *)&from);
+	doit((struct sockaddr *)&from, (struct sockaddr *)&local);
 }

 extern char	**environ;

 static void
-doit(struct sockaddr *fromp)
+doit(struct sockaddr *fromp, struct sockaddr *localp)
 {
 	struct passwd *pwd, pwres;
 	in_port_t port;
@@ -356,7 +364,7 @@
 	(void) alarm(0);
 	if (port != 0) {
 		int lport = IPPORT_RESERVED - 1;
-		s = rresvport_af(&lport, af);
+		s = rresvport_af_addr(&lport, af, localp);
 		if (s < 0) {
 			syslog(LOG_ERR, "can't get stderr port: %m");
 			exit(EXIT_FAILURE);

>Release-Note:

>Audit-Trail:

State-Changed-From-To: open->closed
State-Changed-By: darrenr@NetBSD.org
State-Changed-When: Sat, 14 Jul 2012 15:17:27 +0000
State-Changed-Why:
change committed


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.