summaryrefslogtreecommitdiffstats
path: root/crypto/telnet
diff options
context:
space:
mode:
authorkris <kris@FreeBSD.org>2001-07-23 21:52:26 +0000
committerkris <kris@FreeBSD.org>2001-07-23 21:52:26 +0000
commitd05113329370acaef185fddba13412afb6e9a48e (patch)
tree3c1b48a6d3cf3b3648f6830bb5e30fd25bdb1186 /crypto/telnet
parent512b8c359f8701836cb505107ceab0c5c104d02f (diff)
downloadFreeBSD-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.h2
-rw-r--r--crypto/telnet/telnetd/slc.c1
-rw-r--r--crypto/telnet/telnetd/state.c50
-rw-r--r--crypto/telnet/telnetd/telnetd.c1
-rw-r--r--crypto/telnet/telnetd/termstat.c2
-rw-r--r--crypto/telnet/telnetd/utility.c39
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 */
OpenPOWER on IntegriCloud