From chris@minotaur.onthe.net.au Sun Dec 10 00:23:19 2000
Received: from MIT.EDU (PACIFIC-CARRIER-ANNEX.MIT.EDU [18.69.0.28])
by rt-11.mit.edu (8.9.3/8.9.3) with SMTP id AAA28068
for <bugs@RT-11.MIT.EDU>; Sun, 10 Dec 2000 00:23:18 -0500 (EST)
Received: from minotaur.onthe.net.au by MIT.EDU with SMTP
id AA29800; Sat, 9 Dec 00 22:39:40 EST
Received: (from chris@localhost)
by minotaur.onthe.net.au (8.9.3/8.9.3) id OAA15721;
Sun, 10 Dec 2000 14:38:08 +1100
Message-Id: <200012100338.OAA15721@minotaur.onthe.net.au>
Date: Sun, 10 Dec 2000 14:38:08 +1100
From: chris@onthe.net.au
Reply-To: chris@onthe.net.au
To: krb5-bugs@MIT.EDU
Cc: kerberos@MIT.EDU
Subject: Patch
X-Send-Pr-Version: 3.99
Show quoted text
>Number: 907
>Category: krb5-libs
>Synopsis: Patch: bind to a specific IP address when contacting KDC
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: krb5-unassigned
>State: open
>Class: change-request
>Submitter-Id: unknown
>Arrival-Date: Sun Dec 10 00:24:00 EST 2000
>Last-Modified:
>Originator: Chris Dunlop
>Organization:
OnTheNet Pty Ltd
Show quoted text
>Release: krb5-1.2.1
>Environment:
All
System: Linux minotaur.onthe.net.au 2.2.14-6.1.1smp #1 SMP Thu Apr 13 19:55:55 EDT 2000 i686 unknown
Architecture: i686
Show quoted text
>Description:
This patch allows a multi-homed machine to bind to a particular address
(and optionally a particular port) when contacting the kerberos domain
contoller.
This can help with some of the issues associated with configuring
Kerberos on multi-homed machines. For more details see:
Kerberos FAQ V2.0
1.24. Does Kerberos support multi-homed machines ?
http://www.nrl.navy.mil/CCS/people/kenh/kerberos-faq.html#multihomed 2.14. How should I configure my DNS for Kerberos ?
http://www.nrl.navy.mil/CCS/people/kenh/kerberos-faq.html#kerbdnsThe address binding is configured in the krb5.conf file like so:
[realms]
EXAMPLE.COM = {
bind_address = host-name-or-ip-address[:port]
}
Cheers,
Chris Dunlop,
OnTheNet Pty Ltd
diff -cr krb5-1.2.1.orig/src/lib/krb5/os/locate_kdc.c krb5-1.2.1/src/lib/krb5/os/locate_kdc.c
*** krb5-1.2.1.orig/src/lib/krb5/os/locate_kdc.c Fri Jun 30 12:28:13 2000
--- krb5-1.2.1/src/lib/krb5/os/locate_kdc.c Tue Nov 14 17:15:43 2000
***************
*** 325,330 ****
--- 325,415 ----
return 0;
}
+ krb5_error_code
+ krb5_bind_addr(context, realm, addr_pp, addrlen_p)
+ krb5_context context;
+ const krb5_data *realm;
+ struct sockaddr **addr_pp;
+ socklen_t *addrlen_p;
+ {
+ const char *realm_srv_names[4];
+ char *host, *port, *cp;
+ struct sockaddr *addr_p;
+ struct sockaddr_in *sin_p;
+ struct hostent *hp;
+ krb5_error_code code;
+ char *bind_addr;
+ #ifdef HAVE_NETINET_IN_H
+ u_short udpport;
+ #endif
+
+ bind_addr = NULL;
+ *addr_pp = NULL;
+
+ if ((host = malloc(realm->length + 1)) == NULL)
+ return ENOMEM;
+
+ strncpy(host, realm->data, realm->length);
+ host[realm->length] = '\0';
+
+ realm_srv_names[0] = "realms";
+ realm_srv_names[1] = host;
+ realm_srv_names[2] = "bind_address";
+ realm_srv_names[3] = 0;
+
+ code = profile_get_value(context->profile, realm_srv_names, &bind_addr);
+
+ if (code == 0) {
+ addr_p = (struct sockaddr *)malloc (sizeof (struct sockaddr));
+ if (addr_p == NULL)
+ return ENOMEM;
+ /*
+ * Strip off excess whitespace
+ */
+ cp = strchr(bind_addr, ' ');
+ if (cp)
+ *cp = 0;
+ cp = strchr(bind_addr, '\t');
+ if (cp)
+ *cp = 0;
+ port = strchr(bind_addr, ':');
+ if (port) {
+ *port = 0;
+ port++;
+ }
+ else {
+ float max = IPPORT_USERRESERVED - IPPORT_RESERVED;
+ srand(getpid() + time(NULL));
+ udpport = IPPORT_RESERVED + 1 + (int) (max * rand() /(RAND_MAX+1.0));
+ }
+
+ if ((hp = gethostbyname(bind_addr)) == 0)
+ return KRB5KRB_AP_ERR_BADADDR;
+
+ switch (hp->h_addrtype) {
+
+ #ifdef HAVE_NETINET_IN_H
+ case AF_INET:
+ if (hp->h_addr_list[0]) {
+ sin_p = (struct sockaddr_in *) addr_p;
+ memset ((char *)sin_p, 0, sizeof(struct sockaddr));
+ sin_p->sin_family = hp->h_addrtype;
+ sin_p->sin_port = port ? htons(atoi(port)) : htons(udpport);
+ memcpy((char *)&sin_p->sin_addr,
+ (char *)hp->h_addr_list[0],
+ sizeof(struct in_addr));
+ *addr_pp = addr_p;
+ *addrlen_p = sizeof(struct sockaddr_in);
+ }
+ break;
+ #endif
+ default:
+ break;
+ }
+ }
+ return 0;
+ }
+
#ifdef KRB5_DNS_LOOKUP
/*
diff -cr krb5-1.2.1.orig/src/lib/krb5/os/os-proto.h krb5-1.2.1/src/lib/krb5/os/os-proto.h
*** krb5-1.2.1.orig/src/lib/krb5/os/os-proto.h Fri Jun 30 12:28:13 2000
--- krb5-1.2.1/src/lib/krb5/os/os-proto.h Tue Nov 14 17:16:39 2000
***************
*** 37,42 ****
--- 37,48 ----
struct sockaddr **,
int *,
int));
+
+ krb5_error_code krb5_bind_addr
+ PROTOTYPE((krb5_context,
+ const krb5_data *,
+ struct sockaddr **,
+ int *));
#endif
#ifdef HAVE_NETINET_IN_H
diff -cr krb5-1.2.1.orig/src/lib/krb5/os/sendto_kdc.c krb5-1.2.1/src/lib/krb5/os/sendto_kdc.c
*** krb5-1.2.1.orig/src/lib/krb5/os/sendto_kdc.c Fri Jun 30 12:28:13 2000
--- krb5-1.2.1/src/lib/krb5/os/sendto_kdc.c Tue Nov 14 17:17:32 2000
***************
*** 69,74 ****
--- 69,76 ----
{
register int timeout, host, i;
struct sockaddr *addr;
+ struct sockaddr *bind_addr;
+ int bind_addr_len;
int naddr;
int sent, nready;
krb5_error_code retval;
***************
*** 116,121 ****
--- 118,128 ----
}
#endif
+ bind_addr = NULL;
+ if (retval = krb5_bind_addr (context, realm, &bind_addr,
+ &bind_addr_len))
+ return retval;
+
/*
* do exponential backoff.
*/
***************
*** 141,147 ****
socklist[host] = socket(addr[host].sa_family, SOCK_DGRAM, 0);
if (socklist[host] == INVALID_SOCKET)
continue; /* try other hosts */
! /* have a socket to send/recv from */
/* On BSD systems, a connected UDP socket will get connection
refused and net unreachable errors while an unconnected
socket will time out, so use connect, send, recv instead of
--- 148,159 ----
socklist[host] = socket(addr[host].sa_family, SOCK_DGRAM, 0);
if (socklist[host] == INVALID_SOCKET)
continue; /* try other hosts */
! /*
! * have a socket to send/recv from: bind to local
! * address if necessary
! */
! if (bind_addr && bind(socklist[host], bind_addr, bind_addr_len) < 0)
! continue; /* try other hosts */
/* On BSD systems, a connected UDP socket will get connection
refused and net unreachable errors while an unconnected
socket will time out, so use connect, send, recv instead of
***************
*** 222,227 ****
--- 234,242 ----
#if 0
SOCKET_CLEANUP(); /* Done with sockets for now */
#endif
+ if (bind_addr) {
+ krb5_xfree(bind_addr);
+ }
krb5_xfree(addr);
krb5_xfree(socklist);
if (retval) {
diff -cr krb5-1.2.1.orig/src/lib/krb5/os/t_std_conf.c krb5-1.2.1/src/lib/krb5/os/t_std_conf.c
*** krb5-1.2.1.orig/src/lib/krb5/os/t_std_conf.c Fri Jun 30 12:28:13 2000
--- krb5-1.2.1/src/lib/krb5/os/t_std_conf.c Tue Nov 14 17:15:43 2000
***************
*** 119,128 ****
retval = krb5_locate_kdc(ctx, &rlm, &addrs, &naddrs,
get_masters);
if (retval) {
! com_err("krb5_get_krbhst", retval, 0);
return;
}
! printf("krb_get_krbhst(%s) returned:", realm);
for (i=0; i < naddrs; i++) {
sin = (struct sockaddr_in *) &addrs[i];
printf(" %s/%d", inet_ntoa(sin->sin_addr),
--- 119,128 ----
retval = krb5_locate_kdc(ctx, &rlm, &addrs, &naddrs,
get_masters);
if (retval) {
! com_err("krb5_locate_kdc", retval, 0);
return;
}
! printf("krb_locate_kdc(%s) returned:", realm);
for (i=0; i < naddrs; i++) {
sin = (struct sockaddr_in *) &addrs[i];
printf(" %s/%d", inet_ntoa(sin->sin_addr),
***************
*** 132,137 ****
--- 132,179 ----
printf("\n");
}
+ void test_bind_addr (ctx, realm)
+ krb5_context ctx;
+ char *realm;
+ {
+ struct sockaddr *addr = NULL;
+ struct sockaddr_in *sin;
+ int addrlen;
+ krb5_data rlm;
+ krb5_error_code retval;
+ int s;
+
+ rlm.data = realm;
+ rlm.length = strlen(realm);
+ retval = krb5_bind_addr (ctx, &rlm, &addr, &addrlen);
+ if (retval) {
+ com_err("krb5_bind_addr", retval, 0);
+ return;
+ }
+ sin = (struct sockaddr_in *) addr;
+ printf("krb_bind_addr(%s) returned:", realm);
+ if (sin == 0) {
+ printf(" [null]");
+ }
+ else {
+ printf(" %s/%d", inet_ntoa(sin->sin_addr),
+ ntohs(sin->sin_port));
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ perror(" socket");
+ }
+ else if (bind(s, addr, addrlen) < 0) {
+ perror(" bind");
+ }
+ else {
+ printf(" bind succeeded");
+ }
+ free(addr);
+ }
+ printf ("\n");
+ }
+
void test_get_host_realm(ctx, host)
krb5_context ctx;
char *host;
***************
*** 181,187 ****
void usage(progname)
char *progname;
{
! fprintf(stderr, "%s: Usage: %s [-dc] [-k realm] [-r host] [-C ccname] [-D realm]\n",
progname, progname);
exit(1);
}
--- 223,229 ----
void usage(progname)
char *progname;
{
! fprintf(stderr, "%s: Usage: %s [-dc] [-k realm] [-r host] [-C ccname] [-D realm] [-l realm] [-b realm]\n",
progname, progname);
exit(1);
}
***************
*** 202,209 ****
exit(1);
}
! while ((c = getopt(argc, argv, "cdk:r:C:D:l:s:")) != -1) {
switch (c) {
case 'c': /* Get default ccname */
test_get_default_ccname(ctx);
break;
--- 244,254 ----
exit(1);
}
! while ((c = getopt(argc, argv, "b:cdk:r:C:D:l:s:")) != -1) {
switch (c) {
+ case 'b':
+ test_bind_addr(ctx, optarg);
+ break;
case 'c': /* Get default ccname */
test_get_default_ccname(ctx);
break;
Show quoted text
>How-To-Repeat:
>Fix:
>Audit-Trail:
>Unformatted: