diff options
author | kris <kris@FreeBSD.org> | 2001-07-23 21:52:26 +0000 |
---|---|---|
committer | kris <kris@FreeBSD.org> | 2001-07-23 21:52:26 +0000 |
commit | d05113329370acaef185fddba13412afb6e9a48e (patch) | |
tree | 3c1b48a6d3cf3b3648f6830bb5e30fd25bdb1186 /crypto/telnet | |
parent | 512b8c359f8701836cb505107ceab0c5c104d02f (diff) | |
download | FreeBSD-src-d05113329370acaef185fddba13412afb6e9a48e.zip FreeBSD-src-d05113329370acaef185fddba13412afb6e9a48e.tar.gz |
output_data(), output_datalen() and netflush() didn't actually guarantee
to do what they are supposed to: under some circumstances output data would
be truncated, or the buffer would not actually be flushed (possibly leading
to overflows when the caller assumes the operation succeeded). Change the
semantics so that these functions ensure they complete the operation before
returning.
Comment out diagnostic code enabled by '-D reports' which causes an
infinite recursion and an eventual crash.
Patch developed with assistance from ru and assar.
Diffstat (limited to 'crypto/telnet')
-rw-r--r-- | crypto/telnet/telnetd/ext.h | 2 | ||||
-rw-r--r-- | crypto/telnet/telnetd/slc.c | 1 | ||||
-rw-r--r-- | crypto/telnet/telnetd/state.c | 50 | ||||
-rw-r--r-- | crypto/telnet/telnetd/telnetd.c | 1 | ||||
-rw-r--r-- | crypto/telnet/telnetd/termstat.c | 2 | ||||
-rw-r--r-- | crypto/telnet/telnetd/utility.c | 39 |
6 files changed, 50 insertions, 45 deletions
diff --git a/crypto/telnet/telnetd/ext.h b/crypto/telnet/telnetd/ext.h index 74dd985..0744db1 100644 --- a/crypto/telnet/telnetd/ext.h +++ b/crypto/telnet/telnetd/ext.h @@ -190,7 +190,7 @@ extern void wontoption P((int)); int output_data __P((const char *, ...)) __printflike(1, 2); -int output_datalen __P((const char *, size_t)); +void output_datalen __P((const char *, int)); #ifdef ENCRYPTION extern void (*encrypt_output) P((unsigned char *, int)); diff --git a/crypto/telnet/telnetd/slc.c b/crypto/telnet/telnetd/slc.c index 01c4258..780adf1 100644 --- a/crypto/telnet/telnetd/slc.c +++ b/crypto/telnet/telnetd/slc.c @@ -176,7 +176,6 @@ end_slc(bufp) register unsigned char **bufp; { register int len; - void netflush(); /* * If a change has occured, store the new terminal control diff --git a/crypto/telnet/telnetd/state.c b/crypto/telnet/telnetd/state.c index 1b9372c..f5b1299 100644 --- a/crypto/telnet/telnetd/state.c +++ b/crypto/telnet/telnetd/state.c @@ -1615,40 +1615,46 @@ send_status() /* * This function appends data to nfrontp and advances nfrontp. + * Returns the number of characters written altogether (the + * buffer may have been flushed in the process). */ int output_data(const char *format, ...) { va_list args; - size_t remaining, ret; + int len; + char *buf; 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 < remaining) ? ret : remaining; + if ((len = vasprintf(&buf, format, args)) == -1) + return -1; + output_datalen(buf, len); va_end(args); - return ret; + free(buf); + return (len); } -int -output_datalen(const char *buf, size_t len) +void +output_datalen(const char *buf, int len) { - size_t remaining; - + int remaining, copied; + remaining = BUFSIZ - (nfrontp - netobuf); - if (remaining < len) { - netflush(); - remaining = BUFSIZ - (nfrontp - netobuf); - if (remaining < len) - return -1; + while (len > 0) { + /* Free up enough space if the room is too low*/ + if ((len > BUFSIZ ? BUFSIZ : len) > remaining) { + netflush(); + remaining = BUFSIZ - (nfrontp - netobuf); + } + + /* Copy out as much as will fit */ + copied = remaining > len ? len : remaining; + memmove(nfrontp, buf, copied); + nfrontp += copied; + len -= copied; + remaining -= copied; + buf += copied; } - memmove(nfrontp, buf, len); - nfrontp += len; - return (len); + return; } diff --git a/crypto/telnet/telnetd/telnetd.c b/crypto/telnet/telnetd/telnetd.c index 60353d6..7ae4568 100644 --- a/crypto/telnet/telnetd/telnetd.c +++ b/crypto/telnet/telnetd/telnetd.c @@ -952,7 +952,6 @@ telnet(f, p, host) char *HE; char *HN; char *IM; - void netflush(); int nfd; /* diff --git a/crypto/telnet/telnetd/termstat.c b/crypto/telnet/telnetd/termstat.c index 30230d4..a24135b 100644 --- a/crypto/telnet/telnetd/termstat.c +++ b/crypto/telnet/telnetd/termstat.c @@ -140,7 +140,6 @@ int newmap = 1; /* nonzero if \n maps to ^M^J */ void localstat() { - void netflush(); int need_will_echo = 0; #if defined(CRAY2) && defined(UNICOS5) @@ -404,7 +403,6 @@ flowstat() clientstat(code, parm1, parm2) register int code, parm1, parm2; { - void netflush(); /* * Get a copy of terminal characteristics. diff --git a/crypto/telnet/telnetd/utility.c b/crypto/telnet/telnetd/utility.c index d59657f..48eac65 100644 --- a/crypto/telnet/telnetd/utility.c +++ b/crypto/telnet/telnetd/utility.c @@ -69,10 +69,9 @@ static const char rcsid[] = void ttloop() { - void netflush(); DIAG(TD_REPORT, output_data("td: ttloop\r\n")); - if (nfrontp-nbackp) { + if (nfrontp - nbackp > 0) { netflush(); } ncc = read(net, netibuf, sizeof netibuf); @@ -257,10 +256,13 @@ netflush() int n; extern int not42; - if ((n = nfrontp - nbackp) > 0) { + while ((n = nfrontp - nbackp) > 0) { +#if 0 + /* XXX This causes output_data() to recurse and die */ DIAG(TD_REPORT, { n += output_data("td: netflush %d chars\r\n", n); }); +#endif #ifdef ENCRYPTION if (encrypt_output) { char *s = nclearto ? nclearto : nbackp; @@ -293,25 +295,26 @@ netflush() n = send(net, nbackp, n, MSG_OOB); /* URGENT data */ } } - } - if (n < 0) { - if (errno == EWOULDBLOCK || errno == EINTR) - return; - cleanup(0); - } - nbackp += n; + if (n == -1) { + if (errno == EWOULDBLOCK || errno == EINTR) + continue; + cleanup(0); + /* NOTREACHED */ + } + nbackp += n; #ifdef ENCRYPTION - if (nbackp > nclearto) - nclearto = 0; + if (nbackp > nclearto) + nclearto = 0; #endif /* ENCRYPTION */ - if (nbackp >= neturg) { - neturg = 0; - } - if (nbackp == nfrontp) { - nbackp = nfrontp = netobuf; + if (nbackp >= neturg) { + neturg = 0; + } + if (nbackp == nfrontp) { + nbackp = nfrontp = netobuf; #ifdef ENCRYPTION - nclearto = 0; + nclearto = 0; #endif /* ENCRYPTION */ + } } return; } /* end of netflush */ |