diff --git a/distrib/sets/lists/comp/mi b/distrib/sets/lists/comp/mi index f053152e9f8b..1ed2c1893fa3 100644 --- a/distrib/sets/lists/comp/mi +++ b/distrib/sets/lists/comp/mi @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.187 2000/01/26 13:20:26 itojun Exp $ +# $NetBSD: mi,v 1.188 2000/01/27 05:33:07 itojun Exp $ ./sys ./usr/bin/ar ./usr/bin/as @@ -1882,6 +1882,7 @@ ./usr/share/man/cat3/ipsec_set_policy.0 ./usr/share/man/cat3/ipsec_strerror.0 ./usr/share/man/cat3/iruserok.0 +./usr/share/man/cat3/iruserok_sa.0 ./usr/share/man/cat3/isalnum.0 ./usr/share/man/cat3/isalpha.0 ./usr/share/man/cat3/isascii.0 @@ -2040,6 +2041,7 @@ ./usr/share/man/cat3/openlog.0 ./usr/share/man/cat3/openpty.0 ./usr/share/man/cat3/orcmd.0 +./usr/share/man/cat3/orcmd_af.0 ./usr/share/man/cat3/ossaudio.0 ./usr/share/man/cat3/pause.0 ./usr/share/man/cat3/pcap.0 @@ -2083,6 +2085,7 @@ ./usr/share/man/cat3/rand_r.0 ./usr/share/man/cat3/random.0 ./usr/share/man/cat3/rcmd.0 +./usr/share/man/cat3/rcmd_af.0 ./usr/share/man/cat3/re_comp.0 ./usr/share/man/cat3/re_exec.0 ./usr/share/man/cat3/readdir.0 @@ -2118,6 +2121,7 @@ ./usr/share/man/cat3/rpc.0 ./usr/share/man/cat3/rpc_createerr.0 ./usr/share/man/cat3/rresvport.0 +./usr/share/man/cat3/rresvport_af.0 ./usr/share/man/cat3/ruserok.0 ./usr/share/man/cat3/scalb.0 ./usr/share/man/cat3/scalbf.0 @@ -2988,6 +2992,7 @@ ./usr/share/man/man3/bcmp.3 ./usr/share/man/man3/bcopy.3 ./usr/share/man/man3/bindresvport.3 +./usr/share/man/man3/bindresvport_sa.3 ./usr/share/man/man3/bitstring.3 ./usr/share/man/man3/bm.3 ./usr/share/man/man3/bm_comp.3 @@ -3357,6 +3362,7 @@ ./usr/share/man/man3/ipsec_set_policy.3 ./usr/share/man/man3/ipsec_strerror.3 ./usr/share/man/man3/iruserok.3 +./usr/share/man/man3/iruserok_sa.3 ./usr/share/man/man3/isalnum.3 ./usr/share/man/man3/isalpha.3 ./usr/share/man/man3/isascii.3 @@ -3515,6 +3521,7 @@ ./usr/share/man/man3/openlog.3 ./usr/share/man/man3/openpty.3 ./usr/share/man/man3/orcmd.3 +./usr/share/man/man3/orcmd_af.3 ./usr/share/man/man3/ossaudio.3 ./usr/share/man/man3/pause.3 ./usr/share/man/man3/pcap.3 @@ -3558,6 +3565,7 @@ ./usr/share/man/man3/rand_r.3 ./usr/share/man/man3/random.3 ./usr/share/man/man3/rcmd.3 +./usr/share/man/man3/rcmd_af.3 ./usr/share/man/man3/re_comp.3 ./usr/share/man/man3/re_exec.3 ./usr/share/man/man3/readdir.3 @@ -3593,6 +3601,7 @@ ./usr/share/man/man3/rpc.3 ./usr/share/man/man3/rpc_createerr.3 ./usr/share/man/man3/rresvport.3 +./usr/share/man/man3/rresvport_af.3 ./usr/share/man/man3/ruserok.3 ./usr/share/man/man3/scalb.3 ./usr/share/man/man3/scalbf.3 diff --git a/include/unistd.h b/include/unistd.h index 3705e79d2631..4b116b4f6b99 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -1,4 +1,4 @@ -/* $NetBSD: unistd.h,v 1.80 2000/01/10 16:58:38 kleink Exp $ */ +/* $NetBSD: unistd.h,v 1.81 2000/01/27 05:33:07 itojun Exp $ */ /*- * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. @@ -331,9 +331,10 @@ quad_t __syscall __P((quad_t, ...)); int undelete __P((const char *)); #if 1 /*INET6*/ +int rcmd_af __P((char **, int, const char *, + const char *, const char *, int *, int)); int rresvport_af __P((int *, int)); -int ruserok_af __P((const char *, int, const char *, const char *, int)); -int iruserok_af __P((const void *, int, const char *, const char *, int)); +int iruserok_sa __P((const void *, int, int, const char *, const char *)); #endif extern __const char *__const *sys_siglist __RENAME(__sys_siglist14); diff --git a/lib/libc/net/Makefile.inc b/lib/libc/net/Makefile.inc index 4329597d567a..1c98245d3add 100644 --- a/lib/libc/net/Makefile.inc +++ b/lib/libc/net/Makefile.inc @@ -1,4 +1,4 @@ -# $NetBSD: Makefile.inc,v 1.47 2000/01/26 02:46:36 itojun Exp $ +# $NetBSD: Makefile.inc,v 1.48 2000/01/27 05:33:06 itojun Exp $ # @(#)Makefile.inc 8.2 (Berkeley) 9/5/93 # net sources @@ -19,7 +19,7 @@ CPPFLAGS+=-DRESOLVSORT -I. # IPv6 SRCS+= getaddrinfo.c getnameinfo.c ifname.c ip6opt.c rthdr.c vars6.c # need to revisit -#SRCS+= name6.c rresvport_af.c freehostent.c +#SRCS+= name6.c freehostent.c #CPPFLAGS+= -DUSE_GETIPNODEBY LPREFIX=_nsyy @@ -86,7 +86,9 @@ MLINKS+=getaddrinfo.3 freeaddrinfo.3 getaddrinfo.3 gai_strerror.3 \ inet6_rthdr_space.3 inet6_rthdr_reverse.3 \ inet6_rthdr_space.3 inet6_rthdr_segments.3 \ inet6_rthdr_space.3 inet6_rthdr_getaddr.3 \ - inet6_rthdr_space.3 inet6_rthdr_getflags.3 + inet6_rthdr_space.3 inet6_rthdr_getflags.3 \ + rcmd.3 rcmd_af.3 rcmd.3 iruserok_sa.3 rcmd.3 rresvport_af.3 \ + rcmd.3 orcmd_af.3 # need to revisit -#MAN+= getipnodebyname.3 rresvport_af.3 +#MAN+= getipnodebyname.3 #MLINKS+=getipnodebyname.3 getipnodebyaddr.3 getipnodebyname.3 freehostent.3 \ diff --git a/lib/libc/net/rcmd.3 b/lib/libc/net/rcmd.3 index 9507902b5917..e2645106e55d 100644 --- a/lib/libc/net/rcmd.3 +++ b/lib/libc/net/rcmd.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: rcmd.3,v 1.18 1999/07/04 00:43:44 itojun Exp $ +.\" $NetBSD: rcmd.3,v 1.19 2000/01/27 05:33:06 itojun Exp $ .\" .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -38,11 +38,14 @@ .Os .Sh NAME .Nm rcmd , +.Nm orcmd , +.Nm rcmd_af , +.Nm orcmd_af , .Nm rresvport , .Nm rresvport_af , .Nm iruserok , .Nm ruserok , -.Nm orcmd +.Nm iruserok_sa .Nd routines for returning a stream to a remote command .Sh LIBRARY .Lb libc @@ -53,6 +56,10 @@ .Ft int .Fn orcmd "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p" .Ft int +.Fn rcmd_af "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p" "int af" +.Ft int +.Fn orcmd_af "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p" "int af" +.Ft int .Fn rresvport "int *port" .Ft int .Fn rresvport_af "int *port" "int family" @@ -60,6 +67,8 @@ .Fn iruserok "u_int32_t raddr" "int superuser" "const char *ruser" "const char *luser" .Ft int .Fn ruserok "const char *rhost" "int superuser" "const char *ruser" "const char *luser" +.Ft int +.Fn iruserok_sa "const void *raddr" "int rlen" "int superuser" "const char *ruser" "const char *luser" .Sh DESCRIPTION The .Fn rcmd @@ -80,6 +89,15 @@ function is used by the super-user to execute a command on a remote machine using an authentication scheme based on reserved port numbers. +While +.Fn rcmd +and +.Fn orcmd +can only handle IPv4 address in the first argument, +.Fn rcmd_af +and +.Fn orcmd_af +can handle other cases as well. The .Fn rresvport function @@ -107,6 +125,9 @@ All six functions are present in the same file and are used by the .Xr rshd 8 server (among others). +.Fn iruserok_sa +is an address family independent variant of +.Fn iruserok . .Pp The .Fn rcmd @@ -154,6 +175,16 @@ and no provision is made for sending arbitrary signals to the remote process, although you may be able to get its attention by using out-of-band data. .Pp +.Fn rcmd_af +and +.Fn orcmd_af +take address family in the last argument. +If the last argument is +.Dv PF_UNSPEC , +interpretation of +.Fa *ahost +will obey the underlying address resolution like DNS. +.Pp The protocol is described in detail in .Xr rshd 8 . .Pp @@ -207,6 +238,22 @@ If the IP address of the remote host is known, should be used in preference to .Fn ruserok , as it does not require trusting the DNS server for the remote host's domain. +.Pp +While +.Fn iruserok +can handle IPv4 addresses only, +.Fn iruserok_sa +and +.Fn ruserok +can handle other address families as well, like IPv6. +The first argument of +.Fn iruserok_sa +is typed as +.Fa "void *" +to avoid dependency between +.Aq Li unistd.h +and +.Aq Li sys/socket.h . .Sh DIAGNOSTICS The .Fn rcmd @@ -244,7 +291,7 @@ function, this variable is used as the program to run instead of .Xr rhosts 5 , .Xr rexecd 8 , .Xr rlogind 8 , -.Xr rshd 8 . +.Xr rshd 8 .Sh HISTORY The .Fn orcmd , @@ -257,13 +304,15 @@ functions appeared in where the .Fn orcmd function was called -.Fn rcmd. +.Fn rcmd . The (newer) .Fn rcmd function appeared in .Nx 1.3 . +.Fn rcmd_af +and .Fn rresvport_af -was defined in RFC2292. +were defined in RFC2292. .Sh BUGS As the .Nm diff --git a/lib/libc/net/rcmd.c b/lib/libc/net/rcmd.c index 56d4e1dd6022..e67a929ff740 100644 --- a/lib/libc/net/rcmd.c +++ b/lib/libc/net/rcmd.c @@ -1,4 +1,4 @@ -/* $NetBSD: rcmd.c,v 1.36 2000/01/22 23:36:17 mycroft Exp $ */ +/* $NetBSD: rcmd.c,v 1.37 2000/01/27 05:33:06 itojun Exp $ */ /* * Copyright (c) 1997 Matthew R. Green. @@ -39,7 +39,7 @@ #if 0 static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94"; #else -__RCSID("$NetBSD: rcmd.c,v 1.36 2000/01/22 23:36:17 mycroft Exp $"); +__RCSID("$NetBSD: rcmd.c,v 1.37 2000/01/27 05:33:06 itojun Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -75,13 +75,17 @@ __RCSID("$NetBSD: rcmd.c,v 1.36 2000/01/22 23:36:17 mycroft Exp $"); int orcmd __P((char **, u_int, const char *, const char *, const char *, int *)); +int orcmd_af __P((char **, u_int, const char *, const char *, const char *, + int *, int)); int __ivaliduser __P((FILE *, u_int32_t, const char *, const char *)); +int __ivaliduser_sa __P((FILE *, struct sockaddr *, const char *, + const char *)); static int rshrcmd __P((char **, u_int32_t, const char *, const char *, const char *, int *, const char *)); -static int hprcmd __P((struct hostent *, char **, u_int32_t, const char *, +static int resrcmd __P((struct addrinfo *, char **, u_int32_t, const char *, const char *, const char *, int *)); -static int __icheckhost __P((u_int32_t, const char *)); -static char *__gethostloop __P((u_int32_t)); +static int __icheckhost __P((struct sockaddr *, const char *)); +static char *__gethostloop __P((struct sockaddr *)); int rcmd(ahost, rport, locuser, remuser, cmd, fd2p) @@ -90,7 +94,22 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p) const char *locuser, *remuser, *cmd; int *fd2p; { - struct hostent *hp; + + return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET); +} + +int +rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af) + char **ahost; + u_short rport; + const char *locuser, *remuser, *cmd; + int *fd2p; + int af; +{ + static char hbuf[MAXHOSTNAMELEN]; + char pbuf[NI_MAXSERV]; + struct addrinfo hints, *res; + int error; struct servent *sp; _DIAGASSERT(ahost != NULL); @@ -99,16 +118,25 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p) _DIAGASSERT(cmd != NULL); /* fd2p may be NULL */ - /* - * Canonicalise hostname. - * XXX: Should we really do this? - */ - hp = gethostbyname(*ahost); - if (hp == NULL) { - herror(*ahost); + snprintf(pbuf, sizeof(pbuf), "%u", ntohs(rport)); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = af; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + error = getaddrinfo(*ahost, pbuf, &hints, &res); + if (error) { + warnx("%s: %s", *ahost, gai_strerror(error)); /*XXX*/ return (-1); } - *ahost = hp->h_name; + if (res->ai_canonname) { + /* + * Canonicalise hostname. + * XXX: Should we really do this? + */ + strncpy(hbuf, res->ai_canonname, sizeof(hbuf) - 1); + hbuf[sizeof(hbuf) - 1] = '\0'; + *ahost = hbuf; + } /* * Check if rport is the same as the shell port, and that the fd2p. If @@ -117,11 +145,13 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p) */ sp = getservbyname("shell", "tcp"); if (sp != NULL && sp->s_port == rport) - return (rshrcmd(ahost, (u_int32_t)rport, - locuser, remuser, cmd, fd2p, getenv("RCMD_CMD"))); + error = rshrcmd(ahost, (u_int32_t)rport, + locuser, remuser, cmd, fd2p, getenv("RCMD_CMD")); else - return (hprcmd(hp, ahost, (u_int32_t)rport, - locuser, remuser, cmd, fd2p)); + error = resrcmd(res, ahost, (u_int32_t)rport, + locuser, remuser, cmd, fd2p); + freeaddrinfo(res); + return (error); } /* this is simply a wrapper around hprcmd() that handles ahost first */ @@ -132,7 +162,21 @@ orcmd(ahost, rport, locuser, remuser, cmd, fd2p) const char *locuser, *remuser, *cmd; int *fd2p; { - struct hostent *hp; + return orcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET); +} + +int +orcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af) + char **ahost; + u_int rport; + const char *locuser, *remuser, *cmd; + int *fd2p; + int af; +{ + static char hbuf[MAXHOSTNAMELEN]; + char pbuf[NI_MAXSERV]; + struct addrinfo hints, *res; + int error; _DIAGASSERT(ahost != NULL); _DIAGASSERT(locuser != NULL); @@ -140,25 +184,37 @@ orcmd(ahost, rport, locuser, remuser, cmd, fd2p) _DIAGASSERT(cmd != NULL); /* fd2p may be NULL */ - hp = gethostbyname(*ahost); - if (hp == NULL) { - herror(*ahost); + snprintf(pbuf, sizeof(pbuf), "%u", ntohs(rport)); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = af; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + error = getaddrinfo(*ahost, pbuf, &hints, &res); + if (error) { + warnx("%s: %s", *ahost, gai_strerror(error)); /*XXX*/ return (-1); } - *ahost = hp->h_name; + if (res->ai_canonname) { + strncpy(hbuf, res->ai_canonname, sizeof(hbuf) - 1); + hbuf[sizeof(hbuf) - 1] = '\0'; + *ahost = hbuf; + } - return (hprcmd(hp, ahost, rport, locuser, remuser, cmd, fd2p)); + error = resrcmd(res, ahost, rport, locuser, remuser, cmd, fd2p); + freeaddrinfo(res); + return (error); } static int -hprcmd(hp, ahost, rport, locuser, remuser, cmd, fd2p) - struct hostent *hp; +resrcmd(res, ahost, rport, locuser, remuser, cmd, fd2p) + struct addrinfo *res; char **ahost; u_int32_t rport; const char *locuser, *remuser, *cmd; int *fd2p; { - struct sockaddr_in sin, from; + struct addrinfo *r; + struct sockaddr_storage from; struct pollfd reads[2]; sigset_t nmask, omask; pid_t pid; @@ -166,20 +222,21 @@ hprcmd(hp, ahost, rport, locuser, remuser, cmd, fd2p) int pollr; char c; - _DIAGASSERT(hp != NULL); + _DIAGASSERT(res != NULL); _DIAGASSERT(ahost != NULL); _DIAGASSERT(locuser != NULL); _DIAGASSERT(remuser != NULL); _DIAGASSERT(cmd != NULL); /* fd2p may be NULL */ + r = res; pid = getpid(); sigemptyset(&nmask); sigaddset(&nmask, SIGURG); if (sigprocmask(SIG_BLOCK, &nmask, &omask) == -1) return -1; for (timo = 1, lport = IPPORT_RESERVED - 1;;) { - s = rresvport(&lport); + s = rresvport_af(&lport, r->ai_family); if (s < 0) { if (errno == EAGAIN) warnx("rcmd: socket: All ports in use"); @@ -189,14 +246,7 @@ hprcmd(hp, ahost, rport, locuser, remuser, cmd, fd2p) return (-1); } fcntl(s, F_SETOWN, pid); -#ifdef BSD4_4 - sin.sin_len = sizeof(struct sockaddr_in); -#endif - sin.sin_family = hp->h_addrtype; - sin.sin_port = rport; - memmove(&sin.sin_addr, - hp->h_addr_list[0], (size_t)hp->h_length); - if (connect(s, (struct sockaddr *)(void *)&sin, sizeof(sin)) >= 0) + if (connect(s, r->ai_addr, r->ai_addrlen) >= 0) break; (void)close(s); if (errno == EADDRINUSE) { @@ -208,21 +258,32 @@ hprcmd(hp, ahost, rport, locuser, remuser, cmd, fd2p) timo *= 2; continue; } - if (hp->h_addr_list[1] != NULL) { + if (r->ai_next) { int oerrno = errno; + char hbuf[NI_MAXHOST]; +#ifdef NI_WITHSCOPEID + const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID; +#else + const int niflags = NI_NUMERICHOST; +#endif - warnx("rcmd: connect to address %s", - inet_ntoa(sin.sin_addr)); + hbuf[0] = '\0'; + if (getnameinfo(r->ai_addr, r->ai_addrlen, + hbuf, sizeof(hbuf), NULL, 0, niflags) != 0) + strcpy(hbuf, "(invalid)"); + warnx("rcmd: connect to address %s", hbuf); errno = oerrno; perror(0); - hp->h_addr_list++; - memmove(&sin.sin_addr, hp->h_addr_list[0], - (size_t)hp->h_length); - (void)fprintf(stderr, "Trying %s...\n", - inet_ntoa(sin.sin_addr)); + r = r->ai_next; + hbuf[0] = '\0'; + if (getnameinfo(r->ai_addr, r->ai_addrlen, + hbuf, sizeof(hbuf), NULL, 0, niflags) != 0) + strcpy(hbuf, "(invalid)"); + (void)fprintf(stderr, "Trying %s...\n", hbuf); continue; } - (void)fprintf(stderr, "%s: %s\n", hp->h_name, strerror(errno)); + (void)fprintf(stderr, "%s: %s\n", res->ai_canonname, + strerror(errno)); (void)sigprocmask(SIG_SETMASK, &omask, NULL); return (-1); } @@ -232,7 +293,7 @@ hprcmd(hp, ahost, rport, locuser, remuser, cmd, fd2p) lport = 0; } else { char num[8]; - int s2 = rresvport(&lport), s3; + int s2 = rresvport_af(&lport, r->ai_family), s3; socklen_t len = sizeof(from); if (s2 < 0) @@ -266,12 +327,21 @@ hprcmd(hp, ahost, rport, locuser, remuser, cmd, fd2p) goto bad; } *fd2p = s3; - from.sin_port = ntohs(from.sin_port); - if (from.sin_family != AF_INET || - from.sin_port >= IPPORT_RESERVED || - from.sin_port < IPPORT_RESERVED / 2) { - warnx("rcmd: protocol failure in circuit setup."); - goto bad2; + switch (((struct sockaddr *)&from)->sa_family) { + case AF_INET: +#ifdef INET6 + case AF_INET6: +#endif + if (getnameinfo((struct sockaddr *)&from, len, + NULL, 0, num, sizeof(num), NI_NUMERICSERV) != 0 || + (atoi(num) >= IPPORT_RESERVED || + atoi(num) < IPPORT_RESERVED / 2)) { + warnx("rcmd: protocol failure in circuit setup."); + goto bad2; + } + break; + default: + break; } } @@ -452,6 +522,7 @@ rresvport_af(alport, family) salen = sizeof(struct sockaddr_in); portp = &((struct sockaddr_in *)sa)->sin_port; break; +#ifdef INET6 case AF_INET6: #ifdef BSD4_4 sa->sa_len = @@ -459,6 +530,7 @@ rresvport_af(alport, family) salen = sizeof(struct sockaddr_in6); portp = &((struct sockaddr_in6 *)sa)->sin6_port; break; +#endif default: portp = NULL; return EAFNOSUPPORT; @@ -468,7 +540,9 @@ rresvport_af(alport, family) if (s < 0) return (-1); #ifdef BSD4_4 - if (family == AF_INET) { + switch (family) { + case AF_INET: + case AF_INET6: *portp = 0; if (bindresvport(s, (struct sockaddr_in *)sa) < 0) { int sverr = errno; @@ -479,6 +553,9 @@ rresvport_af(alport, family) } *alport = (int)ntohs(*portp); return (s); + default: + /* is it necessary to try keep code for other AFs? */ + break; } #endif for (;;) { @@ -506,25 +583,28 @@ ruserok(rhost, superuser, ruser, luser) const char *rhost, *ruser, *luser; int superuser; { - struct hostent *hp; - char **ap; - int i; -#define MAXADDRS 35 - u_int32_t addrs[MAXADDRS + 1]; + struct addrinfo hints, *res, *r; + int error; _DIAGASSERT(rhost != NULL); _DIAGASSERT(ruser != NULL); _DIAGASSERT(luser != NULL); - if ((hp = gethostbyname(rhost)) == NULL) + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + error = getaddrinfo(rhost, "0", &hints, &res); + if (error) return (-1); - for (i = 0, ap = hp->h_addr_list; *ap && i < MAXADDRS; ++ap, ++i) - memmove(&addrs[i], *ap, sizeof(addrs[i])); - addrs[i] = 0; - for (i = 0; i < MAXADDRS && addrs[i]; i++) - if (iruserok(addrs[i], superuser, ruser, luser) == 0) + for (r = res; r; r = r->ai_next) { + if (iruserok_sa(r->ai_addr, r->ai_addrlen, superuser, ruser, + luser) == 0) { + freeaddrinfo(res); return (0); + } + } + freeaddrinfo(res); return (-1); } @@ -543,6 +623,28 @@ iruserok(raddr, superuser, ruser, luser) int superuser; const char *ruser, *luser; { + struct sockaddr_in sin; + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_len = sizeof(struct sockaddr_in); + memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr)); + return iruserok_sa(&sin, sizeof(struct sockaddr_in), superuser, luser, + ruser); +} + +/* + * 2nd and 3rd arguments are typed like this, to avoid dependency between + * unistd.h and sys/socket.h. There's no better way. + */ +int +iruserok_sa(raddr, rlen, superuser, ruser, luser) + const void *raddr; + int rlen; + int superuser; + const char *ruser, *luser; +{ + struct sockaddr *sa; register char *cp; struct stat sbuf; struct passwd *pwd; @@ -552,14 +654,20 @@ iruserok(raddr, superuser, ruser, luser) int first; char pbuf[MAXPATHLEN]; + _DIAGASSERT(raddr != NULL); _DIAGASSERT(ruser != NULL); _DIAGASSERT(luser != NULL); + sa = (struct sockaddr *)raddr; +#ifdef lint + rlen = rlen; +#endif + first = 1; hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r"); again: if (hostf) { - if (__ivaliduser(hostf, raddr, luser, ruser) == 0) { + if (__ivaliduser_sa(hostf, sa, luser, ruser) == 0) { (void)fclose(hostf); return (0); } @@ -625,6 +733,21 @@ __ivaliduser(hostf, raddr, luser, ruser) FILE *hostf; u_int32_t raddr; const char *luser, *ruser; +{ + struct sockaddr_in sin; + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_len = sizeof(struct sockaddr_in); + memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr)); + return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, luser, ruser); +} + +int +__ivaliduser_sa(hostf, raddr, luser, ruser) + FILE *hostf; + struct sockaddr *raddr; + const char *luser, *ruser; { register char *user, *p; int ch; @@ -770,72 +893,122 @@ __ivaliduser(hostf, raddr, luser, ruser) /* * Returns "true" if match, 0 if no match. + * + * NI_WITHSCOPEID is useful for comparing sin6_scope_id portion + * if af == AF_INET6. */ static int __icheckhost(raddr, lhost) - u_int32_t raddr; + struct sockaddr *raddr; const char *lhost; { - struct hostent *hp; - struct in_addr laddr; - char **pp; + struct addrinfo hints, *res, *r; + char h1[NI_MAXHOST], h2[NI_MAXHOST]; + int error; +#ifdef NI_WITHSCOPEID + const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID; +#else + const int niflags = NI_NUMERICHOST; +#endif + _DIAGASSERT(raddr != NULL); _DIAGASSERT(lhost != NULL); - /* Try for raw ip address first. */ - if (isdigit((unsigned char)*lhost) && inet_aton(lhost, &laddr) != 0) - return (raddr == laddr.s_addr); - - /* Better be a hostname. */ - if ((hp = gethostbyname(lhost)) == NULL) + h1[0] = '\0'; + if (getnameinfo(raddr, raddr->sa_len, h1, sizeof(h1), NULL, 0, + niflags) != 0) return (0); - /* Spin through ip addresses. */ - for (pp = hp->h_addr_list; *pp; ++pp) - if (!memcmp(&raddr, *pp, sizeof(u_int32_t))) + /* Resolve laddr into sockaddr */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = raddr->sa_family; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + res = NULL; + error = getaddrinfo(lhost, "0", &hints, &res); + if (error) + return (0); + + /* + * Try string comparisons between raddr and laddr. + */ + for (r = res; r; r = r->ai_next) { + h2[0] = '\0'; + if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2), + NULL, 0, niflags) != 0) + continue; + if (strcmp(h1, h2) == 0) { + freeaddrinfo(res); return (1); + } + } /* No match. */ + freeaddrinfo(res); return (0); } /* * Return the hostname associated with the supplied address. * Do a reverse lookup as well for security. If a loop cannot - * be found, pack the result of inet_ntoa() into the string. + * be found, pack the numeric IP address into the string. + * + * NI_WITHSCOPEID is useful for comparing sin6_scope_id portion + * if af == AF_INET6. */ static char * __gethostloop(raddr) - u_int32_t raddr; + struct sockaddr *raddr; { - static char remotehost[MAXHOSTNAMELEN]; - struct hostent *hp; - struct in_addr in; + static char remotehost[NI_MAXHOST]; + char h1[NI_MAXHOST], h2[NI_MAXHOST]; + struct addrinfo hints, *res, *r; + int error; +#ifdef NI_WITHSCOPEID + const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID; +#else + const int niflags = NI_NUMERICHOST; +#endif - hp = gethostbyaddr((char *)(void *)&raddr, sizeof(raddr), AF_INET); - if (hp == NULL) + _DIAGASSERT(raddr != NULL); + + h1[0] = remotehost[0] = '\0'; + if (getnameinfo(raddr, raddr->sa_len, remotehost, sizeof(remotehost), + NULL, 0, NI_NAMEREQD) != 0) + return (NULL); + if (getnameinfo(raddr, raddr->sa_len, h1, sizeof(h1), NULL, 0, + niflags) != 0) return (NULL); /* * Look up the name and check that the supplied * address is in the list */ - strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1); - remotehost[sizeof(remotehost) - 1] = '\0'; - hp = gethostbyname(remotehost); - if (hp == NULL) + memset(&hints, 0, sizeof(hints)); + hints.ai_family = raddr->sa_family; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_flags = AI_CANONNAME; + res = NULL; + error = getaddrinfo(remotehost, "0", &hints, &res); + if (error) return (NULL); - for (; hp->h_addr_list[0] != NULL; hp->h_addr_list++) - if (!memcmp(hp->h_addr_list[0], &raddr, sizeof(raddr))) + for (r = res; r; r = r->ai_next) { + h2[0] = '\0'; + if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2), + NULL, 0, niflags) != 0) + continue; + if (strcmp(h1, h2) == 0) { + freeaddrinfo(res); return (remotehost); + } + } /* * either the DNS adminstrator has made a configuration * mistake, or someone has attempted to spoof us */ - in.s_addr = raddr; syslog(LOG_NOTICE, "rcmd: address %s not listed for host %s", - inet_ntoa(in), hp->h_name); + h1, res->ai_canonname ? res->ai_canonname : remotehost); + freeaddrinfo(res); return (NULL); }