]> arthur.barton.de Git - ngircd.git/commitdiff
Allow mixed line terminations (CR+LF/CR/LF) in non-RFC-compliant mode
authorAlexander Barton <alex@barton.de>
Wed, 11 Jun 2008 14:00:38 +0000 (16:00 +0200)
committerAlexander Barton <alex@barton.de>
Wed, 11 Jun 2008 14:38:11 +0000 (16:38 +0200)
Up to now ngIRCd accepted CR+LF as well as a single CR or LF in "non RFC
compliant" mode (the default). But ngIRCd became confused when it received
data containing mixed line endings (e. g. "111\r222\n333\r\n").

This patch enables ngIRCd (in "non RFC compliant" mode) to detect CR+LF,
CR, and LF as equally good line termination sequences and to always end the
command after the first one detected.

Some clients (for exmaple Trilian) are that ... broken to send such mixed
line terminations ...

First patch proposed by Scott Perry <scperry@ucsd.edu>,
Thanks to Ali Shemiran <ashemira@ucsd.edu> for testing!

(manually cherry picked from commit a84f7dcee5a1b32c74188aa5374d30eddd24852b)

src/ngircd/conn.c
src/ngircd/parse.c

index 6094735486083aede5007e1823e52c662c37a561..7efc5b88c0620423862882ed4a254317499fb2de 100644 (file)
@@ -1227,7 +1227,7 @@ Handle_Buffer( CONN_ID Idx )
        /* Handle Data in Connections Read-Buffer.
         * Return true if a reuqest was handled, false otherwise (also returned on errors). */
 #ifndef STRICT_RFC
-       char *ptr1, *ptr2;
+       char *ptr1, *ptr2, *first_eol;
 #endif
        char *ptr;
        size_t len, delta;
@@ -1255,19 +1255,32 @@ Handle_Buffer( CONN_ID Idx )
                        return false;
 
                /* A Complete Request end with CR+LF, see RFC 2812. */
+               delta = 2;
                ptr = strstr( array_start(&My_Connections[Idx].rbuf), "\r\n" );
 
-               if( ptr ) delta = 2; /* complete request */
 #ifndef STRICT_RFC
-               else {
-                       /* Check for non-RFC-compliant request (only CR or LF)? Unfortunately,
-                        * there are quite a few clients that do this (incl. "mIRC" :-( */
-                       ptr1 = strchr( array_start(&My_Connections[Idx].rbuf), '\r' );
-                       ptr2 = strchr( array_start(&My_Connections[Idx].rbuf), '\n' );
+               /* Check for non-RFC-compliant request (only CR or LF)?
+                * Unfortunately, there are quite a few clients out there
+                * that do this -- e. g. mIRC, BitchX, and Trillian :-( */
+               ptr1 = strchr(array_start(&My_Connections[Idx].rbuf), '\r');
+               ptr2 = strchr(array_start(&My_Connections[Idx].rbuf), '\n');
+               if (ptr) {
+                       /* Check if there is a single CR or LF _before_ the
+                        * corerct CR+LF line terminator:  */
+                       first_eol = ptr1 < ptr2 ? ptr1 : ptr2;
+                       if (first_eol < ptr) {
+                               /* Single CR or LF before CR+LF found */
+                               ptr = first_eol;
+                               delta = 1;
+                       }
+               } else if (ptr1 || ptr2) {
+                       /* No CR+LF terminated command found, but single
+                        * CR or LF found ... */
+                       if (ptr1 && ptr2)
+                               ptr = ptr1 < ptr2 ? ptr1 : ptr2;
+                       else
+                               ptr = ptr1 ? ptr1 : ptr2;
                        delta = 1;
-                       if( ptr1 && ptr2 ) ptr = ptr1 > ptr2 ? ptr2 : ptr1;
-                       else if( ptr1 ) ptr = ptr1;
-                       else if( ptr2 ) ptr = ptr2;
                }
 #endif
 
index 7be52710f9a3df471fc3264d33a507109389c157..409231ae0364f751afd60982f8c3b4ce7b1f0812 100644 (file)
@@ -337,12 +337,20 @@ Validate_Command( UNUSED CONN_ID Idx, UNUSED REQUEST *Req, bool *Closed )
 static bool
 Validate_Args(CONN_ID Idx, REQUEST *Req, bool *Closed)
 {
+#ifdef STRICT_RFC
        int i;
+#endif
 
        assert( Idx >= 0 );
        assert( Req != NULL );
        *Closed = false;
 
+#ifdef STRICT_RFC
+       /* CR and LF are never allowed in command parameters.
+        * But since we do accept lines terminated only with CR or LF in
+        * "non-RFC-compliant mode" (besides the correct CR+LF combination),
+        * this check can only trigger in "strict RFC" mode; therefore we
+        * optimize it away otherwise ... */
        for (i = 0; i < Req->argc; i++) {
                if (strchr(Req->argv[i], '\r') || strchr(Req->argv[i], '\n')) {
                        Log(LOG_ERR,
@@ -354,6 +362,8 @@ Validate_Args(CONN_ID Idx, REQUEST *Req, bool *Closed)
                        return false;
                }
        }
+#endif
+
        return true;
 } /* Validate_Args */