From 52f91ff04ca89ad8e9bf4f2ae88d53089b08a563 Mon Sep 17 00:00:00 2001 From: David Rhodus Date: Mon, 28 Mar 2005 18:03:32 +0000 Subject: [PATCH] Correct a pair of buffer overflows in the telnet(1) command: CAN-2005-0468) A heap buffer overflow in env_opt_add() and related functions. (CAN-2005-0469) A global uninitialized data section buffer overflow in slc_add_reply() and related functions. As a result of these vulnerabilities, it may be possible for a malicious telnet server or active network attacker to cause telnet(1) to execute arbitrary code with the privileges of the user running it. These fixes are based in part on patches Submitted by: Solar Designer With calibration with the FreeBSD security officer: Jacques Vidrine --- .../heimdal-0.6.3/appl/telnet/telnet/telnet.c | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/crypto/heimdal-0.6.3/appl/telnet/telnet/telnet.c b/crypto/heimdal-0.6.3/appl/telnet/telnet/telnet.c index bbc99990e2..4dfb041d02 100644 --- a/crypto/heimdal-0.6.3/appl/telnet/telnet/telnet.c +++ b/crypto/heimdal-0.6.3/appl/telnet/telnet/telnet.c @@ -1294,6 +1294,7 @@ slc_check() unsigned char slc_reply[128]; +unsigned char const * const slc_reply_eom = &slc_reply[sizeof(slc_reply)]; unsigned char *slc_replyp; void @@ -1309,6 +1310,14 @@ slc_start_reply() void slc_add_reply(unsigned char func, unsigned char flags, cc_t value) { + /* A sequence of up to 6 bytes my be written for this member of the SLC + * suboption list by this function. The end of negotiation command, + * which is written by slc_end_reply(), will require 2 additional + * bytes. Do not proceed unless there is sufficient space for these + * items. + */ + if (&slc_replyp[6+2] > slc_reply_eom) + return; if ((*slc_replyp++ = func) == IAC) *slc_replyp++ = IAC; if ((*slc_replyp++ = flags) == IAC) @@ -1321,7 +1330,9 @@ void slc_end_reply() { int len; - + /* The ned of negotiation command requires 2 bytes. */ + if (&slc_replyp[2] > s;c_reply_eom) + return; *slc_replyp++ = IAC; *slc_replyp++ = SE; len = slc_replyp - slc_reply; @@ -1415,8 +1426,8 @@ env_opt(unsigned char *buf, int len) } } -#define OPT_REPLY_SIZE 256 -unsigned char *opt_reply; +#define OPT_REPLY_SIZE (2 * SUBBUFSIZE) +unsigned char *opt_reply = NULL; unsigned char *opt_replyp; unsigned char *opt_replyend; @@ -1474,9 +1485,8 @@ env_opt_add(unsigned char *ep) env_opt_add(ep); return; } - vp = env_getvalue(ep); - if (opt_replyp + (vp ? strlen((char *)vp) : 0) + - strlen((char *)ep) + 6 > opt_replyend) + if (opt_replyp + (vp ? 2 * strlen((char *)vp) : 0) + + 2 * strlen((char *)ep) + 6 > opt_replyend) { int len; void *tmp; @@ -1503,6 +1513,8 @@ env_opt_add(unsigned char *ep) *opt_replyp++ = ENV_USERVAR; for (;;) { while ((c = *ep++)) { + if (opt_replyp + (2 + 2) > opt_replyend) + return; switch(c&0xff) { case IAC: *opt_replyp++ = IAC; @@ -1517,6 +1529,8 @@ env_opt_add(unsigned char *ep) *opt_replyp++ = c; } if ((ep = vp)) { + if (opt_replyp + (1 + 2 + 2) > opt_replyend) + return; #ifdef OLD_ENVIRON if (telopt_environ == TELOPT_OLD_ENVIRON) *opt_replyp++ = old_env_value; @@ -1547,7 +1561,9 @@ env_opt_end(int emptyok) { int len; - len = opt_replyp - opt_reply + 2; + if (opt_replyp + 2 > opt_replyend) + return; + len = opt_replyp + 2 - opt_reply; if (emptyok || len > 6) { *opt_replyp++ = IAC; *opt_replyp++ = SE; -- 2.32.0