Blob Blame History Raw
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 the 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.

--- 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
+@comment MAX_DGRAM_SIZE
+@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}.
 
+@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
+@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__ */