aboutsummaryrefslogtreecommitdiff
path: root/crypto/telnet
diff options
context:
space:
mode:
authorKris Kennaway <kris@FreeBSD.org>2001-07-23 21:52:26 +0000
committerKris Kennaway <kris@FreeBSD.org>2001-07-23 21:52:26 +0000
commita2a887b56afec03d01e0d9c2507f64bc595e3aff (patch)
tree3c1b48a6d3cf3b3648f6830bb5e30fd25bdb1186 /crypto/telnet
parent27daeab3ecac3dc7f764b36f22daad2eee56bebb (diff)
downloadsrc-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.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 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 */