From: Ken Raeburn Date: Tue, 4 Jun 2002 06:59:28 +0000 (+0000) Subject: Add capability of looking up TCP addresses for KDC in DNS; not enabled yet. X-Git-Tag: krb5-1.3-alpha1~737 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=b02232ffdf69f75caaf10c78e00a9fa8f93b3286;p=krb5.git Add capability of looking up TCP addresses for KDC in DNS; not enabled yet. Internal "addrlist" structure now includes socket type, by way of using struct addrinfo where struct sockaddr was used before; updated uses. No support for noting TCP/UDP vs UDP-only addresses in config files. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@14465 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/include/ChangeLog b/src/include/ChangeLog index 2fdec2914..0872f7104 100644 --- a/src/include/ChangeLog +++ b/src/include/ChangeLog @@ -1,3 +1,8 @@ +2002-06-04 Ken Raeburn + + * k5-int.h (struct addrlist): Field "addrs" now points to + addrinfo instead of sockaddr. + 2002-05-31 Ken Raeburn * socket-utils.h (socklen) [! HAVE_SA_LEN]: Return a socklen_t diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 1b90386f5..e53585a15 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -485,8 +485,10 @@ krb5_error_code krb5_find_config_files (void); krb5_error_code krb5_os_hostaddr (krb5_context, const char *, krb5_address ***); +/* N.B.: You need to include fake-addrinfo.h *before* k5-int.h if you're + going to use this structure. */ struct addrlist { - struct sockaddr **addrs; + struct addrinfo **addrs; int naddrs; int space; }; diff --git a/src/krb524/ChangeLog b/src/krb524/ChangeLog index 68b0a832a..6f35970ed 100644 --- a/src/krb524/ChangeLog +++ b/src/krb524/ChangeLog @@ -1,3 +1,8 @@ +2002-06-04 Ken Raeburn + + * sendmsg.c: Include fake-addrinfo.h. + (krb524_sendto_kdc): Update for addrlist changes. + 2002-04-10 Danilo Almeida * encode.c, cnv_tkt_skey.c: Need port-sockets.h for Win32 (now diff --git a/src/krb524/sendmsg.c b/src/krb524/sendmsg.c index 00c55f0d2..2335dad31 100644 --- a/src/krb524/sendmsg.c +++ b/src/krb524/sendmsg.c @@ -28,6 +28,7 @@ /* Grab socket stuff. This might want to go away later. */ #define NEED_SOCKETS #define NEED_LOWLEVEL_IO +#include "fake-addrinfo.h" /* for custom addrinfo if needed */ #include "k5-int.h" #ifndef _WIN32 @@ -101,8 +102,8 @@ krb524_sendto_kdc (context, message, realm, reply) */ if (retval == 0) for (i = 0; i < al.naddrs; i++) { - if (al.addrs[i]->sa_family == AF_INET) - sa2sin (al.addrs[i])->sin_port = port; + if (al.addrs[i]->ai_family == AF_INET) + sa2sin (al.addrs[i]->ai_addr)->sin_port = port; } } if (retval) @@ -163,7 +164,7 @@ krb524_sendto_kdc (context, message, realm, reply) * protocol exists to support a particular socket type * within a given protocol family. */ - socklist[host] = socket(al.addrs[host]->sa_family, SOCK_DGRAM, + socklist[host] = socket(al.addrs[host]->ai_family, SOCK_DGRAM, 0); if (socklist[host] == INVALID_SOCKET) continue; /* try other hosts */ @@ -173,8 +174,8 @@ krb524_sendto_kdc (context, message, realm, reply) socket will time out, so use connect, send, recv instead of sendto, recvfrom. The connect here may return an error if the destination host is known to be unreachable. */ - if (connect(socklist[host], al.addrs[host], - socklen(al.addrs[host])) == SOCKET_ERROR) + if (connect(socklist[host], al.addrs[host]->ai_addr, + al.addrs[host]->ai_addrlen) == SOCKET_ERROR) continue; } if (send(socklist[host], message->data, (int) message->length, 0) diff --git a/src/lib/krb5/os/ChangeLog b/src/lib/krb5/os/ChangeLog index 9f981c884..9f75d40b9 100644 --- a/src/lib/krb5/os/ChangeLog +++ b/src/lib/krb5/os/ChangeLog @@ -1,3 +1,29 @@ +2002-06-04 Ken Raeburn + + * locate_kdc.c: Include fake-addrinfo.h before k5-int.h. + (grow_list, krb5int_free_addrlist) + (add_addrinfo_to_list): Incorporate list-updating code from + add_sockaddr_to_list. Store an addrinfo pointer, and set the + ai_next field to null. + (add_host_to_list): New arg SOCKTYPE. Write port numbers into + buffers and let getaddrinfo fill in the sin*_port fields. Call + getaddrinfo twice, and use two loops to add entries to the + addrlist structure. + (add_sockaddr_to_list, set_port_num): Deleted. + (krb5_locate_srv_conf_1, krb5_locate_srv_dns_1): Pass extra arg + to add_host_to_list. + (krb5int_locate_server): New value 2 for is_stream arg means + accept both UDP and TCP. + * changepw.c: Include fake-addrinfo.h. + (krb5_locate_passwd, krb5_change_password): Update for addrlist + changes. + * sendto_kdc.c: Include fake-addrinfo.h. + (krb5_sendto_kdc): Update for addrlist changes. Skip any + addresses that are not SOCK_DGRAM. + * t_locate_kdc.c (stypename): New function. + (print_addrs): Update for addrlist changes. Print socket type + with address and port. + 2002-04-12 Ken Raeburn * lock_file.c (krb5_lock_file) [POSIX_FILE_LOCKS]: Make static diff --git a/src/lib/krb5/os/changepw.c b/src/lib/krb5/os/changepw.c index 88d50cc90..42b77286e 100644 --- a/src/lib/krb5/os/changepw.c +++ b/src/lib/krb5/os/changepw.c @@ -26,6 +26,7 @@ */ #define NEED_SOCKETS +#include "fake-addrinfo.h" #include "k5-int.h" #include "os-proto.h" #include "adm_err.h" @@ -75,9 +76,9 @@ krb5_locate_kpasswd(krb5_context context, const krb5_data *realm, port number to use DEFAULT_KPASSWD_PORT. */ int i; for ( i=0;inaddrs;i++ ) { - struct sockaddr *a = addrlist->addrs[i]; - if (a->sa_family == AF_INET) - sa2sin (a)->sin_port = htons(DEFAULT_KPASSWD_PORT); + struct addrinfo *a = addrlist->addrs[i]; + if (a->ai_family == AF_INET) + sa2sin (a->ai_addr)->sin_port = htons(DEFAULT_KPASSWD_PORT); } } } @@ -169,11 +170,11 @@ krb5_change_password(context, creds, newpw, result_code, struct timeval timeout; /* XXX Now the locate_ functions can return IPv6 addresses. */ - if (al.addrs[i]->sa_family != AF_INET) + if (al.addrs[i]->ai_family != AF_INET) continue; tried_one = 1; - if (connect(s2, al.addrs[i], socklen(al.addrs[i])) == SOCKET_ERROR) { + if (connect(s2, al.addrs[i]->ai_addr, al.addrs[i]->ai_addrlen) == SOCKET_ERROR) { if (SOCKET_ERRNO == ECONNREFUSED || SOCKET_ERRNO == EHOSTUNREACH) continue; /* try the next addr */ @@ -254,7 +255,7 @@ krb5_change_password(context, creds, newpw, result_code, if ((cc = sendto(s1, chpw_req.data, (GETSOCKNAME_ARG3_TYPE) chpw_req.length, 0, - al.addrs[i], socklen(al.addrs[i]))) != chpw_req.length) + al.addrs[i]->ai_addr, al.addrs[i]->ai_addrlen)) != chpw_req.length) { if ((cc < 0) && ((SOCKET_ERRNO == ECONNREFUSED) || (SOCKET_ERRNO == EHOSTUNREACH))) diff --git a/src/lib/krb5/os/locate_kdc.c b/src/lib/krb5/os/locate_kdc.c index cc6d9c567..d1819939d 100644 --- a/src/lib/krb5/os/locate_kdc.c +++ b/src/lib/krb5/os/locate_kdc.c @@ -28,6 +28,7 @@ */ #define NEED_SOCKETS +#include "fake-addrinfo.h" #include "k5-int.h" #include "os-proto.h" #include @@ -44,8 +45,6 @@ #define T_SRV 33 #endif /* T_SRV */ -#include "fake-addrinfo.h" - /* for old Unixes and friends ... */ #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 @@ -133,7 +132,7 @@ grow_list (struct addrlist *lp, int nmore) int i; int newspace = lp->space + nmore; size_t newsize = newspace * sizeof (struct addrlist); - struct sockaddr **newaddrs; + struct addrinfo **newaddrs; /* NULL check a concession to SunOS4 compatibility for now; not required for pure ANSI support. */ @@ -158,57 +157,13 @@ krb5int_free_addrlist (struct addrlist *lp) { int i; for (i = 0; i < lp->naddrs; i++) - free (lp->addrs[i]); + freeaddrinfo (lp->addrs[i]); free (lp->addrs); lp->addrs = NULL; lp->naddrs = lp->space = 0; } #define free_list krb5int_free_addrlist -static int -add_sockaddr_to_list (struct addrlist *lp, const struct sockaddr *addr, - size_t len) -{ - struct sockaddr *copy; - int err; - -#ifdef TEST - char name[NI_MAXHOST]; - - fprintf (stderr, "\tadding sockaddr family %2d, len %d", addr->sa_family, - len); - - err = getnameinfo (addr, len, name, sizeof (name), NULL, 0, - NI_NUMERICHOST | NI_NUMERICSERV); - if (err == 0) - fprintf (stderr, "\t%s", name); - fprintf (stderr, "\n"); -#endif - - if (lp->naddrs == lp->space) { - err = grow_list (lp, 1); - if (err) { -#ifdef TEST - fprintf (stderr, "grow_list failed %d\n", err); -#endif - return err; - } - } - copy = malloc (len); - if (copy == NULL) { -#ifdef TEST - perror ("malloc"); -#endif - return errno; - } - memcpy (copy, addr, len); - lp->addrs[lp->naddrs++] = copy; -#ifdef TEST - fprintf (stderr, "count is now %d\n", lp->naddrs); -#endif - return 0; -} - static int translate_ai_error (int err) { switch (err) { @@ -249,8 +204,8 @@ static int translate_ai_error (int err) static int add_addrinfo_to_list (struct addrlist *lp, struct addrinfo *a) { - int r; - r = add_sockaddr_to_list (lp, a->ai_addr, a->ai_addrlen); + int err; + #ifdef TEST switch (a->ai_socktype) { case SOCK_DGRAM: @@ -269,29 +224,31 @@ static int add_addrinfo_to_list (struct addrlist *lp, struct addrinfo *a) break; } #endif - return r; -} -static void set_port_num (struct sockaddr *addr, int num) -{ - switch (addr->sa_family) { - case AF_INET: - ((struct sockaddr_in *)addr)->sin_port = num; - break; -#ifdef KRB5_USE_INET6 - case AF_INET6: - ((struct sockaddr_in6 *)addr)->sin6_port = num; - break; + if (lp->naddrs == lp->space) { + err = grow_list (lp, 1); + if (err) { +#ifdef TEST + fprintf (stderr, "grow_list failed %d\n", err); #endif + return err; + } } + lp->addrs[lp->naddrs++] = a; + a->ai_next = 0; +#ifdef TEST + fprintf (stderr, "count is now %d\n", lp->naddrs); +#endif + return 0; } static int add_host_to_list (struct addrlist *lp, const char *hostname, - int port, int secport) + int port, int secport, int socktype) { - struct addrinfo *addrs, *a, hint; + struct addrinfo *addrs, *a, *anext, hint; int err; + char portbuf[10], secportbuf[10]; #ifdef TEST fprintf (stderr, "adding hostname %s, ports %d,%d\n", hostname, @@ -299,25 +256,29 @@ add_host_to_list (struct addrlist *lp, const char *hostname, #endif memset(&hint, 0, sizeof(hint)); - hint.ai_socktype = SOCK_DGRAM; - err = getaddrinfo (hostname, NULL, &hint, &addrs); + hint.ai_socktype = socktype; + sprintf(portbuf, "%d", ntohs(port)); + sprintf(secportbuf, "%d", ntohs(secport)); + err = getaddrinfo (hostname, portbuf, &hint, &addrs); if (err) return translate_ai_error (err); - for (a = addrs; a; a = a->ai_next) { - set_port_num (a->ai_addr, port); + anext = 0; + for (a = addrs; a != 0 && err == 0; a = anext) { + anext = a->ai_next; err = add_addrinfo_to_list (lp, a); - if (err) - break; - - if (secport == 0) - continue; - - set_port_num (a->ai_addr, secport); + } + if (err || secport == 0) + goto egress; + err = getaddrinfo (hostname, secportbuf, &hint, &addrs); + if (err) + return translate_ai_error (err); + for (a = addrs; a != 0 && err == 0; a = anext) { + anext = a->ai_next; err = add_addrinfo_to_list (lp, a); - if (err) - break; } - freeaddrinfo (addrs); +egress: + if (anext) + freeaddrinfo (anext); return err; } @@ -470,7 +431,7 @@ krb5_locate_srv_conf_1(krb5_context context, const krb5_data *realm, p2 = sec_udpport; } - code = add_host_to_list (addrlist, hostlist[i], p1, p2); + code = add_host_to_list (addrlist, hostlist[i], p1, p2, SOCK_DGRAM); if (code) { #ifdef TEST fprintf (stderr, "error %d returned from add_host_to_list\n", code); @@ -732,7 +693,10 @@ krb5_locate_srv_dns_1 (const krb5_data *realm, #ifdef TEST fprintf (stderr, "\tport=%d host=%s\n", entry->port, entry->host); #endif - code = add_host_to_list (addrlist, entry->host, htons (entry->port), 0); + code = add_host_to_list (addrlist, entry->host, htons (entry->port), 0, + (strcmp("_tcp", protocol) + ? SOCK_DGRAM + : SOCK_STREAM)); if (code) break; } @@ -795,9 +759,31 @@ krb5int_locate_server (krb5_context context, const krb5_data *realm, #ifdef KRB5_DNS_LOOKUP if (code && dnsname != 0) { int use_dns = _krb5_use_dns_kdc(context); - if (use_dns) - code = krb5_locate_srv_dns_1(realm, dnsname, - is_stream ? "_tcp" : "_udp", &al); + if (use_dns) { + /* Values of is_stream: + 0: udp only + 1: tcp only + 2: udp or tcp + No other values currently allowed. */ + code = 0; +#ifdef TEST + fprintf(stderr, "is_stream = %d\n", is_stream); +#endif + if (is_stream != 1) { + code = krb5_locate_srv_dns_1(realm, dnsname, "_udp", &al); +#ifdef TEST + if (code) + fprintf(stderr, "dns lookup returned error %d\n", code); +#endif + } + if (is_stream != 0 && code == 0) { + code = krb5_locate_srv_dns_1(realm, dnsname, "_tcp", &al); +#ifdef TEST + if (code) + fprintf(stderr, "dns lookup returned error %d\n", code); +#endif + } + } } #endif /* KRB5_DNS_LOOKUP */ #ifdef TEST diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c index 7bb63522c..595e2c9d8 100644 --- a/src/lib/krb5/os/sendto_kdc.c +++ b/src/lib/krb5/os/sendto_kdc.c @@ -30,6 +30,7 @@ #define NEED_SOCKETS #define NEED_LOWLEVEL_IO +#include "fake-addrinfo.h" #include "k5-int.h" #ifdef HAVE_SYS_TIME_H @@ -120,9 +121,11 @@ krb5_sendto_kdc (context, message, realm, reply, use_master) timeout <<= krb5_skdc_timeout_shift) { sent = 0; for (host = 0; host < addrs.naddrs; host++) { - /* send to the host, wait timeout seconds for a response, + if (addrs.addrs[host]->ai_socktype != SOCK_DGRAM) + continue; + /* Send to the host, wait timeout seconds for a response, then move on. */ - /* cache some sockets for each host */ + /* Cache some sockets for each host. */ if (socklist[host] == INVALID_SOCKET) { /* XXX 4.2/4.3BSD has PF_xxx = AF_xxx, so the socket creation here will work properly... */ @@ -136,22 +139,22 @@ krb5_sendto_kdc (context, message, realm, reply, use_master) */ #ifdef DEBUG fprintf (stderr, "getting dgram socket in family %d...", - addrs.addrs[host]->sa_family); + addrs.addrs[host]->ai_family); #endif - socklist[host] = socket(addrs.addrs[host]->sa_family, + socklist[host] = socket(addrs.addrs[host]->ai_family, SOCK_DGRAM, 0); if (socklist[host] == INVALID_SOCKET) { #ifdef DEBUG perror ("socket"); - fprintf (stderr, "af was %d\n", addrs.addrs[host]->sa_family); + fprintf (stderr, "af was %d\n", addrs.addrs[host]->ai_family); #endif continue; /* try other hosts */ } #ifdef DEBUG { char addrbuf[NI_MAXHOST], portbuf[NI_MAXSERV]; - if (0 != getnameinfo (addrs.addrs[host], - socklen (addrs.addrs[host]), + if (0 != getnameinfo (addrs.addrs[host]->ai_addr, + addrs.addrs[host]->ai_addrlen, addrbuf, sizeof (addrbuf), portbuf, sizeof (portbuf), NI_NUMERICHOST | NI_NUMERICSERV)) @@ -167,7 +170,7 @@ krb5_sendto_kdc (context, message, realm, reply, use_master) sendto, recvfrom. The connect here may return an error if the destination host is known to be unreachable. */ if (connect(socklist[host], - addrs.addrs[host], socklen(addrs.addrs[host])) == SOCKET_ERROR) { + addrs.addrs[host]->ai_addr, addrs.addrs[host]->ai_addrlen) == SOCKET_ERROR) { #ifdef DEBUG perror ("connect"); #endif diff --git a/src/lib/krb5/os/t_locate_kdc.c b/src/lib/krb5/os/t_locate_kdc.c index e93b6d877..5bb334b6d 100644 --- a/src/lib/krb5/os/t_locate_kdc.c +++ b/src/lib/krb5/os/t_locate_kdc.c @@ -27,18 +27,34 @@ void kfatal (krb5_error_code err) exit (1); } +const char *stypename (int stype) +{ + static char buf[20]; + switch (stype) { + case SOCK_STREAM: + return "stream"; + case SOCK_DGRAM: + return "dgram"; + case SOCK_RAW: + return "raw"; + default: + sprintf(buf, "?%d", stype); + return buf; + } +} + void print_addrs () { int i; - struct sockaddr **addrs = al.addrs; + struct addrinfo **addrs = al.addrs; int naddrs = al.naddrs; printf ("%d addresses:\n", naddrs); for (i = 0; i < naddrs; i++) { int err; char hostbuf[NI_MAXHOST], srvbuf[NI_MAXSERV]; - err = getnameinfo (addrs[i], socklen(addrs[i]), + err = getnameinfo (addrs[i]->ai_addr, addrs[i]->ai_addrlen, hostbuf, sizeof (hostbuf), srvbuf, sizeof (srvbuf), NI_NUMERICHOST | NI_NUMERICSERV); @@ -46,7 +62,8 @@ void print_addrs () printf ("%2d: getnameinfo returns error %d=%s\n", i, err, gai_strerror (err)); else - printf ("%2d: address %s\tport %s\n", i, hostbuf, srvbuf); + printf ("%2d: address %s\t%s\tport %s\n", i, hostbuf, + stypename (addrs[i]->ai_socktype), srvbuf); } }