--- networking/telnetd.c.orig	2008-12-19 13:49:40.000000000 +0100
+++ networking/telnetd.c	2008-12-19 13:49:41.000000000 +0100
@@ -27,7 +27,7 @@
 #include <syslog.h>
 
 #if DEBUG
-#define TELCMDS
+#define TELCMDS ""
 #define TELOPTS
 #endif
 #include <arpa/telnet.h>
@@ -46,6 +46,9 @@
 #define TS_BUF2 (((unsigned char*)(ts + 1)) + BUFSIZE)
 	int rdidx1, wridx1, size1;
 	int rdidx2, wridx2, size2;
+    /*--- State for remove telnet-cmds ---*/
+    enum  {State_NonIAC, State_IAC, State_CmdwithOption, State_SB_Start, State_SB,  State_SB_IAC} state;
+    unsigned char tmp[4], tmp_count;
 };
 
 /* Two buffers are directly after tsession in malloced memory.
@@ -80,6 +83,26 @@
    CR-LF ->'s CR mapping is also done here, for convenience.
 
    NB: may fail to remove iacs which wrap around buffer!
+
+   mbahr: Changed on 13.08.2008:  
+   IAC escape IAC
+   Complete handling of IAC, so that 2- or 3-byte-cmds
+   will removed and also always in area IAC SB until IAC SE,
+   because RFC-854 says:
+   > All TELNET commands consist of at least a two byte sequence:  the
+   >"Interpret as Command" (IAC) escape character followed by the code
+   >for the command.  The commands dealing with option negotiation are
+   >three byte sequences, the third byte being the code for the option
+   >referenced.  This format was chosen so that as more comprehensive use
+   >of the "data space" is made -- by negotiations from the basic NVT, of
+   >course -- collisions of data bytes with reserved command values will
+   >be minimized, all such collisions requiring the inconvenience, and
+   >inefficiency, of "escaping" the data bytes into the stream.  With the
+   >current set-up, only the IAC need be doubled to be sent as data, and
+   >the other 255 codes may be passed transparently.
+
+    Fixme: the actually version do not filter 0xff for send to socket, so echo 
+    of 0xFF can confuse client!
  */
 static unsigned char *
 remove_iacs(struct tsession *ts, int *pnum_totty)
@@ -88,54 +111,90 @@
 	unsigned char *ptr = ptr0;
 	unsigned char *totty = ptr;
 	unsigned char *end = ptr + MIN(BUFSIZE - ts->wridx1, ts->size1);
-	int num_totty;
+	int num_totty, flag =0;
 
 	while (ptr < end) {
-		if (*ptr != IAC) {
-			char c = *ptr;
-
-			*totty++ = c;
-			ptr++;
-			/* We now map \r\n ==> \r for pragmatic reasons.
-			 * Many client implementations send \r\n when
-			 * the user hits the CarriageReturn key.
-			 */
-			if (c == '\r' && ptr < end && (*ptr == '\n' || *ptr == '\0'))
-				ptr++;
-		} else {
-			/*
-			 * TELOPT_NAWS support!
-			 */
-			if ((ptr+2) >= end) {
-				/* only the beginning of the IAC is in the
-				buffer we were asked to process, we can't
-				process this char. */
-				break;
-			}
-
-			/*
-			 * IAC -> SB -> TELOPT_NAWS -> 4-byte -> IAC -> SE
-			 */
-			else if (ptr[1] == SB && ptr[2] == TELOPT_NAWS) {
-				struct winsize ws;
-
-				if ((ptr+8) >= end)
-					break;	/* incomplete, can't process */
-				ws.ws_col = (ptr[3] << 8) | ptr[4];
-				ws.ws_row = (ptr[5] << 8) | ptr[6];
-				ioctl(ts->ptyfd, TIOCSWINSZ, (char *)&ws);
-				ptr += 9;
-			} else {
-				/* skip 3-byte IAC non-SB cmd */
+        switch(ts->state) {
+            case State_NonIAC:
+                if (*ptr != IAC) {
+                    *totty++ = *ptr;
+                    /* We now map \r\n ==> \r for pragmatic reasons.
+                     * Many client implementations send \r\n when
+                     * the user hits the CarriageReturn key.
+                     */
+                    if (*ptr == '\r' && (*(ptr+1) == '\n' || *(ptr+1) == 0) && (ptr+1) < end)
+                        ptr++;
+                    break;
+                }
+                ts->state = State_IAC;
+                break;
+            case State_IAC:
+                switch(*ptr) {
+                    case IAC:
+                        *totty++ = *ptr; /*--- 0xFF for terminal ---*/
+                        ts->state = State_NonIAC;
+                        break;
+                    case DONT:
+                    case DO:
+                    case WONT:
+                    case WILL:
 #if DEBUG
-				fprintf(stderr, "Ignoring IAC %s,%s\n",
-					TELCMD(ptr[1]), TELOPT(ptr[2]));
+                        fprintf(stderr, "Ignoring IAC %s\n", TELCMDS(*ptr));
 #endif
-				ptr += 3;
-			}
-		}
-	}
-
+                        ts->state = State_CmdwithOption;
+                        break;
+                    case SB:
+                        /*--- Subnegation begins, end with SE ---*/
+                        ts->state = State_SB_Start;
+                        break;
+                    default:
+                        /*--- only 2 byte Command -> skip ---*/
+#if DEBUG
+                        fprintf(stderr, "Ignoring IAC %s\n", TELCMDS(*ptr));
+#endif
+                        ts->state = State_NonIAC;
+                }
+                break;
+            case State_CmdwithOption:
+                /*--- ignore option ---*/
+                ts->state = State_NonIAC;
+                break;
+            case State_SB_Start:
+                /* TELOPT_NAWS support!  */
+                /* TELOPT_NAWS -> 4-byte */
+                if(*ptr == TELOPT_NAWS) {
+                    struct winsize ws;
+                    int tail =  MIN(4 - ts->tmp_count, end - ptr - 1);
+                    memcpy(&ts->tmp[ts->tmp_count], ptr + 1, tail);
+                    ts->tmp_count += tail;
+                    if(ts->tmp_count < 4) {
+                        ptr = end;
+                        break; 	/* incomplete, can't process */
+                    }
+                    ws.ws_col = (ts->tmp[0] << 8) | ts->tmp[1];
+                    ws.ws_row = (ts->tmp[2] << 8) | ts->tmp[3];
+                    (void) ioctl(ts->ptyfd, TIOCSWINSZ, (char *)&ws);
+                    ts->tmp_count = 0;
+                    ptr += tail;
+                }
+                ts->state = State_SB;
+                break;
+            case State_SB:
+                if (*ptr == IAC) {
+                    ts->state = State_SB_IAC;
+                }
+                break;
+            case State_SB_IAC:
+                if (*ptr == SE) {
+                    /*--- SE found ---*/
+                    ts->state = State_NonIAC;
+                    break;
+                }
+                ts->state = State_SB;
+                break;
+        }
+        ptr++;
+    }
 	num_totty = totty - ptr0;
 	*pnum_totty = num_totty;
 	/* the difference between ptr and totty is number of iacs
