From 3ef1ecb6226c6d976b2eccc4d6882c7dafa466fa Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Wed, 20 Jun 2001 00:00:05 +0000 Subject: [PATCH] Use a "struct addrlist" instead of separate count and pointer-to-pointer values for internal interfaces for looking up servers. Add a new routine to free the addrlist contents, so that memory management can be changed in one place. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@13390 dc483132-0cff-0310-8789-dd5450dbe970 --- src/include/ChangeLog | 10 ++++++ src/include/k5-int.h | 22 ++++++++------ src/krb524/ChangeLog | 4 +++ src/krb524/sendmsg.c | 43 +++++++++++++------------- src/lib/krb5/os/ChangeLog | 23 ++++++++++++++ src/lib/krb5/os/accessor.c | 1 + src/lib/krb5/os/changepw.c | 50 +++++++++++++++--------------- src/lib/krb5/os/locate_kdc.c | 59 ++++++++++++------------------------ src/lib/krb5/os/os-proto.h | 6 +--- src/lib/krb5/os/sendto_kdc.c | 34 ++++++++++----------- 10 files changed, 136 insertions(+), 116 deletions(-) diff --git a/src/include/ChangeLog b/src/include/ChangeLog index cb73197a1..8858905f8 100644 --- a/src/include/ChangeLog +++ b/src/include/ChangeLog @@ -1,3 +1,13 @@ +2001-06-19 Ken Raeburn + + * k5-int.h (struct addrlist): New type. + (ADDRLIST_INIT): New macro. + (krb5int_free_addrlist): Declare. + (krb5int_locate_server): Update declaration. + (KRB5INT_ACCESS_STRUCT_VERSION): Update to 3. + (struct _krb5int_access): Change locale_server prototype. Add + free_addrlist function pointer field. + 2001-06-11 Ezra Peisach * k5-util.h: Add prototypes for krb5_compat_recvauth_version() and diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 0a6c9a8fb..a58d2821d 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -544,14 +544,18 @@ void krb5_os_free_context (krb5_context); krb5_error_code krb5_find_config_files (void); +struct addrlist { + struct sockaddr **addrs; + int naddrs; + int space; +}; +#define ADDRLIST_INIT { 0, 0, 0 } +extern void krb5int_free_addrlist (struct addrlist *); + krb5_error_code krb5int_locate_server (krb5_context, const krb5_data *realm, - /* Thing pointed to will be filled in with a - pointer to a block of sockaddr pointers, - with each sockaddr allocated separately - (wasteful, oh well). */ - struct sockaddr ***addrs, int *naddrs, + struct addrlist *, /* Only meaningful for kdc, really... */ int want_masters, /* look up [realms]->$realm->$name in krb5.conf */ @@ -1566,16 +1570,16 @@ void krb5int_set_prompt_types /* To keep happy libraries which are (for now) accessing internal stuff */ /* Make sure to increment by one when changing the struct */ -#define KRB5INT_ACCESS_STRUCT_VERSION 2 +#define KRB5INT_ACCESS_STRUCT_VERSION 3 typedef struct _krb5int_access { krb5_error_code (*krb5_locate_kdc) (krb5_context, const krb5_data *, - struct sockaddr ***, int *, int); + struct addrlist *, int); krb5_error_code (*krb5_locate_server) (krb5_context, const krb5_data *, - struct sockaddr ***, int *, - int, + struct addrlist *, int, const char *, const char *, int, int, int); + void (*free_addrlist) (struct addrlist *); unsigned int krb5_max_skdc_timeout; unsigned int krb5_skdc_timeout_shift; unsigned int krb5_skdc_timeout_1; diff --git a/src/krb524/ChangeLog b/src/krb524/ChangeLog index 938902003..ba597d54f 100644 --- a/src/krb524/ChangeLog +++ b/src/krb524/ChangeLog @@ -1,3 +1,7 @@ +2001-06-19 Ken Raeburn + + * sendmsg.c (krb524_sendto_kdc): Use new locate_server interface. + 2001-06-06 Ezra Peisach * test.c (print_key): Pass in des_cblock* instead of char *. diff --git a/src/krb524/sendmsg.c b/src/krb524/sendmsg.c index 3d7b433a7..00c55f0d2 100644 --- a/src/krb524/sendmsg.c +++ b/src/krb524/sendmsg.c @@ -68,8 +68,7 @@ krb524_sendto_kdc (context, message, realm, reply) krb5_data * reply; { register int timeout, host, i; - struct sockaddr **addr; - int naddr; + struct addrlist al = ADDRLIST_INIT; struct servent *serv; int sent, nready; krb5_error_code retval; @@ -90,37 +89,37 @@ krb524_sendto_kdc (context, message, realm, reply) serv = getservbyname(KRB524_SERVICE, "udp"); port = serv ? serv->s_port : htons (KRB524_PORT); - retval = internals.krb5_locate_server(context, realm, &addr, &naddr, 0, + retval = internals.krb5_locate_server(context, realm, &al, 0, "krb524_server", "_krb524", 0, port, 0); if (retval == KRB5_REALM_CANT_RESOLVE || retval == KRB5_REALM_UNKNOWN) { /* Fallback heuristic: Assume krb524 port on every KDC might work. */ - retval = internals.krb5_locate_kdc(context, realm, &addr, &naddr, 0); + retval = internals.krb5_locate_kdc(context, realm, &al, 0); /* * Bash the ports numbers. */ if (retval == 0) - for (i = 0; i < naddr; i++) { - if (addr[i]->sa_family == AF_INET) - sa2sin (addr[i])->sin_port = port; + for (i = 0; i < al.naddrs; i++) { + if (al.addrs[i]->sa_family == AF_INET) + sa2sin (al.addrs[i])->sin_port = port; } } if (retval) return retval; - if (naddr == 0) + if (al.naddrs == 0) return KRB5_REALM_UNKNOWN; - socklist = (SOCKET *)malloc(naddr * sizeof(SOCKET)); + socklist = (SOCKET *)malloc(al.naddrs * sizeof(SOCKET)); if (socklist == NULL) { - free(addr); + internals.free_addrlist (&al); return ENOMEM; } - for (i = 0; i < naddr; i++) + for (i = 0; i < al.naddrs; i++) socklist[i] = INVALID_SOCKET; if (!(reply->data = malloc(internals.krb5_max_dgram_size))) { - free(addr); + internals.free_addrlist (&al); free(socklist); return ENOMEM; } @@ -145,10 +144,11 @@ krb524_sendto_kdc (context, message, realm, reply) * do exponential backoff. */ - for (timeout = internals.krb5_skdc_timeout_1; timeout < internals.krb5_max_skdc_timeout; + for (timeout = internals.krb5_skdc_timeout_1; + timeout < internals.krb5_max_skdc_timeout; timeout <<= internals.krb5_skdc_timeout_shift) { sent = 0; - for (host = 0; host < naddr; host++) { + for (host = 0; host < al.naddrs; host++) { /* send to the host, wait timeout seconds for a response, then move on. */ /* cache some sockets for each host */ @@ -163,7 +163,8 @@ krb524_sendto_kdc (context, message, realm, reply) * protocol exists to support a particular socket type * within a given protocol family. */ - socklist[host] = socket(addr[host]->sa_family, SOCK_DGRAM, 0); + socklist[host] = socket(al.addrs[host]->sa_family, SOCK_DGRAM, + 0); if (socklist[host] == INVALID_SOCKET) continue; /* try other hosts */ /* have a socket to send/recv from */ @@ -172,12 +173,12 @@ 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], - addr[host], socklen(addr[host])) == SOCKET_ERROR) + if (connect(socklist[host], al.addrs[host], + socklen(al.addrs[host])) == SOCKET_ERROR) continue; } - if (send(socklist[host], - message->data, (int) message->length, 0) != message->length) + if (send(socklist[host], message->data, (int) message->length, 0) + != message->length) continue; retry: waitlen.tv_usec = 0; @@ -238,13 +239,13 @@ krb524_sendto_kdc (context, message, realm, reply) } retval = KRB5_KDC_UNREACH; out: - for (i = 0; i < naddr; i++) + for (i = 0; i < al.naddrs; i++) if (socklist[i] != INVALID_SOCKET) (void) closesocket (socklist[i]); #if 0 SOCKET_CLEANUP(); /* Done with sockets for now */ #endif - free(addr); + internals.free_addrlist (&al); free(socklist); if (retval) { free(reply->data); diff --git a/src/lib/krb5/os/ChangeLog b/src/lib/krb5/os/ChangeLog index 2767311a5..137ef7680 100644 --- a/src/lib/krb5/os/ChangeLog +++ b/src/lib/krb5/os/ChangeLog @@ -1,3 +1,26 @@ +2001-06-19 Ken Raeburn + + * locate_kdc.c (struct addrlist, ADDRLIST_INIT): Moved to + k5-int.h. + (krb5int_free_addrlist): Renamed from free_list; no longer + static. + (krb5_locate_srv_conf, krb5_locate_srv_dns, krb5int_locate_server, + krb5_locate_kdc): Use addrlist in interface. + + * sendto_kdc.c (krb5_sendto_kdc): Use new struct addrlist + interface. + + * changepw.c (krb5_locate_kpasswd): Use addrlist structure in + interface and implementation. + (krb5_change_password): Likewise. + + * accessor.c (krb5int_accessor): Fill in free_addrlist function + pointer field. + + * os-proto.h (krb5_locate_kdc): Update prototype. + + * t_std_conf.c (test_locate_kdc): Update tests for new API. + 2001-06-12 Ezra Peisach * sn2princ.c, hst_realm.c, an_to_ln.c: Cast argument to diff --git a/src/lib/krb5/os/accessor.c b/src/lib/krb5/os/accessor.c index d3c842a86..bcf89a7b6 100644 --- a/src/lib/krb5/os/accessor.c +++ b/src/lib/krb5/os/accessor.c @@ -39,6 +39,7 @@ krb5int_accessor(internals, version) krb5int_access internals_temp; internals_temp.krb5_locate_server = krb5int_locate_server; internals_temp.krb5_locate_kdc = krb5_locate_kdc; + internals_temp.free_addrlist = krb5int_free_addrlist; internals_temp.krb5_max_skdc_timeout = krb5_max_skdc_timeout; internals_temp.krb5_skdc_timeout_shift = krb5_skdc_timeout_shift; internals_temp.krb5_skdc_timeout_1 = krb5_skdc_timeout_1; diff --git a/src/lib/krb5/os/changepw.c b/src/lib/krb5/os/changepw.c index 0a6d0e5ee..7153b75ec 100644 --- a/src/lib/krb5/os/changepw.c +++ b/src/lib/krb5/os/changepw.c @@ -54,27 +54,24 @@ */ static krb5_error_code -krb5_locate_kpasswd(context, realm, addr_pp, naddrs) - krb5_context context; - const krb5_data *realm; - struct sockaddr ***addr_pp; - int *naddrs; +krb5_locate_kpasswd(krb5_context context, const krb5_data *realm, + struct addrlist *addrlist) { krb5_error_code code; - code = krb5int_locate_server (context, realm, addr_pp, naddrs, 0, + code = krb5int_locate_server (context, realm, addrlist, 0, "kpasswd_server", "_kpasswd", 0, DEFAULT_KPASSWD_PORT, 0); if (code) { - code = krb5int_locate_server (context, realm, addr_pp, naddrs, 0, + code = krb5int_locate_server (context, realm, addrlist, 0, "admin_server", "_kerberos-adm", 1, DEFAULT_KPASSWD_PORT, 0); if (!code) { /* Success with admin_server but now we need to change the port number to use DEFAULT_KPASSWD_PORT. */ int i; - for ( i=0;i<*naddrs;i++ ) { - struct sockaddr *a = (*addr_pp)[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); } @@ -100,17 +97,15 @@ krb5_change_password(context, creds, newpw, result_code, char *code_string; krb5_error_code code = 0; int i, addrlen; - struct sockaddr **addr_p; struct sockaddr_storage local_addr, remote_addr, tmp_addr; - int naddr_p; int cc, local_result_code, tmp_len; SOCKET s1 = INVALID_SOCKET, s2 = INVALID_SOCKET; int tried_one = 0; + struct addrlist al = ADDRLIST_INIT; /* Initialize values so that cleanup call can safely check for NULL */ auth_context = NULL; - addr_p = NULL; memset(&chpw_req, 0, sizeof(krb5_data)); memset(&chpw_rep, 0, sizeof(krb5_data)); memset(&ap_req, 0, sizeof(krb5_data)); @@ -126,7 +121,7 @@ krb5_change_password(context, creds, newpw, result_code, if ((code = krb5_locate_kpasswd(context, krb5_princ_realm(context, creds->client), - &addr_p, &naddr_p))) + &al))) goto cleanup; /* this is really obscure. s1 is used for all communications. it @@ -155,16 +150,23 @@ krb5_change_password(context, creds, newpw, result_code, goto cleanup; } - for (i=0; isa_family != AF_INET) + if (al.addrs[i]->sa_family != AF_INET) continue; tried_one = 1; - if (connect(s2, addr_p[i], socklen(addr_p[i])) == SOCKET_ERROR) { + if (connect(s2, al.addrs[i], socklen(al.addrs[i])) == SOCKET_ERROR) { if (SOCKET_ERRNO == ECONNREFUSED || SOCKET_ERRNO == EHOSTUNREACH) continue; /* try the next addr */ @@ -244,7 +246,7 @@ krb5_change_password(context, creds, newpw, result_code, } if ((cc = sendto(s1, chpw_req.data, (int) chpw_req.length, 0, - addr_p[i], socklen(addr_p[i]))) != chpw_req.length) + al.addrs[i], socklen(al.addrs[i]))) != chpw_req.length) { if ((cc < 0) && ((SOCKET_ERRNO == ECONNREFUSED) || (SOCKET_ERRNO == EHOSTUNREACH))) @@ -316,9 +318,11 @@ krb5_change_password(context, creds, newpw, result_code, goto cleanup; result_code_string->length = strlen(code_string); - if ((result_code_string->data = - (char *) malloc(result_code_string->length)) == NULL) - return(ENOMEM); + result_code_string->data = malloc(result_code_string->length); + if (result_code_string->data == NULL) { + code = ENOMEM; + goto cleanup; + } strncpy(result_code_string->data, code_string, result_code_string->length); } @@ -339,11 +343,7 @@ cleanup: if (auth_context != NULL) krb5_auth_con_free(context, auth_context); - if (addr_p != NULL) { - for (i = 0; i < naddr_p; i++) - krb5_xfree (addr_p[i]); - krb5_xfree(addr_p); - } + krb5int_free_addrlist (&al); if (s1 != INVALID_SOCKET) closesocket(s1); diff --git a/src/lib/krb5/os/locate_kdc.c b/src/lib/krb5/os/locate_kdc.c index c518c1f1f..a4587e089 100644 --- a/src/lib/krb5/os/locate_kdc.c +++ b/src/lib/krb5/os/locate_kdc.c @@ -133,13 +133,6 @@ static int get_port (const char *service, int stream, int defalt) #endif } -struct addrlist { - struct sockaddr **addrs; - int naddrs; - int space; -}; -#define ADDRLIST_INIT { 0, 0, 0 } - static int grow_list (struct addrlist *lp, int nmore) { @@ -164,8 +157,10 @@ grow_list (struct addrlist *lp, int nmore) return 0; } -static void -free_list (struct addrlist *lp) +/* Free up everything pointed to by the addrlist structure, but don't + free the structure itself. */ +void +krb5int_free_addrlist (struct addrlist *lp) { int i; for (i = 0; i < lp->naddrs; i++) @@ -174,6 +169,7 @@ free_list (struct addrlist *lp) 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, @@ -516,29 +512,23 @@ krb5_locate_srv_conf_1(krb5_context context, const krb5_data *realm, #ifdef TEST static krb5_error_code -krb5_locate_srv_conf(context, realm, name, addr_pp, naddrs, get_masters, +krb5_locate_srv_conf(context, realm, name, al, get_masters, udpport, sec_udpport) krb5_context context; const krb5_data *realm; const char * name; - struct sockaddr ***addr_pp; - int *naddrs; + struct addrlist *al; int get_masters; int udpport, sec_udpport; { krb5_error_code ret; - struct addrlist al = ADDRLIST_INIT; - ret = krb5_locate_srv_conf_1 (context, realm, name, &al, + ret = krb5_locate_srv_conf_1 (context, realm, name, al, get_masters, udpport, sec_udpport); - if (ret) { - free_list (&al); + if (ret) return ret; - } - if (al.naddrs == 0) /* Couldn't resolve any KDC names */ + if (al->naddrs == 0) /* Couldn't resolve any KDC names */ return KRB5_REALM_CANT_RESOLVE; - *addr_pp = al.addrs; - *naddrs = al.naddrs; return 0; } #endif @@ -789,15 +779,9 @@ krb5_locate_srv_dns_1 (const krb5_data *realm, static krb5_error_code krb5_locate_srv_dns(const krb5_data *realm, const char *service, const char *protocol, - struct sockaddr ***addr_pp, int *naddrs) + struct addrlist *al) { - struct addrlist al = ADDRLIST_INIT; - krb5_error_code code; - - code = krb5_locate_srv_dns_1 (realm, service, protocol, &al); - *addr_pp = al.addrs; - *naddrs = al.naddrs; - return code; + return krb5_locate_srv_dns_1 (realm, service, protocol, al); } #endif #endif /* KRB5_DNS_LOOKUP */ @@ -808,7 +792,7 @@ krb5_locate_srv_dns(const krb5_data *realm, krb5_error_code krb5int_locate_server (krb5_context context, const krb5_data *realm, - struct sockaddr ***addr_pp, int *naddrs, + struct addrlist *addrlist, int get_masters, const char *profname, const char *dnsname, int is_stream, @@ -818,6 +802,8 @@ krb5int_locate_server (krb5_context context, const krb5_data *realm, krb5_error_code code; struct addrlist al = ADDRLIST_INIT; + *addrlist = al; + /* * We always try the local file first */ @@ -851,18 +837,14 @@ krb5int_locate_server (krb5_context context, const krb5_data *realm, free_list (&al); return KRB5_REALM_CANT_RESOLVE; } - *addr_pp = al.addrs; - *naddrs = al.naddrs; + *addrlist = al; return 0; } krb5_error_code -krb5_locate_kdc(context, realm, addr_pp, naddrs, get_masters) - krb5_context context; - const krb5_data *realm; - struct sockaddr ***addr_pp; - int *naddrs; - int get_masters; +krb5_locate_kdc(krb5_context context, const krb5_data *realm, + struct addrlist *addrlist, + int get_masters) { int udpport, sec_udpport; @@ -874,8 +856,7 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, get_masters) if (sec_udpport == udpport) sec_udpport = 0; - return krb5int_locate_server (context, realm, addr_pp, naddrs, get_masters, - "kdc", + return krb5int_locate_server (context, realm, addrlist, get_masters, "kdc", (get_masters ? "_kerberos-master" : "_kerberos"), diff --git a/src/lib/krb5/os/os-proto.h b/src/lib/krb5/os/os-proto.h index ceba9b477..7be2c3fc6 100644 --- a/src/lib/krb5/os/os-proto.h +++ b/src/lib/krb5/os/os-proto.h @@ -32,11 +32,7 @@ #ifdef SOCK_DGRAM /* XXX hack... */ krb5_error_code krb5_locate_kdc - PROTOTYPE((krb5_context, - const krb5_data *, - struct sockaddr ***, - int *, - int)); + PROTOTYPE((krb5_context, const krb5_data *, struct addrlist *, int)); #endif #ifdef HAVE_NETINET_IN_H diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c index 486066b56..45e6d00b3 100644 --- a/src/lib/krb5/os/sendto_kdc.c +++ b/src/lib/krb5/os/sendto_kdc.c @@ -62,37 +62,36 @@ krb5_sendto_kdc (context, message, realm, reply, use_master) krb5_data * reply; int use_master; { - register int timeout, host, i; - struct sockaddr **addr; - int naddr; + int timeout, host, i; int sent, nready; krb5_error_code retval; SOCKET *socklist; fd_set readable; struct timeval waitlen; int cc; + struct addrlist addrs; /* * find KDC location(s) for realm */ - if ((retval = krb5_locate_kdc(context, realm, &addr, &naddr, use_master))) + if ((retval = krb5_locate_kdc(context, realm, &addrs, use_master))) return retval; - if (naddr == 0) + if (addrs.naddrs == 0) return (use_master ? KRB5_KDC_UNREACH : KRB5_REALM_UNKNOWN); - socklist = (SOCKET *)malloc(naddr * sizeof(SOCKET)); + socklist = (SOCKET *)malloc(addrs.naddrs * sizeof(SOCKET)); if (socklist == NULL) { - krb5_xfree(addr); + krb5int_free_addrlist (&addrs); return ENOMEM; } - for (i = 0; i < naddr; i++) + for (i = 0; i < addrs.naddrs; i++) socklist[i] = INVALID_SOCKET; if (!(reply->data = malloc(krb5_max_dgram_size))) { - for (i = 0; i < naddr; i++) - krb5_xfree (addr[i]); - krb5_xfree(addr); + for (i = 0; i < addrs.naddrs; i++) + krb5_xfree (addrs.addrs[i]); + krb5int_free_addrlist (&addrs); krb5_xfree(socklist); return ENOMEM; } @@ -106,7 +105,7 @@ krb5_sendto_kdc (context, message, realm, reply, use_master) * See below for commented out SOCKET_CLEANUP() */ if (SOCKET_INITIALIZE()) { /* PC needs this for some tcp/ip stacks */ - krb5_xfree(addr); + krb5int_free_addrlist (&addrs); krb5_xfree(socklist); free(reply->data); return SOCKET_ERRNO; @@ -120,7 +119,7 @@ krb5_sendto_kdc (context, message, realm, reply, use_master) for (timeout = krb5_skdc_timeout_1; timeout < krb5_max_skdc_timeout; timeout <<= krb5_skdc_timeout_shift) { sent = 0; - for (host = 0; host < naddr; host++) { + for (host = 0; host < addrs.naddrs; host++) { /* send to the host, wait timeout seconds for a response, then move on. */ /* cache some sockets for each host */ @@ -135,7 +134,8 @@ krb5_sendto_kdc (context, message, realm, reply, use_master) * protocol exists to support a particular socket type * within a given protocol family. */ - socklist[host] = socket(addr[host]->sa_family, SOCK_DGRAM, 0); + socklist[host] = socket(addrs.addrs[host]->sa_family, + SOCK_DGRAM, 0); if (socklist[host] == INVALID_SOCKET) continue; /* try other hosts */ /* have a socket to send/recv from */ @@ -145,7 +145,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], - addr[host], socklen(addr[host])) == SOCKET_ERROR) + addrs.addrs[host], socklen(addrs.addrs[host])) == SOCKET_ERROR) continue; } if (send(socklist[host], @@ -214,13 +214,13 @@ krb5_sendto_kdc (context, message, realm, reply, use_master) } retval = KRB5_KDC_UNREACH; out: - for (i = 0; i < naddr; i++) + for (i = 0; i < addrs.naddrs; i++) if (socklist[i] != INVALID_SOCKET) (void) closesocket (socklist[i]); #if 0 SOCKET_CLEANUP(); /* Done with sockets for now */ #endif - krb5_xfree(addr); + krb5int_free_addrlist (&addrs); krb5_xfree(socklist); if (retval) { free(reply->data); -- 2.26.2