diff options
author | Kris Kennaway <kris@FreeBSD.org> | 2001-07-23 21:52:26 +0000 |
---|---|---|
committer | Kris Kennaway <kris@FreeBSD.org> | 2001-07-23 21:52:26 +0000 |
commit | a2a887b56afec03d01e0d9c2507f64bc595e3aff (patch) | |
tree | 3c1b48a6d3cf3b3648f6830bb5e30fd25bdb1186 /crypto/telnet | |
parent | 27daeab3ecac3dc7f764b36f22daad2eee56bebb (diff) | |
download | src-a2a887b56afec03d01e0d9c2507f64bc595e3aff.tar.gz src-a2a887b56afec03d01e0d9c2507f64bc595e3aff.zip |
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.
Notes
Notes:
svn path=/head/; revision=80224
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 74dd9858f141..0744db1bd4e4 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 01c4258382d8..780adf1be1ab 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 1b9372cd3fa8..f5b1299b77fa 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 60353d6079fb..7ae45689eec3 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 30230d4f5785..a24135b48d1f 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 d59657f9195c..48eac6526144 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 */ |