From 9cac33d71fc5f6846362da63a753c08e90efa427 Mon Sep 17 00:00:00 2001 From: ru Date: Thu, 19 Jul 2001 17:48:57 +0000 Subject: Fixed the exploitable remote buffer overflow. Reported on: bugtraq Obtained from: Heimdal, NetBSD Reviewed by: obrien, imp --- contrib/telnet/telnetd/state.c | 61 +++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 13 deletions(-) (limited to 'contrib/telnet/telnetd/state.c') diff --git a/contrib/telnet/telnetd/state.c b/contrib/telnet/telnetd/state.c index 4a066b7..ec012cf 100644 --- a/contrib/telnet/telnetd/state.c +++ b/contrib/telnet/telnetd/state.c @@ -39,6 +39,7 @@ static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ +#include #include "telnetd.h" #if defined(AUTHENTICATION) #include @@ -205,8 +206,7 @@ gotiac: switch (c) { } netclear(); /* clear buffer back */ - *nfrontp++ = IAC; - *nfrontp++ = DM; + output_data("%c%c", IAC, DM); neturg = nfrontp-1; /* off by one XXX */ DIAG(TD_OPTIONS, printoption("td: send IAC", DM)); @@ -459,8 +459,7 @@ send_do(option, init) set_his_want_state_will(option); do_dont_resp[option]++; } - (void) sprintf(nfrontp, (char *)doopt, option); - nfrontp += sizeof (dont) - 2; + output_data((const char *)doopt, option); DIAG(TD_OPTIONS, printoption("td: send do", option)); } @@ -679,8 +678,7 @@ send_dont(option, init) set_his_want_state_wont(option); do_dont_resp[option]++; } - (void) sprintf(nfrontp, (char *)dont, option); - nfrontp += sizeof (doopt) - 2; + output_data((const char *)dont, option); DIAG(TD_OPTIONS, printoption("td: send dont", option)); } @@ -828,8 +826,7 @@ send_will(option, init) set_my_want_state_will(option); will_wont_resp[option]++; } - (void) sprintf(nfrontp, (char *)will, option); - nfrontp += sizeof (doopt) - 2; + output_data((const char *)will, option); DIAG(TD_OPTIONS, printoption("td: send will", option)); } @@ -987,8 +984,7 @@ send_wont(option, init) set_my_want_state_wont(option); will_wont_resp[option]++; } - (void) sprintf(nfrontp, (char *)wont, option); - nfrontp += sizeof (wont) - 2; + output_data((const char *)wont, option); DIAG(TD_OPTIONS, printoption("td: send wont", option)); } @@ -1384,9 +1380,8 @@ suboption() env_ovar_wrong: env_ovar = OLD_ENV_VALUE; env_ovalue = OLD_ENV_VAR; - DIAG(TD_OPTIONS, {sprintf(nfrontp, - "ENVIRON VALUE and VAR are reversed!\r\n"); - nfrontp += strlen(nfrontp);}); + DIAG(TD_OPTIONS, + output_data("ENVIRON VALUE and VAR are reversed!\r\n")); } } @@ -1617,3 +1612,43 @@ send_status() DIAG(TD_OPTIONS, {printsub('>', statusbuf, ncp - statusbuf); netflush();}); } + +/* + * This function appends data to nfrontp and advances nfrontp. + */ + +int +output_data(const char *format, ...) +{ + va_list args; + size_t remaining, ret; + + va_start(args, format); + remaining = BUFSIZ - (nfrontp - netobuf); + /* try a netflush() if the room is too low */ + if (strlen(format) > remaining || BUFSIZ / 4 > remaining) { + netflush(); + remaining = BUFSIZ - (nfrontp - netobuf); + } + ret = vsnprintf(nfrontp, remaining, format, args); + nfrontp += ret; + va_end(args); + return ret; +} + +int +output_datalen(const char *buf, size_t len) +{ + size_t remaining; + + remaining = BUFSIZ - (nfrontp - netobuf); + if (remaining < len) { + netflush(); + remaining = BUFSIZ - (nfrontp - netobuf); + } + if (remaining < len) + return -1; + memmove(nfrontp, buf, len); + nfrontp += len; + return (len); +} -- cgit v1.1