[krbdev.mit.edu #3357] Would be nice to be able to test if clients handle KRB5KDC_ERR_RESPONSE_TOO_BIG correctly.

The RT System itself via RT rt-comment at krbdev.mit.edu
Thu Jan 19 19:36:55 EST 2006


>From krb5-bugs-incoming-bounces at PCH.mit.edu  Thu Jan 19 19:36:47 2006
Received: from pch.mit.edu (PCH.MIT.EDU [18.7.21.90]) by krbdev.mit.edu (8.9.3p2) with ESMTP
	id TAA25040; Thu, 19 Jan 2006 19:36:47 -0500 (EST)
Received: from pch.mit.edu (pch.mit.edu [127.0.0.1])
	by pch.mit.edu (8.12.8p2/8.12.8) with ESMTP id k0K0aHei016281
	for <krb5-send-pr at krbdev.mit.edu>; Thu, 19 Jan 2006 19:36:17 -0500
Received: from fort-point-station.mit.edu (FORT-POINT-STATION.MIT.EDU
	[18.7.7.76])
	by pch.mit.edu (8.12.8p2/8.12.8) with ESMTP id k0K0Onei014828
	for <krb5-bugs-incoming at PCH.mit.edu>; Thu, 19 Jan 2006 19:24:49 -0500
Received: from rapier.boston.redhat.com (nat-pool-bos.redhat.com
	[66.187.230.200])
	by fort-point-station.mit.edu (8.12.4/8.9.2) with ESMTP id
	k0K0OY2W007035
	for <krb5-bugs at mit.edu>; Thu, 19 Jan 2006 19:24:34 -0500 (EST)
Received: from rapier.boston.redhat.com (localhost.localdomain [127.0.0.1])
	by rapier.boston.redhat.com (8.13.5/8.13.5) with ESMTP id
	k0K0OXUQ030636
	for <krb5-bugs at mit.edu>; Thu, 19 Jan 2006 19:24:34 -0500
Received: (from nalin at localhost)
	by rapier.boston.redhat.com (8.13.5/8.13.5/Submit) id k0K0OXN5030635;
	Thu, 19 Jan 2006 19:24:33 -0500
Date: Thu, 19 Jan 2006 19:24:33 -0500
Message-Id: <200601200024.k0K0OXN5030635 at rapier.boston.redhat.com>
To: krb5-bugs at mit.edu
Subject: Enhancement: provide a means to force a KRB5KDC_ERR_RESPONSE_TOO_BIG
	error to be returned
From: nalin at redhat.com
X-send-pr-version: 3.99
X-Spam-Score: -1.638
X-Spam-Flag: NO
X-Scanned-By: MIMEDefang 2.42
X-Mailman-Approved-At: Thu, 19 Jan 2006 19:36:16 -0500
X-BeenThere: krb5-bugs-incoming at mailman.mit.edu
X-Mailman-Version: 2.1.6
Precedence: list
Sender: krb5-bugs-incoming-bounces at PCH.mit.edu
Errors-To: krb5-bugs-incoming-bounces at PCH.mit.edu


>Submitter-Id:	net
>Originator:	Nalin Dahyabhai
>Organization:
>Confidential:	no
>Synopsis:	Would be nice to be able to test if clients handle KRB5KDC_ERR_RESPONSE_TOO_BIG correctly.
>Severity:	non-critical
>Priority:	low
>Category:	krb5-kdc
>Class:		change-request
>Release:	1.4.3
>Environment:
	
System: Linux rapier.boston.redhat.com 2.6.15-1.1826.2.10_FC5 #1 Wed Jan 11 18:12:42 EST 2006 i686 i686 i386 GNU/Linux
Architecture: i686

>Description:
	It's useful to test if clients can properly handle
	KRB_ERR_RESPONSE_TOO_BIG responses from the KDC.  The KDC wouldn't
	normally generate such replies, which is great, but it's useful to
	be able to test what would happen if it did (i.e., not on a production
	KDC, but one being used for testing).
>How-To-Repeat:
	Issue requests to the KDC, observe that you never get
	KRB_ERR_RESPONSE_TOO_BIG errors back.
>Fix:
	Add a "max_dgram_size" option in kdc.conf which can impose an arbitrary
	limit on the size of datagram replies.  Patch:

Implement a "max_dgram_size" parameter for realms, which will control when/if
the server will respond with KRB_ERR_RESPONSE_TOO_BIG errors to requests from
its clients.

Because it reads settings by using libkadm5's krb5_read_realm_params function,
its returned structure type needs to be expanded to hold this information,
which breaks the ABI.

When processing AS or TGS requests, the server needs to keep track of whether
or not the client is issuing a request over a connected socket so that it
won't issue RESPONSE_TOO_BIG errors to connected clients.

The lookaside cache also needs to take note of the distinction so that it
doesn't replay error messages to clients who've switched from using a
connectionless socket to a connected socket and are sending the same request.
Alternatively, we could switch to using different lookaside caches.

--- krb5-1.4.3/doc/definitions.texinfo	2006-01-05 15:12:12.000000000 -0500
+++ krb5-1.4.3/doc/definitions.texinfo	2006-01-05 15:12:50.000000000 -0500
@@ -97,6 +97,8 @@
 @set DefaultKDCRCache krb5kdc_rcache
 @comment KDCRCACHE
 @set DefaultRCTmpDirs /var/tmp, /usr/tmp, /var/usr/tmp, and /tmp
+ at comment MAX_DGRAM_SIZE
+ at set DefaultMaxDgramSize 4096
 
 @ignore
 the following defaults should be consistent with the numbers set in
--- krb5-1.4.3/doc/admin.texinfo	2006-01-05 15:13:04.000000000 -0500
+++ krb5-1.4.3/doc/admin.texinfo	2006-01-05 15:14:22.000000000 -0500
@@ -1264,6 +1264,14 @@
 valid ticket may be renewed in this realm.  The default value is
 @value{DefaultMaxRenewableLife}.
 
+ at itemx max_dgram_size
+(Numeric value.)  Specifies the maximum allowed size for responses to
+client requests which are received over unconnected sockets (usually,
+UDP, as opposed to TCP).  If the response to a request would be larger
+than the specified size, a KRB_ERR_RESPONSE_TOO_BIG error is sent in
+its stead.  The default value is
+ at value{DefaultMaxDgramSize}.
+
 @itemx supported_enctypes
 List of key:salt strings.  Specifies the default key/salt combinations of
 principals for this realm.  Any principals created through @code{kadmin}
--- krb5-1.4.3/src/lib/kadm5/srv/Makefile.in	2004-06-16 21:56:34.000000000 -0400
+++ krb5-1.4.3/src/lib/kadm5/srv/Makefile.in	2006-01-05 15:08:23.000000000 -0500
@@ -9,8 +9,8 @@
 ##DOSLIBNAME = libkadm5srv.lib
 
 LIBBASE=kadm5srv
-LIBMAJOR=5
-LIBMINOR=1
+LIBMAJOR=6
+LIBMINOR=0
 STOBJLISTS=../OBJS.ST OBJS.ST
 
 SHLIB_EXPDEPS=\
--- krb5-1.4.3/src/lib/kadm5/clnt/Makefile.in	2004-06-16 16:18:10.000000000 -0400
+++ krb5-1.4.3/src/lib/kadm5/clnt/Makefile.in	2006-01-05 15:08:23.000000000 -0500
@@ -5,8 +5,8 @@
 LOCALINCLUDES = -I$(BUILDTOP)/include/kadm5
 
 LIBBASE=kadm5clnt
-LIBMAJOR=5
-LIBMINOR=1
+LIBMAJOR=6
+LIBMINOR=0
 STOBJLISTS=../OBJS.ST OBJS.ST
 SHLIB_EXPDEPS=\
 	$(TOPLIBD)/libgssrpc$(SHLIBEXT) \
--- krb5-1.4.3/src/lib/kadm5/alt_prof.c	2004-06-24 16:08:30.000000000 -0400
+++ krb5-1.4.3/src/lib/kadm5/alt_prof.c	2006-01-05 15:08:23.000000000 -0500
@@ -936,6 +936,13 @@
 	krb5_xfree(svalue);
     }
 
+    /* Get the value for the maximum datagram response size */
+    hierarchy[2] = "max_dgram_size";
+    if (!krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue)) {
+	rparams->realm_max_dgram_size = ivalue;
+	rparams->realm_max_dgram_size_valid = 1;
+    }
+	    
     hierarchy[2] = "reject_bad_transit";
     if (!krb5_aprof_get_boolean(aprofile, hierarchy, TRUE, &bvalue)) {
 	rparams->realm_reject_bad_transit = bvalue;
--- krb5-1.4.3/src/kdc/extern.h	2003-06-03 00:32:41.000000000 -0400
+++ krb5-1.4.3/src/kdc/extern.h	2006-01-05 15:08:23.000000000 -0500
@@ -64,6 +64,7 @@
     krb5_deltat		realm_maxlife;	/* Maximum ticket life for realm    */
     krb5_deltat		realm_maxrlife;	/* Maximum renewable life for realm */
     krb5_boolean	realm_reject_bad_transit; /* Accept unverifiable transited_realm ? */
+    int			realm_max_dgram_size; /* Maximum datagram response size */
 } kdc_realm_t;
 
 extern kdc_realm_t	**kdc_realmlist;
@@ -87,6 +88,7 @@
 #define	dbm_db_name			kdc_active_realm->realm_dbname
 #define	primary_port			kdc_active_realm->realm_pport
 #define reject_bad_transit		kdc_active_realm->realm_reject_bad_transit
+#define max_dgram_size			kdc_active_realm->realm_max_dgram_size
 
 /* various externs for KDC */
 extern krb5_data 	empty_string;	/* an empty string */
--- krb5-1.4.3/src/lib/kadm5/admin.h	2005-03-22 18:53:59.000000000 -0500
+++ krb5-1.4.3/src/lib/kadm5/admin.h	2006-01-05 15:08:23.000000000 -0500
@@ -263,6 +263,7 @@
     krb5_deltat		realm_max_rlife;
     krb5_timestamp	realm_expiration;
     krb5_flags		realm_flags;
+    int			realm_max_dgram_size;
     krb5_key_salt_tuple	*realm_keysalts;
     unsigned int	realm_reject_bad_transit:1;
     unsigned int	realm_kadmind_port_valid:1;
@@ -272,6 +273,7 @@
     unsigned int	realm_expiration_valid:1;
     unsigned int	realm_flags_valid:1;
     unsigned int	realm_reject_bad_transit_valid:1;
+    unsigned int	realm_max_dgram_size_valid:1;
     krb5_int32		realm_num_keysalts;
 } krb5_realm_params;
 
--- krb5-1.4.3/src/kdc/do_as_req.c	2005-07-12 16:59:52.000000000 -0400
+++ krb5-1.4.3/src/kdc/do_as_req.c	2006-01-05 15:08:23.000000000 -0500
@@ -52,7 +52,7 @@
 /*ARGSUSED*/
 krb5_error_code
 process_as_req(krb5_kdc_req *request, const krb5_fulladdr *from,
-	       krb5_data **response)
+	       krb5_boolean connected, krb5_data **response)
 {
     krb5_db_entry client, server;
     krb5_kdc_rep reply;
@@ -403,6 +403,13 @@
 	status = "ENCODE_KDC_REP";
 	goto errout;
     }
+
+    if (!connected && ((*response)->length > max_dgram_size)) {
+	errcode = KRB5KRB_ERR_RESPONSE_TOO_BIG;
+	krb5_free_data(kdc_context, *response);
+	*response = NULL;
+	goto errout;
+    }
     
     /* these parts are left on as a courtesy from krb5_encode_kdc_rep so we
        can use them in raw form if needed.  But, we don't... */
--- krb5-1.4.3/src/kdc/dispatch.c	2002-09-10 23:59:27.000000000 -0400
+++ krb5-1.4.3/src/kdc/dispatch.c	2006-01-05 15:08:23.000000000 -0500
@@ -39,7 +39,8 @@
 static krb5_int32 last_usec = 0, last_os_random = 0;
 
 krb5_error_code
-dispatch(krb5_data *pkt, const krb5_fulladdr *from, krb5_data **response)
+dispatch(krb5_data *pkt, const krb5_fulladdr *from, krb5_boolean connected,
+	 krb5_data **response)
 {
 
     krb5_error_code retval;
@@ -50,7 +51,7 @@
 
 #ifndef NOCACHE
     /* try the replay lookaside buffer */
-    if (kdc_check_lookaside(pkt, from, response)) {
+    if (kdc_check_lookaside(pkt, from, connected, response)) {
 	/* a hit! */
 	const char *name = 0;
 	char buf[46];
@@ -87,7 +88,7 @@
     /* try TGS_REQ first; they are more common! */
 
     if (krb5_is_tgs_req(pkt)) {
-	retval = process_tgs_req(pkt, from, response);
+	retval = process_tgs_req(pkt, from, connected, response);
     } else if (krb5_is_as_req(pkt)) {
 	if (!(retval = decode_krb5_as_req(pkt, &as_req))) {
 	    /*
@@ -95,7 +96,7 @@
 	     * pointer.
 	     */
 	    if (!(retval = setup_server_realm(as_req->server))) {
-		retval = process_as_req(as_req, from, response);
+		retval = process_as_req(as_req, from, connected, response);
 	    }
 	    krb5_free_kdc_req(kdc_context, as_req);
 	}
@@ -109,7 +110,7 @@
 #ifndef NOCACHE
     /* put the response into the lookaside buffer */
     if (!retval)
-	kdc_insert_lookaside(pkt, from, *response);
+	kdc_insert_lookaside(pkt, from, connected, *response);
 #endif
 
     return retval;
--- krb5-1.4.3/src/kdc/network.c	2005-07-12 16:59:52.000000000 -0400
+++ krb5-1.4.3/src/kdc/network.c	2006-01-05 15:08:23.000000000 -0500
@@ -744,7 +744,7 @@
     faddr.address = &addr;
     init_addr(&faddr, ss2sa(&saddr));
     /* this address is in net order */
-    if ((retval = dispatch(&request, &faddr, &response))) {
+    if ((retval = dispatch(&request, &faddr, FALSE, &response))) {
 	com_err(prog, retval, "while dispatching (udp)");
 	return;
     }
@@ -982,7 +982,7 @@
 	    /* have a complete message, and exactly one message */
 	    request.length = conn->u.tcp.msglen;
 	    request.data = conn->u.tcp.buffer + 4;
-	    err = dispatch(&request, &conn->u.tcp.faddr,
+	    err = dispatch(&request, &conn->u.tcp.faddr, TRUE,
 			   &conn->u.tcp.response);
 	    if (err) {
 		com_err(prog, err, "while dispatching (tcp)");
--- krb5-1.4.3/src/kdc/kdc_util.h	2004-09-23 22:19:42.000000000 -0400
+++ krb5-1.4.3/src/kdc/kdc_util.h	2006-01-05 15:08:23.000000000 -0500
@@ -107,15 +107,18 @@
 /* do_as_req.c */
 krb5_error_code process_as_req (krb5_kdc_req *,
 					  const krb5_fulladdr *,
+					  krb5_boolean,
 					  krb5_data ** );
 
 /* do_tgs_req.c */
 krb5_error_code process_tgs_req (krb5_data *,
 					   const krb5_fulladdr *,
+					   krb5_boolean,
 					   krb5_data ** );
 /* dispatch.c */
 krb5_error_code dispatch (krb5_data *,
 				    const krb5_fulladdr *,
+				    krb5_boolean,
 				    krb5_data **);
 
 /* main.c */
@@ -155,9 +158,9 @@
     
 /* replay.c */
 krb5_boolean kdc_check_lookaside (krb5_data *, const krb5_fulladdr *,
-					    krb5_data **);
-void kdc_insert_lookaside (krb5_data *, const krb5_fulladdr *,
-				     krb5_data *);
+			   krb5_boolean, krb5_data **);
+void kdc_insert_lookaside (krb5_data *, const krb5_fulladdr *, krb5_boolean,
+			   krb5_data *);
 void kdc_free_lookaside(krb5_context);
 
 /* which way to convert key? */
--- krb5-1.4.3/src/kdc/replay.c	2003-01-12 08:07:49.000000000 -0500
+++ krb5-1.4.3/src/kdc/replay.c	2006-01-05 15:08:23.000000000 -0500
@@ -42,6 +42,7 @@
     krb5_data *req_packet;
     krb5_data *reply_packet;
     krb5_address *addr;		/* XXX should these not be pointers? */
+    krb5_boolean connected;
 } krb5_kdc_replay_ent;
 
 static krb5_kdc_replay_ent root_ptr = {0};
@@ -62,6 +63,7 @@
 		    !memcmp((ptr)->addr->contents,			\
 			    from->address->contents,			\
 			    from->address->length)&&			\
+		    (ptr->connected == connected) &&		\
 		    ((ptr)->db_age == db_age))
 /* XXX
    Todo:  quench the size of the queue...
@@ -72,7 +74,7 @@
 
 krb5_boolean
 kdc_check_lookaside(krb5_data *inpkt, const krb5_fulladdr *from,
-		    krb5_data **outpkt)
+		    krb5_boolean connected, krb5_data **outpkt)
 {
     krb5_int32 timenow;
     register krb5_kdc_replay_ent *eptr, *last, *hold;
@@ -126,7 +128,7 @@
 
 void
 kdc_insert_lookaside(krb5_data *inpkt, const krb5_fulladdr *from,
-		     krb5_data *outpkt)
+		     krb5_boolean connected, krb5_data *outpkt)
 {
     register krb5_kdc_replay_ent *eptr;    
     krb5_int32 timenow;
@@ -142,6 +144,7 @@
 	return;
     eptr->timein = timenow;
     eptr->db_age = db_age;
+    eptr->connected = connected;
     /*
      * This is going to hurt a lot malloc()-wise due to the need to
      * allocate memory for the krb5_data and krb5_address elements.
--- krb5-1.4.3/src/kdc/main.c	2004-02-24 16:07:22.000000000 -0500
+++ krb5-1.4.3/src/kdc/main.c	2006-01-05 15:08:23.000000000 -0500
@@ -231,6 +231,10 @@
     rdp->realm_maxrlife = (rparams && rparams->realm_max_rlife_valid) ?
 	rparams->realm_max_rlife : KRB5_KDB_MAX_RLIFE;
 
+    /* Handle maximum datagram response size */
+    rdp->realm_max_dgram_size = (rparams && rparams->realm_max_dgram_size_valid) ?
+	rparams->realm_max_dgram_size : MAX_DGRAM_SIZE;
+
     if (rparams)
 	krb5_free_realm_params(rdp->realm_context, rparams);
 
--- krb5-1.4.3/src/kdc/do_tgs_req.c	2005-07-12 16:59:52.000000000 -0400
+++ krb5-1.4.3/src/kdc/do_tgs_req.c	2006-01-05 15:08:23.000000000 -0500
@@ -56,7 +56,7 @@
 /*ARGSUSED*/
 krb5_error_code
 process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from,
-		krb5_data **response)
+		krb5_boolean connected, krb5_data **response)
 {
     krb5_keyblock * subkey;
     krb5_kdc_req *request = 0;
@@ -630,7 +630,13 @@
     if (errcode) {
 	status = "ENCODE_KDC_REP";
     } else {
-	status = "ISSUE";
+	if (!connected && ((*response)->length > max_dgram_size)) {
+	    errcode = KRB5KRB_ERR_RESPONSE_TOO_BIG;
+	    krb5_free_data(kdc_context, *response);
+	    *response = NULL;
+	} else {
+	    status = "ISSUE";
+	}
     }
 
     memset(ticket_reply.enc_part.ciphertext.data, 0,
--- krb5-1.4.3/src/config-files/kdc.conf.M	2006-01-05 15:06:30.000000000 -0500
+++ krb5-1.4.3/src/config-files/kdc.conf.M	2006-01-05 15:08:23.000000000 -0500
@@ -208,6 +208,14 @@
 .B key type string
 represents the master key's key type.
 
+.IP max_dgram_size
+This
+.B size
+specifes the maximum size for a response which the KDC will provide
+to clients which use datagrams to communicate with it.  Clients whose
+requests require larger responses will instead receive RESPONSE_TOO_BIG
+errors.
+
 .IP max_life
 This
 .B delta time string
--- krb5-1.4.3/src/include/krb5/adm.h	2002-09-18 16:45:36.000000000 -0400
+++ krb5-1.4.3/src/include/krb5/adm.h	2006-01-05 15:08:23.000000000 -0500
@@ -208,6 +208,7 @@
     krb5_deltat		realm_max_rlife;
     krb5_timestamp	realm_expiration;
     krb5_flags		realm_flags;
+    krb5_int32		realm_max_dgram_size;
     krb5_key_salt_tuple	*realm_keysalts;
     unsigned int	realm_reject_bad_transit:1;
     unsigned int	realm_kadmind_port_valid:1;
@@ -217,6 +218,7 @@
     unsigned int	realm_expiration_valid:1;
     unsigned int	realm_flags_valid:1;
     unsigned int	realm_reject_bad_transit_valid:1;
+    unsigned int	realm_max_dgram_size_valid:1;
     krb5_int32		realm_num_keysalts;
 } krb5_realm_params;
 #endif	/* KRB5_ADM_H__ */




More information about the krb5-bugs mailing list