Add domain checking to HTTP cookie checking.
authorMark A. Hershberger <mah@users.mediawiki.org>
Fri, 5 Feb 2010 04:08:19 +0000 (04:08 +0000)
committerMark A. Hershberger <mah@users.mediawiki.org>
Fri, 5 Feb 2010 04:08:19 +0000 (04:08 +0000)
includes/HttpFunctions.php
maintenance/tests/HttpTest.php

index 551206e..07efc6b 100644 (file)
@@ -502,7 +502,7 @@ class Cookie {
 }
 
 class CookieJar {
-       private $cookie;
+       private $cookie = array();
 
        /**
         * Set a cookie in the cookie jar.      Make sure only one cookie per-name exists.
@@ -538,30 +538,44 @@ class CookieJar {
         * Parse the content of an Set-Cookie HTTP Response header.
         * @param $cookie string
         */
-       public function parseCookieResponseHeader ( $cookie, $domain = null ) {
+       public function parseCookieResponseHeader ( $cookie, $domain ) {
                $len = strlen( "Set-Cookie:" );
                if ( substr_compare( "Set-Cookie:", $cookie, 0, $len, TRUE ) === 0 ) {
                        $cookie = substr( $cookie, $len );
                }
 
                $bit = array_map( 'trim', explode( ";", $cookie ) );
-               list($name, $value) = explode( "=", array_shift( $bit ), 2 );
-               $attr = array();
-               foreach( $bit as $piece ) {
-                       $parts = explode( "=", $piece );
-                       if( count( $parts ) > 1 ) {
-                               $attr[strtolower( $parts[0] )] = $parts[1];
-                       } else {
-                               $attr[strtolower( $parts[0] )] = true;
+               if ( count($bit) >= 1 ) {
+                       list($name, $value) = explode( "=", array_shift( $bit ), 2 );
+                       $attr = array();
+                       foreach( $bit as $piece ) {
+                               $parts = explode( "=", $piece );
+                               if( count( $parts ) > 1 ) {
+                                       $attr[strtolower( $parts[0] )] = $parts[1];
+                               } else {
+                                       $attr[strtolower( $parts[0] )] = true;
+                               }
                        }
-               }
 
-               if( !isset( $attr['domain'] ) ) {
-                       $attr['domain'] = $domain;
-               } else {
-                       /* FIXME: Check that domain is valid */
+                       if( !isset( $attr['domain'] ) ) {
+                               $attr['domain'] = $domain;
+                       } else {
+                               /* If domain is given, it has to contain at least two dots */
+                               if ( strrpos( $attr['domain'], '.' ) === false
+                                        || strrpos( $attr['domain'], '.' ) === strpos( $attr['domain'], '.' ) ) {
+                                       return;
+                               }
+                               if ( substr( $attr['domain'], 0, 1 ) === '.' ) {
+                                       $attr['domain'] = substr( $attr['domain'], 1 );
+                               }
+                               if ( strlen( $attr['domain'] ) < strlen( $domain )
+                                        && substr_compare( $domain, $attr['domain'], -strlen( $attr['domain'] ),
+                                                                               strlen( $attr['domain'] ), TRUE ) != 0 ) {
+                                       return; /* silently reject a bad cookie */
+                               }
+                       }
+                       $this->setCookie( $name, $value, $attr );
                }
-               $this->setCookie( $name, $value, $attr );
        }
 }
 
index c0b6c58..b5d6716 100644 (file)
@@ -443,24 +443,28 @@ class HttpTest extends PhpUnit_Framework_TestCase {
                $cj = new CookieJar;
 
                $h[] = "Set-Cookie: name4=value; domain=.example.com; path=/; expires=Mon, 09-Dec-2999 13:46:00 GMT";
-               $cj->parseCookieResponseHeader( $h[0] );
+               $cj->parseCookieResponseHeader( $h[0], "www.example.com" );
                $this->assertEquals("name4=value", $cj->serializeToHttpRequest("/", "www.example.com"));
 
                $h[] = "name4=value2; domain=.example.com; path=/path/; expires=Mon, 09-Dec-2999 13:46:00 GMT";
-               $cj->parseCookieResponseHeader( $h[1] );
+               $cj->parseCookieResponseHeader( $h[1], "www.example.com" );
                $this->assertEquals("", $cj->serializeToHttpRequest("/", "www.example.com"));
                $this->assertEquals("name4=value2", $cj->serializeToHttpRequest("/path/", "www.example.com"));
 
                $h[] = "name5=value3; domain=.example.com; path=/path/; expires=Mon, 09-Dec-2999 13:46:00 GMT";
-               $cj->parseCookieResponseHeader( $h[2] );
+               $cj->parseCookieResponseHeader( $h[2], "www.example.com" );
                $this->assertEquals("name4=value2; name5=value3", $cj->serializeToHttpRequest("/path/", "www.example.com"));
 
-               $h[] = "name6=value3; domain=.example.net; path=/path/; expires=Mon, 09-Dec-1999 13:46:00 GMT";
-               $cj->parseCookieResponseHeader( $h[3] );
+               $h[] = "name6=value3; domain=.example.net; path=/path/; expires=Mon, 09-Dec-2999 13:46:00 GMT";
+               $cj->parseCookieResponseHeader( $h[3], "www.example.com" );
+               $this->assertEquals("", $cj->serializeToHttpRequest("/path/", "www.example.net"));
+
+               $h[] = "name6=value0; domain=.example.net; path=/path/; expires=Mon, 09-Dec-1999 13:46:00 GMT";
+               $cj->parseCookieResponseHeader( $h[4], "www.example.net" );
                $this->assertEquals("", $cj->serializeToHttpRequest("/path/", "www.example.net"));
 
                $h[] = "name6=value4; domain=.example.net; path=/path/; expires=Mon, 09-Dec-2999 13:46:00 GMT";
-               $cj->parseCookieResponseHeader( $h[4] );
+               $cj->parseCookieResponseHeader( $h[5], "www.example.net" );
                $this->assertEquals("name6=value4", $cj->serializeToHttpRequest("/path/", "www.example.net"));
        }