4e3c008
Patch from MITKRB5-SA-2008-001.
4e3c008
Index: src/kdc/dispatch.c
4e3c008
===================================================================
4e3c008
--- src/kdc/dispatch.c	(revision 20192)
4e3c008
+++ src/kdc/dispatch.c	(working copy)
4e3c008
@@ -1,7 +1,7 @@
4e3c008
 /*
4e3c008
  * kdc/dispatch.c
4e3c008
  *
4e3c008
- * Copyright 1990 by the Massachusetts Institute of Technology.
4e3c008
+ * Copyright 1990, 2007 by the Massachusetts Institute of Technology.
4e3c008
  *
4e3c008
  * Export of this software from the United States of America may
4e3c008
  *   require a specific license from the United States Government.
4e3c008
@@ -107,7 +107,7 @@
4e3c008
 	retval = KRB5KRB_AP_ERR_MSG_TYPE;
4e3c008
 #ifndef NOCACHE
4e3c008
     /* put the response into the lookaside buffer */
4e3c008
-    if (!retval)
4e3c008
+    if (!retval && *response != NULL)
4e3c008
 	kdc_insert_lookaside(pkt, *response);
4e3c008
 #endif
4e3c008
 
4e3c008
Index: src/kdc/kerberos_v4.c
4e3c008
===================================================================
4e3c008
--- src/kdc/kerberos_v4.c	(revision 20192)
4e3c008
+++ src/kdc/kerberos_v4.c	(working copy)
4e3c008
@@ -1,7 +1,7 @@
4e3c008
 /*
4e3c008
  * kdc/kerberos_v4.c
4e3c008
  *
4e3c008
- * Copyright 1985, 1986, 1987, 1988,1991 by the Massachusetts Institute
4e3c008
+ * Copyright 1985, 1986, 1987, 1988,1991,2007 by the Massachusetts Institute
4e3c008
  * of Technology.
4e3c008
  * All Rights Reserved.
4e3c008
  *
4e3c008
@@ -87,11 +87,6 @@
4e3c008
 #define		MSB_FIRST		0	/* 68000, IBM RT/PC */
4e3c008
 #define		LSB_FIRST		1	/* Vax, PC8086 */
4e3c008
 
4e3c008
-int     f;
4e3c008
-
4e3c008
-/* XXX several files in libkdb know about this */
4e3c008
-char *progname;
4e3c008
-
4e3c008
 #ifndef BACKWARD_COMPAT
4e3c008
 static Key_schedule master_key_schedule;
4e3c008
 static C_Block master_key;
4e3c008
@@ -143,10 +138,8 @@
4e3c008
 #include "com_err.h"
4e3c008
 #include "extern.h"		/* to pick up master_princ */
4e3c008
 
4e3c008
-static krb5_data *response;
4e3c008
-
4e3c008
-void kerberos_v4 (struct sockaddr_in *, KTEXT);
4e3c008
-void kerb_err_reply (struct sockaddr_in *, KTEXT, long, char *);
4e3c008
+static krb5_data *kerberos_v4 (struct sockaddr_in *, KTEXT);
4e3c008
+static krb5_data *kerb_err_reply (struct sockaddr_in *, KTEXT, long, char *);
4e3c008
 static int set_tgtkey (char *, krb5_kvno, krb5_boolean);
4e3c008
 
4e3c008
 /* Attributes converted from V5 to V4 - internal representation */
4e3c008
@@ -262,12 +255,12 @@
4e3c008
 	    (void) klog(L_KRB_PERR, "V4 request too long.");
4e3c008
 	    return KRB5KRB_ERR_FIELD_TOOLONG;
4e3c008
     }
4e3c008
+    memset( &v4_pkt, 0, sizeof(v4_pkt));
4e3c008
     v4_pkt.length = pkt->length;
4e3c008
     v4_pkt.mbz = 0;
4e3c008
     memcpy( v4_pkt.dat, pkt->data, pkt->length);
4e3c008
 
4e3c008
-    kerberos_v4( &client_sockaddr, &v4_pkt);
4e3c008
-    *resp = response;
4e3c008
+    *resp = kerberos_v4( &client_sockaddr, &v4_pkt);
4e3c008
     return(retval);
4e3c008
 }
4e3c008
 
4e3c008
@@ -300,19 +293,20 @@
4e3c008
 }
4e3c008
 
4e3c008
 static
4e3c008
-int krb4_sendto(int s, const char *msg, int len, int flags,
4e3c008
-		const struct sockaddr *to, int to_len)
4e3c008
+krb5_data *make_response(const char *msg, int len)
4e3c008
 {
4e3c008
+    krb5_data *response;
4e3c008
+
4e3c008
     if (  !(response = (krb5_data *) malloc( sizeof *response))) {
4e3c008
-	return ENOMEM;
4e3c008
+	return 0;
4e3c008
     }
4e3c008
     if ( !(response->data = (char *) malloc( len))) {
4e3c008
 	krb5_free_data(kdc_context,  response);
4e3c008
-	return ENOMEM;
4e3c008
+	return 0;
4e3c008
     }
4e3c008
     response->length = len;
4e3c008
     memcpy( response->data, msg, len);
4e3c008
-    return( 0);
4e3c008
+    return response;
4e3c008
 }
4e3c008
 static void
4e3c008
 hang(void)
4e3c008
@@ -586,7 +580,7 @@
4e3c008
 	*cp = 0;
4e3c008
 }
4e3c008
 
4e3c008
-void
4e3c008
+static krb5_data *
4e3c008
 kerberos_v4(struct sockaddr_in *client, KTEXT pkt)
4e3c008
 {
4e3c008
     static KTEXT_ST rpkt_st;
4e3c008
@@ -599,8 +593,8 @@
4e3c008
     KTEXT   auth = &auth_st;
4e3c008
     AUTH_DAT ad_st;
4e3c008
     AUTH_DAT *ad = &ad_st;
4e3c008
+    krb5_data *response = 0;
4e3c008
 
4e3c008
-
4e3c008
     static struct in_addr client_host;
4e3c008
     static int msg_byte_order;
4e3c008
     static int swap_bytes;
4e3c008
@@ -637,8 +631,7 @@
4e3c008
 		  inet_ntoa(client_host));
4e3c008
 	/* send an error reply */
4e3c008
 	req_name_ptr = req_inst_ptr = req_realm_ptr = "";
4e3c008
-	kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
4e3c008
-	return;
4e3c008
+	return kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
4e3c008
     }
4e3c008
 
4e3c008
     /* check packet version */
4e3c008
@@ -648,8 +641,7 @@
4e3c008
 		  KRB_PROT_VERSION, req_version, 0);
4e3c008
 	/* send an error reply */
4e3c008
 	req_name_ptr = req_inst_ptr = req_realm_ptr = "";
4e3c008
-	kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
4e3c008
-	return;
4e3c008
+	return kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
4e3c008
     }
4e3c008
     msg_byte_order = req_msg_type & 1;
4e3c008
 
4e3c008
@@ -707,10 +699,10 @@
4e3c008
 
4e3c008
 	    if ((i = check_princ(req_name_ptr, req_inst_ptr, 0,
4e3c008
 				 &a_name_data, &k5key, 0, &ck5life))) {
4e3c008
-		kerb_err_reply(client, pkt, i, "check_princ failed");
4e3c008
+		response = kerb_err_reply(client, pkt, i, "check_princ failed");
4e3c008
 		a_name_data.key_low = a_name_data.key_high = 0;
4e3c008
 		krb5_free_keyblock_contents(kdc_context, &k5key);
4e3c008
-		return;
4e3c008
+		return response;
4e3c008
 	    }
4e3c008
 	    /* don't use k5key for client */
4e3c008
 	    krb5_free_keyblock_contents(kdc_context, &k5key);
4e3c008
@@ -722,11 +714,11 @@
4e3c008
 	    /* this does all the checking */
4e3c008
 	    if ((i = check_princ(service, instance, lifetime,
4e3c008
 				 &s_name_data, &k5key, 1, &sk5life))) {
4e3c008
-		kerb_err_reply(client, pkt, i, "check_princ failed");
4e3c008
+		response = kerb_err_reply(client, pkt, i, "check_princ failed");
4e3c008
 		a_name_data.key_high = a_name_data.key_low = 0;
4e3c008
 		s_name_data.key_high = s_name_data.key_low = 0;
4e3c008
 		krb5_free_keyblock_contents(kdc_context, &k5key);
4e3c008
-		return;
4e3c008
+		return response;
4e3c008
 	    }
4e3c008
 	    /* Bound requested lifetime with service and user */
4e3c008
 	    v4req_end = krb_life_to_time(kerb_time.tv_sec, req_life);
4e3c008
@@ -797,8 +789,7 @@
4e3c008
 	    rpkt = create_auth_reply(req_name_ptr, req_inst_ptr,
4e3c008
 		req_realm_ptr, req_time_ws, 0, a_name_data.exp_date,
4e3c008
 		a_name_data.key_version, ciph);
4e3c008
-	    krb4_sendto(f, (char *) rpkt->dat, rpkt->length, 0,
4e3c008
-		   (struct sockaddr *) client, sizeof (struct sockaddr_in));
4e3c008
+	    response = make_response((char *) rpkt->dat, rpkt->length);
4e3c008
 	    memset(&a_name_data, 0, sizeof(a_name_data));
4e3c008
 	    memset(&s_name_data, 0, sizeof(s_name_data));
4e3c008
 	    break;
4e3c008
@@ -824,9 +815,8 @@
4e3c008
 		lt = klog(L_KRB_PERR,
4e3c008
 			  "APPL request with realm length too long from %s",
4e3c008
 			  inet_ntoa(client_host));
4e3c008
-		kerb_err_reply(client, pkt, RD_AP_INCON,
4e3c008
-			       "realm length too long");
4e3c008
-		return;
4e3c008
+		return kerb_err_reply(client, pkt, RD_AP_INCON,
4e3c008
+				      "realm length too long");
4e3c008
 	    }
4e3c008
 
4e3c008
 	    auth->length += (int) *(pkt->dat + auth->length) +
4e3c008
@@ -835,9 +825,8 @@
4e3c008
 		lt = klog(L_KRB_PERR,
4e3c008
 			  "APPL request with funky tkt or req_id length from %s",
4e3c008
 			  inet_ntoa(client_host));
4e3c008
-		kerb_err_reply(client, pkt, RD_AP_INCON,
4e3c008
-			       "funky tkt or req_id length");
4e3c008
-		return;
4e3c008
+		return kerb_err_reply(client, pkt, RD_AP_INCON,
4e3c008
+				      "funky tkt or req_id length");
4e3c008
 	    }
4e3c008
 
4e3c008
 	    memcpy(auth->dat, pkt->dat, auth->length);
4e3c008
@@ -848,18 +837,16 @@
4e3c008
 	    if ((!allow_v4_crossrealm)&&strcmp(tktrlm, local_realm) != 0) {
4e3c008
 	      lt = klog(L_ERR_UNK,
4e3c008
 			"Cross realm ticket from %s denied by policy,", tktrlm);
4e3c008
-	      kerb_err_reply(client, pkt,
4e3c008
-			       KERB_ERR_PRINCIPAL_UNKNOWN, lt);
4e3c008
-		return;
4e3c008
+	      return kerb_err_reply(client, pkt,
4e3c008
+				    KERB_ERR_PRINCIPAL_UNKNOWN, lt);
4e3c008
 	    }
4e3c008
 	    if (set_tgtkey(tktrlm, kvno, 0)) {
4e3c008
-	      lt = klog(L_ERR_UNK,
4e3c008
+		lt = klog(L_ERR_UNK,
4e3c008
 			  "FAILED set_tgtkey realm %s, kvno %d. Host: %s ",
4e3c008
 			  tktrlm, kvno, inet_ntoa(client_host));
4e3c008
 		/* no better error code */
4e3c008
-		kerb_err_reply(client, pkt,
4e3c008
-			       KERB_ERR_PRINCIPAL_UNKNOWN, lt);
4e3c008
-		return;
4e3c008
+		return kerb_err_reply(client, pkt,
4e3c008
+				      KERB_ERR_PRINCIPAL_UNKNOWN, lt);
4e3c008
 	    }
4e3c008
 	    kerno = krb_rd_req(auth, "krbtgt", tktrlm, client_host.s_addr,
4e3c008
 		ad, 0);
4e3c008
@@ -869,9 +856,8 @@
4e3c008
 			      "FAILED 3des set_tgtkey realm %s, kvno %d. Host: %s ",
4e3c008
 			      tktrlm, kvno, inet_ntoa(client_host));
4e3c008
 		    /* no better error code */
4e3c008
-		    kerb_err_reply(client, pkt,
4e3c008
-				   KERB_ERR_PRINCIPAL_UNKNOWN, lt);
4e3c008
-		    return;
4e3c008
+		    return kerb_err_reply(client, pkt,
4e3c008
+					  KERB_ERR_PRINCIPAL_UNKNOWN, lt);
4e3c008
 		}
4e3c008
 		kerno = krb_rd_req(auth, "krbtgt", tktrlm, client_host.s_addr,
4e3c008
 				   ad, 0);
4e3c008
@@ -881,8 +867,7 @@
4e3c008
 		klog(L_ERR_UNK, "FAILED krb_rd_req from %s: %s",
4e3c008
 		     inet_ntoa(client_host), krb_get_err_text(kerno));
4e3c008
 		req_name_ptr = req_inst_ptr = req_realm_ptr = "";
4e3c008
-		kerb_err_reply(client, pkt, kerno, "krb_rd_req failed");
4e3c008
-		return;
4e3c008
+		return kerb_err_reply(client, pkt, kerno, "krb_rd_req failed");
4e3c008
 	    }
4e3c008
 	    ptr = (char *) pkt->dat + auth->length;
4e3c008
 
4e3c008
@@ -904,22 +889,21 @@
4e3c008
 	    req_realm_ptr = ad->prealm;
4e3c008
 
4e3c008
 	    if (strcmp(ad->prealm, tktrlm)) {
4e3c008
-		kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
4e3c008
-		     "Can't hop realms");
4e3c008
-		return;
4e3c008
+		return kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
4e3c008
+				      "Can't hop realms");
4e3c008
 	    }
4e3c008
 	    if (!strcmp(service, "changepw")) {
4e3c008
-		kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
4e3c008
-		     "Can't authorize password changed based on TGT");
4e3c008
-		return;
4e3c008
+		return kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
4e3c008
+				      "Can't authorize password changed based on TGT");
4e3c008
 	    }
4e3c008
 	    kerno = check_princ(service, instance, req_life,
4e3c008
 				&s_name_data, &k5key, 1, &sk5life);
4e3c008
 	    if (kerno) {
4e3c008
-		kerb_err_reply(client, pkt, kerno, "check_princ failed");
4e3c008
+		response = kerb_err_reply(client, pkt, kerno,
4e3c008
+					  "check_princ failed");
4e3c008
 		s_name_data.key_high = s_name_data.key_low = 0;
4e3c008
 		krb5_free_keyblock_contents(kdc_context, &k5key);
4e3c008
-		return;
4e3c008
+		return response;
4e3c008
 	    }
4e3c008
 	    /* Bound requested lifetime with service and user */
4e3c008
 	    v4endtime = krb_life_to_time((KRB4_32)ad->time_sec, ad->life);
4e3c008
@@ -975,8 +959,7 @@
4e3c008
 	    rpkt = create_auth_reply(ad->pname, ad->pinst,
4e3c008
 				     ad->prealm, time_ws,
4e3c008
 				     0, 0, 0, ciph);
4e3c008
-	    krb4_sendto(f, (char *) rpkt->dat, rpkt->length, 0,
4e3c008
-		   (struct sockaddr *) client, sizeof (struct sockaddr_in));
4e3c008
+	    response = make_response((char *) rpkt->dat, rpkt->length);
4e3c008
 	    memset(&s_name_data, 0, sizeof(s_name_data));
4e3c008
 	    break;
4e3c008
 	}
4e3c008
@@ -1001,6 +984,7 @@
4e3c008
 	    break;
4e3c008
 	}
4e3c008
     }
4e3c008
+    return response;
4e3c008
 }
4e3c008
 
4e3c008
 
4e3c008
@@ -1010,7 +994,7 @@
4e3c008
  * client. 
4e3c008
  */
4e3c008
 
4e3c008
-void
4e3c008
+static krb5_data *
4e3c008
 kerb_err_reply(struct sockaddr_in *client, KTEXT pkt, long int err, char *string)
4e3c008
 {
4e3c008
     static KTEXT_ST e_pkt_st;
4e3c008
@@ -1021,9 +1005,7 @@
4e3c008
     strncat(e_msg, string, sizeof(e_msg) - 1 - 19);
4e3c008
     cr_err_reply(e_pkt, req_name_ptr, req_inst_ptr, req_realm_ptr,
4e3c008
 		 req_time_ws, err, e_msg);
4e3c008
-    krb4_sendto(f, (char *) e_pkt->dat, e_pkt->length, 0,
4e3c008
-	   (struct sockaddr *) client, sizeof (struct sockaddr_in));
4e3c008
-
4e3c008
+    return make_response((char *) e_pkt->dat, e_pkt->length);
4e3c008
 }
4e3c008
 
4e3c008
 static int
4e3c008
Index: src/kdc/network.c
4e3c008
===================================================================
4e3c008
--- src/kdc/network.c	(revision 20192)
4e3c008
+++ src/kdc/network.c	(working copy)
4e3c008
@@ -1,7 +1,7 @@
4e3c008
 /*
4e3c008
  * kdc/network.c
4e3c008
  *
4e3c008
- * Copyright 1990,2000 by the Massachusetts Institute of Technology.
4e3c008
+ * Copyright 1990,2000,2007 by the Massachusetts Institute of Technology.
4e3c008
  *
4e3c008
  * Export of this software from the United States of America may
4e3c008
  *   require a specific license from the United States Government.
4e3c008
@@ -747,6 +747,8 @@
4e3c008
 	com_err(prog, retval, "while dispatching (udp)");
4e3c008
 	return;
4e3c008
     }
4e3c008
+    if (response == NULL)
4e3c008
+	return;
4e3c008
     cc = sendto(port_fd, response->data, (socklen_t) response->length, 0,
4e3c008
 		(struct sockaddr *)&saddr, saddr_len);
4e3c008
     if (cc == -1) {
4e3c008