Add IPv6 support to rshd test/debug code:
authorKen Raeburn <raeburn@mit.edu>
Wed, 1 Jan 2003 10:13:20 +0000 (10:13 +0000)
committerKen Raeburn <raeburn@mit.edu>
Wed, 1 Jan 2003 10:13:20 +0000 (10:13 +0000)
* compat_recv.c: Include sys/select.h and port-sockets.h.
(krb5_compat_recvauth_version): Only attempt krb4 authentication if the source
address is an IPv4 one.
(accept_a_connection): New function, derived from old krshd.c.  Listen on IPv6
as well as IPv4, if possible.
* krshd.c (main): Call accept_a_connection.  Change fromlen to a socklen_t.
(doit): Initialize s.  Change length passed to getsockname to a socklen_t.
(recvauth): Change len to socklen_t.  Cast peer IPv4 address before calling
krb5_compat_recvauth_version.
* defines.h: Include port-sockets.h.
(accept_a_connection): Declare.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@15075 dc483132-0cff-0310-8789-dd5450dbe970

src/appl/bsd/ChangeLog
src/appl/bsd/compat_recv.c
src/appl/bsd/defines.h
src/appl/bsd/krshd.c

index 34b9b5361158f9dd7eb9d5c4f9994f897d5a6267..9eba96dc42488cdf63d11f77c155230a799d9f98 100644 (file)
@@ -1,3 +1,19 @@
+2003-01-01  Ken Raeburn  <raeburn@mit.edu>
+
+       * compat_recv.c: Include sys/select.h and port-sockets.h.
+       (krb5_compat_recvauth_version): Only attempt krb4 authentication
+       if the source address is an IPv4 one.
+       (accept_a_connection): New function, derived from old krshd.c.
+       Listen on IPv6 as well as IPv4, if possible.
+       * krshd.c (main): Call accept_a_connection.  Change fromlen to a
+       socklen_t.
+       (doit): Initialize s.  Change length passed to getsockname to a
+       socklen_t.
+       (recvauth): Change len to socklen_t.  Cast peer IPv4 address
+       before calling krb5_compat_recvauth_version.
+       * defines.h: Include port-sockets.h.
+       (accept_a_connection): Declare.
+
 2002-12-06  Ezra Peisach  <epeisach@bu.edu>
 
        * configure.in: Quote the argument to AC_CHECK_HEADER. Autoconf
index 7bb27feb1713c7e697497e4879c6bddbf3ff238a..5450c1c103bca8f1c23e15e06a09ac41c9f4bda9 100644 (file)
@@ -251,7 +251,8 @@ krb5_compat_recvauth_version(context, auth_context,
                return((retval < 0) ? errno : ECONNABORTED);
 
 #ifdef KRB5_KRB4_COMPAT
-       if (!strncmp(vers.vers, KRB_V4_SENDAUTH_VERS, 4)) {
+       if (v4_faddr->sin_family == AF_INET
+           && !strncmp(vers.vers, KRB_V4_SENDAUTH_VERS, 4)) {
                /*
                 * We must be talking to a V4 sendauth; read in the
                 * rest of the version string and make sure.
@@ -456,3 +457,118 @@ mutual_fail:
 }
 #endif
 #endif
+
+#include <sys/select.h>
+#include "port-sockets.h"
+
+int
+accept_a_connection (int debug_port, struct sockaddr *from,
+                    socklen_t *fromlenp)
+{
+    int n, s, fd, s4 = -1, s6 = -1, on = 1;
+    fd_set sockets;
+
+    FD_ZERO(&sockets);
+
+#ifdef KRB5_USE_INET6
+    {
+       struct sockaddr_in6 sock_in6;
+
+       if ((s = socket(AF_INET6, SOCK_STREAM, PF_UNSPEC)) < 0) {
+           if (errno == EPROTONOSUPPORT)
+               goto skip_ipv6;
+           fprintf(stderr, "Error in socket(INET6): %s\n", strerror(errno));
+           exit(2);
+       }
+
+       memset((char *) &sock_in6, 0,sizeof(sock_in6));
+       sock_in6.sin6_family = AF_INET6;
+       sock_in6.sin6_port = htons(debug_port);
+       sock_in6.sin6_addr = in6addr_any;
+
+       (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+                         (char *)&on, sizeof(on));
+
+       if ((bind(s, (struct sockaddr *) &sock_in6, sizeof(sock_in6))) < 0) {
+           fprintf(stderr, "Error in bind(INET6): %s\n", strerror(errno));
+           exit(2);
+       }
+
+       if ((listen(s, 5)) < 0) {
+           fprintf(stderr, "Error in listen(INET6): %s\n", strerror(errno));
+           exit(2);
+       }
+       s6 = s;
+       FD_SET(s, &sockets);
+    skip_ipv6:
+       ;
+    }
+#endif
+
+    {
+       struct sockaddr_in sock_in;
+
+       if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
+           fprintf(stderr, "Error in socket: %s\n", strerror(errno));
+           exit(2);
+       }
+
+       memset((char *) &sock_in, 0,sizeof(sock_in));
+       sock_in.sin_family = AF_INET;
+       sock_in.sin_port = htons(debug_port);
+       sock_in.sin_addr.s_addr = INADDR_ANY;
+
+       (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+                         (char *)&on, sizeof(on));
+
+       if ((bind(s, (struct sockaddr *) &sock_in, sizeof(sock_in))) < 0) {
+           if (s6 >= 0 && errno == EADDRINUSE)
+               goto try_ipv6_only;
+           fprintf(stderr, "Error in bind: %s\n", strerror(errno));
+           exit(2);
+       }
+
+       if ((listen(s, 5)) < 0) {
+           fprintf(stderr, "Error in listen: %s\n", strerror(errno));
+           exit(2);
+       }
+       s4 = s;
+       FD_SET(s, &sockets);
+    try_ipv6_only:
+       ;
+    }
+    if (s4 == -1 && s6 == -1) {
+       fprintf(stderr, "No valid sockets established, exiting\n");
+       exit(2);
+    }
+    n = select(((s4 < s6) ? s6 : s4) + 1, &sockets, 0, 0, 0);
+    if (n < 0) {
+       fprintf(stderr, "select error: %s\n", strerror(errno));
+       exit(2);
+    } else if (n == 0) {
+       fprintf(stderr, "internal error? select returns 0\n");
+       exit(2);
+    }
+    if (s6 != -1 && FD_ISSET(s6, &sockets)) {
+       if (s4 != -1)
+           close(s4);
+       s = s6;
+    } else if (FD_ISSET(s4, &sockets)) {
+       if (s6 != -1)
+           close(s6);
+       s = s4;
+    } else {
+       fprintf(stderr,
+               "internal error? select returns positive, "
+               "but neither fd available\n");
+       exit(2);
+    }
+
+    if ((fd = accept(s, from, fromlenp)) < 0) {
+       fprintf(stderr, "Error in accept: %s\n", strerror(errno));
+       exit(2);
+    }
+
+    close(s);
+    return fd;
+}
index 6c4d9b8719e3dc3fe084ed3fc7db1ea15efcc30f..ac7948ab961c852551c30b315324fa87945685a0 100644 (file)
@@ -93,3 +93,8 @@ krb5_compat_recvauth_version(krb5_context, krb5_auth_context *,
                             char *, krb5_ticket **, krb5_int32*, 
                             AUTH_DAT **,  Key_schedule, krb5_data *);
 #endif
+
+#include "port-sockets.h"
+
+int accept_a_connection (int debug_port, struct sockaddr *from,
+                        socklen_t *fromlenp);
index b3fea3a7af5ff86f048b78d0be05def1ec735a1d..2a67b761308f4fc61baa8cb3af113f99bcec3edd 100644 (file)
@@ -281,7 +281,8 @@ int main(argc, argv)
 #if defined(BSD) && BSD+0 >= 43
     struct linger linger;
 #endif
-    int on = 1, fromlen;
+    int on = 1;
+    socklen_t fromlen;
     struct sockaddr_storage from;
     extern int opterr, optind;
     extern char *optarg;
@@ -426,49 +427,19 @@ int main(argc, argv)
     
     fromlen = sizeof (from);
 
-    if (debug_port) {
-       int s;
-       struct sockaddr_in sock_in;
-       
-       if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
-           fprintf(stderr, "Error in socket: %s\n", strerror(errno));
-           exit(2);
-       }
-       
-       memset((char *) &sock_in, 0,sizeof(sock_in));
-       sock_in.sin_family = AF_INET;
-       sock_in.sin_port = htons(debug_port);
-       sock_in.sin_addr.s_addr = INADDR_ANY;
-       
-       (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
-                         (char *)&on, sizeof(on));
-
-       if ((bind(s, (struct sockaddr *) &sock_in, sizeof(sock_in))) < 0) {
-           fprintf(stderr, "Error in bind: %s\n", strerror(errno));
-           exit(2);
-       }
-       
-       if ((listen(s, 5)) < 0) {
-           fprintf(stderr, "Error in listen: %s\n", strerror(errno));
-           exit(2);
-       }
-       
-       if ((fd = accept(s, (struct sockaddr *) &from, &fromlen)) < 0) {
-           fprintf(stderr, "Error in accept: %s\n", strerror(errno));
-           exit(2);
-       }
-       
-       close(s);
-    } else {
+    if (debug_port)
+       fd = accept_a_connection(debug_port, (struct sockaddr *)&from,
+                                &fromlen);
+    else {
        if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
            fprintf(stderr, "%s: ", progname);
            perror("getpeername");
            _exit(1);
        }
-       
+
        fd = 0;
     }
-    
+
     if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
                   sizeof (on)) < 0)
        syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
@@ -632,7 +603,7 @@ void doit(f, fromp)
     long packet_compart;            /* Packet compartments */
 #endif  /* CRAY */
     
-    int s;
+    int s = -1;
     char hostname[NI_MAXHOST];
     char *sane_host;
     char hostaddra[NI_MAXHOST];
@@ -663,11 +634,11 @@ void doit(f, fromp)
 #endif /* IP_TOS */
     
     { 
-      int sin_len = sizeof (localaddr);
-      if (getsockname(f, (struct sockaddr*)&localaddr, &sin_len) < 0) {
-       perror("getsockname");
-       exit(1);
-      }
+       socklen_t sin_len = sizeof (localaddr);
+       if (getsockname(f, (struct sockaddr*)&localaddr, &sin_len) < 0) {
+           perror("getsockname");
+           exit(1);
+       }
     }
 
 #ifdef POSIX_SIGNALS
@@ -1799,7 +1770,7 @@ recvauth(netfd, peersin, valid_checksum)
     krb5_auth_context auth_context = NULL;
     krb5_error_code status;
     struct sockaddr_in laddr;
-    int len;
+    socklen_t len;
     krb5_data inbuf;
 #ifdef KRB5_KRB4_COMPAT
     char v4_instance[INST_SZ]; /* V4 Instance */
@@ -1866,7 +1837,7 @@ recvauth(netfd, peersin, valid_checksum)
                                  0,            /* v4_opts */
                                  "rcmd",       /* v4_service */
                                  v4_instance,  /* v4_instance */
-                                 peersin,      /* foreign address */
+                                 (struct sockaddr_in *)peersin, /* foreign address */
                                  &laddr,       /* our local address */
                                  "",           /* use default srvtab */
 
@@ -1882,7 +1853,6 @@ recvauth(netfd, peersin, valid_checksum)
                                   &version); /* application version string */
     auth_sys = KRB5_RECVAUTH_V5;
 #endif
-
     if (status) {
        if (auth_sys == KRB5_RECVAUTH_V5) {
            /*