add IPv6 support to rcmd() and friends.
rcmd() and iruserok(): unchanged ruserok(): became address family independent rcmd_af(), iruesrok_sa(): address family independent
This commit is contained in:
parent
6e5a5cc306
commit
5b1aaa939e
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user