summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@mit.edu>2007-07-27 04:39:21 +0000
committerKen Raeburn <raeburn@mit.edu>2007-07-27 04:39:21 +0000
commit76fdc16a95093e399c43e8597275a5cc95ff4925 (patch)
treed6234c9d4ea2a7fe0acf2e3b4bc384176e0ac517 /src/lib
parent7cedd31c584a59626a749ea609a23c237a82b3ea (diff)
Debugged version of patch worked up with Luke
Adds a callback to krb5int_sendto to examine the response and indicate whether to quit the loop or not. For sendto_kdc, keep going if the returned error is "service unavailable". Updated all other callers to pass a null function pointer, which means to always break out of the loop on any response (the old behavior). ticket: 3334 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19738 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/krb4/send_to_kdc.c2
-rw-r--r--src/lib/krb5/error_tables/krb5_err.et4
-rw-r--r--src/lib/krb5/os/changepw.c2
-rw-r--r--src/lib/krb5/os/send524.c2
-rw-r--r--src/lib/krb5/os/sendto_kdc.c78
5 files changed, 70 insertions, 18 deletions
diff --git a/src/lib/krb4/send_to_kdc.c b/src/lib/krb4/send_to_kdc.c
index a33ad2b03..95d9d9113 100644
--- a/src/lib/krb4/send_to_kdc.c
+++ b/src/lib/krb4/send_to_kdc.c
@@ -181,7 +181,7 @@ krb4int_send_to_kdc_addr(
message.length = pkt->length;
message.data = (char *)pkt->dat; /* XXX yuck */
retval = internals.sendto_udp(NULL, &message, &al, NULL, &reply, addr,
- addrlen, NULL, 0, NULL);
+ addrlen, NULL, 0, NULL, NULL, NULL);
DEB(("sendto_udp returns %d\n", retval));
free_al:
internals.free_addrlist(&al);
diff --git a/src/lib/krb5/error_tables/krb5_err.et b/src/lib/krb5/error_tables/krb5_err.et
index 92e45ad61..e16624287 100644
--- a/src/lib/krb5/error_tables/krb5_err.et
+++ b/src/lib/krb5/error_tables/krb5_err.et
@@ -1,7 +1,7 @@
#
# lib/krb5/error_tables/krb5_err.et
#
-# Copyright 1989,1990,1991 by the Massachusetts Institute of Technology.
+# Copyright 1989,1990,1991,2007 by the Massachusetts Institute of Technology.
# All Rights Reserved.
#
# Export of this software from the United States of America may
@@ -68,7 +68,7 @@ error_code KRB5KDC_ERR_PREAUTH_REQUIRED, "Additional pre-authentication required
error_code KRB5KDC_ERR_SERVER_NOMATCH, "Requested server and ticket don't match"
error_code KRB5PLACEHOLD_27, "KRB5 error code 27"
error_code KRB5PLACEHOLD_28, "KRB5 error code 28"
-error_code KRB5PLACEHOLD_29, "KRB5 error code 29"
+error_code KRB5KDC_ERR_SVC_UNAVAILABLE, "A service is not available that is required to process the request"
error_code KRB5PLACEHOLD_30, "KRB5 error code 30"
# vv 31
error_code KRB5KRB_AP_ERR_BAD_INTEGRITY, "Decrypt integrity check failed"
diff --git a/src/lib/krb5/os/changepw.c b/src/lib/krb5/os/changepw.c
index a2bf8f0b3..816713dc4 100644
--- a/src/lib/krb5/os/changepw.c
+++ b/src/lib/krb5/os/changepw.c
@@ -247,6 +247,8 @@ krb5_change_set_password(krb5_context context, krb5_creds *creds, char *newpw,
NULL,
ss2sa(&remote_addr),
&addrlen,
+ NULL,
+ NULL,
NULL
))) {
diff --git a/src/lib/krb5/os/send524.c b/src/lib/krb5/os/send524.c
index f6e7a0b56..1792b4930 100644
--- a/src/lib/krb5/os/send524.c
+++ b/src/lib/krb5/os/send524.c
@@ -98,7 +98,7 @@ krb5int_524_sendto_kdc (context, message, realm, reply, addr, addrlen)
if (al.naddrs == 0)
return KRB5_REALM_UNKNOWN;
- retval = krb5int_sendto (context, message, &al, NULL, reply, addr, addrlen, NULL, 0, NULL);
+ retval = krb5int_sendto (context, message, &al, NULL, reply, addr, addrlen, NULL, 0, NULL, NULL, NULL);
krb5int_free_addrlist (&al);
return retval;
#else
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
index 3be46de9f..0c63b22ec 100644
--- a/src/lib/krb5/os/sendto_kdc.c
+++ b/src/lib/krb5/os/sendto_kdc.c
@@ -1,7 +1,7 @@
/*
* lib/krb5/os/sendto_kdc.c
*
- * Copyright 1990,1991,2001,2002,2004,2005 by the Massachusetts Institute of Technology.
+ * Copyright 1990,1991,2001,2002,2004,2005,2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
@@ -312,6 +312,30 @@ in_addrlist (struct addrinfo *thisaddr, struct addrlist *list)
return 0;
}
+static int
+check_for_svc_unavailable (krb5_context context,
+ const krb5_data *reply,
+ void *msg_handler_data)
+{
+ krb5_error_code *retval = (krb5_error_code *)msg_handler_data;
+
+ *retval = 0;
+
+ if (krb5_is_krb_error(reply)) {
+ krb5_error *err_reply;
+
+ if (decode_krb5_error(reply, &err_reply) == 0) {
+ *retval = err_reply->error;
+ krb5_free_error(context, err_reply);
+
+ /* Returning 0 means continue to next KDC */
+ return (*retval != KDC_ERR_SVC_UNAVAILABLE);
+ }
+ }
+
+ return 1;
+}
+
/*
* send the formatted request 'message' to a KDC for realm 'realm' and
* return the response (if any) in 'reply'.
@@ -398,8 +422,10 @@ krb5_sendto_kdc (krb5_context context, const krb5_data *message,
}
if (addrs.naddrs > 0) {
+ krb5_error_code err = 0;
+
retval = krb5int_sendto (context, message, &addrs, 0, reply, 0, 0,
- 0, 0, &addr_used);
+ 0, 0, &addr_used, check_for_svc_unavailable, &err);
switch (retval) {
case 0:
/*
@@ -423,9 +449,13 @@ krb5_sendto_kdc (krb5_context context, const krb5_data *message,
break;
/* Cases here are for constructing useful error messages. */
case KRB5_KDC_UNREACH:
- krb5_set_error_message(context, retval,
- "Cannot contact any KDC for realm '%.*s'",
- realm->length, realm->data);
+ if (err == KDC_ERR_SVC_UNAVAILABLE) {
+ retval = KRB5KDC_ERR_SVC_UNAVAILABLE;
+ } else {
+ krb5_set_error_message(context, retval,
+ "Cannot contact any KDC for realm '%.*s'",
+ realm->length, realm->data);
+ }
break;
}
krb5int_free_addrlist (&addrs);
@@ -1041,9 +1071,12 @@ service_udp_fd(struct conn_state *conn, struct select_state *selstate,
}
static int
-service_fds (struct select_state *selstate,
+service_fds (krb5_context context,
+ struct select_state *selstate,
struct conn_state *conns, size_t n_conns, int *winning_conn,
- struct select_state *seltemp)
+ struct select_state *seltemp,
+ int (*msg_handler)(krb5_context, const krb5_data *, void *),
+ void *msg_handler_data)
{
int e, selret;
@@ -1087,9 +1120,22 @@ service_fds (struct select_state *selstate,
state_strings[(int) conns[i].state]);
if (conns[i].service (&conns[i], selstate, ssflags)) {
- dprint("fd service routine says we're done\n");
- *winning_conn = i;
- return 1;
+ int stop = 1;
+
+ if (msg_handler != NULL) {
+ krb5_data reply;
+
+ reply.data = conns[i].x.in.buf;
+ reply.length = conns[i].x.in.pos - conns[i].x.in.buf;
+
+ stop = (msg_handler(context, &reply, msg_handler_data) != 0);
+ }
+
+ if (stop) {
+ dprint("fd service routine says we're done\n");
+ *winning_conn = i;
+ return 1;
+ }
}
}
}
@@ -1129,7 +1175,10 @@ krb5int_sendto (krb5_context context, const krb5_data *message,
struct sendto_callback_info* callback_info, krb5_data *reply,
struct sockaddr *localaddr, socklen_t *localaddrlen,
struct sockaddr *remoteaddr, socklen_t *remoteaddrlen,
- int *addr_used)
+ int *addr_used,
+ /* return 0 -> keep going, 1 -> quit */
+ int (*msg_handler)(krb5_context, const krb5_data *, void *),
+ void *msg_handler_data)
{
int i, pass;
int delay_this_pass = 2;
@@ -1216,8 +1265,8 @@ krb5int_sendto (krb5_context context, const krb5_data *message,
goto egress;
sel_state->end_time = now;
sel_state->end_time.tv_sec += 1;
- e = service_fds(sel_state, conns, host+1, &winning_conn,
- sel_state+1);
+ e = service_fds(context, sel_state, conns, host+1, &winning_conn,
+ sel_state+1, msg_handler, msg_handler_data);
if (e)
break;
if (pass > 0 && sel_state->nfds == 0)
@@ -1237,7 +1286,8 @@ krb5int_sendto (krb5_context context, const krb5_data *message,
call with the last one from the above loop, if the loop
actually calls select. */
sel_state->end_time.tv_sec += delay_this_pass;
- e = service_fds(sel_state, conns, host+1, &winning_conn, sel_state+1);
+ e = service_fds(context, sel_state, conns, host+1, &winning_conn,
+ sel_state+1, msg_handler, msg_handler_data);
if (e)
break;
if (sel_state->nfds == 0)