aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacques Vidrine <nectar@FreeBSD.org>2005-03-28 15:58:28 +0000
committerJacques Vidrine <nectar@FreeBSD.org>2005-03-28 15:58:28 +0000
commit04293d7d1ade5be5987bb1be9d46947aef3b8ac4 (patch)
tree87659b064f50538a7205d2ca96122386acf6f2c1
parenta84f9c8c4d27b7ce34314e6eed0a53ace0abe1dd (diff)
downloadsrc-04293d7d1ade5be5987bb1be9d46947aef3b8ac4.tar.gz
src-04293d7d1ade5be5987bb1be9d46947aef3b8ac4.zip
MFC src/contrib/telnet/telnet.c 1.16: Correct buffer overflows in
telnet(1). Security: CAN-2005-0468, CAN-2005-0469 Approved by: security-officer
Notes
Notes: svn path=/releng/4.11/; revision=144235
-rw-r--r--UPDATING12
-rw-r--r--crypto/heimdal/appl/telnet/telnet/telnet.c30
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/telnet.c30
-rw-r--r--crypto/telnet/telnet/telnet.c30
-rw-r--r--sys/conf/newvers.sh2
-rw-r--r--usr.bin/telnet/telnet.c30
6 files changed, 109 insertions, 25 deletions
diff --git a/UPDATING b/UPDATING
index 4c349e61dda5..edb695ee9011 100644
--- a/UPDATING
+++ b/UPDATING
@@ -8,6 +8,18 @@ A reverse chronology since 4.0 was released is included, followed by
the common items quick how-tos, followed by entries for versions of
-current prior to 4.0 Release.
+This is for the 4.11 release branch. All entries since 4.11 are an
+itemized list of commits to this branch, numbered from the beginning.
+
+The security advisories related to various patches contain information
+on how to build/install a minimal set of binaries and start/stop a
+minimal number of processes, if possible, for that patch. For those
+updates that don't have an advisory, or to be safe, you can do a full
+build and install as described in the COMMON ITEMS section.
+
+20050328: p1 FreeBSD-SA-05:01.telnet
+ Correct buffer overflows in telnet(1).
+
20050124:
FreeBSD 4.11-RELEASE.
diff --git a/crypto/heimdal/appl/telnet/telnet/telnet.c b/crypto/heimdal/appl/telnet/telnet/telnet.c
index bbc99990e201..8ea82d6494ba 100644
--- a/crypto/heimdal/appl/telnet/telnet/telnet.c
+++ b/crypto/heimdal/appl/telnet/telnet/telnet.c
@@ -1294,6 +1294,7 @@ slc_check()
unsigned char slc_reply[128];
+unsigned char const * const slc_reply_eom = &slc_reply[sizeof(slc_reply)];
unsigned char *slc_replyp;
void
@@ -1309,6 +1310,14 @@ slc_start_reply()
void
slc_add_reply(unsigned char func, unsigned char flags, cc_t value)
{
+ /* A sequence of up to 6 bytes my be written for this member of the SLC
+ * suboption list by this function. The end of negotiation command,
+ * which is written by slc_end_reply(), will require 2 additional
+ * bytes. Do not proceed unless there is sufficient space for these
+ * items.
+ */
+ if (&slc_replyp[6+2] > slc_reply_eom)
+ return;
if ((*slc_replyp++ = func) == IAC)
*slc_replyp++ = IAC;
if ((*slc_replyp++ = flags) == IAC)
@@ -1322,6 +1331,9 @@ slc_end_reply()
{
int len;
+ /* The end of negotiation command requires 2 bytes. */
+ if (&slc_replyp[2] > slc_reply_eom)
+ return;
*slc_replyp++ = IAC;
*slc_replyp++ = SE;
len = slc_replyp - slc_reply;
@@ -1415,8 +1427,8 @@ env_opt(unsigned char *buf, int len)
}
}
-#define OPT_REPLY_SIZE 256
-unsigned char *opt_reply;
+#define OPT_REPLY_SIZE (2 * SUBBUFSIZE)
+unsigned char *opt_reply = NULL;
unsigned char *opt_replyp;
unsigned char *opt_replyend;
@@ -1475,9 +1487,9 @@ env_opt_add(unsigned char *ep)
return;
}
vp = env_getvalue(ep);
- if (opt_replyp + (vp ? strlen((char *)vp) : 0) +
- strlen((char *)ep) + 6 > opt_replyend)
- {
+ if (opt_replyp + (vp ? 2 * strlen((char *)vp) : 0) +
+ 2 * strlen((char *)ep) + 6 > opt_replyend)
+ {
int len;
void *tmp;
opt_replyend += OPT_REPLY_SIZE;
@@ -1503,6 +1515,8 @@ env_opt_add(unsigned char *ep)
*opt_replyp++ = ENV_USERVAR;
for (;;) {
while ((c = *ep++)) {
+ if (opt_replyp + (2 + 2) > opt_replyend)
+ return;
switch(c&0xff) {
case IAC:
*opt_replyp++ = IAC;
@@ -1517,6 +1531,8 @@ env_opt_add(unsigned char *ep)
*opt_replyp++ = c;
}
if ((ep = vp)) {
+ if (opt_replyp + (1 + 2 + 2) > opt_replyend)
+ return;
#ifdef OLD_ENVIRON
if (telopt_environ == TELOPT_OLD_ENVIRON)
*opt_replyp++ = old_env_value;
@@ -1547,7 +1563,9 @@ env_opt_end(int emptyok)
{
int len;
- len = opt_replyp - opt_reply + 2;
+ if (opt_replyp + 2 > opt_replyend)
+ return;
+ len = opt_replyp + 2 - opt_reply;
if (emptyok || len > 6) {
*opt_replyp++ = IAC;
*opt_replyp++ = SE;
diff --git a/crypto/kerberosIV/appl/telnet/telnet/telnet.c b/crypto/kerberosIV/appl/telnet/telnet/telnet.c
index 1df4d6ea35b2..0275357025ed 100644
--- a/crypto/kerberosIV/appl/telnet/telnet/telnet.c
+++ b/crypto/kerberosIV/appl/telnet/telnet/telnet.c
@@ -1285,6 +1285,7 @@ slc_check()
unsigned char slc_reply[128];
+unsigned char const * const slc_reply_eom = &slc_reply[sizeof(slc_reply)];
unsigned char *slc_replyp;
void
@@ -1300,6 +1301,14 @@ slc_start_reply()
void
slc_add_reply(unsigned char func, unsigned char flags, cc_t value)
{
+ /* A sequence of up to 6 bytes my be written for this member of the SLC
+ * suboption list by this function. The end of negotiation command,
+ * which is written by slc_end_reply(), will require 2 additional
+ * bytes. Do not proceed unless there is sufficient space for these
+ * items.
+ */
+ if (&slc_replyp[6+2] > slc_reply_eom)
+ return;
if ((*slc_replyp++ = func) == IAC)
*slc_replyp++ = IAC;
if ((*slc_replyp++ = flags) == IAC)
@@ -1313,6 +1322,9 @@ slc_end_reply()
{
int len;
+ /* The end of negotiation command requires 2 bytes. */
+ if (&slc_replyp[2] > slc_reply_eom)
+ return;
*slc_replyp++ = IAC;
*slc_replyp++ = SE;
len = slc_replyp - slc_reply;
@@ -1406,8 +1418,8 @@ env_opt(unsigned char *buf, int len)
}
}
-#define OPT_REPLY_SIZE 256
-unsigned char *opt_reply;
+#define OPT_REPLY_SIZE (2 * SUBBUFSIZE)
+unsigned char *opt_reply = NULL;
unsigned char *opt_replyp;
unsigned char *opt_replyend;
@@ -1460,9 +1472,9 @@ env_opt_add(unsigned char *ep)
return;
}
vp = env_getvalue(ep);
- if (opt_replyp + (vp ? strlen((char *)vp) : 0) +
- strlen((char *)ep) + 6 > opt_replyend)
- {
+ if (opt_replyp + (vp ? 2 * strlen((char *)vp) : 0) +
+ 2 * strlen((char *)ep) + 6 > opt_replyend)
+ {
int len;
opt_replyend += OPT_REPLY_SIZE;
len = opt_replyend - opt_reply;
@@ -1486,6 +1498,8 @@ env_opt_add(unsigned char *ep)
*opt_replyp++ = ENV_USERVAR;
for (;;) {
while ((c = *ep++)) {
+ if (opt_replyp + (2 + 2) > opt_replyend)
+ return;
switch(c&0xff) {
case IAC:
*opt_replyp++ = IAC;
@@ -1500,6 +1514,8 @@ env_opt_add(unsigned char *ep)
*opt_replyp++ = c;
}
if ((ep = vp)) {
+ if (opt_replyp + (1 + 2 + 2) > opt_replyend)
+ return;
#ifdef OLD_ENVIRON
if (telopt_environ == TELOPT_OLD_ENVIRON)
*opt_replyp++ = old_env_value;
@@ -1530,7 +1546,9 @@ env_opt_end(int emptyok)
{
int len;
- len = opt_replyp - opt_reply + 2;
+ if (opt_replyp + 2 > opt_replyend)
+ return;
+ len = opt_replyp + 2 - opt_reply;
if (emptyok || len > 6) {
*opt_replyp++ = IAC;
*opt_replyp++ = SE;
diff --git a/crypto/telnet/telnet/telnet.c b/crypto/telnet/telnet/telnet.c
index 4644531376fa..c9f58ebcbe9a 100644
--- a/crypto/telnet/telnet/telnet.c
+++ b/crypto/telnet/telnet/telnet.c
@@ -1318,6 +1318,7 @@ slc_check(void)
}
unsigned char slc_reply[128];
+unsigned char const * const slc_reply_eom = &slc_reply[sizeof(slc_reply)];
unsigned char *slc_replyp;
void
@@ -1333,6 +1334,14 @@ slc_start_reply(void)
void
slc_add_reply(unsigned char func, unsigned char flags, cc_t value)
{
+ /* A sequence of up to 6 bytes my be written for this member of the SLC
+ * suboption list by this function. The end of negotiation command,
+ * which is written by slc_end_reply(), will require 2 additional
+ * bytes. Do not proceed unless there is sufficient space for these
+ * items.
+ */
+ if (&slc_replyp[6+2] > slc_reply_eom)
+ return;
if ((*slc_replyp++ = func) == IAC)
*slc_replyp++ = IAC;
if ((*slc_replyp++ = flags) == IAC)
@@ -1346,6 +1355,9 @@ slc_end_reply(void)
{
int len;
+ /* The end of negotiation command requires 2 bytes. */
+ if (&slc_replyp[2] > slc_reply_eom)
+ return;
*slc_replyp++ = IAC;
*slc_replyp++ = SE;
len = slc_replyp - slc_reply;
@@ -1463,8 +1475,8 @@ env_opt(unsigned char *buf, int len)
}
}
-#define OPT_REPLY_SIZE 256
-unsigned char *opt_reply;
+#define OPT_REPLY_SIZE (2 * SUBBUFSIZE)
+unsigned char *opt_reply = NULL;
unsigned char *opt_replyp;
unsigned char *opt_replyend;
@@ -1517,9 +1529,9 @@ env_opt_add(unsigned char *ep)
return;
}
vp = env_getvalue(ep);
- if (opt_replyp + (vp ? strlen((char *)vp) : 0) +
- strlen((char *)ep) + 6 > opt_replyend)
- {
+ if (opt_replyp + (vp ? 2 * strlen((char *)vp) : 0) +
+ 2 * strlen((char *)ep) + 6 > opt_replyend)
+ {
int len;
opt_replyend += OPT_REPLY_SIZE;
len = opt_replyend - opt_reply;
@@ -1543,6 +1555,8 @@ env_opt_add(unsigned char *ep)
*opt_replyp++ = ENV_USERVAR;
for (;;) {
while ((c = *ep++)) {
+ if (opt_replyp + (2 + 2) > opt_replyend)
+ return;
switch(c&0xff) {
case IAC:
*opt_replyp++ = IAC;
@@ -1557,6 +1571,8 @@ env_opt_add(unsigned char *ep)
*opt_replyp++ = c;
}
if ((ep = vp)) {
+ if (opt_replyp + (1 + 2 + 2) > opt_replyend)
+ return;
#ifdef OLD_ENVIRON
if (telopt_environ == TELOPT_OLD_ENVIRON)
*opt_replyp++ = old_env_value;
@@ -1587,7 +1603,9 @@ env_opt_end(int emptyok)
{
int len;
- len = opt_replyp - opt_reply + 2;
+ if (opt_replyp + 2 > opt_replyend)
+ return;
+ len = opt_replyp + 2 - opt_reply;
if (emptyok || len > 6) {
*opt_replyp++ = IAC;
*opt_replyp++ = SE;
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index 322f0a7e2248..39109ce246ab 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -36,7 +36,7 @@
TYPE="FreeBSD"
REVISION="4.11"
-BRANCH="RELEASE"
+BRANCH="RELEASE-p1"
RELEASE="${REVISION}-${BRANCH}"
VERSION="${TYPE} ${RELEASE}"
diff --git a/usr.bin/telnet/telnet.c b/usr.bin/telnet/telnet.c
index a570a8609680..c450a394d496 100644
--- a/usr.bin/telnet/telnet.c
+++ b/usr.bin/telnet/telnet.c
@@ -1193,6 +1193,7 @@ slc_check(void)
}
unsigned char slc_reply[128];
+unsigned char const * const slc_reply_eom = &slc_reply[sizeof(slc_reply)];
unsigned char *slc_replyp;
void
@@ -1208,6 +1209,14 @@ slc_start_reply(void)
void
slc_add_reply(unsigned char func, unsigned char flags, cc_t value)
{
+ /* A sequence of up to 6 bytes my be written for this member of the SLC
+ * suboption list by this function. The end of negotiation command,
+ * which is written by slc_end_reply(), will require 2 additional
+ * bytes. Do not proceed unless there is sufficient space for these
+ * items.
+ */
+ if (&slc_replyp[6+2] > slc_reply_eom)
+ return;
if ((*slc_replyp++ = func) == IAC)
*slc_replyp++ = IAC;
if ((*slc_replyp++ = flags) == IAC)
@@ -1221,6 +1230,9 @@ slc_end_reply(void)
{
int len;
+ /* The end of negotiation command requires 2 bytes. */
+ if (&slc_replyp[2] > slc_reply_eom)
+ return;
*slc_replyp++ = IAC;
*slc_replyp++ = SE;
len = slc_replyp - slc_reply;
@@ -1338,8 +1350,8 @@ env_opt(unsigned char *buf, int len)
}
}
-#define OPT_REPLY_SIZE 256
-unsigned char *opt_reply;
+#define OPT_REPLY_SIZE (2 * SUBBUFSIZE)
+unsigned char *opt_reply = NULL;
unsigned char *opt_replyp;
unsigned char *opt_replyend;
@@ -1392,9 +1404,9 @@ env_opt_add(unsigned char *ep)
return;
}
vp = env_getvalue(ep);
- if (opt_replyp + (vp ? strlen((char *)vp) : 0) +
- strlen((char *)ep) + 6 > opt_replyend)
- {
+ if (opt_replyp + (vp ? 2 * strlen((char *)vp) : 0) +
+ 2 * strlen((char *)ep) + 6 > opt_replyend)
+ {
int len;
opt_replyend += OPT_REPLY_SIZE;
len = opt_replyend - opt_reply;
@@ -1418,6 +1430,8 @@ env_opt_add(unsigned char *ep)
*opt_replyp++ = ENV_USERVAR;
for (;;) {
while ((c = *ep++)) {
+ if (opt_replyp + (2 + 2) > opt_replyend)
+ return;
switch(c&0xff) {
case IAC:
*opt_replyp++ = IAC;
@@ -1432,6 +1446,8 @@ env_opt_add(unsigned char *ep)
*opt_replyp++ = c;
}
if ((ep = vp)) {
+ if (opt_replyp + (1 + 2 + 2) > opt_replyend)
+ return;
#ifdef OLD_ENVIRON
if (telopt_environ == TELOPT_OLD_ENVIRON)
*opt_replyp++ = old_env_value;
@@ -1462,7 +1478,9 @@ env_opt_end(int emptyok)
{
int len;
- len = opt_replyp - opt_reply + 2;
+ if (opt_replyp + 2 > opt_replyend)
+ return;
+ len = opt_replyp + 2 - opt_reply;
if (emptyok || len > 6) {
*opt_replyp++ = IAC;
*opt_replyp++ = SE;