* kdc/network.c (make_toolong_error): New function.
authorKen Raeburn <raeburn@mit.edu>
Mon, 26 Jun 2006 23:47:03 +0000 (23:47 +0000)
committerKen Raeburn <raeburn@mit.edu>
Mon, 26 Jun 2006 23:47:03 +0000 (23:47 +0000)
(process_tcp_connection): If the specified length exceeds the internal limit,
stop reading and send back a FIELD_TOOLONG error.
* tests/dejagnu/krb-standalone/standalone.exp (doit): When testing TCP mode,
connect to the KDC and send a length of -1, and check that it sends back a
non-empty message.

ticket: 3923
tags: pullup

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@18233 dc483132-0cff-0310-8789-dd5450dbe970

src/kdc/network.c
src/tests/dejagnu/krb-standalone/standalone.exp

index af5e7d036260fd91d9149f5c023d6b390f0762cf..f7bb958f3e7c0668474ab3f3426f61e36d5d8468 100644 (file)
@@ -891,6 +891,36 @@ kill_tcp_connection(struct connection *conn)
     tcp_data_counter--;
 }
 
+static krb5_error_code
+make_toolong_error (krb5_data **out)
+{
+    krb5_error errpkt;
+    krb5_error_code retval;
+    krb5_data *scratch;
+
+    retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec);
+    if (retval)
+       return retval;
+    errpkt.error = KRB_ERR_FIELD_TOOLONG;
+    errpkt.server = tgs_server;
+    errpkt.client = NULL;
+    errpkt.text.length = 0;
+    errpkt.text.data = 0;
+    errpkt.e_data.length = 0;
+    errpkt.e_data.data = 0;
+    scratch = malloc(sizeof(*scratch));
+    if (scratch == NULL)
+       return ENOMEM;
+    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
+    if (retval) {
+       free(scratch);
+       return retval;
+    }
+
+    *out = scratch;
+    return 0;
+}
+
 static void
 process_tcp_connection(struct connection *conn, const char *prog, int selflags)
 {
@@ -953,12 +983,20 @@ process_tcp_connection(struct connection *conn, const char *prog, int selflags)
                                      | (p[2] <<  8)
                                      | p[3]);
                if (conn->u.tcp.msglen > conn->u.tcp.bufsiz - 4) {
+                   krb5_error_code err;
                    /* message too big */
                    krb5_klog_syslog(LOG_ERR, "TCP client %s wants %lu bytes, cap is %lu",
                                     conn->u.tcp.addrbuf, (unsigned long) conn->u.tcp.msglen,
                                     (unsigned long) conn->u.tcp.bufsiz - 4);
                    /* XXX Should return an error.  */
-                   goto kill_tcp_connection;
+                   err = make_toolong_error (&conn->u.tcp.response);
+                   if (err) {
+                       krb5_klog_syslog(LOG_ERR,
+                                        "error constructing KRB_ERR_FIELD_TOOLONG error! %s",
+                                        error_message(err));
+                       goto kill_tcp_connection;
+                   }
+                   goto have_response;
                }
            }
        } else {
@@ -987,6 +1025,7 @@ process_tcp_connection(struct connection *conn, const char *prog, int selflags)
                com_err(prog, err, "while dispatching (tcp)");
                goto kill_tcp_connection;
            }
+       have_response:
            conn->u.tcp.lenbuf[0] = 0xff & (conn->u.tcp.response->length >> 24);
            conn->u.tcp.lenbuf[1] = 0xff & (conn->u.tcp.response->length >> 16);
            conn->u.tcp.lenbuf[2] = 0xff & (conn->u.tcp.response->length >> 8);
index dbe9b950c43cda5a35b4e93255fcfadd80def105..554906e4462da8764c3d593ab7a96008f746a8c5 100644 (file)
@@ -31,6 +31,8 @@ proc doit { } {
     global spawn_id
     global supported_enctypes
     global KRBIV
+    global portbase
+    global mode
 
     # Start up the kerberos and kadmind daemons.
     if ![start_kerberos_daemons 1] {
@@ -143,6 +145,36 @@ proc doit { } {
            pass "kadmin.local correct high kvno"
        }
     }
+
+    if { $mode == "tcp" } {
+       set response {}
+       set got_response 0
+       set kdcsock ""
+       catch {
+           send_log "connecting to $hostname [expr 3 + $portbase]\n"
+           set kdcsock [socket $hostname [expr 3 + $portbase]]
+           fconfigure $kdcsock -encoding binary -blocking 0 -buffering none
+           puts -nonewline $kdcsock [binary format H* ffffffff]
+           # XXX
+           sleep 3
+           set response [read $kdcsock]
+           set got_response 1
+       } msg
+       if [string length $kdcsock] { catch "close $kdcsock" }
+       if $got_response {
+#      send_log [list sent length -1, got back $response]
+#      send_log "\n"
+           if [string length $response]>10 {
+               pass "too-long TCP request"
+           } else {
+               send_log "response too short\n"
+               fail "too-long TCP request"
+           }
+       } else {
+           send_log "too-long connect/exchange failure: $msg\n"
+           fail "too-long TCP request"
+       }
+    }
 }
 
 set status [catch doit msg]