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