Tue May 31 06:49:27 2011 UTC ()
PR/45007: rcmd_af(3) and thusly rsh(1) ignore requested address family
Pass in the address family to rshrcmd and DTRT.
While here KNF.


(christos)
diff -r1.65 -r1.66 src/lib/libc/net/rcmd.c

cvs diff -r1.65 -r1.66 src/lib/libc/net/rcmd.c (expand / switch to unified diff)

--- src/lib/libc/net/rcmd.c 2007/01/03 11:46:22 1.65
+++ src/lib/libc/net/rcmd.c 2011/05/31 06:49:26 1.66
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: rcmd.c,v 1.65 2007/01/03 11:46:22 ws Exp $ */ 1/* $NetBSD: rcmd.c,v 1.66 2011/05/31 06:49:26 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1983, 1993, 1994 4 * Copyright (c) 1983, 1993, 1994
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -24,27 +24,27 @@ @@ -24,27 +24,27 @@
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33#if defined(LIBC_SCCS) && !defined(lint) 33#if defined(LIBC_SCCS) && !defined(lint)
34#if 0 34#if 0
35static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94"; 35static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94";
36#else 36#else
37__RCSID("$NetBSD: rcmd.c,v 1.65 2007/01/03 11:46:22 ws Exp $"); 37__RCSID("$NetBSD: rcmd.c,v 1.66 2011/05/31 06:49:26 christos Exp $");
38#endif 38#endif
39#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
40 40
41#ifdef _LIBC 41#ifdef _LIBC
42#include "namespace.h" 42#include "namespace.h"
43#endif 43#endif
44#include <sys/param.h> 44#include <sys/param.h>
45#include <sys/socket.h> 45#include <sys/socket.h>
46#include <sys/stat.h> 46#include <sys/stat.h>
47#include <sys/poll.h> 47#include <sys/poll.h>
48#include <sys/wait.h> 48#include <sys/wait.h>
49 49
50#include <netinet/in.h> 50#include <netinet/in.h>
@@ -60,165 +60,146 @@ __RCSID("$NetBSD: rcmd.c,v 1.65 2007/01/ @@ -60,165 +60,146 @@ __RCSID("$NetBSD: rcmd.c,v 1.65 2007/01/
60#include <grp.h> 60#include <grp.h>
61#include <netdb.h> 61#include <netdb.h>
62#include <paths.h> 62#include <paths.h>
63#include <pwd.h> 63#include <pwd.h>
64#include <signal.h> 64#include <signal.h>
65#include <stdio.h> 65#include <stdio.h>
66#include <stdlib.h> 66#include <stdlib.h>
67#include <string.h> 67#include <string.h>
68#include <syslog.h> 68#include <syslog.h>
69#include <unistd.h> 69#include <unistd.h>
70 70
71#include "pathnames.h" 71#include "pathnames.h"
72 72
73int orcmd __P((char **, u_int, const char *, const char *, const char *, 73int orcmd(char **, u_int, const char *, const char *, const char *, int *);
74 int *)); 74int orcmd_af(char **, u_int, const char *, const char *, const char *,
75int orcmd_af __P((char **, u_int, const char *, const char *, const char *, 75 int *, int);
76 int *, int)); 76int __ivaliduser(FILE *, u_int32_t, const char *, const char *);
77int __ivaliduser __P((FILE *, u_int32_t, const char *, const char *)); 77int __ivaliduser_sa(FILE *, const struct sockaddr *, socklen_t,
78int __ivaliduser_sa __P((FILE *, const struct sockaddr *, socklen_t, 78 const char *, const char *);
79 const char *, const char *)); 79static int rshrcmd(int, char **, u_int32_t, const char *,
80static int rshrcmd __P((char **, u_int32_t, const char *, const char *, 80 const char *, const char *, int *, const char *);
81 const char *, int *, const char *)); 81static int resrcmd(struct addrinfo *, char **, u_int32_t, const char *,
82static int resrcmd __P((struct addrinfo *, char **, u_int32_t, const char *, 82 const char *, const char *, int *);
83 const char *, const char *, int *)); 83static int __icheckhost(const struct sockaddr *, socklen_t,
84static int __icheckhost __P((const struct sockaddr *, socklen_t, 84 const char *);
85 const char *)); 85static char *__gethostloop(const struct sockaddr *, socklen_t);
86static char *__gethostloop __P((const struct sockaddr *, socklen_t)); 
87 86
88int 87int
89rcmd(ahost, rport, locuser, remuser, cmd, fd2p) 88rcmd(char **ahost, int rport, const char *locuser, const char *remuser,
90 char **ahost; 89 const char *cmd, int *fd2p)
91 u_short rport; 
92 const char *locuser, *remuser, *cmd; 
93 int *fd2p; 
94{ 90{
95 91
96 return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET); 92 return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
97} 93}
98 94
99int 95int
100rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af) 96rcmd_af(char **ahost, int rport, const char *locuser, const char *remuser,
101 char **ahost; 97 const char *cmd, int *fd2p, int af)
102 u_short rport; 
103 const char *locuser, *remuser, *cmd; 
104 int *fd2p; 
105 int af; 
106{ 98{
107 static char hbuf[MAXHOSTNAMELEN]; 99 static char hbuf[MAXHOSTNAMELEN];
108 char pbuf[NI_MAXSERV]; 100 char pbuf[NI_MAXSERV];
109 struct addrinfo hints, *res; 101 struct addrinfo hints, *res;
110 int error; 102 int error;
111 struct servent *sp; 103 struct servent *sp;
112 104
113 _DIAGASSERT(ahost != NULL); 105 _DIAGASSERT(ahost != NULL);
114 _DIAGASSERT(locuser != NULL); 106 _DIAGASSERT(locuser != NULL);
115 _DIAGASSERT(remuser != NULL); 107 _DIAGASSERT(remuser != NULL);
116 _DIAGASSERT(cmd != NULL); 108 _DIAGASSERT(cmd != NULL);
117 /* fd2p may be NULL */ 109 /* fd2p may be NULL */
118 110
119 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(rport)); 111 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(rport));
120 memset(&hints, 0, sizeof(hints)); 112 memset(&hints, 0, sizeof(hints));
121 hints.ai_family = af; 113 hints.ai_family = af;
122 hints.ai_socktype = SOCK_STREAM; 114 hints.ai_socktype = SOCK_STREAM;
123 hints.ai_flags = AI_CANONNAME; 115 hints.ai_flags = AI_CANONNAME;
124 error = getaddrinfo(*ahost, pbuf, &hints, &res); 116 error = getaddrinfo(*ahost, pbuf, &hints, &res);
125 if (error) { 117 if (error) {
126 warnx("%s: %s", *ahost, gai_strerror(error)); /*XXX*/ 118 warnx("%s: %s", *ahost, gai_strerror(error)); /*XXX*/
127 return (-1); 119 return -1;
128 } 120 }
129 if (res->ai_canonname) { 121 if (res->ai_canonname) {
130 /* 122 /*
131 * Canonicalise hostname. 123 * Canonicalise hostname.
132 * XXX: Should we really do this? 124 * XXX: Should we really do this?
133 */ 125 */
134 strlcpy(hbuf, res->ai_canonname, sizeof(hbuf)); 126 strlcpy(hbuf, res->ai_canonname, sizeof(hbuf));
135 *ahost = hbuf; 127 *ahost = hbuf;
136 } 128 }
137 129
138 /* 130 /*
139 * Check if rport is the same as the shell port, and that the fd2p. If 131 * Check if rport is the same as the shell port, and that the fd2p. If
140 * it is not, the program isn't expecting 'rsh' and so we can't use the 132 * it is not, the program isn't expecting 'rsh' and so we can't use the
141 * RCMD_CMD environment. 133 * RCMD_CMD environment.
142 */ 134 */
143 sp = getservbyname("shell", "tcp"); 135 sp = getservbyname("shell", "tcp");
144 if (sp != NULL && sp->s_port == rport) 136 if (sp != NULL && sp->s_port == rport)
145 error = rshrcmd(ahost, (u_int32_t)rport, 137 error = rshrcmd(af, ahost, (u_int32_t)rport,
146 locuser, remuser, cmd, fd2p, getenv("RCMD_CMD")); 138 locuser, remuser, cmd, fd2p, getenv("RCMD_CMD"));
147 else 139 else
148 error = resrcmd(res, ahost, (u_int32_t)rport, 140 error = resrcmd(res, ahost, (u_int32_t)rport,
149 locuser, remuser, cmd, fd2p); 141 locuser, remuser, cmd, fd2p);
150 freeaddrinfo(res); 142 freeaddrinfo(res);
151 return (error); 143 return error;
152} 144}
153 145
154/* this is simply a wrapper around hprcmd() that handles ahost first */ 146/* this is simply a wrapper around hprcmd() that handles ahost first */
155int 147int
156orcmd(ahost, rport, locuser, remuser, cmd, fd2p) 148orcmd(char **ahost, u_int rport, const char *locuser, const char *remuser,
157 char **ahost; 149 const char *cmd, int *fd2p)
158 u_int rport; 
159 const char *locuser, *remuser, *cmd; 
160 int *fd2p; 
161{ 150{
162 return orcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET); 151 return orcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
163} 152}
164 153
165int 154int
166orcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af) 155orcmd_af(char **ahost, u_int rport, const char *locuser, const char *remuser,
167 char **ahost; 156 const char *cmd, int *fd2p, int af)
168 u_int rport; 
169 const char *locuser, *remuser, *cmd; 
170 int *fd2p; 
171 int af; 
172{ 157{
173 static char hbuf[MAXHOSTNAMELEN]; 158 static char hbuf[MAXHOSTNAMELEN];
174 char pbuf[NI_MAXSERV]; 159 char pbuf[NI_MAXSERV];
175 struct addrinfo hints, *res; 160 struct addrinfo hints, *res;
176 int error; 161 int error;
177 162
178 _DIAGASSERT(ahost != NULL); 163 _DIAGASSERT(ahost != NULL);
179 _DIAGASSERT(locuser != NULL); 164 _DIAGASSERT(locuser != NULL);
180 _DIAGASSERT(remuser != NULL); 165 _DIAGASSERT(remuser != NULL);
181 _DIAGASSERT(cmd != NULL); 166 _DIAGASSERT(cmd != NULL);
182 /* fd2p may be NULL */ 167 /* fd2p may be NULL */
183 168
184 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(rport)); 169 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(rport));
185 memset(&hints, 0, sizeof(hints)); 170 memset(&hints, 0, sizeof(hints));
186 hints.ai_family = af; 171 hints.ai_family = af;
187 hints.ai_socktype = SOCK_STREAM; 172 hints.ai_socktype = SOCK_STREAM;
188 hints.ai_flags = AI_CANONNAME; 173 hints.ai_flags = AI_CANONNAME;
189 error = getaddrinfo(*ahost, pbuf, &hints, &res); 174 error = getaddrinfo(*ahost, pbuf, &hints, &res);
190 if (error) { 175 if (error) {
191 warnx("%s: %s", *ahost, gai_strerror(error)); /*XXX*/ 176 warnx("%s: %s", *ahost, gai_strerror(error)); /*XXX*/
192 return (-1); 177 return -1;
193 } 178 }
194 if (res->ai_canonname) { 179 if (res->ai_canonname) {
195 strlcpy(hbuf, res->ai_canonname, sizeof(hbuf)); 180 strlcpy(hbuf, res->ai_canonname, sizeof(hbuf));
196 *ahost = hbuf; 181 *ahost = hbuf;
197 } 182 }
198  183
199 error = resrcmd(res, ahost, rport, locuser, remuser, cmd, fd2p); 184 error = resrcmd(res, ahost, rport, locuser, remuser, cmd, fd2p);
200 freeaddrinfo(res); 185 freeaddrinfo(res);
201 return (error); 186 return error;
202} 187}
203 188
204/*ARGSUSED*/ 189/*ARGSUSED*/
205static int 190static int
206resrcmd(res, ahost, rport, locuser, remuser, cmd, fd2p) 191resrcmd(struct addrinfo *res, char **ahost, u_int32_t rport,
207 struct addrinfo *res; 192 const char *locuser, const char *remuser, const char *cmd, int *fd2p)
208 char **ahost; 
209 u_int32_t rport; 
210 const char *locuser, *remuser, *cmd; 
211 int *fd2p; 
212{ 193{
213 struct addrinfo *r; 194 struct addrinfo *r;
214 struct sockaddr_storage from; 195 struct sockaddr_storage from;
215 struct pollfd reads[2]; 196 struct pollfd reads[2];
216 sigset_t nmask, omask; 197 sigset_t nmask, omask;
217 pid_t pid; 198 pid_t pid;
218 int s, lport, timo; 199 int s, lport, timo;
219 int pollr; 200 int pollr;
220 char c; 201 char c;
221 int refused; 202 int refused;
222 203
223 _DIAGASSERT(res != NULL); 204 _DIAGASSERT(res != NULL);
224 _DIAGASSERT(ahost != NULL); 205 _DIAGASSERT(ahost != NULL);
@@ -236,27 +217,27 @@ resrcmd(res, ahost, rport, locuser, remu @@ -236,27 +217,27 @@ resrcmd(res, ahost, rport, locuser, remu
236 return -1; 217 return -1;
237 for (timo = 1, lport = IPPORT_RESERVED - 1;;) { 218 for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
238 s = rresvport_af(&lport, r->ai_family); 219 s = rresvport_af(&lport, r->ai_family);
239 if (s < 0) { 220 if (s < 0) {
240 if (errno == EAGAIN) 221 if (errno == EAGAIN)
241 warnx("rcmd: socket: All ports in use"); 222 warnx("rcmd: socket: All ports in use");
242 else 223 else
243 warn("rcmd: socket"); 224 warn("rcmd: socket");
244 if (r->ai_next) { 225 if (r->ai_next) {
245 r = r->ai_next; 226 r = r->ai_next;
246 continue; 227 continue;
247 } else { 228 } else {
248 (void)sigprocmask(SIG_SETMASK, &omask, NULL); 229 (void)sigprocmask(SIG_SETMASK, &omask, NULL);
249 return (-1); 230 return -1;
250 } 231 }
251 } 232 }
252 fcntl(s, F_SETOWN, pid); 233 fcntl(s, F_SETOWN, pid);
253 if (connect(s, r->ai_addr, r->ai_addrlen) >= 0) 234 if (connect(s, r->ai_addr, r->ai_addrlen) >= 0)
254 break; 235 break;
255 (void)close(s); 236 (void)close(s);
256 if (errno == EADDRINUSE) { 237 if (errno == EADDRINUSE) {
257 lport--; 238 lport--;
258 continue; 239 continue;
259 } else if (errno == ECONNREFUSED) 240 } else if (errno == ECONNREFUSED)
260 refused++; 241 refused++;
261 if (r->ai_next) { 242 if (r->ai_next) {
262 int oerrno = errno; 243 int oerrno = errno;
@@ -277,27 +258,27 @@ resrcmd(res, ahost, rport, locuser, remu @@ -277,27 +258,27 @@ resrcmd(res, ahost, rport, locuser, remu
277 (void)fprintf(stderr, "Trying %s...\n", hbuf); 258 (void)fprintf(stderr, "Trying %s...\n", hbuf);
278 continue; 259 continue;
279 } 260 }
280 if (refused && timo <= 16) { 261 if (refused && timo <= 16) {
281 (void)sleep((unsigned int)timo); 262 (void)sleep((unsigned int)timo);
282 timo *= 2; 263 timo *= 2;
283 r = res; 264 r = res;
284 refused = 0; 265 refused = 0;
285 continue; 266 continue;
286 } 267 }
287 (void)fprintf(stderr, "%s: %s\n", res->ai_canonname, 268 (void)fprintf(stderr, "%s: %s\n", res->ai_canonname,
288 strerror(errno)); 269 strerror(errno));
289 (void)sigprocmask(SIG_SETMASK, &omask, NULL); 270 (void)sigprocmask(SIG_SETMASK, &omask, NULL);
290 return (-1); 271 return -1;
291 } 272 }
292 lport--; 273 lport--;
293 if (fd2p == 0) { 274 if (fd2p == 0) {
294 write(s, "", 1); 275 write(s, "", 1);
295 lport = 0; 276 lport = 0;
296 } else { 277 } else {
297 char num[8]; 278 char num[8];
298 int s2 = rresvport_af(&lport, r->ai_family), s3; 279 int s2 = rresvport_af(&lport, r->ai_family), s3;
299 socklen_t len = sizeof(from); 280 socklen_t len = sizeof(from);
300 281
301 if (s2 < 0) 282 if (s2 < 0)
302 goto bad; 283 goto bad;
303 listen(s2, 1); 284 listen(s2, 1);
@@ -308,395 +289,398 @@ resrcmd(res, ahost, rport, locuser, remu @@ -308,395 +289,398 @@ resrcmd(res, ahost, rport, locuser, remu
308 (void)close(s2); 289 (void)close(s2);
309 goto bad; 290 goto bad;
310 } 291 }
311 reads[0].fd = s; 292 reads[0].fd = s;
312 reads[0].events = POLLIN; 293 reads[0].events = POLLIN;
313 reads[1].fd = s2; 294 reads[1].fd = s2;
314 reads[1].events = POLLIN; 295 reads[1].events = POLLIN;
315 errno = 0; 296 errno = 0;
316 pollr = poll(reads, 2, INFTIM); 297 pollr = poll(reads, 2, INFTIM);
317 if (pollr < 1 || (reads[1].revents & POLLIN) == 0) { 298 if (pollr < 1 || (reads[1].revents & POLLIN) == 0) {
318 if (errno != 0) 299 if (errno != 0)
319 warn("poll: setting up stderr"); 300 warn("poll: setting up stderr");
320 else 301 else
321 warnx("poll: protocol failure in circuit setup"); 302 warnx(
 303 "poll: protocol failure in circuit setup");
322 (void)close(s2); 304 (void)close(s2);
323 goto bad; 305 goto bad;
324 } 306 }
325 s3 = accept(s2, (struct sockaddr *)(void *)&from, &len); 307 s3 = accept(s2, (struct sockaddr *)(void *)&from, &len);
326 (void)close(s2); 308 (void)close(s2);
327 if (s3 < 0) { 309 if (s3 < 0) {
328 warn("rcmd: accept"); 310 warn("rcmd: accept");
329 lport = 0; 311 lport = 0;
330 goto bad; 312 goto bad;
331 } 313 }
332 *fd2p = s3; 314 *fd2p = s3;
333 switch (((struct sockaddr *)(void *)&from)->sa_family) { 315 switch (((struct sockaddr *)(void *)&from)->sa_family) {
334 case AF_INET: 316 case AF_INET:
335#ifdef INET6 317#ifdef INET6
336 case AF_INET6: 318 case AF_INET6:
337#endif 319#endif
338 if (getnameinfo((struct sockaddr *)(void *)&from, len, 320 if (getnameinfo((struct sockaddr *)(void *)&from, len,
339 NULL, 0, num, sizeof(num), NI_NUMERICSERV) != 0 || 321 NULL, 0, num, sizeof(num), NI_NUMERICSERV) != 0 ||
340 (atoi(num) >= IPPORT_RESERVED || 322 (atoi(num) >= IPPORT_RESERVED ||
341 atoi(num) < IPPORT_RESERVED / 2)) { 323 atoi(num) < IPPORT_RESERVED / 2)) {
342 warnx("rcmd: protocol failure in circuit setup."); 324 warnx(
 325 "rcmd: protocol failure in circuit setup.");
343 goto bad2; 326 goto bad2;
344 } 327 }
345 break; 328 break;
346 default: 329 default:
347 break; 330 break;
348 } 331 }
349 } 332 }
350 333
351 (void)write(s, locuser, strlen(locuser)+1); 334 (void)write(s, locuser, strlen(locuser)+1);
352 (void)write(s, remuser, strlen(remuser)+1); 335 (void)write(s, remuser, strlen(remuser)+1);
353 (void)write(s, cmd, strlen(cmd)+1); 336 (void)write(s, cmd, strlen(cmd)+1);
354 if (read(s, &c, 1) != 1) { 337 if (read(s, &c, 1) != 1) {
355 warn("%s", *ahost); 338 warn("%s", *ahost);
356 goto bad2; 339 goto bad2;
357 } 340 }
358 if (c != 0) { 341 if (c != 0) {
359 while (read(s, &c, 1) == 1) { 342 while (read(s, &c, 1) == 1) {
360 (void)write(STDERR_FILENO, &c, 1); 343 (void)write(STDERR_FILENO, &c, 1);
361 if (c == '\n') 344 if (c == '\n')
362 break; 345 break;
363 } 346 }
364 goto bad2; 347 goto bad2;
365 } 348 }
366 (void)sigprocmask(SIG_SETMASK, &omask, NULL); 349 (void)sigprocmask(SIG_SETMASK, &omask, NULL);
367 return (s); 350 return s;
368bad2: 351bad2:
369 if (lport) 352 if (lport)
370 (void)close(*fd2p); 353 (void)close(*fd2p);
371bad: 354bad:
372 (void)close(s); 355 (void)close(s);
373 (void)sigprocmask(SIG_SETMASK, &omask, NULL); 356 (void)sigprocmask(SIG_SETMASK, &omask, NULL);
374 return (-1); 357 return -1;
375} 358}
376 359
377/* 360/*
378 * based on code written by Chris Siebenmann <cks@utcc.utoronto.ca> 361 * based on code written by Chris Siebenmann <cks@utcc.utoronto.ca>
379 */ 362 */
380/* ARGSUSED */ 363/* ARGSUSED */
381static int 364static int
382rshrcmd(ahost, rport, locuser, remuser, cmd, fd2p, rshcmd) 365rshrcmd(int af, char **ahost, u_int32_t rport, const char *locuser,
383 char **ahost; 366 const char *remuser, const char *cmd, int *fd2p, const char *rshcmd)
384 u_int32_t rport; 
385 const char *locuser, *remuser, *cmd; 
386 int *fd2p; 
387 const char *rshcmd; 
388{ 367{
389 pid_t pid; 368 pid_t pid;
390 int sp[2], ep[2]; 369 int sp[2], ep[2];
391 char *p; 370 char *p;
392 struct passwd *pw, pwres; 371 struct passwd *pw, pwres;
393 char pwbuf[1024]; 372 char pwbuf[1024];
394 373
395 _DIAGASSERT(ahost != NULL); 374 _DIAGASSERT(ahost != NULL);
396 _DIAGASSERT(locuser != NULL); 375 _DIAGASSERT(locuser != NULL);
397 _DIAGASSERT(remuser != NULL); 376 _DIAGASSERT(remuser != NULL);
398 _DIAGASSERT(cmd != NULL); 377 _DIAGASSERT(cmd != NULL);
399 /* fd2p may be NULL */ 378 /* fd2p may be NULL */
400 379
401 /* What rsh/shell to use. */ 380 /* What rsh/shell to use. */
402 if (rshcmd == NULL) 381 if (rshcmd == NULL)
403 rshcmd = _PATH_BIN_RCMD; 382 rshcmd = _PATH_BIN_RCMD;
404 383
405 /* locuser must exist on this host. */ 384 /* locuser must exist on this host. */
406 if (getpwnam_r(locuser, &pwres, pwbuf, sizeof(pwbuf), &pw) != 0 || 385 if (getpwnam_r(locuser, &pwres, pwbuf, sizeof(pwbuf), &pw) != 0 ||
407 pw == NULL) { 386 pw == NULL) {
408 warnx("rshrcmd: unknown user: %s", locuser); 387 warnx("%s: unknown user: %s", __func__, locuser);
409 return(-1); 388 return -1;
410 } 389 }
411 390
412 /* get a socketpair we'll use for stdin and stdout. */ 391 /* get a socketpair we'll use for stdin and stdout. */
413 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sp) < 0) { 392 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sp) < 0) {
414 warn("rshrcmd: socketpair"); 393 warn("%s: socketpair", __func__);
415 return (-1); 394 return -1;
416 } 395 }
417 /* we will use this for the fd2 pointer */ 396 /* we will use this for the fd2 pointer */
418 if (fd2p) { 397 if (fd2p) {
419 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, ep) < 0) { 398 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, ep) < 0) {
420 warn("rshrcmd: socketpair"); 399 warn("%s: socketpair", __func__);
421 return (-1); 400 return -1;
422 } 401 }
423 *fd2p = ep[0]; 402 *fd2p = ep[0];
424 } 403 }
425  404
426 pid = fork(); 405 pid = fork();
427 if (pid < 0) { 406 if (pid < 0) {
428 warn("rshrcmd: fork"); 407 warn("%s: fork", __func__);
429 return (-1); 408 return -1;
430 } 409 }
431 if (pid == 0) { 410 if (pid == 0) {
432 /* 411 /*
433 * child 412 * child
434 * - we use sp[1] to be stdin/stdout, and close sp[0] 413 * - we use sp[1] to be stdin/stdout, and close sp[0]
435 * - with fd2p, we use ep[1] for stderr, and close ep[0] 414 * - with fd2p, we use ep[1] for stderr, and close ep[0]
436 */ 415 */
437 (void)close(sp[0]); 416 (void)close(sp[0]);
438 if (dup2(sp[1], 0) < 0 || dup2(0, 1) < 0) { 417 if (dup2(sp[1], 0) < 0 || dup2(0, 1) < 0) {
439 warn("rshrcmd: dup2"); 418 warn("%s: dup2", __func__);
440 _exit(1); 419 _exit(1);
441 } 420 }
442 (void)close(sp[1]); 421 (void)close(sp[1]);
443 if (fd2p) { 422 if (fd2p) {
444 if (dup2(ep[1], 2) < 0) { 423 if (dup2(ep[1], 2) < 0) {
445 warn("rshrcmd: dup2"); 424 warn("%s: dup2", __func__);
446 _exit(1); 425 _exit(1);
447 } 426 }
448 (void)close(ep[0]); 427 (void)close(ep[0]);
449 (void)close(ep[1]); 428 (void)close(ep[1]);
450 } else if (dup2(0, 2) < 0) { 429 } else if (dup2(0, 2) < 0) {
451 warn("rshrcmd: dup2"); 430 warn("%s: dup2", __func__);
452 _exit(1); 431 _exit(1);
453 } 432 }
454 /* fork again to lose parent. */ 433 /* fork again to lose parent. */
455 pid = fork(); 434 pid = fork();
456 if (pid < 0) { 435 if (pid < 0) {
457 warn("rshrcmd: second fork"); 436 warn("%s: second fork", __func__);
458 _exit(1); 437 _exit(1);
459 } 438 }
460 if (pid > 0) 439 if (pid > 0)
461 _exit(0); 440 _exit(0);
462 441
463 /* Orphan. Become local user for rshprog. */ 442 /* Orphan. Become local user for rshprog. */
464 if (setuid(pw->pw_uid)) { 443 if (setuid(pw->pw_uid)) {
465 warn("rshrcmd: setuid(%lu)", (u_long)pw->pw_uid); 444 warn("%s: setuid(%lu)", __func__, (u_long)pw->pw_uid);
466 _exit(1); 445 _exit(1);
467 } 446 }
468 447
469 /* 448 /*
470 * If we are rcmd'ing to "localhost" as the same user as we are, 449 * If we are rcmd'ing to "localhost" as the same user as we
471 * then avoid running remote shell for efficiency. 450 * are, then avoid running remote shell for efficiency.
472 */ 451 */
473 if (strcmp(*ahost, "localhost") == 0 && 452 if (strcmp(*ahost, "localhost") == 0 &&
474 strcmp(locuser, remuser) == 0) { 453 strcmp(locuser, remuser) == 0) {
475 if (pw->pw_shell[0] == '\0') 454 if (pw->pw_shell[0] == '\0')
476 rshcmd = _PATH_BSHELL; 455 rshcmd = _PATH_BSHELL;
477 else 456 else
478 rshcmd = pw->pw_shell; 457 rshcmd = pw->pw_shell;
479 p = strrchr(rshcmd, '/'); 458 p = strrchr(rshcmd, '/');
480 execlp(rshcmd, p ? p + 1 : rshcmd, "-c", cmd, NULL); 459 execlp(rshcmd, p ? p + 1 : rshcmd, "-c", cmd, NULL);
481 } else { 460 } else {
482 p = strrchr(rshcmd, '/'); 461 const char *program;
483 execlp(rshcmd, p ? p + 1 : rshcmd, *ahost, "-l", 462 program = strrchr(rshcmd, '/');
484 remuser, cmd, NULL); 463 program = program ? program + 1 : rshcmd;
 464 switch (af) {
 465 case AF_INET:
 466 execlp(rshcmd, program, "-4", "-l", remuser,
 467 *ahost, cmd, NULL);
 468 break;
 469
 470 case AF_INET6:
 471 execlp(rshcmd, program, "-6", "-l", remuser,
 472 *ahost, cmd, NULL);
 473 break;
 474
 475 default:
 476 /* typically AF_UNSPEC, plus whatever */
 477 execlp(rshcmd, program, "-l", remuser,
 478 *ahost, cmd, NULL);
 479 break;
 480 }
485 } 481 }
486 warn("rshrcmd: exec %s", rshcmd); 482 warn("%s: exec %s", __func__, rshcmd);
487 _exit(1); 483 _exit(1);
488 } 484 }
489 /* Parent */ 485 /* Parent */
490 (void)close(sp[1]); 486 (void)close(sp[1]);
491 if (fd2p) 487 if (fd2p)
492 (void)close(ep[1]); 488 (void)close(ep[1]);
493 489
494 (void)waitpid(pid, NULL, 0); 490 (void)waitpid(pid, NULL, 0);
495 return (sp[0]); 491 return sp[0];
496} 492}
497 493
498int 494int
499rresvport(alport) 495rresvport(int *alport)
500 int *alport; 
501{ 496{
502 497
503 _DIAGASSERT(alport != NULL); 498 _DIAGASSERT(alport != NULL);
504 499
505 return rresvport_af(alport, AF_INET); 500 return rresvport_af(alport, AF_INET);
506} 501}
507 502
508int 503int
509rresvport_af(alport, family) 504rresvport_af(int *alport, int family)
510 int *alport; 
511 int family; 
512{ 505{
513 struct sockaddr_storage ss; 506 struct sockaddr_storage ss;
514 struct sockaddr *sa; 507 struct sockaddr *sa;
515 int salen; 508 socklen_t salen;
516 int s; 509 int s;
517 u_int16_t *portp; 510 u_int16_t *portp;
518 511
519 _DIAGASSERT(alport != NULL); 512 _DIAGASSERT(alport != NULL);
520 513
521 memset(&ss, 0, sizeof(ss)); 514 memset(&ss, 0, sizeof(ss));
522 sa = (struct sockaddr *)(void *)&ss; 515 sa = (struct sockaddr *)(void *)&ss;
523 switch (family) { 516 switch (family) {
524 case AF_INET: 517 case AF_INET:
525#ifdef BSD4_4 518#ifdef BSD4_4
526 sa->sa_len = 519 sa->sa_len =
527#endif 520#endif
528 salen = sizeof(struct sockaddr_in); 521 salen = sizeof(struct sockaddr_in);
529 portp = &((struct sockaddr_in *)(void *)sa)->sin_port; 522 portp = &((struct sockaddr_in *)(void *)sa)->sin_port;
530 break; 523 break;
531#ifdef INET6 524#ifdef INET6
532 case AF_INET6: 525 case AF_INET6:
533#ifdef BSD4_4 526#ifdef BSD4_4
534 sa->sa_len = 527 sa->sa_len =
535#endif 528#endif
536 salen = sizeof(struct sockaddr_in6); 529 salen = sizeof(struct sockaddr_in6);
537 portp = &((struct sockaddr_in6 *)(void *)sa)->sin6_port; 530 portp = &((struct sockaddr_in6 *)(void *)sa)->sin6_port;
538 break; 531 break;
539#endif 532#endif
540 default: 533 default:
541 errno = EAFNOSUPPORT; 534 errno = EAFNOSUPPORT;
542 return (-1); 535 return -1;
543 } 536 }
544 sa->sa_family = family; 537 sa->sa_family = family;
545 s = socket(family, SOCK_STREAM, 0); 538 s = socket(family, SOCK_STREAM, 0);
546 if (s < 0) 539 if (s < 0)
547 return (-1); 540 return -1;
548#ifdef BSD4_4 541#ifdef BSD4_4
549 switch (family) { 542 switch (family) {
550 case AF_INET: 543 case AF_INET:
551 case AF_INET6: 544 case AF_INET6:
552 *portp = 0; 545 *portp = 0;
553 if (bindresvport(s, (struct sockaddr_in *)(void *)sa) < 0) { 546 if (bindresvport(s, (struct sockaddr_in *)(void *)sa) < 0) {
554 int sverr = errno; 547 int sverr = errno;
555 548
556 (void)close(s); 549 (void)close(s);
557 errno = sverr; 550 errno = sverr;
558 return (-1); 551 return -1;
559 } 552 }
560 *alport = (int)ntohs(*portp); 553 *alport = (int)ntohs(*portp);
561 return (s); 554 return s;
562 default: 555 default:
563 /* is it necessary to try keep code for other AFs? */ 556 /* is it necessary to try keep code for other AFs? */
564 break; 557 break;
565 } 558 }
566#endif 559#endif
567 for (;;) { 560 for (;;) {
568 *portp = htons((u_short)*alport); 561 *portp = htons((u_short)*alport);
569 if (bind(s, sa, (socklen_t)salen) >= 0) 562 if (bind(s, sa, salen) >= 0)
570 return (s); 563 return s;
571 if (errno != EADDRINUSE) { 564 if (errno != EADDRINUSE) {
572 (void)close(s); 565 (void)close(s);
573 return (-1); 566 return -1;
574 } 567 }
575 (*alport)--; 568 (*alport)--;
576 if (*alport == IPPORT_RESERVED/2) { 569 if (*alport == IPPORT_RESERVED/2) {
577 (void)close(s); 570 (void)close(s);
578 errno = EAGAIN; /* close */ 571 errno = EAGAIN; /* close */
579 return (-1); 572 return -1;
580 } 573 }
581 } 574 }
582} 575}
583 576
584int __check_rhosts_file = 1; 577int __check_rhosts_file = 1;
585const char *__rcmd_errstr; 578const char *__rcmd_errstr;
586 579
587int 580int
588ruserok(rhost, superuser, ruser, luser) 581ruserok(const char *rhost, int superuser, const char *ruser, const char *luser)
589 const char *rhost, *ruser, *luser; 
590 int superuser; 
591{ 582{
592 struct addrinfo hints, *res, *r; 583 struct addrinfo hints, *res, *r;
593 int error; 584 int error;
594 585
595 _DIAGASSERT(rhost != NULL); 586 _DIAGASSERT(rhost != NULL);
596 _DIAGASSERT(ruser != NULL); 587 _DIAGASSERT(ruser != NULL);
597 _DIAGASSERT(luser != NULL); 588 _DIAGASSERT(luser != NULL);
598 589
599 memset(&hints, 0, sizeof(hints)); 590 memset(&hints, 0, sizeof(hints));
600 hints.ai_family = PF_UNSPEC; 591 hints.ai_family = PF_UNSPEC;
601 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 592 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
602 error = getaddrinfo(rhost, "0", &hints, &res); 593 error = getaddrinfo(rhost, "0", &hints, &res);
603 if (error) 594 if (error)
604 return (-1); 595 return -1;
605 596
606 for (r = res; r; r = r->ai_next) { 597 for (r = res; r; r = r->ai_next) {
607 if (iruserok_sa(r->ai_addr, (int)r->ai_addrlen, superuser, 598 if (iruserok_sa(r->ai_addr, (int)r->ai_addrlen, superuser,
608 ruser, luser) == 0) { 599 ruser, luser) == 0) {
609 freeaddrinfo(res); 600 freeaddrinfo(res);
610 return (0); 601 return 0;
611 } 602 }
612 } 603 }
613 freeaddrinfo(res); 604 freeaddrinfo(res);
614 return (-1); 605 return -1;
615} 606}
616 607
617/* 608/*
618 * New .rhosts strategy: We are passed an ip address. We spin through 609 * New .rhosts strategy: We are passed an ip address. We spin through
619 * hosts.equiv and .rhosts looking for a match. When the .rhosts only 610 * hosts.equiv and .rhosts looking for a match. When the .rhosts only
620 * has ip addresses, we don't have to trust a nameserver. When it 611 * has ip addresses, we don't have to trust a nameserver. When it
621 * contains hostnames, we spin through the list of addresses the nameserver 612 * contains hostnames, we spin through the list of addresses the nameserver
622 * gives us and look for a match. 613 * gives us and look for a match.
623 * 614 *
624 * Returns 0 if ok, -1 if not ok. 615 * Returns 0 if ok, -1 if not ok.
625 */ 616 */
626int 617int
627iruserok(raddr, superuser, ruser, luser) 618iruserok(u_int32_t raddr, int superuser, const char *ruser, const char *luser)
628 u_int32_t raddr; 
629 int superuser; 
630 const char *ruser, *luser; 
631{ 619{
632 struct sockaddr_in irsin; 620 struct sockaddr_in irsin;
633 621
634 memset(&irsin, 0, sizeof(irsin)); 622 memset(&irsin, 0, sizeof(irsin));
635 irsin.sin_family = AF_INET; 623 irsin.sin_family = AF_INET;
636#ifdef BSD4_4 624#ifdef BSD4_4
637 irsin.sin_len = sizeof(struct sockaddr_in); 625 irsin.sin_len = sizeof(irsin);
638#endif 626#endif
639 memcpy(&irsin.sin_addr, &raddr, sizeof(irsin.sin_addr)); 627 memcpy(&irsin.sin_addr, &raddr, sizeof(irsin.sin_addr));
640 return iruserok_sa(&irsin, sizeof(struct sockaddr_in), superuser, ruser, 628 return iruserok_sa(&irsin, sizeof(irsin), superuser, ruser, luser);
641 luser); 
642} 629}
643 630
644/* 631/*
645 * 2nd and 3rd arguments are typed like this, to avoid dependency between 632 * 2nd and 3rd arguments are typed like this, to avoid dependency between
646 * unistd.h and sys/socket.h. There's no better way. 633 * unistd.h and sys/socket.h. There's no better way.
647 */ 634 */
648int 635int
649iruserok_sa(raddr, rlen, superuser, ruser, luser) 636iruserok_sa(const void *raddr, int rlen, int superuser, const char *ruser,
650 const void *raddr; 637 const char *luser)
651 int rlen; 
652 int superuser; 
653 const char *ruser, *luser; 
654{ 638{
655 const struct sockaddr *sa; 639 const struct sockaddr *sa;
656 struct stat sbuf; 640 struct stat sbuf;
657 struct passwd *pwd, pwres; 641 struct passwd *pwd, pwres;
658 FILE *hostf; 642 FILE *hostf;
659 uid_t uid; 643 uid_t uid;
660 gid_t gid; 644 gid_t gid;
661 int isvaliduser; 645 int isvaliduser;
662 char pbuf[MAXPATHLEN]; 646 char pbuf[MAXPATHLEN];
663 char pwbuf[1024]; 647 char pwbuf[1024];
664 648
665 _DIAGASSERT(raddr != NULL); 649 _DIAGASSERT(raddr != NULL);
666 _DIAGASSERT(ruser != NULL); 650 _DIAGASSERT(ruser != NULL);
667 _DIAGASSERT(luser != NULL); 651 _DIAGASSERT(luser != NULL);
668 652
669 sa = raddr; 653 sa = raddr;
670 654
671 __rcmd_errstr = NULL; 655 __rcmd_errstr = NULL;
672 656
673 hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r"); 657 hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
674 658
675 if (hostf) { 659 if (hostf) {
676 if (__ivaliduser_sa(hostf, sa, (socklen_t)rlen, luser, 660 if (__ivaliduser_sa(hostf, sa, (socklen_t)rlen, luser,
677 ruser) == 0) { 661 ruser) == 0) {
678 (void)fclose(hostf); 662 (void)fclose(hostf);
679 return (0); 663 return 0;
680 } 664 }
681 (void)fclose(hostf); 665 (void)fclose(hostf);
682 } 666 }
683 667
684 isvaliduser = -1; 668 isvaliduser = -1;
685 if (__check_rhosts_file || superuser) { 669 if (__check_rhosts_file || superuser) {
686 670
687 if (getpwnam_r(luser, &pwres, pwbuf, sizeof(pwbuf), &pwd) != 0 671 if (getpwnam_r(luser, &pwres, pwbuf, sizeof(pwbuf), &pwd) != 0
688 || pwd == NULL) 672 || pwd == NULL)
689 return (-1); 673 return -1;
690 (void)strlcpy(pbuf, pwd->pw_dir, sizeof(pbuf)); 674 (void)strlcpy(pbuf, pwd->pw_dir, sizeof(pbuf));
691 (void)strlcat(pbuf, "/.rhosts", sizeof(pbuf)); 675 (void)strlcat(pbuf, "/.rhosts", sizeof(pbuf));
692 676
693 /* 677 /*
694 * Change effective uid while opening and reading .rhosts. 678 * Change effective uid while opening and reading .rhosts.
695 * If root and reading an NFS mounted file system, can't 679 * If root and reading an NFS mounted file system, can't
696 * read files that are protected read/write owner only. 680 * read files that are protected read/write owner only.
697 */ 681 */
698 uid = geteuid(); 682 uid = geteuid();
699 gid = getegid(); 683 gid = getegid();
700 (void)setegid(pwd->pw_gid); 684 (void)setegid(pwd->pw_gid);
701 initgroups(pwd->pw_name, pwd->pw_gid); 685 initgroups(pwd->pw_name, pwd->pw_gid);
702 (void)seteuid(pwd->pw_uid); 686 (void)seteuid(pwd->pw_uid);
@@ -720,68 +704,63 @@ iruserok_sa(raddr, rlen, superuser, ruse @@ -720,68 +704,63 @@ iruserok_sa(raddr, rlen, superuser, ruse
720 __rcmd_errstr = 704 __rcmd_errstr =
721 ".rhosts writable by other than owner"; 705 ".rhosts writable by other than owner";
722 else  706 else
723 isvaliduser = 707 isvaliduser =
724 __ivaliduser_sa(hostf, sa, (socklen_t)rlen, 708 __ivaliduser_sa(hostf, sa, (socklen_t)rlen,
725 luser, ruser); 709 luser, ruser);
726 710
727 (void)fclose(hostf); 711 (void)fclose(hostf);
728 } 712 }
729 (void)seteuid(uid); 713 (void)seteuid(uid);
730 (void)setegid(gid); 714 (void)setegid(gid);
731 715
732 } 716 }
733 return (isvaliduser); 717 return isvaliduser;
734} 718}
735 719
736/* 720/*
737 * XXX 721 * XXX
738 * Don't make static, used by lpd(8). We will be able to change the function 722 * Don't make static, used by lpd(8). We will be able to change the function
739 * into static function, when we bump libc major #. 723 * into static function, when we bump libc major #.
740 * 724 *
741 * Returns 0 if ok, -1 if not ok. 725 * Returns 0 if ok, -1 if not ok.
742 */ 726 */
743#ifdef notdef /*_LIBC*/ 727#ifdef notdef /*_LIBC*/
744static 728static
745#endif 729#endif
746int 730int
747__ivaliduser(hostf, raddr, luser, ruser) 731__ivaliduser(FILE *hostf, u_int32_t raddr, const char *luser,
748 FILE *hostf; 732 const char *ruser)
749 u_int32_t raddr; 
750 const char *luser, *ruser; 
751{ 733{
752 struct sockaddr_in ivusin; 734 struct sockaddr_in ivusin;
753 735
754 memset(&ivusin, 0, sizeof(ivusin)); 736 memset(&ivusin, 0, sizeof(ivusin));
755 ivusin.sin_family = AF_INET; 737 ivusin.sin_family = AF_INET;
756#ifdef BSD4_4 738#ifdef BSD4_4
757 ivusin.sin_len = sizeof(struct sockaddr_in); 739 ivusin.sin_len = sizeof(ivusin);
758#endif 740#endif
759 memcpy(&ivusin.sin_addr, &raddr, sizeof(ivusin.sin_addr)); 741 memcpy(&ivusin.sin_addr, &raddr, sizeof(ivusin.sin_addr));
760 return __ivaliduser_sa(hostf, (struct sockaddr *)(void *)&ivusin, 742 return __ivaliduser_sa(hostf, (struct sockaddr *)(void *)&ivusin,
761 sizeof(struct sockaddr_in), luser, ruser); 743 sizeof(ivusin), luser, ruser);
762} 744}
763 745
764#ifdef notdef /*_LIBC*/ 746#ifdef notdef /*_LIBC*/
765static 747static
766#endif 748#endif
767int 749int
768__ivaliduser_sa(hostf, raddr, salen, luser, ruser) 750__ivaliduser_sa(FILE *hostf, const struct sockaddr *raddr, socklen_t salen,
769 FILE *hostf; 751 const char *luser, const char *ruser)
770 const struct sockaddr *raddr; 
771 socklen_t salen; 
772 const char *luser, *ruser; 
773{ 752{
774 register char *user, *p; 753 char *user, *p;
775 int ch; 754 int ch;
776 char buf[MAXHOSTNAMELEN + 128]; /* host + login */ 755 char buf[MAXHOSTNAMELEN + 128]; /* host + login */
777 const char *auser, *ahost; 756 const char *auser, *ahost;
778 int hostok, userok; 757 int hostok, userok;
779 char *rhost = NULL; 758 char *rhost = NULL;
780 int firsttime = 1; 759 int firsttime = 1;
781 char domain[MAXHOSTNAMELEN]; 760 char domain[MAXHOSTNAMELEN];
782 761
783 getdomainname(domain, sizeof(domain)); 762 getdomainname(domain, sizeof(domain));
784 763
785 _DIAGASSERT(hostf != NULL); 764 _DIAGASSERT(hostf != NULL);
786 _DIAGASSERT(luser != NULL); 765 _DIAGASSERT(luser != NULL);
787 _DIAGASSERT(ruser != NULL); 766 _DIAGASSERT(ruser != NULL);
@@ -848,27 +827,28 @@ __ivaliduser_sa(hostf, raddr, salen, lus @@ -848,27 +827,28 @@ __ivaliduser_sa(hostf, raddr, salen, lus
848 case '@': 827 case '@':
849 if (firsttime) { 828 if (firsttime) {
850 rhost = __gethostloop(raddr, salen); 829 rhost = __gethostloop(raddr, salen);
851 firsttime = 0; 830 firsttime = 0;
852 } 831 }
853 if (rhost) 832 if (rhost)
854 hostok = -innetgr(&ahost[2], rhost, 833 hostok = -innetgr(&ahost[2], rhost,
855 NULL, domain); 834 NULL, domain);
856 else 835 else
857 hostok = 0; 836 hostok = 0;
858 break; 837 break;
859 838
860 default: 839 default:
861 hostok = -__icheckhost(raddr, salen, &ahost[1]); 840 hostok =
 841 -__icheckhost(raddr, salen, &ahost[1]);
862 break; 842 break;
863 } 843 }
864 else 844 else
865 hostok = __icheckhost(raddr, salen, ahost); 845 hostok = __icheckhost(raddr, salen, ahost);
866 846
867 847
868 if (auser[0] == '+') 848 if (auser[0] == '+')
869 switch (auser[1]) { 849 switch (auser[1]) {
870 case '\0': 850 case '\0':
871 userok = 1; 851 userok = 1;
872 break; 852 break;
873 853
874 case '@': 854 case '@':
@@ -908,118 +888,111 @@ __ivaliduser_sa(hostf, raddr, salen, lus @@ -908,118 +888,111 @@ __ivaliduser_sa(hostf, raddr, salen, lus
908 return -1; 888 return -1;
909 889
910 /* Check if we got a valid pair */ 890 /* Check if we got a valid pair */
911 if (hostok == 1 && userok == 1) 891 if (hostok == 1 && userok == 1)
912 return 0; 892 return 0;
913 } 893 }
914 return -1; 894 return -1;
915} 895}
916 896
917/* 897/*
918 * Returns "true" if match, 0 if no match. 898 * Returns "true" if match, 0 if no match.
919 */ 899 */
920static int 900static int
921__icheckhost(raddr, salen, lhost) 901__icheckhost(const struct sockaddr *raddr, socklen_t salen, const char *lhost)
922 const struct sockaddr *raddr; 
923 socklen_t salen; 
924 const char *lhost; 
925{ 902{
926 struct addrinfo hints, *res, *r; 903 struct addrinfo hints, *res, *r;
927 char h1[NI_MAXHOST], h2[NI_MAXHOST]; 904 char h1[NI_MAXHOST], h2[NI_MAXHOST];
928 int error; 905 int error;
929 const int niflags = NI_NUMERICHOST; 906 const int niflags = NI_NUMERICHOST;
930 907
931 _DIAGASSERT(raddr != NULL); 908 _DIAGASSERT(raddr != NULL);
932 _DIAGASSERT(lhost != NULL); 909 _DIAGASSERT(lhost != NULL);
933 910
934 h1[0] = '\0'; 911 h1[0] = '\0';
935 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0, 912 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0, niflags) != 0)
936 niflags) != 0) 913 return 0;
937 return (0); 
938 914
939 /* Resolve laddr into sockaddr */ 915 /* Resolve laddr into sockaddr */
940 memset(&hints, 0, sizeof(hints)); 916 memset(&hints, 0, sizeof(hints));
941 hints.ai_family = raddr->sa_family; 917 hints.ai_family = raddr->sa_family;
942 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 918 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
943 res = NULL; 919 res = NULL;
944 error = getaddrinfo(lhost, "0", &hints, &res); 920 error = getaddrinfo(lhost, "0", &hints, &res);
945 if (error) 921 if (error)
946 return (0); 922 return 0;
947 923
948 /* 924 /*
949 * Try string comparisons between raddr and laddr. 925 * Try string comparisons between raddr and laddr.
950 */ 926 */
951 for (r = res; r; r = r->ai_next) { 927 for (r = res; r; r = r->ai_next) {
952 h2[0] = '\0'; 928 h2[0] = '\0';
953 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2), 929 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
954 NULL, 0, niflags) != 0) 930 NULL, 0, niflags) != 0)
955 continue; 931 continue;
956 if (strcmp(h1, h2) == 0) { 932 if (strcmp(h1, h2) == 0) {
957 freeaddrinfo(res); 933 freeaddrinfo(res);
958 return (1); 934 return 1;
959 } 935 }
960 } 936 }
961 937
962 /* No match. */ 938 /* No match. */
963 freeaddrinfo(res); 939 freeaddrinfo(res);
964 return (0); 940 return 0;
965} 941}
966 942
967/* 943/*
968 * Return the hostname associated with the supplied address. 944 * Return the hostname associated with the supplied address.
969 * Do a reverse lookup as well for security. If a loop cannot 945 * Do a reverse lookup as well for security. If a loop cannot
970 * be found, pack the numeric IP address into the string. 946 * be found, pack the numeric IP address into the string.
971 */ 947 */
972static char * 948static char *
973__gethostloop(raddr, salen) 949__gethostloop(const struct sockaddr *raddr, socklen_t salen)
974 const struct sockaddr *raddr; 
975 socklen_t salen; 
976{ 950{
977 static char remotehost[NI_MAXHOST]; 951 static char remotehost[NI_MAXHOST];
978 char h1[NI_MAXHOST], h2[NI_MAXHOST]; 952 char h1[NI_MAXHOST], h2[NI_MAXHOST];
979 struct addrinfo hints, *res, *r; 953 struct addrinfo hints, *res, *r;
980 int error; 954 int error;
981 const int niflags = NI_NUMERICHOST; 955 const int niflags = NI_NUMERICHOST;
982 956
983 _DIAGASSERT(raddr != NULL); 957 _DIAGASSERT(raddr != NULL);
984 958
985 h1[0] = remotehost[0] = '\0'; 959 h1[0] = remotehost[0] = '\0';
986 if (getnameinfo(raddr, salen, remotehost, sizeof(remotehost), 960 if (getnameinfo(raddr, salen, remotehost, sizeof(remotehost),
987 NULL, 0, NI_NAMEREQD) != 0) 961 NULL, 0, NI_NAMEREQD) != 0)
988 return (NULL); 962 return NULL;
989 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0, 963 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0, niflags) != 0)
990 niflags) != 0) 964 return NULL;
991 return (NULL); 
992 965
993 /* 966 /*
994 * Look up the name and check that the supplied 967 * Look up the name and check that the supplied
995 * address is in the list 968 * address is in the list
996 */ 969 */
997 memset(&hints, 0, sizeof(hints)); 970 memset(&hints, 0, sizeof(hints));
998 hints.ai_family = raddr->sa_family; 971 hints.ai_family = raddr->sa_family;
999 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 972 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
1000 hints.ai_flags = AI_CANONNAME; 973 hints.ai_flags = AI_CANONNAME;
1001 res = NULL; 974 res = NULL;
1002 error = getaddrinfo(remotehost, "0", &hints, &res); 975 error = getaddrinfo(remotehost, "0", &hints, &res);
1003 if (error) 976 if (error)
1004 return (NULL); 977 return NULL;
1005 978
1006 for (r = res; r; r = r->ai_next) { 979 for (r = res; r; r = r->ai_next) {
1007 h2[0] = '\0'; 980 h2[0] = '\0';
1008 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2), 981 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
1009 NULL, 0, niflags) != 0) 982 NULL, 0, niflags) != 0)
1010 continue; 983 continue;
1011 if (strcmp(h1, h2) == 0) { 984 if (strcmp(h1, h2) == 0) {
1012 freeaddrinfo(res); 985 freeaddrinfo(res);
1013 return (remotehost); 986 return remotehost;
1014 } 987 }
1015 } 988 }
1016 989
1017 /* 990 /*
1018 * either the DNS adminstrator has made a configuration 991 * either the DNS adminstrator has made a configuration
1019 * mistake, or someone has attempted to spoof us 992 * mistake, or someone has attempted to spoof us
1020 */ 993 */
1021 syslog(LOG_NOTICE, "rcmd: address %s not listed for host %s", 994 syslog(LOG_NOTICE, "rcmd: address %s not listed for host %s",
1022 h1, res->ai_canonname ? res->ai_canonname : remotehost); 995 h1, res->ai_canonname ? res->ai_canonname : remotehost);
1023 freeaddrinfo(res); 996 freeaddrinfo(res);
1024 return (NULL); 997 return NULL;
1025} 998}