Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > e16d0c94ff2c9e93ba4eea60f7b68478 > files > 89

krb5-1.6.1-70.el5_9.2.src.rpm

Backport most of the changes that were made between 1.6.2 and 1.6.3 to
add a message-handler callback to the sendto() routines, and to use one
for KDC access attempts which will cause us to not abort when we see a
service-unavailable error.

Index: src/include/k5-int.h
===================================================================
--- src/include/k5-int.h	(.../krb5-1-6-2-final)	(revision 20213)
+++ src/include/k5-int.h	(.../krb5-1-6-3-final)	(revision 20213)
@@ -216,6 +216,10 @@
 					   /* required */
 #define KDC_ERR_SERVER_NOMATCH		26 /* Requested server and */
 					   /* ticket don't match*/
+#define KDC_ERR_SVC_UNAVAILABLE		29 /* A service is not
+					    * available that is
+					    * required to process the
+					    * request */
 /* Application errors */
 #define	KRB_AP_ERR_BAD_INTEGRITY 31	/* Decrypt integrity check failed */
 #define	KRB_AP_ERR_TKT_EXPIRED	32	/* Ticket expired */
@@ -498,7 +502,9 @@
 krb5_error_code krb5int_sendto (krb5_context context, const krb5_data *message,
                 const struct addrlist *addrs, struct sendto_callback_info* callback_info,
 				krb5_data *reply, struct sockaddr *localaddr, socklen_t *localaddrlen,
-                struct sockaddr *remoteaddr, socklen_t *remoteaddrlen, int *addr_used);
+                struct sockaddr *remoteaddr, socklen_t *remoteaddrlen, int *addr_used,
+		int (*msg_handler)(krb5_context, const krb5_data *, void *),
+		void *msg_handler_data);
 
 krb5_error_code krb5_get_krbhst (krb5_context, const krb5_data *, char *** );
 krb5_error_code krb5_free_krbhst (krb5_context, char * const * );
@@ -1885,7 +1881,9 @@
     krb5_error_code (*sendto_udp) (krb5_context, const krb5_data *msg,
 				   const struct addrlist *, struct sendto_callback_info*, krb5_data *reply,
 				   struct sockaddr *, socklen_t *,struct sockaddr *,
-				   socklen_t *, int *);
+				   socklen_t *, int *,
+				   int (*msg_handler)(krb5_context, const krb5_data *, void *),
+				   void *msg_handler_data);
     krb5_error_code (*add_host_to_list)(struct addrlist *lp,
 					const char *hostname,
 					int port, int secport,
Index: src/lib/krb4/send_to_kdc.c
===================================================================
--- src/lib/krb4/send_to_kdc.c	(.../krb5-1-6-2-final)	(revision 20213)
+++ src/lib/krb4/send_to_kdc.c	(.../krb5-1-6-3-final)	(revision 20213)
@@ -181,7 +181,7 @@
     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);
Index: src/lib/krb5/error_tables/krb5_err.et
===================================================================
--- src/lib/krb5/error_tables/krb5_err.et	(.../krb5-1-6-2-final)	(revision 20213)
+++ src/lib/krb5/error_tables/krb5_err.et	(.../krb5-1-6-3-final)	(revision 20213)
@@ -68,7 +68,7 @@
 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"
Index: src/lib/krb5/os/changepw.c
===================================================================
--- src/lib/krb5/os/changepw.c	(.../krb5-1-6-2-final)	(revision 20213)
+++ src/lib/krb5/os/changepw.c	(.../krb5-1-6-3-final)	(revision 20213)
@@ -247,6 +247,8 @@
 				   NULL,
 				   ss2sa(&remote_addr),
                                    &addrlen,
+				   NULL,
+				   NULL,
 				   NULL
 		 ))) {
 	    /* if we're not using a stream socket, and it's an error which
Index: src/lib/krb5/os/send524.c
===================================================================
--- src/lib/krb5/os/send524.c	(.../krb5-1-6-2-final)	(revision 20213)
+++ src/lib/krb5/os/send524.c	(.../krb5-1-6-3-final)	(revision 20213)
@@ -98,7 +98,7 @@
     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
Index: src/lib/krb5/os/sendto_kdc.c
===================================================================
--- src/lib/krb5/os/sendto_kdc.c	(.../krb5-1-6-2-final)	(revision 20213)
+++ src/lib/krb5/os/sendto_kdc.c	(.../krb5-1-6-3-final)	(revision 20213)
@@ -295,6 +295,30 @@
     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'.
@@ -381,9 +405,12 @@
     }
 
     if (addrs.naddrs > 0) {
+	krb5_error_code err = 0;
+
         retval = krb5int_sendto (context, message, &addrs, 0, reply, 0, 0,
-								 0, 0, &addr_used);
-        if (retval == 0) {
+				 0, 0, &addr_used, check_for_svc_unavailable, &err);
+	switch (retval) {
+	case 0:
             /*
              * Set use_master to 1 if we ended up talking to a master when
              * we didn't explicitly request to
@@ -401,7 +428,19 @@
             }
             krb5int_free_addrlist (&addrs);
             return 0;
-        }
+	default:
+	    break;
+	    /* Cases here are for constructing useful error messages.  */
+	case KRB5_KDC_UNREACH:
+	    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);
     }
     return retval;
@@ -1015,9 +1054,12 @@
 }
 
 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;
 
@@ -1056,9 +1098,22 @@
 		   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;
+		}
 	    }
 	}
     }
@@ -1098,7 +1153,10 @@
 		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;
@@ -1185,8 +1243,8 @@
 		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)
@@ -1206,7 +1264,8 @@
 	   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)