r-commands: Partial IPv6 support.

This commit is contained in:
Mats Erik Andersson
2012-07-21 20:12:22 +02:00
parent 7de0a68599
commit 598e9a9ecf
4 changed files with 197 additions and 40 deletions

View File

@@ -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.

View File

@@ -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)
{

View File

@@ -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;

View File

@@ -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