summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoritojun <>2000-01-27 05:18:47 +0000
committeritojun <>2000-01-27 05:18:47 +0000
commit01a88624fac1f29e9deeedc05b266b38255068c5 (patch)
tree1c90d0b5f77b389005ad7de5528a1c4347523769
parentb2771c0992b93d3fc05508e5ff024fc970f22653 (diff)
downloadopenbsd-01a88624fac1f29e9deeedc05b266b38255068c5.tar.gz
openbsd-01a88624fac1f29e9deeedc05b266b38255068c5.tar.bz2
openbsd-01a88624fac1f29e9deeedc05b266b38255068c5.zip
add IPv6-ready rcmd() friends.
rcmd(): IPv4 only rcmd_af(): af independent ruserok(): af independent iruserok(): IPv4 only iruserok_sa(): af independent
-rw-r--r--src/lib/libc/net/Makefile.inc4
-rw-r--r--src/lib/libc/net/rcmd.343
-rw-r--r--src/lib/libc/net/rcmd.c297
3 files changed, 264 insertions, 80 deletions
diff --git a/src/lib/libc/net/Makefile.inc b/src/lib/libc/net/Makefile.inc
index 447a96f1e1..7174d68220 100644
--- a/src/lib/libc/net/Makefile.inc
+++ b/src/lib/libc/net/Makefile.inc
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile.inc,v 1.27 1999/12/16 21:30:34 deraadt Exp $ 1# $OpenBSD: Makefile.inc,v 1.28 2000/01/27 05:18:46 itojun Exp $
2 2
3# net sources 3# net sources
4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net ${LIBCSRCDIR}/net 4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net ${LIBCSRCDIR}/net
@@ -65,7 +65,7 @@ MLINKS+=link_addr.3 link_ntoa.3
65MLINKS+=ipx.3 ipx_addr.3 ipx.3 ipx_ntoa.3 65MLINKS+=ipx.3 ipx_addr.3 ipx.3 ipx_ntoa.3
66MLINKS+=ns.3 ns_addr.3 ns.3 ns_ntoa.3 66MLINKS+=ns.3 ns_addr.3 ns.3 ns_ntoa.3
67MLINKS+=rcmd.3 iruserok.3 rcmd.3 rresvport.3 rcmd.3 ruserok.3 \ 67MLINKS+=rcmd.3 iruserok.3 rcmd.3 rresvport.3 rcmd.3 ruserok.3 \
68 rcmd.3 rresvport_af.3 68 rcmd.3 rresvport_af.3 rcmd.3 rcmd_af.3 rcmd.3 iruserok_sa.3
69MLINKS+=resolver.3 dn_comp.3 resolver.3 dn_expand.3 resolver.3 res_init.3 \ 69MLINKS+=resolver.3 dn_comp.3 resolver.3 dn_expand.3 resolver.3 res_init.3 \
70 resolver.3 res_mkquery.3 resolver.3 res_send.3 resolver.3 res_query.3 \ 70 resolver.3 res_mkquery.3 resolver.3 res_send.3 resolver.3 res_query.3 \
71 resolver.3 res_search.3 71 resolver.3 res_search.3
diff --git a/src/lib/libc/net/rcmd.3 b/src/lib/libc/net/rcmd.3
index fa7be72c8d..6df614b419 100644
--- a/src/lib/libc/net/rcmd.3
+++ b/src/lib/libc/net/rcmd.3
@@ -1,4 +1,4 @@
1.\" $OpenBSD: rcmd.3,v 1.16 2000/01/26 06:22:52 deraadt Exp $ 1.\" $OpenBSD: rcmd.3,v 1.17 2000/01/27 05:18:47 itojun Exp $
2.\" 2.\"
3.\" Copyright (c) 1983, 1991, 1993 3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -36,16 +36,20 @@
36.Os 36.Os
37.Sh NAME 37.Sh NAME
38.Nm rcmd , 38.Nm rcmd ,
39.Nm rcmd_af ,
39.Nm rresvport , 40.Nm rresvport ,
40.Nm rresvport_af , 41.Nm rresvport_af ,
41.Nm iruserok , 42.Nm iruserok ,
42.Nm ruserok 43.Nm ruserok ,
44.Nm iruserok_sa
43.Nd routines for returning a stream to a remote command 45.Nd routines for returning a stream to a remote command
44.Sh SYNOPSIS 46.Sh SYNOPSIS
45.Fd #include <unistd.h> 47.Fd #include <unistd.h>
46.Ft int 48.Ft int
47.Fn rcmd "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p" 49.Fn rcmd "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p"
48.Ft int 50.Ft int
51.Fn rcmd_af "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p" "int af"
52.Ft int
49.Fn rresvport "int *port" 53.Fn rresvport "int *port"
50.Ft int 54.Ft int
51.Fn rresvport_af "int *port" "int af" 55.Fn rresvport_af "int *port" "int af"
@@ -53,6 +57,8 @@
53.Fn iruserok "u_int32_t raddr" "int superuser" "const char *ruser" "const char *luser" 57.Fn iruserok "u_int32_t raddr" "int superuser" "const char *ruser" "const char *luser"
54.Ft int 58.Ft int
55.Fn ruserok "const char *rhost" "int superuser" "const char *ruser" "const char *luser" 59.Fn ruserok "const char *rhost" "int superuser" "const char *ruser" "const char *luser"
60.Ft int
61.Fn iruserok_sa "const void *sa" "int salen" "int superuser" "const char *ruser"
56.Sh DESCRIPTION 62.Sh DESCRIPTION
57The 63The
58.Fn rcmd 64.Fn rcmd
@@ -74,6 +80,12 @@ will invoke
74.Xr rcmdsh 3 80.Xr rcmdsh 3
75to run the command via 81to run the command via
76.Xr rsh 1 . 82.Xr rsh 1 .
83While
84.Fn rcmd
85can handle IPv4 cases only,
86the
87.Fn rcmd_af
88function can handle other cases as well.
77The 89The
78.Fn rresvport 90.Fn rresvport
79and 91and
@@ -92,6 +104,9 @@ All four functions are present in the same file and are used
92by the 104by the
93.Xr rshd 8 105.Xr rshd 8
94server (among others). 106server (among others).
107.Fn iruserok_sa
108is an address family independent variant of
109.Fn iruserok .
95.Pp 110.Pp
96The 111The
97.Fn rcmd 112.Fn rcmd
@@ -142,6 +157,14 @@ Note that if the user is not the super-user,
142.Fa fd2p 157.Fa fd2p
143must be 0. 158must be 0.
144.Pp 159.Pp
160.Fn rcmd_af
161takes address family in the last argument.
162If the last argument is
163.Dv PF_UNSPEC ,
164interpretation of
165.Fa *ahost
166will obey the underlying address resolution like DNS.
167.Pp
145The protocol is described in detail in 168The protocol is described in detail in
146.Xr rshd 8 . 169.Xr rshd 8 .
147.Pp 170.Pp
@@ -200,6 +223,22 @@ If the IP address of the remote host is known,
200should be used in preference to 223should be used in preference to
201.Fn ruserok , 224.Fn ruserok ,
202as it does not require trusting the DNS server for the remote host's domain. 225as it does not require trusting the DNS server for the remote host's domain.
226.Pp
227While
228.Fn iruserok
229can handle IPv4 addresses only,
230.Fn iruserok_sa
231and
232.Fn ruserok
233can handle other address families as well, like IPv6.
234The first argument of
235.Fn iruserok_sa
236is typed as
237.Fa "void *"
238to avoid dependency between
239.Aq Li unistd.h
240and
241.Aq Li sys/socket.h .
203.Sh DIAGNOSTICS 242.Sh DIAGNOSTICS
204The 243The
205.Fn rcmd 244.Fn rcmd
diff --git a/src/lib/libc/net/rcmd.c b/src/lib/libc/net/rcmd.c
index bd920faadb..79892bd5a1 100644
--- a/src/lib/libc/net/rcmd.c
+++ b/src/lib/libc/net/rcmd.c
@@ -34,7 +34,7 @@
34 */ 34 */
35 35
36#if defined(LIBC_SCCS) && !defined(lint) 36#if defined(LIBC_SCCS) && !defined(lint)
37static char *rcsid = "$OpenBSD: rcmd.c,v 1.32 1999/12/16 21:30:34 deraadt Exp $"; 37static char *rcsid = "$OpenBSD: rcmd.c,v 1.33 2000/01/27 05:18:47 itojun Exp $";
38#endif /* LIBC_SCCS and not lint */ 38#endif /* LIBC_SCCS and not lint */
39 39
40#include <sys/param.h> 40#include <sys/param.h>
@@ -58,8 +58,9 @@ static char *rcsid = "$OpenBSD: rcmd.c,v 1.32 1999/12/16 21:30:34 deraadt Exp $"
58#include <netgroup.h> 58#include <netgroup.h>
59 59
60int __ivaliduser __P((FILE *, in_addr_t, const char *, const char *)); 60int __ivaliduser __P((FILE *, in_addr_t, const char *, const char *));
61static int __icheckhost __P((u_int32_t, const char *)); 61int __ivaliduser_sa __P((FILE *, struct sockaddr *, const char *, const char *));
62static char *__gethostloop __P((u_int32_t)); 62static int __icheckhost __P((struct sockaddr *, const char *));
63static char *__gethostloop __P((struct sockaddr *));
63 64
64int 65int
65rcmd(ahost, rport, locuser, remuser, cmd, fd2p) 66rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
@@ -68,8 +69,22 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
68 const char *locuser, *remuser, *cmd; 69 const char *locuser, *remuser, *cmd;
69 int *fd2p; 70 int *fd2p;
70{ 71{
71 struct hostent *hp; 72 return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
72 struct sockaddr_in sin, from; 73}
74
75int
76rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
77 char **ahost;
78 in_port_t rport;
79 const char *locuser, *remuser, *cmd;
80 int *fd2p;
81 int af;
82{
83 static char hbuf[MAXHOSTNAMELEN];
84 char pbuf[NI_MAXSERV];
85 struct addrinfo hints, *res, *r;
86 int error;
87 struct sockaddr_storage from;
73 fd_set *readsp = NULL; 88 fd_set *readsp = NULL;
74 int oldmask; 89 int oldmask;
75 pid_t pid; 90 pid_t pid;
@@ -95,16 +110,29 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
95 } 110 }
96 111
97 pid = getpid(); 112 pid = getpid();
98 hp = gethostbyname(*ahost); 113 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(rport));
99 if (hp == NULL) { 114 memset(&hints, 0, sizeof(hints));
100 herror(*ahost); 115 hints.ai_family = af;
116 hints.ai_socktype = SOCK_STREAM;
117 hints.ai_flags = AI_CANONNAME;
118 error = getaddrinfo(*ahost, pbuf, &hints, &res);
119 if (error) {
120#if 0
121 warnx("%s: %s", *ahost, gai_strerror(error));
122#endif
101 return (-1); 123 return (-1);
102 } 124 }
103 *ahost = hp->h_name; 125 if (res->ai_canonname) {
104 126 strncpy(hbuf, res->ai_canonname, sizeof(hbuf) - 1);
127 hbuf[sizeof(hbuf) - 1] = '\0';
128 *ahost = hbuf;
129 } else
130 ; /*XXX*/
131
132 r = res;
105 oldmask = sigblock(sigmask(SIGURG)); 133 oldmask = sigblock(sigmask(SIGURG));
106 for (timo = 1, lport = IPPORT_RESERVED - 1;;) { 134 for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
107 s = rresvport(&lport); 135 s = rresvport_af(&lport, r->ai_family);
108 if (s < 0) { 136 if (s < 0) {
109 if (errno == EAGAIN) 137 if (errno == EAGAIN)
110 (void)fprintf(stderr, 138 (void)fprintf(stderr,
@@ -113,15 +141,11 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
113 (void)fprintf(stderr, "rcmd: socket: %s\n", 141 (void)fprintf(stderr, "rcmd: socket: %s\n",
114 strerror(errno)); 142 strerror(errno));
115 sigsetmask(oldmask); 143 sigsetmask(oldmask);
144 freeaddrinfo(res);
116 return (-1); 145 return (-1);
117 } 146 }
118 fcntl(s, F_SETOWN, pid); 147 fcntl(s, F_SETOWN, pid);
119 bzero(&sin, sizeof sin); 148 if (connect(s, r->ai_addr, r->ai_addrlen) >= 0)
120 sin.sin_len = sizeof(struct sockaddr_in);
121 sin.sin_family = hp->h_addrtype;
122 sin.sin_port = rport;
123 bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
124 if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
125 break; 149 break;
126 (void)close(s); 150 (void)close(s);
127 if (errno == EADDRINUSE) { 151 if (errno == EADDRINUSE) {
@@ -133,23 +157,39 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
133 timo *= 2; 157 timo *= 2;
134 continue; 158 continue;
135 } 159 }
136 if (hp->h_addr_list[1] != NULL) { 160 if (r->ai_next) {
137 int oerrno = errno; 161 int oerrno = errno;
162 char hbuf[NI_MAXHOST];
163#ifdef NI_WITHSCOPEID
164 const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
165#else
166 const int niflags = NI_NUMERICHOST;
167#endif
138 168
139 (void)fprintf(stderr, "connect to address %s: ", 169 hbuf[0] = '\0';
140 inet_ntoa(sin.sin_addr)); 170 if (getnameinfo(r->ai_addr, r->ai_addrlen,
171 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0)
172 strcpy(hbuf, "(invalid)");
173 (void)fprintf(stderr, "connect to address %s: ", hbuf);
141 errno = oerrno; 174 errno = oerrno;
142 perror(0); 175 perror(0);
143 hp->h_addr_list++; 176 r = r->ai_next;
144 bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length); 177 hbuf[0] = '\0';
145 (void)fprintf(stderr, "Trying %s...\n", 178 if (getnameinfo(r->ai_addr, r->ai_addrlen,
146 inet_ntoa(sin.sin_addr)); 179 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0)
180 strcpy(hbuf, "(invalid)");
181 (void)fprintf(stderr, "Trying %s...\n", hbuf);
147 continue; 182 continue;
148 } 183 }
149 (void)fprintf(stderr, "%s: %s\n", hp->h_name, strerror(errno)); 184 (void)fprintf(stderr, "%s: %s\n", res->ai_canonname,
185 strerror(errno));
150 sigsetmask(oldmask); 186 sigsetmask(oldmask);
187 freeaddrinfo(res);
151 return (-1); 188 return (-1);
152 } 189 }
190 /* given "af" can be PF_UNSPEC, we need the real af for "s" */
191 af = r->ai_family;
192 freeaddrinfo(res);
153#if 0 193#if 0
154 /* 194 /*
155 * try to rresvport() to the same port. This will make rresvport() 195 * try to rresvport() to the same port. This will make rresvport()
@@ -162,7 +202,7 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
162 lport = 0; 202 lport = 0;
163 } else { 203 } else {
164 char num[8]; 204 char num[8];
165 int s2 = rresvport(&lport), s3; 205 int s2 = rresvport_af(&lport, af), s3;
166 int len = sizeof(from); 206 int len = sizeof(from);
167 int fdssize = howmany(MAX(s, s2)+1, NFDBITS) * sizeof(fd_mask); 207 int fdssize = howmany(MAX(s, s2)+1, NFDBITS) * sizeof(fd_mask);
168 208
@@ -202,9 +242,18 @@ again:
202 * XXX careful for ftp bounce attacks. If discovered, shut them 242 * XXX careful for ftp bounce attacks. If discovered, shut them
203 * down and check for the real auxiliary channel to connect. 243 * down and check for the real auxiliary channel to connect.
204 */ 244 */
205 if (from.sin_family == AF_INET && from.sin_port == htons(20)) { 245 switch (from.ss_family) {
246 case AF_INET:
247 case AF_INET6:
248 if (getnameinfo((struct sockaddr *)&from, len,
249 NULL, 0, num, sizeof(num), NI_NUMERICSERV) == 0 &&
250 atoi(num) != 20) {
251 break;
252 }
206 close(s3); 253 close(s3);
207 goto again; 254 goto again;
255 default:
256 break;
208 } 257 }
209 (void)close(s2); 258 (void)close(s2);
210 if (s3 < 0) { 259 if (s3 < 0) {
@@ -214,13 +263,20 @@ again:
214 goto bad; 263 goto bad;
215 } 264 }
216 *fd2p = s3; 265 *fd2p = s3;
217 from.sin_port = ntohs(from.sin_port); 266 switch (from.ss_family) {
218 if (from.sin_family != AF_INET || 267 case AF_INET:
219 from.sin_port >= IPPORT_RESERVED || 268 case AF_INET6:
220 from.sin_port < IPPORT_RESERVED / 2) { 269 if (getnameinfo((struct sockaddr *)&from, len,
221 (void)fprintf(stderr, 270 NULL, 0, num, sizeof(num), NI_NUMERICSERV) != 0 ||
222 "socket: protocol failure in circuit setup.\n"); 271 (atoi(num) >= IPPORT_RESERVED ||
223 goto bad2; 272 atoi(num) < IPPORT_RESERVED / 2)) {
273 (void)fprintf(stderr,
274 "socket: protocol failure in circuit setup.\n");
275 goto bad2;
276 }
277 break;
278 default:
279 break;
224 } 280 }
225 } 281 }
226 (void)write(s, locuser, strlen(locuser)+1); 282 (void)write(s, locuser, strlen(locuser)+1);
@@ -261,21 +317,24 @@ ruserok(rhost, superuser, ruser, luser)
261 const char *rhost, *ruser, *luser; 317 const char *rhost, *ruser, *luser;
262 int superuser; 318 int superuser;
263{ 319{
264 struct hostent *hp; 320 struct addrinfo hints, *res, *r;
265 char **ap; 321 int error;
266 int i; 322
267#define MAXADDRS 35 323 memset(&hints, 0, sizeof(hints));
268 u_int32_t addrs[MAXADDRS + 1]; 324 hints.ai_family = PF_UNSPEC;
269 325 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
270 if ((hp = gethostbyname(rhost)) == NULL) 326 error = getaddrinfo(rhost, "0", &hints, &res);
327 if (error)
271 return (-1); 328 return (-1);
272 for (i = 0, ap = hp->h_addr_list; *ap && i < MAXADDRS; ++ap, ++i)
273 bcopy(*ap, &addrs[i], sizeof(addrs[i]));
274 addrs[i] = 0;
275 329
276 for (i = 0; i < MAXADDRS && addrs[i]; i++) 330 for (r = res; r; r = r->ai_next) {
277 if (iruserok((in_addr_t)addrs[i], superuser, ruser, luser) == 0) 331 if (iruserok_sa(r->ai_addr, r->ai_addrlen, superuser, ruser,
332 luser) == 0) {
333 freeaddrinfo(res);
278 return (0); 334 return (0);
335 }
336 }
337 freeaddrinfo(res);
279 return (-1); 338 return (-1);
280} 339}
281 340
@@ -294,6 +353,24 @@ iruserok(raddr, superuser, ruser, luser)
294 int superuser; 353 int superuser;
295 const char *ruser, *luser; 354 const char *ruser, *luser;
296{ 355{
356 struct sockaddr_in sin;
357
358 memset(&sin, 0, sizeof(sin));
359 sin.sin_family = AF_INET;
360 sin.sin_len = sizeof(struct sockaddr_in);
361 memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
362 return iruserok_sa(&sin, sizeof(struct sockaddr_in), superuser, ruser,
363 luser);
364}
365
366int
367iruserok_sa(raddr, rlen, superuser, ruser, luser)
368 const void *raddr;
369 int rlen;
370 int superuser;
371 const char *ruser, *luser;
372{
373 struct sockaddr *sa;
297 register char *cp; 374 register char *cp;
298 struct stat sbuf; 375 struct stat sbuf;
299 struct passwd *pwd; 376 struct passwd *pwd;
@@ -302,11 +379,15 @@ iruserok(raddr, superuser, ruser, luser)
302 int first; 379 int first;
303 char pbuf[MAXPATHLEN]; 380 char pbuf[MAXPATHLEN];
304 381
382 sa = (struct sockaddr *)raddr;
383#ifdef lint
384 rlen = rlen;
385#endif
305 first = 1; 386 first = 1;
306 hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r"); 387 hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
307again: 388again:
308 if (hostf) { 389 if (hostf) {
309 if (__ivaliduser(hostf, raddr, luser, ruser) == 0) { 390 if (__ivaliduser_sa(hostf, sa, luser, ruser) == 0) {
310 (void)fclose(hostf); 391 (void)fclose(hostf);
311 return (0); 392 return (0);
312 } 393 }
@@ -369,13 +450,27 @@ __ivaliduser(hostf, raddrl, luser, ruser)
369 in_addr_t raddrl; 450 in_addr_t raddrl;
370 const char *luser, *ruser; 451 const char *luser, *ruser;
371{ 452{
453 struct sockaddr_in sin;
454
455 memset(&sin, 0, sizeof(sin));
456 sin.sin_family = AF_INET;
457 sin.sin_len = sizeof(struct sockaddr_in);
458 memcpy(&sin.sin_addr, &raddrl, sizeof(sin.sin_addr));
459 return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, luser, ruser);
460}
461
462int
463__ivaliduser_sa(hostf, raddr, luser, ruser)
464 FILE *hostf;
465 struct sockaddr *raddr;
466 const char *luser, *ruser;
467{
372 register char *user, *p; 468 register char *user, *p;
373 char *buf; 469 char *buf;
374 const char *auser, *ahost; 470 const char *auser, *ahost;
375 int hostok, userok; 471 int hostok, userok;
376 char *rhost = (char *)-1; 472 char *rhost = (char *)-1;
377 char domain[MAXHOSTNAMELEN]; 473 char domain[MAXHOSTNAMELEN];
378 u_int32_t raddr = (u_int32_t)raddrl;
379 size_t buflen; 474 size_t buflen;
380 475
381 getdomainname(domain, sizeof(domain)); 476 getdomainname(domain, sizeof(domain));
@@ -509,27 +604,54 @@ bail:
509/* 604/*
510 * Returns "true" if match, 0 if no match. If we do not find any 605 * Returns "true" if match, 0 if no match. If we do not find any
511 * semblance of an A->PTR->A loop, allow a simple #.#.#.# match to work. 606 * semblance of an A->PTR->A loop, allow a simple #.#.#.# match to work.
607 *
608 * NI_WITHSCOPEID is useful for comparing sin6_scope_id portion
609 * if af == AF_INET6.
512 */ 610 */
513static int 611static int
514__icheckhost(raddr, lhost) 612__icheckhost(raddr, lhost)
515 u_int32_t raddr; 613 struct sockaddr *raddr;
516 const char *lhost; 614 const char *lhost;
517{ 615{
518 register struct hostent *hp; 616 struct addrinfo hints, *res, *r;
519 register char **pp; 617 char h1[NI_MAXHOST], h2[NI_MAXHOST];
520 struct in_addr in; 618 int error;
521 619#ifdef NI_WITHSCOPEID
522 hp = gethostbyname(lhost); 620 const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
523 if (hp != NULL) { 621#else
524 /* Spin through ip addresses. */ 622 const int niflags = NI_NUMERICHOST;
525 for (pp = hp->h_addr_list; *pp; ++pp) 623#endif
526 if (!bcmp(&raddr, *pp, sizeof(raddr))) 624
527 return (1); 625 h1[0] = '\0';
626 if (getnameinfo(raddr, raddr->sa_len, h1, sizeof(h1), NULL, 0,
627 niflags) != 0)
628 return (0);
629
630 /* Resolve laddr into sockaddr */
631 memset(&hints, 0, sizeof(hints));
632 hints.ai_family = raddr->sa_family;
633 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
634 res = NULL;
635 error = getaddrinfo(lhost, "0", &hints, &res);
636 if (error)
637 return (0);
638
639 /*
640 * Try string comparisons between raddr and laddr.
641 */
642 for (r = res; r; r = r->ai_next) {
643 h2[0] = '\0';
644 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
645 NULL, 0, niflags) != 0)
646 continue;
647 if (strcmp(h1, h2) == 0) {
648 freeaddrinfo(res);
649 return (1);
650 }
528 } 651 }
529 652
530 in.s_addr = raddr; 653 /* No match. */
531 if (strcmp(lhost, inet_ntoa(in)) == 0) 654 freeaddrinfo(res);
532 return (1);
533 return (0); 655 return (0);
534} 656}
535 657
@@ -537,39 +659,62 @@ __icheckhost(raddr, lhost)
537 * Return the hostname associated with the supplied address. 659 * Return the hostname associated with the supplied address.
538 * Do a reverse lookup as well for security. If a loop cannot 660 * Do a reverse lookup as well for security. If a loop cannot
539 * be found, pack the result of inet_ntoa() into the string. 661 * be found, pack the result of inet_ntoa() into the string.
662 *
663 * NI_WITHSCOPEID is useful for comparing sin6_scope_id portion
664 * if af == AF_INET6.
540 */ 665 */
541static char * 666static char *
542__gethostloop(raddr) 667__gethostloop(raddr)
543 u_int32_t raddr; 668 struct sockaddr *raddr;
544{ 669{
545 static char remotehost[MAXHOSTNAMELEN]; 670 static char remotehost[NI_MAXHOST];
546 struct hostent *hp; 671 char h1[NI_MAXHOST], h2[NI_MAXHOST];
547 struct in_addr in; 672 struct addrinfo hints, *res, *r;
673 int error;
674#ifdef NI_WITHSCOPEID
675 const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
676#else
677 const int niflags = NI_NUMERICHOST;
678#endif
548 679
549 hp = gethostbyaddr((char *) &raddr, sizeof(raddr), AF_INET); 680 h1[0] = remotehost[0] = '\0';
550 if (hp == NULL) 681 if (getnameinfo(raddr, raddr->sa_len, remotehost, sizeof(remotehost),
682 NULL, 0, NI_NAMEREQD) != 0)
683 return (NULL);
684 if (getnameinfo(raddr, raddr->sa_len, h1, sizeof(h1), NULL, 0,
685 niflags) != 0)
551 return (NULL); 686 return (NULL);
552 687
553 /* 688 /*
554 * Look up the name and check that the supplied 689 * Look up the name and check that the supplied
555 * address is in the list 690 * address is in the list
556 */ 691 */
557 strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1); 692 memset(&hints, 0, sizeof(hints));
558 remotehost[sizeof(remotehost) - 1] = '\0'; 693 hints.ai_family = raddr->sa_family;
559 hp = gethostbyname(remotehost); 694 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
560 if (hp == NULL) 695 hints.ai_flags = AI_CANONNAME;
696 res = NULL;
697 error = getaddrinfo(remotehost, "0", &hints, &res);
698 if (error)
561 return (NULL); 699 return (NULL);
562 700
563 for (; hp->h_addr_list[0] != NULL; hp->h_addr_list++) 701 for (r = res; r; r = r->ai_next) {
564 if (!bcmp(hp->h_addr_list[0], (caddr_t)&raddr, sizeof(raddr))) 702 h2[0] = '\0';
703 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
704 NULL, 0, niflags) != 0)
705 continue;
706 if (strcmp(h1, h2) == 0) {
707 freeaddrinfo(res);
565 return (remotehost); 708 return (remotehost);
709 }
710 }
566 711
567 /* 712 /*
568 * either the DNS adminstrator has made a configuration 713 * either the DNS adminstrator has made a configuration
569 * mistake, or someone has attempted to spoof us 714 * mistake, or someone has attempted to spoof us
570 */ 715 */
571 in.s_addr = raddr;
572 syslog(LOG_NOTICE, "rcmd: address %s not listed for host %s", 716 syslog(LOG_NOTICE, "rcmd: address %s not listed for host %s",
573 inet_ntoa(in), hp->h_name); 717 h1, res->ai_canonname ? res->ai_canonname : remotehost);
718 freeaddrinfo(res);
574 return (NULL); 719 return (NULL);
575} 720}