mirror of
https://github.com/sheumann/telnetd.git
synced 2024-11-26 12:49:21 +00:00
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. git-svn-id: http://svn0.us-east.freebsd.org/base/head/contrib/telnet@80224 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f
This commit is contained in:
parent
2c684cfa07
commit
9de6e7ba10
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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;
|
||||
free(buf);
|
||||
return (len);
|
||||
}
|
||||
|
||||
void
|
||||
output_datalen(const char *buf, int len)
|
||||
{
|
||||
int remaining, copied;
|
||||
|
||||
remaining = BUFSIZ - (nfrontp - netobuf);
|
||||
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;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -952,7 +952,6 @@ telnet(f, p, host)
|
||||
char *HE;
|
||||
char *HN;
|
||||
char *IM;
|
||||
void netflush();
|
||||
int nfd;
|
||||
|
||||
/*
|
||||
|
@ -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.
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user