summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@mit.edu>2006-06-26 23:47:03 +0000
committerKen Raeburn <raeburn@mit.edu>2006-06-26 23:47:03 +0000
commitb0fcaccdf948c549c71a66f75d897ea25a909f67 (patch)
tree53ed77bdc924ca41a48faf4f18cf651f6c60ad95
parent509e591a07a9d6f6053db1f2fb38ae37c602aa27 (diff)
downloadkrb5-b0fcaccdf948c549c71a66f75d897ea25a909f67.tar.gz
krb5-b0fcaccdf948c549c71a66f75d897ea25a909f67.tar.xz
krb5-b0fcaccdf948c549c71a66f75d897ea25a909f67.zip
* kdc/network.c (make_toolong_error): New function.
(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
-rw-r--r--src/kdc/network.c41
-rw-r--r--src/tests/dejagnu/krb-standalone/standalone.exp32
2 files changed, 72 insertions, 1 deletions
diff --git a/src/kdc/network.c b/src/kdc/network.c
index af5e7d036..f7bb958f3 100644
--- a/src/kdc/network.c
+++ b/src/kdc/network.c
@@ -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);
diff --git a/src/tests/dejagnu/krb-standalone/standalone.exp b/src/tests/dejagnu/krb-standalone/standalone.exp
index dbe9b950c..554906e44 100644
--- a/src/tests/dejagnu/krb-standalone/standalone.exp
+++ b/src/tests/dejagnu/krb-standalone/standalone.exp
@@ -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]