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.

Security: CAN-2005-0468, CAN-2005-0469
Security: FreeBSD-SA-05:01.telnet
Security: http://www.idefense.com/application/poi/display?id=220&type=vulnerabilities
Security: http://www.idefense.com/application/poi/display?id=221&type=vulnerabilities

These fixes are based in part on patches
Submitted by:	Solar Designer <solar@openwall.com>


git-svn-id: http://svn0.us-east.freebsd.org/base/head/contrib/telnet@144231 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f
This commit is contained in:
nectar 2005-03-28 14:45:12 +00:00
parent 0f4e951657
commit e1492a80cd

View File

@ -1326,6 +1326,7 @@ slc_check(void)
} }
unsigned char slc_reply[128]; unsigned char slc_reply[128];
unsigned char const * const slc_reply_eom = &slc_reply[sizeof(slc_reply)];
unsigned char *slc_replyp; unsigned char *slc_replyp;
void void
@ -1341,6 +1342,14 @@ slc_start_reply(void)
void void
slc_add_reply(unsigned char func, unsigned char flags, cc_t value) 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) if ((*slc_replyp++ = func) == IAC)
*slc_replyp++ = IAC; *slc_replyp++ = IAC;
if ((*slc_replyp++ = flags) == IAC) if ((*slc_replyp++ = flags) == IAC)
@ -1354,6 +1363,9 @@ slc_end_reply(void)
{ {
int len; int len;
/* The end of negotiation command requires 2 bytes. */
if (&slc_replyp[2] > slc_reply_eom)
return;
*slc_replyp++ = IAC; *slc_replyp++ = IAC;
*slc_replyp++ = SE; *slc_replyp++ = SE;
len = slc_replyp - slc_reply; len = slc_replyp - slc_reply;
@ -1471,8 +1483,8 @@ env_opt(unsigned char *buf, int len)
} }
} }
#define OPT_REPLY_SIZE 256 #define OPT_REPLY_SIZE (2 * SUBBUFSIZE)
unsigned char *opt_reply; unsigned char *opt_reply = NULL;
unsigned char *opt_replyp; unsigned char *opt_replyp;
unsigned char *opt_replyend; unsigned char *opt_replyend;
@ -1525,9 +1537,9 @@ env_opt_add(unsigned char *ep)
return; return;
} }
vp = env_getvalue(ep); vp = env_getvalue(ep);
if (opt_replyp + (vp ? strlen((char *)vp) : 0) + if (opt_replyp + (vp ? 2 * strlen((char *)vp) : 0) +
strlen((char *)ep) + 6 > opt_replyend) 2 * strlen((char *)ep) + 6 > opt_replyend)
{ {
int len; int len;
opt_replyend += OPT_REPLY_SIZE; opt_replyend += OPT_REPLY_SIZE;
len = opt_replyend - opt_reply; len = opt_replyend - opt_reply;
@ -1551,6 +1563,8 @@ env_opt_add(unsigned char *ep)
*opt_replyp++ = ENV_USERVAR; *opt_replyp++ = ENV_USERVAR;
for (;;) { for (;;) {
while ((c = *ep++)) { while ((c = *ep++)) {
if (opt_replyp + (2 + 2) > opt_replyend)
return;
switch(c&0xff) { switch(c&0xff) {
case IAC: case IAC:
*opt_replyp++ = IAC; *opt_replyp++ = IAC;
@ -1565,6 +1579,8 @@ env_opt_add(unsigned char *ep)
*opt_replyp++ = c; *opt_replyp++ = c;
} }
if ((ep = vp)) { if ((ep = vp)) {
if (opt_replyp + (1 + 2 + 2) > opt_replyend)
return;
#ifdef OLD_ENVIRON #ifdef OLD_ENVIRON
if (telopt_environ == TELOPT_OLD_ENVIRON) if (telopt_environ == TELOPT_OLD_ENVIRON)
*opt_replyp++ = old_env_value; *opt_replyp++ = old_env_value;
@ -1595,7 +1611,9 @@ env_opt_end(int emptyok)
{ {
int len; 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) { if (emptyok || len > 6) {
*opt_replyp++ = IAC; *opt_replyp++ = IAC;
*opt_replyp++ = SE; *opt_replyp++ = SE;