Blob Blame History Raw
Provide an option to make the KDC also listen on loopback interfaces for
datagram requests.  Adds an internal symbol to libkrb5 which the KDC
needs if listening on loopback is enabled.

The default might be better changed from FALSE to TRUE so that the
default matches what we do with stream sockets.

FIXME: doesn't add documentation anywhere.

diff -up src/include/foreachaddr.h src/include/foreachaddr.h
--- src/include/foreachaddr.h	2004-05-05 18:44:46.000000000 -0400
+++ src/include/foreachaddr.h	2008-04-04 15:39:28.000000000 -0400
@@ -62,3 +62,18 @@ krb5int_foreach_localaddr (/*@null@*/ vo
     ;
 
 #define foreach_localaddr krb5int_foreach_localaddr
+
+extern int
+krb5int_foreach_localaddr_ext (/*@null@*/ void *data,
+			       int (*pass1fn) (/*@null@*/ void *,
+					       struct sockaddr *) /*@*/,
+			       /*@null@*/ krb5_boolean (*skipfn) (/*@null@*/ struct sockaddr *, int) /*@*/,
+			       /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
+			       /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
+							  struct sockaddr *) /*@*/)
+#if defined(DEBUG) || defined(TEST)
+     /*@modifies fileSystem@*/
+#endif
+    ;
+
+#define foreach_localaddr_ext krb5int_foreach_localaddr_ext
diff -up src/kdc/kdc_util.h src/kdc/kdc_util.h
--- src/kdc/kdc_util.h	2008-04-04 16:28:18.000000000 -0400
+++ src/kdc/kdc_util.h	2008-04-04 16:51:27.000000000 -0400
@@ -126,6 +126,7 @@ krb5_error_code kdc_initialize_rcache (k
 krb5_error_code setup_server_realm (krb5_principal);
 
 /* network.c */
+void process_listen_loopback (krb5_boolean);
 krb5_error_code listen_and_process (const char *);
 krb5_error_code setup_network (const char *);
 krb5_error_code closedown_network (const char *);
diff -up src/kdc/main.c src/kdc/main.c
--- src/kdc/main.c	2008-04-04 16:22:43.000000000 -0400
+++ src/kdc/main.c	2008-04-04 16:55:22.000000000 -0400
@@ -422,6 +422,7 @@ initialize_realms(krb5_context kcontext,
     krb5_enctype	menctype = ENCTYPE_UNKNOWN;
     kdc_realm_t		*rdatap;
     krb5_boolean	manual = FALSE;
+    krb5_boolean	listen_loopback = FALSE;
     char		*default_udp_ports = 0;
     char		*default_tcp_ports = 0;
     krb5_pointer	aprof;
@@ -448,6 +449,9 @@ initialize_realms(krb5_context kcontext,
 	if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &v4mode))
 	    v4mode = 0;
 #endif
+	hierarchy[1] = "kdc_listen_loopback";
+	if (krb5_aprof_get_boolean(aprof, hierarchy, TRUE, &listen_loopback))
+	    listen_loopback = FALSE;
 	/* aprof_init can return 0 with aprof == NULL */
 	if (aprof)
 	     krb5_aprof_finish(aprof);
@@ -587,6 +591,8 @@ initialize_realms(krb5_context kcontext,
     free(v4mode);
 #endif
 
+    process_listen_loopback(listen_loopback);
+
     /*
      * Check to see if we processed any realms.
      */
diff -up src/kdc/network.c src/kdc/network.c
--- src/kdc/network.c	2008-04-04 15:39:28.000000000 -0400
+++ src/kdc/network.c	2008-04-04 16:51:44.000000000 -0400
@@ -221,6 +221,7 @@ static SET(u_short) udp_port_data, tcp_p
 #include "cm.h"
 
 static struct select_state sstate;
+static krb5_boolean listen_loopback;
 
 static krb5_error_code add_udp_port(int port)
 {
@@ -604,6 +605,12 @@ scan_for_newlines:
 }
 #endif
 
+void
+process_listen_loopback(krb5_boolean listen_loop)
+{
+    listen_loopback = listen_loop;
+}
+
 /* XXX */
 extern int krb5int_debug_sendto_kdc;
 extern void (*krb5int_sendtokdc_debug_handler)(const void*, size_t);
@@ -662,7 +669,9 @@ setup_network(const char *prog)
        so we might need only one UDP socket; fall back to binding
        sockets on each address only if IPV6_PKTINFO isn't
        supported.  */
-    if (foreach_localaddr (&setup_data, setup_udp_port, 0, 0)) {
+    if (listen_loopback ?
+	foreach_localaddr_ext (&setup_data, setup_udp_port, 0, 0, 0) :
+	foreach_localaddr (&setup_data, setup_udp_port, 0, 0)) {
 	return setup_data.retval;
     }
     setup_tcp_listener_ports(&setup_data);
diff -up src/lib/krb5/os/localaddr.c src/lib/krb5/os/localaddr.c
--- src/lib/krb5/os/localaddr.c	2005-04-13 12:55:43.000000000 -0400
+++ src/lib/krb5/os/localaddr.c	2008-04-04 15:39:28.000000000 -0400
@@ -242,6 +242,17 @@ addr_eq (const struct sockaddr *s1, cons
 }
 #endif
 
+static krb5_boolean
+skip_loopback (struct sockaddr *addr, int flags)
+{
+#ifdef IFF_LOOPBACK
+    if (flags & IFF_LOOPBACK) {
+	return TRUE;
+    }
+#endif
+    return FALSE;
+}
+
 #ifndef HAVE_IFADDRS_H
 /*@-usereleased@*/ /* lclint doesn't understand realloc */
 static /*@null@*/ void *
@@ -413,14 +424,27 @@ get_linux_ipv6_addrs ()
    indication, it should do it via some field pointed to by the DATA
    argument.  */
 
-#ifdef HAVE_IFADDRS_H
-
 int
 foreach_localaddr (/*@null@*/ void *data,
 		   int (*pass1fn) (/*@null@*/ void *, struct sockaddr *) /*@*/,
 		   /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
 		   /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
 					      struct sockaddr *) /*@*/)
+{
+    return foreach_localaddr_ext(data, pass1fn,
+				 &skip_loopback, betweenfn,
+				 pass2fn);
+}
+
+#ifdef HAVE_IFADDRS_H
+
+int
+foreach_localaddr_ext (/*@null@*/ void *data,
+		       int (*pass1fn) (/*@null@*/ void *, struct sockaddr *) /*@*/,
+		       /*@null@*/ krb5_boolean (*skipfn) (/*@null@*/ struct sockaddr *, int) /*@*/,
+		       /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
+		       /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
+						  struct sockaddr *) /*@*/)
 #if defined(DEBUG) || defined(TEST)
      /*@modifies fileSystem@*/
 #endif
@@ -436,7 +460,7 @@ foreach_localaddr (/*@null@*/ void *data
 #endif
 	if ((ifp->ifa_flags & IFF_UP) == 0)
 	    continue;
-	if (ifp->ifa_flags & IFF_LOOPBACK) {
+	if (skipfn && (*skipfn)(ifp->ifa_addr, ifp->ifa_flags)) {
 	    /* Pretend it's not up, so the second pass will skip
 	       it.  */
 	    ifp->ifa_flags &= ~IFF_UP;
@@ -459,7 +483,7 @@ foreach_localaddr (/*@null@*/ void *data
 	for (ifp2 = ifp_head; ifp2 && ifp2 != ifp; ifp2 = ifp2->ifa_next) {
 	    if ((ifp2->ifa_flags & IFF_UP) == 0)
 		continue;
-	    if (ifp2->ifa_flags & IFF_LOOPBACK)
+	    if (skipfn && (*skipfn)(ifp2->ifa_addr, ifp2->ifa_flags))
 		continue;
 	    if (addr_eq (ifp->ifa_addr, ifp2->ifa_addr)) {
 		match = 1;
@@ -488,11 +512,12 @@ foreach_localaddr (/*@null@*/ void *data
 #elif defined (SIOCGLIFNUM) && defined(HAVE_STRUCT_LIFCONF) /* Solaris 8 and later; Sol 7? */
 
 int
-foreach_localaddr (/*@null@*/ void *data,
-		   int (*pass1fn) (/*@null@*/ void *, struct sockaddr *) /*@*/,
-		   /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
-		   /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
-					      struct sockaddr *) /*@*/)
+foreach_localaddr_ext (/*@null@*/ void *data,
+		       int (*pass1fn) (/*@null@*/ void *, struct sockaddr *) /*@*/,
+		       /*@null@*/ int (*skipfn) (/*@null@*/ struct sockaddr *, int) /*@*/,
+		       /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
+		       /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
+					          struct sockaddr *) /*@*/)
 #if defined(DEBUG) || defined(TEST)
      /*@modifies fileSystem@*/
 #endif
@@ -583,13 +608,12 @@ foreach_localaddr (/*@null@*/ void *data
 	    }
 	    /*@=moduncon@*/
 
-#ifdef IFF_LOOPBACK
-	    /* None of the current callers want loopback addresses.  */
-	    if (lifreq.lifr_flags & IFF_LOOPBACK) {
-		Tprintf (("  loopback\n"));
+	    if (skipfn && (*skipfn)(lifreq.lifr_addr, lifreq.lifr_flags))
+		if (skipfn && (skipfn == &skip_loopback))
+		    Tprintf (("  loopback\n"));
 		goto skip;
 	    }
-#endif
+
 	    /* Ignore interfaces that are down.  */
 	    if ((lifreq.lifr_flags & IFF_UP) == 0) {
 		Tprintf (("  down\n"));
@@ -755,13 +779,12 @@ foreach_localaddr (/*@null@*/ void *data
 	    }
 	    /*@=moduncon@*/
 
-#ifdef IFF_LOOPBACK
 	    /* None of the current callers want loopback addresses.  */
-	    if (lifreq.iflr_flags & IFF_LOOPBACK) {
-		Tprintf (("  loopback\n"));
+	    if (skipfn && (*skipfn)(ifp2->ifa_addr, lifreq.lifr_flags))
+		if (skipfn && (skipfn == &skip_loopback))
+		    Tprintf (("  loopback\n"));
 		goto skip;
 	    }
-#endif
 	    /* Ignore interfaces that are down.  */
 	    if ((lifreq.iflr_flags & IFF_UP) == 0) {
 		Tprintf (("  down\n"));
@@ -971,13 +994,12 @@ foreach_localaddr (/*@null@*/ void *data
 	}
 	/*@=moduncon@*/
 
-#ifdef IFF_LOOPBACK
-	/* None of the current callers want loopback addresses.  */
-	if (ifreq.ifr_flags & IFF_LOOPBACK) {
-	    Tprintf (("  loopback\n"));
+	if (skipfn && (*skipfn)(NULL, ifreq.ifr_flags))
+	    if (skipfn && (skipfn == &skip_loopback))
+		Tprintf (("  loopback\n"));
 	    goto skip;
 	}
-#endif
+
 	/* Ignore interfaces that are down.  */
 	if ((ifreq.ifr_flags & IFF_UP) == 0) {
 	    Tprintf (("  down\n"));