mirror of
https://git.savannah.gnu.org/git/inetutils.git
synced 2026-01-12 00:19:39 +08:00
r-commands: Partial IPv6 support.
This commit is contained in:
26
ChangeLog
26
ChangeLog
@@ -1,3 +1,29 @@
|
||||
2012-07-21 Mats Erik Andersson <gnu@gisladisker.se>
|
||||
|
||||
r-commands: Partial IPv6 support.
|
||||
Adapt host resolution to cope with IPv6,
|
||||
in particular for libshishi related code.
|
||||
|
||||
* libinetutils/kcmd.c (getport): New signature
|
||||
`(int *, int)', adding address family parameter.
|
||||
Update code to use `struct sockaddr_storage'.
|
||||
New variable LEN.
|
||||
(kcmd): New alternate code using getaddrinfo(),
|
||||
instead of gethostbyname().
|
||||
[HAVE_DECL_GETADDRINFO]: New variables HINTS, AI, RES.
|
||||
|
||||
* libinetutils/shishi_def.h <struct auth_data>: Changed
|
||||
type of FROM to `struct sockaddr_storage'.
|
||||
* src/rlogind.c <struct auth_data> [!SHISHI]: Likewise.
|
||||
(rlogind_auth): New variables ADDRP, PORT. Adapt to new
|
||||
type of `auth_data.from'.
|
||||
[!KERBEROS]: Accept families AF_INET and AF_INET6.
|
||||
(rlogind_mainloop): Adapt to new `auth_data.from'.
|
||||
(do_rlogin): Likewise.
|
||||
[WITH_IRUSEROK_AF || WITH_IRUSEROK]: New variable ADDRP.
|
||||
(do_shishi_login): New type `struct sockaddr_storage'
|
||||
for SOCK.
|
||||
|
||||
2012-07-18 Mats Erik Andersson <gnu@gisladisker.se>
|
||||
|
||||
rlogin: Close libshishi handle.
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
|
||||
# define START_PORT 5120 /* arbitrary */
|
||||
|
||||
int getport (int *);
|
||||
int getport (int *, int);
|
||||
|
||||
# if defined KERBEROS
|
||||
int
|
||||
@@ -120,7 +120,12 @@ kcmd (Shishi ** h, int *sock, char **ahost, unsigned short rport, char *locuser,
|
||||
# else
|
||||
int lport = START_PORT;
|
||||
# endif
|
||||
# ifdef HAVE_DECL_GETADDRINFO
|
||||
struct addrinfo hints, *ai, *res;
|
||||
char portstr[8];
|
||||
# else /* !HAVE_DECL_GETADDRINFO */
|
||||
struct hostent *hp;
|
||||
# endif
|
||||
int rc;
|
||||
char *host_save;
|
||||
int status;
|
||||
@@ -131,7 +136,29 @@ kcmd (Shishi ** h, int *sock, char **ahost, unsigned short rport, char *locuser,
|
||||
|
||||
pid = getpid ();
|
||||
|
||||
/* FIXME: Often the following rejects non-IPv4.
|
||||
# ifdef HAVE_DECL_GETADDRINFO
|
||||
memset (&hints, 0, sizeof (hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
snprintf (portstr, sizeof (portstr), "%hu", ntohs (rport));
|
||||
|
||||
rc = getaddrinfo (*ahost, portstr, &hints, &res);
|
||||
if (rc)
|
||||
{
|
||||
fprintf (stderr, "kcmd: host %s: %s\n", *ahost, gai_strerror (rc));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ai = res;
|
||||
|
||||
host_save = malloc (strlen (ai->ai_canonname) + 1);
|
||||
if (host_save == NULL)
|
||||
return (-1);
|
||||
strcpy (host_save, ai->ai_canonname);
|
||||
|
||||
# else /* !HAVE_DECL_GETADDRINFO */
|
||||
/* Often the following rejects non-IPv4.
|
||||
* This is dependent on system implementation. */
|
||||
hp = gethostbyname (*ahost);
|
||||
if (hp == NULL)
|
||||
@@ -144,6 +171,8 @@ kcmd (Shishi ** h, int *sock, char **ahost, unsigned short rport, char *locuser,
|
||||
if (host_save == NULL)
|
||||
return -1;
|
||||
strcpy (host_save, hp->h_name);
|
||||
# endif /* !HAVE_DECL_GETADDRINFO */
|
||||
|
||||
*ahost = host_save;
|
||||
|
||||
# ifdef KERBEROS
|
||||
@@ -161,7 +190,11 @@ kcmd (Shishi ** h, int *sock, char **ahost, unsigned short rport, char *locuser,
|
||||
# endif /* !HAVE_SIGACTION */
|
||||
for (;;)
|
||||
{
|
||||
s = getport (&lport);
|
||||
# ifdef HAVE_DECL_GETADDRINFO
|
||||
s = getport (&lport, ai->ai_family);
|
||||
# else /* !HAVE_DECL_GETADDRINFO */
|
||||
s = getport (&lport, hp->h_addrtype);
|
||||
# endif
|
||||
if (s < 0)
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
@@ -176,14 +209,19 @@ kcmd (Shishi ** h, int *sock, char **ahost, unsigned short rport, char *locuser,
|
||||
return (-1);
|
||||
}
|
||||
fcntl (s, F_SETOWN, pid);
|
||||
|
||||
# ifdef HAVE_DECL_GETADDRINFO
|
||||
len = ai->ai_addrlen;
|
||||
memcpy (&sin, ai->ai_addr, ai->ai_addrlen);
|
||||
# else /* !HAVE_DECL_GETADDRINFO */
|
||||
sin.ss_family = hp->h_addrtype;
|
||||
switch (hp->h_addrtype)
|
||||
{
|
||||
case AF_INET6:
|
||||
len = sizeof (struct sockaddr_in6);
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||
# ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||
sin.ss_len = len;
|
||||
#endif
|
||||
# endif
|
||||
memcpy (&((struct sockaddr_in6 *) &sin)->sin6_addr,
|
||||
hp->h_addr, hp->h_length);
|
||||
((struct sockaddr_in6 *) &sin)->sin6_port = rport;
|
||||
@@ -191,13 +229,14 @@ kcmd (Shishi ** h, int *sock, char **ahost, unsigned short rport, char *locuser,
|
||||
case AF_INET:
|
||||
default:
|
||||
len = sizeof (struct sockaddr_in);
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||
# ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||
sin.ss_len = len;
|
||||
#endif
|
||||
# endif
|
||||
memcpy (&((struct sockaddr_in *) &sin)->sin_addr,
|
||||
hp->h_addr, hp->h_length);
|
||||
((struct sockaddr_in *) &sin)->sin_port = rport;
|
||||
}
|
||||
# endif /* !HAVE_DECL_GETADDRINFO */
|
||||
|
||||
if (connect (s, (struct sockaddr *) &sin, len) >= 0)
|
||||
break;
|
||||
@@ -217,11 +256,28 @@ kcmd (Shishi ** h, int *sock, char **ahost, unsigned short rport, char *locuser,
|
||||
continue;
|
||||
}
|
||||
# if ! defined ultrix || defined sun
|
||||
# ifdef HAVE_DECL_GETADDRINFO
|
||||
if (ai->ai_next)
|
||||
# else /* !HAVE_DECL_GETADDRINFO */
|
||||
if (hp->h_addr_list[1] != NULL)
|
||||
# endif
|
||||
{
|
||||
int oerrno = errno;
|
||||
char addrstr[INET6_ADDRSTRLEN];
|
||||
|
||||
# ifdef HAVE_DECL_GETADDRINFO
|
||||
getnameinfo (ai->ai_addr, ai->ai_addrlen,
|
||||
addrstr, sizeof (addrstr), NULL, 0,
|
||||
NI_NUMERICHOST);
|
||||
fprintf (stderr, "kcmd: connect to address %s: ", addrstr);
|
||||
errno = oerrno;
|
||||
perror (NULL);
|
||||
ai = ai->ai_next;
|
||||
getnameinfo (ai->ai_addr, ai->ai_addrlen,
|
||||
addrstr, sizeof (addrstr), NULL, 0,
|
||||
NI_NUMERICHOST);
|
||||
fprintf (stderr, "Trying %s...\n", addrstr);
|
||||
# else /* !HAVE_DECL_GETADDRINFO */
|
||||
fprintf (stderr, "kcmd: connect to address %s: ",
|
||||
inet_ntop (hp->h_addrtype, hp->h_addr_list[0],
|
||||
addrstr, sizeof (addrstr)));
|
||||
@@ -231,11 +287,20 @@ kcmd (Shishi ** h, int *sock, char **ahost, unsigned short rport, char *locuser,
|
||||
fprintf (stderr, "Trying %s...\n",
|
||||
inet_ntop (hp->h_addrtype, hp->h_addr_list[0],
|
||||
addrstr, sizeof (addrstr)));
|
||||
# endif /* !HAVE_DECL_GETADDRINFO */
|
||||
continue;
|
||||
}
|
||||
# endif /* !(defined(ultrix) || defined(sun)) */
|
||||
# ifdef HAVE_DECL_GETADDRINFO
|
||||
if (errno != ECONNREFUSED)
|
||||
perror (res->ai_canonname);
|
||||
|
||||
if (res)
|
||||
freeaddrinfo (res);
|
||||
# else /* !HAVE_DECL_GETADDRINFO */
|
||||
if (errno != ECONNREFUSED)
|
||||
perror (hp->h_name);
|
||||
# endif
|
||||
|
||||
# if HAVE_SIGACTION
|
||||
sigprocmask (SIG_SETMASK, &osigs, NULL);
|
||||
@@ -245,6 +310,11 @@ kcmd (Shishi ** h, int *sock, char **ahost, unsigned short rport, char *locuser,
|
||||
|
||||
return (-1);
|
||||
}
|
||||
# ifdef HAVE_DECL_GETADDRINFO
|
||||
if (res)
|
||||
freeaddrinfo (res);
|
||||
#endif
|
||||
|
||||
lport--;
|
||||
if (fd2p == 0)
|
||||
{
|
||||
@@ -256,7 +326,7 @@ kcmd (Shishi ** h, int *sock, char **ahost, unsigned short rport, char *locuser,
|
||||
char num[8];
|
||||
int port, s2, s3;
|
||||
|
||||
s2 = getport (&lport);
|
||||
s2 = getport (&lport, sin.ss_family);
|
||||
len = sizeof (from);
|
||||
|
||||
if (s2 < 0)
|
||||
@@ -403,23 +473,38 @@ bad:
|
||||
}
|
||||
|
||||
int
|
||||
getport (int *alport)
|
||||
getport (int *alport, int af)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage sin;
|
||||
socklen_t len;
|
||||
int s;
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||
sin.sin_len = sizeof (sin);
|
||||
#endif
|
||||
sin.sin_addr.s_addr = INADDR_ANY;
|
||||
s = socket (sin.sin_family, SOCK_STREAM, 0);
|
||||
memset (&sin, 0, sizeof (sin));
|
||||
sin.ss_family = af;
|
||||
len = (af == AF_INET6) ? sizeof (struct sockaddr_in6)
|
||||
: sizeof (struct sockaddr_in);
|
||||
# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
|
||||
sin.ss_len = len;
|
||||
# endif
|
||||
|
||||
s = socket (sin.ss_family, SOCK_STREAM, 0);
|
||||
if (s < 0)
|
||||
return (-1);
|
||||
for (;;)
|
||||
{
|
||||
sin.sin_port = htons ((unsigned short) * alport);
|
||||
if (bind (s, (struct sockaddr *) &sin, sizeof (sin)) >= 0)
|
||||
switch (af)
|
||||
{
|
||||
case AF_INET6:
|
||||
((struct sockaddr_in6 *) &sin)->sin6_port =
|
||||
htons ((unsigned short) * alport);
|
||||
break;
|
||||
case AF_INET:
|
||||
default:
|
||||
((struct sockaddr_in *) &sin)->sin_port =
|
||||
htons ((unsigned short) * alport);
|
||||
}
|
||||
|
||||
if (bind (s, (struct sockaddr *) &sin, len) >= 0)
|
||||
return (s);
|
||||
if (errno != EADDRINUSE)
|
||||
{
|
||||
|
||||
@@ -36,7 +36,7 @@ typedef struct shishi_iv shishi_ivector;
|
||||
|
||||
struct auth_data
|
||||
{
|
||||
struct sockaddr_in from;
|
||||
struct sockaddr_storage from;
|
||||
socklen_t fromlen;
|
||||
char *hostaddr;
|
||||
char *hostname;
|
||||
|
||||
@@ -144,7 +144,7 @@ extern int __check_rhosts_file;
|
||||
#ifndef SHISHI
|
||||
struct auth_data
|
||||
{
|
||||
struct sockaddr_in from;
|
||||
struct sockaddr_storage from;
|
||||
socklen_t fromlen;
|
||||
char *hostaddr;
|
||||
char *hostname;
|
||||
@@ -442,6 +442,7 @@ main (int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: Migrate to IPv6 supported listener. */
|
||||
|
||||
void
|
||||
rlogin_daemon (int maxchildren, int port)
|
||||
@@ -546,7 +547,7 @@ rlogin_daemon (int maxchildren, int port)
|
||||
int
|
||||
rlogind_auth (int fd, struct auth_data *ap)
|
||||
{
|
||||
#if defined HAVE_DECL_GETNAMEINFO || defined HAVE_DECL_GETADDRINFO
|
||||
#if defined HAVE_DECL_GETNAMEINFO && defined HAVE_DECL_GETADDRINFO
|
||||
int rc;
|
||||
char hoststr[NI_MAXHOST];
|
||||
#else
|
||||
@@ -554,11 +555,25 @@ rlogind_auth (int fd, struct auth_data *ap)
|
||||
#endif
|
||||
char *hostname;
|
||||
int authenticated = 0;
|
||||
void * addrp;
|
||||
int port;
|
||||
|
||||
#ifdef SHISHI
|
||||
int len, c;
|
||||
#endif
|
||||
|
||||
switch (ap->from.ss_family)
|
||||
{
|
||||
case AF_INET6:
|
||||
addrp = (void *) &((struct sockaddr_in6 *) &ap->from)->sin6_addr;
|
||||
port = ntohs (((struct sockaddr_in6 *) &ap->from)->sin6_port);
|
||||
break;
|
||||
case AF_INET:
|
||||
default:
|
||||
addrp = (void *) &((struct sockaddr_in *) &ap->from)->sin_addr;
|
||||
port = ntohs (((struct sockaddr_in *) &ap->from)->sin_port);
|
||||
}
|
||||
|
||||
confirmed = 0;
|
||||
|
||||
/* Check the remote host name */
|
||||
@@ -568,8 +583,17 @@ rlogind_auth (int fd, struct auth_data *ap)
|
||||
if (!rc)
|
||||
hostname = hoststr;
|
||||
#else /* !HAVE_DECL_GETNAMEINFO */
|
||||
hp = gethostbyaddr ((char *) &ap->from.sin_addr, sizeof (struct in_addr),
|
||||
ap->from.sin_family);
|
||||
switch (ap->from.ss_family)
|
||||
{
|
||||
case AF_INET6:
|
||||
hp = gethostbyaddr (addrp, sizeof (struct in6_addr),
|
||||
ap->from.ss_family);
|
||||
break;
|
||||
case AF_INET:
|
||||
default:
|
||||
hp = gethostbyaddr (addrp, sizeof (struct in_addr),
|
||||
ap->from.ss_family);
|
||||
}
|
||||
if (hp)
|
||||
hostname = hp->h_name;
|
||||
#endif /* !HAVE_DECL_GETNAMEINFO */
|
||||
@@ -591,7 +615,7 @@ rlogind_auth (int fd, struct auth_data *ap)
|
||||
char astr[INET6_ADDRSTRLEN];
|
||||
|
||||
memset (&hints, 0, sizeof (hints));
|
||||
hints.ai_family = ap->from.sin_family;
|
||||
hints.ai_family = ap->from.ss_family;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
rc = getaddrinfo (ap->hostname, NULL, &hints, &res);
|
||||
@@ -615,8 +639,7 @@ rlogind_auth (int fd, struct auth_data *ap)
|
||||
{
|
||||
if (hp->h_addr_list[0] == NULL)
|
||||
break;
|
||||
match = memcmp (hp->h_addr_list[0], &ap->from.sin_addr,
|
||||
sizeof (ap->from.sin_addr)) == 0;
|
||||
match = memcmp (hp->h_addr_list[0], addrp, hp->h_length) == 0;
|
||||
}
|
||||
#endif /* !HAVE_DECL_GETADDRINFO */
|
||||
if (!match)
|
||||
@@ -638,15 +661,17 @@ rlogind_auth (int fd, struct auth_data *ap)
|
||||
else
|
||||
fatal (fd, err_msg, 0);
|
||||
write (fd, &c, 1);
|
||||
confirmed = 1; /* we sent the null! */
|
||||
confirmed = 1; /* We have sent the null! */
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
int port = ntohs (ap->from.sin_port);
|
||||
|
||||
if (ap->from.sin_family != AF_INET ||
|
||||
port >= IPPORT_RESERVED || port < IPPORT_RESERVED / 2)
|
||||
if ((ap->from.ss_family != AF_INET
|
||||
#ifndef KERBEROS
|
||||
&& ap->from.ss_family != AF_INET6
|
||||
#endif
|
||||
)
|
||||
|| port >= IPPORT_RESERVED || port < IPPORT_RESERVED / 2)
|
||||
{
|
||||
syslog (LOG_NOTICE, "Connection from %s on illegal port %d",
|
||||
ap->hostaddr, port);
|
||||
@@ -818,7 +843,10 @@ rlogind_mainloop (int infd, int outfd)
|
||||
fatal (outfd, "Can't get peer name of remote host", 1);
|
||||
}
|
||||
|
||||
reply = inet_ntop (auth_data.from.sin_family, &auth_data.from.sin_addr,
|
||||
reply = inet_ntop (auth_data.from.ss_family,
|
||||
(auth_data.from.ss_family == AF_INET6)
|
||||
? (void *) &((struct sockaddr_in6 *) &auth_data.from)->sin6_addr
|
||||
: (void *) &((struct sockaddr_in *) &auth_data.from)->sin_addr,
|
||||
addrstr, sizeof (addrstr));
|
||||
if (reply == NULL)
|
||||
{
|
||||
@@ -828,7 +856,9 @@ rlogind_mainloop (int infd, int outfd)
|
||||
auth_data.hostaddr = xstrdup (addrstr);
|
||||
|
||||
syslog (LOG_INFO, "Connect from %s:%d", auth_data.hostaddr,
|
||||
ntohs (auth_data.from.sin_port));
|
||||
(auth_data.from.ss_family == AF_INET6)
|
||||
? ntohs (((struct sockaddr_in6 *) &auth_data.from)->sin6_port)
|
||||
: ntohs (((struct sockaddr_in *) &auth_data.from)->sin_port));
|
||||
|
||||
true = 1;
|
||||
if (keepalive
|
||||
@@ -923,6 +953,19 @@ do_rlogin (int infd, struct auth_data *ap)
|
||||
{
|
||||
struct passwd *pwd;
|
||||
int rc;
|
||||
#if defined WITH_IRUSEROK_AF || defined WITH_IRUSEROK
|
||||
void *addrp;
|
||||
|
||||
switch (ap->from.ss_family)
|
||||
{
|
||||
case AF_INET6:
|
||||
addrp = (void *) &((struct sockaddr_in6 *) &ap->from)->sin6_addr;
|
||||
break;
|
||||
case AF_INET:
|
||||
default:
|
||||
addrp = (void *) &((struct sockaddr_in *) &ap->from)->sin_addr;
|
||||
}
|
||||
#endif /* WITH_IRUSEROK_AF || WITH_IRUSEROK */
|
||||
|
||||
getstr (infd, &ap->rusername, NULL);
|
||||
getstr (infd, &ap->lusername, NULL);
|
||||
@@ -946,10 +989,10 @@ do_rlogin (int infd, struct auth_data *ap)
|
||||
rc = iruserok_sa ((struct sockaddr *) &ap->from, ap->fromlen, 0,
|
||||
ap->rusername, ap->lusername);
|
||||
# elif defined WITH_IRUSEROK_AF
|
||||
rc = iruserok_af (&ap->from.sin_addr, 0, ap->rusername, ap->lusername,
|
||||
ap->from.sin_family);
|
||||
rc = iruserok_af (addrp, 0, ap->rusername, ap->lusername,
|
||||
ap->from.ss_family);
|
||||
# else /* WITH_IRUSEROK */
|
||||
rc = iruserok (ap->from.sin_addr.s_addr, 0, ap->rusername, ap->lusername);
|
||||
rc = iruserok (addrp, 0, ap->rusername, ap->lusername);
|
||||
# endif /* WITH_IRUSEROK_SA || WITH_IRUSEROK_AF || WITH_IRUSEROK */
|
||||
if (rc)
|
||||
syslog (LOG_ERR | LOG_AUTH,
|
||||
@@ -958,7 +1001,7 @@ do_rlogin (int infd, struct auth_data *ap)
|
||||
#elif defined WITH_RUSEROK_AF || defined WITH_RUSEROK
|
||||
# ifdef WITH_RUSEROK_AF
|
||||
rc = ruserok_af (ap->hostaddr, 0, ap->rusername, ap->lusername,
|
||||
ap->from.sin_family);
|
||||
ap->from.ss_family);
|
||||
# else /* WITH_RUSEROK */
|
||||
rc = ruserok (ap->hostaddr, 0, ap->rusername, ap->lusername);
|
||||
# endif /* WITH_RUSEROK_AF || WITH_RUSEROK */
|
||||
@@ -1187,7 +1230,7 @@ do_shishi_login (int infd, struct auth_data *ad, const char **err_msg)
|
||||
char *compcksum;
|
||||
size_t compcksumlen, cksumlen = 30;
|
||||
char cksumdata[100];
|
||||
struct sockaddr_in sock;
|
||||
struct sockaddr_storage sock;
|
||||
socklen_t socklen = sizeof (sock);
|
||||
|
||||
# ifdef ENCRYPTION
|
||||
@@ -1296,8 +1339,11 @@ do_shishi_login (int infd, struct auth_data *ad, const char **err_msg)
|
||||
fatal (infd, "Can't get sockname", 1);
|
||||
}
|
||||
|
||||
snprintf (cksumdata, 100, "%u:%s%s", ntohs (sock.sin_port), ad->term + 5,
|
||||
ad->lusername);
|
||||
snprintf (cksumdata, 100, "%u:%s%s",
|
||||
(sock.ss_family == AF_INET6)
|
||||
? ntohs (((struct sockaddr_in6 *) &sock)->sin6_port)
|
||||
: ntohs (((struct sockaddr_in *) &sock)->sin_port),
|
||||
ad->term + 5, ad->lusername);
|
||||
rc = shishi_checksum (ad->h, ad->enckey, 0, cksumtype, cksumdata,
|
||||
strlen (cksumdata), &compcksum, &compcksumlen);
|
||||
if (rc != SHISHI_OK
|
||||
|
||||
Reference in New Issue
Block a user