+2001-06-19 Ken Raeburn <raeburn@mit.edu>
+
+ * 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 <epeisach@mit.edu>
* k5-util.h: Add prototypes for krb5_compat_recvauth_version() and
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 */
/* 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;
+2001-06-19 Ken Raeburn <raeburn@mit.edu>
+
+ * sendmsg.c (krb524_sendto_kdc): Use new locate_server interface.
+
2001-06-06 Ezra Peisach <epeisach@mit.edu>
* test.c (print_key): Pass in des_cblock* instead of char *.
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;
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;
}
* 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 */
* 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 */
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;
}
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);
+2001-06-19 Ken Raeburn <raeburn@mit.edu>
+
+ * 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 <epeisach@mit.edu>
* sn2princ.c, hst_realm.c, an_to_ln.c: Cast argument to
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;
*/
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;i<addrlist->naddrs;i++ ) {
+ struct sockaddr *a = addrlist->addrs[i];
if (a->sa_family == AF_INET)
sa2sin (a)->sin_port = htons(DEFAULT_KPASSWD_PORT);
}
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));
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
goto cleanup;
}
- for (i=0; i<naddr_p; i++) {
+ /*
+ * This really should try fallback addresses in cases of timeouts.
+ * For now, where the MIT KDC implementation only supports one
+ * kpasswd server machine anyways, we'll only try the first IPv4
+ * address we can connect() to. This isn't right for multi-homed
+ * servers; oh well.
+ */
+ for (i=0; i<al.naddrs; i++) {
fd_set fdset;
struct timeval timeout;
/* XXX Now the locate_ functions can return IPv6 addresses. */
- if (addr_p[i]->sa_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 */
}
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)))
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);
}
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);
#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)
{
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++)
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,
#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
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 */
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,
krb5_error_code code;
struct addrlist al = ADDRLIST_INIT;
+ *addrlist = al;
+
/*
* We always try the local file first
*/
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;
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"),
#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
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;
}
* 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;
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 */
* 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 */
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],
}
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);