bin/52032: Telnet option contra telnet protocol

Valentin Nechayev netch at netch.kiev.ua
Sat May 10 12:40:13 PDT 2003


>Number:         52032
>Category:       bin
>Synopsis:       Telnet option contra telnet protocol
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sat May 10 12:40:10 PDT 2003
>Closed-Date:
>Last-Modified:
>Originator:     Valentin Nechayev
>Release:        FreeBSD 4.8-RELEASE i386
>Organization:
Dark side of coredump
>Environment:
FreeBSD 4.8-RELEASE
FreeBSD 5.1-BETA

>Description:

As for nowadays, telnet program is not widely used as remote login program,
but first of all (on my statistics) as tester for line-oriented text
network protocols. The most known examples are SMTP, POP3, NNTP, HTTP
(query/response headers and simple-formatted reply bodies). All they
don't use TELNET option negotiation mechanism and may transfer data with
high bit set, including 0xff code. In this case, telnet tries to interpret
them as control sequences and shows behavior unexpected by command runner.

My own example, found during testing new squid;), is to say
"GET http://segfault.kiev.ua/ HTTP/1.0" in telnet to squid or httpd; resulting
output was cut just on 0xFF 0xF2 sequence, which is part of Russian text in
windows-1251 coding, but is `Data Mark' in telnet, and only data after
this sequence was showed on screen.

As protocol tester (and simple protocol client) of this type is quite useful
in practice, it isn't wise IMO to exclude possibility of being such client
or to send to ports for functionality which can be covered in existing
telnet using simple patch. There is no applicable program in ports;
netcat is closest one, but it doesn't have this functionality because
it can't translate "\n" <-> CRLF between local and network sides.

>How-To-Repeat:
>Fix:

The following patch abuses existing syntax, which treats '-' in front of
port specification to force telnet negotiation sending initial command set.
Proposed variant uses '+' as reverse to '-' (style is similar to /bin/sh
options one;)) to disable telnet negotiation syntax sequences at all:
they aren't sent under any circumstances and aren't interpreted on input.

The patch is applicable to 4.8-RELEASE, and 5.1-BETA of 2003-05-05,
and tested on both.

Also separate change is applied to telnet.1: in options for `open' command,
`-l user' is read correctly before host, not after it; man page says opposite.
(Try both variants with autologin-complied server and you'll see difference.)

This fix is somehow incomplete: it doesn't allow client's option control
core to understand that options never will be negotiated just because
they don't be sent to server side. For traditional use in line-to-line mode
without explicit requesting of option negotiating, this is enough
because none negotiation will be requested ever. But as such usage is
much too rare, I think its covering is possible to fix later.

Please fix english text if needed, I'm not native English speaker.

>Release-Note:
>Audit-Trail:
>Unformatted:

diff -rNu 0/src/usr.bin/telnet/commands.c 1/src/usr.bin/telnet/commands.c
--- 0/src/usr.bin/telnet/commands.c	Tue Mar 25 00:04:20 2003
+++ 1/src/usr.bin/telnet/commands.c	Sat May 10 19:16:55 2003
@@ -2041,6 +2041,9 @@
     } else if (*portp == '-') {
       portp++;
       telnetport = 1;
+    } else if (*portp == '+') {
+      portp++;
+      telnetport = -1;
     } else
       telnetport = 0;
 
diff -rNu 0/src/usr.bin/telnet/telnet.1 1/src/usr.bin/telnet/telnet.1
--- 0/src/usr.bin/telnet/telnet.1	Tue Mar 25 00:04:20 2003
+++ 1/src/usr.bin/telnet/telnet.1	Sat May 10 20:05:49 2003
@@ -571,9 +571,10 @@
 command.
 .El
 .It Xo
-.Ic open Ar host
+.Ic open
 .Op Fl l Ar user
-.Op Oo Fl Oc Ns Ar port
+.Op Ar host
+.Op Oo Fl /+ Oc Ns Ar port
 .Xc
 Open a connection to the named host.
 If no port number
@@ -598,7 +599,12 @@
 omits any automatic initiation of
 .Tn TELNET
 options.  When the port number is preceded by a minus sign,
-the initial option negotiation is done.
+the initial option negotiation is done. As opposite, when the port number
+is preceded by a plus sign, any option negotiation and understanding
+is prohibited, making telnet dumb client for POP3/SMTP/NNTP/HTTP-like
+protocols with any data including
+.Tn TELNET
+IAC character (0xff).
 After establishing a connection, the file
 .Pa \&.telnetrc
 in the
diff -rNu 0/src/usr.bin/telnet/telnet.c 1/src/usr.bin/telnet/telnet.c
--- 0/src/usr.bin/telnet/telnet.c	Fri Apr 26 21:53:52 2002
+++ 1/src/usr.bin/telnet/telnet.c	Sat May 10 19:23:27 2003
@@ -203,6 +203,8 @@
 	set_my_want_state_do(c);
 	do_dont_resp[c]++;
     }
+    if (telnetport < 0)
+	return;
     NET2ADD(IAC, DO);
     NETADD(c);
     printoption("SENT", DO, c);
@@ -218,6 +220,8 @@
 	set_my_want_state_dont(c);
 	do_dont_resp[c]++;
     }
+    if (telnetport < 0)
+	return;
     NET2ADD(IAC, DONT);
     NETADD(c);
     printoption("SENT", DONT, c);
@@ -233,6 +237,8 @@
 	set_my_want_state_will(c);
 	will_wont_resp[c]++;
     }
+    if (telnetport < 0)
+	return;
     NET2ADD(IAC, WILL);
     NETADD(c);
     printoption("SENT", WILL, c);
@@ -248,6 +254,8 @@
 	set_my_want_state_wont(c);
 	will_wont_resp[c]++;
     }
+    if (telnetport < 0)
+	return;
     NET2ADD(IAC, WONT);
     NETADD(c);
     printoption("SENT", WONT, c);
@@ -1522,7 +1530,7 @@
 	    /* Else, fall through */
 
 	case TS_DATA:
-	    if (c == IAC) {
+	    if (c == IAC && telnetport >= 0) {
 		telrcv_state = TS_IAC;
 		break;
 	    }
@@ -1914,7 +1922,7 @@
 {
     sys_telnet_init();
 
-    if (telnetport) {
+    if (telnetport > 0) {
 	send_do(TELOPT_SGA, 1);
 	send_will(TELOPT_TTYPE, 1);
 	send_will(TELOPT_NAWS, 1);


More information about the freebsd-bugs mailing list