TYPO3 API  SVNRelease
tx_feloginTest.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2010-2011 Helmut Hummel <helmut@typo3.org>
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *
00017 *  This script is distributed in the hope that it will be useful,
00018 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 *  GNU General Public License for more details.
00021 *
00022 *  This copyright notice MUST APPEAR in all copies of the script!
00023 ***************************************************************/
00024 
00025 
00026 require_once t3lib_extMgm::extPath('felogin', 'pi1/class.tx_felogin_pi1.php');
00027 
00028 /**
00029  * Testcase for URL validation in class tx_felogin_pi1
00030  *
00031  * @author Helmut Hummel <helmut@typo3.org>
00032  * @package TYPO3
00033  * @subpackage tests/typo3/sysext/felogin
00034  */
00035 class tx_feloginTest extends tx_phpunit_testcase {
00036 
00037     /**
00038      * @var array
00039      */
00040     private $backupGlobalVariables;
00041 
00042     /**
00043      * @var tx_felogin_pi1
00044      */
00045     private $txFelogin;
00046 
00047     /**
00048      * @var string
00049      */
00050     private $testHostName;
00051 
00052     /**
00053      * @var string
00054      */
00055     private $testSitePath;
00056 
00057     /**
00058      * @var string
00059      */
00060     private $testTableName;
00061 
00062     public function setUp() {
00063         $this->backupGlobalVariables = array(
00064             '_SERVER' => $_SERVER,
00065             'TYPO3_DB' => $GLOBALS['TYPO3_DB'],
00066             'TSFE' => $GLOBALS['TSFE'],
00067         );
00068 
00069         $this->testTableName = 'sys_domain';
00070         $this->testHostName = 'hostname.tld';
00071         $this->testSitePath = '/';
00072 
00073         // we need to subclass because the method we want to test is protected
00074         $className = uniqid('FeLogin_');
00075         eval('
00076             class ' . $className. ' extends tx_felogin_pi1 {
00077                 public function validateRedirectUrl($url) {
00078                     return parent::validateRedirectUrl($url);
00079                 }
00080             }
00081         ');
00082 
00083         $this->txFelogin = new $className();
00084         $this->txFelogin->cObj = $this->getMock('tslib_cObj');
00085 
00086         $this->setUpTSFE();
00087         $this->setUpFakeSitePathAndHost();
00088     }
00089 
00090     private function setUpTSFE() {
00091         $GLOBALS['TSFE'] = $this->getMock('tslib_fe', array(), array(), '', FALSE);
00092     }
00093 
00094     private function setUpFakeSitePathAndHost() {
00095         $_SERVER['ORIG_PATH_INFO'] =
00096         $_SERVER['PATH_INFO'] =
00097         $_SERVER['ORIG_SCRIPT_NAME'] =
00098         $_SERVER['SCRIPT_NAME'] = $this->testSitePath . TYPO3_mainDir;
00099         $_SERVER['HTTP_HOST'] = $this->testHostName;
00100     }
00101 
00102     private function setUpDatabaseMock() {
00103         $GLOBALS['TYPO3_DB'] = $this->getMock('t3lib_DB', array('exec_SELECTgetRows'));
00104         $GLOBALS['TYPO3_DB']->expects($this->any())->method('exec_SELECTgetRows')->will(
00105             $this->returnCallback(array($this, 'getDomainRecordsCallback'))
00106         );
00107     }
00108 
00109     /**
00110      * Callback method for pageIdCanBeDetermined test cases.
00111      * Simulates TYPO3_DB->exec_SELECTgetRows().
00112      *
00113      * @param   string      $fields
00114      * @param   string      $table
00115      * @param   string      $where
00116      * @return  mixed
00117      * @see setUpDatabaseMock
00118      */
00119     public function getDomainRecordsCallback($fields, $table, $where) {
00120 
00121         if ($table !== $this->testTableName) {
00122             return FALSE;
00123         }
00124 
00125         return array(
00126                 array('domainName' => 'domainhostname.tld'),
00127                 array('domainName' => 'otherhostname.tld/path'),
00128                 array('domainName' => 'sub.domainhostname.tld/path/')
00129             );
00130     }
00131 
00132     public function tearDown() {
00133         $this->txFelogin = null;
00134 
00135         foreach ($this->backupGlobalVariables as $key => $data) {
00136             $GLOBALS[$key] = $data;
00137         }
00138 
00139         $this->backupGlobalVariables = null;
00140 
00141     }
00142 
00143     /**
00144      * @test
00145      */
00146     public function typo3SitePathEqualsStubSitePath() {
00147         $this->assertEquals(t3lib_div::getIndpEnv('TYPO3_SITE_PATH'), $this->testSitePath);
00148     }
00149 
00150     /**
00151      * @test
00152      */
00153     public function typo3SiteUrlEqualsStubSiteUrl() {
00154         $this->assertEquals(t3lib_div::getIndpEnv('TYPO3_SITE_URL'), 'http://' . $this->testHostName . $this->testSitePath);
00155     }
00156 
00157     /**
00158      * @test
00159      */
00160     public function typo3SitePathEqualsStubSitePathAfterChangingInTest() {
00161         $this->testHostName = 'somenewhostname.com';
00162         $this->testSitePath = '/somenewpath/';
00163         $this->setUpFakeSitePathAndHost();
00164 
00165         $this->assertEquals(t3lib_div::getIndpEnv('TYPO3_SITE_PATH'), $this->testSitePath);
00166     }
00167 
00168     /**
00169      * @test
00170      */
00171     public function typo3SiteUrlEqualsStubSiteUrlAfterChangingInTest() {
00172         $this->testHostName = 'somenewhostname.com';
00173         $this->testSitePath = '/somenewpath/';
00174         $this->setUpFakeSitePathAndHost();
00175 
00176         $this->assertEquals(t3lib_div::getIndpEnv('TYPO3_SITE_URL'), 'http://' . $this->testHostName . $this->testSitePath);
00177     }
00178 
00179     /**
00180      * Data provider for malicousUrlsWillBeCleared
00181      *
00182      * @see malicousUrlsWillBeCleared
00183      */
00184     public function variousUrlsDataProviderForMalicousUrlsWillBeCleared() {
00185         return array(
00186             'absolute URL, hostname not in sys_domain, trailing slash' => array('http://badhost.tld/'),
00187             'absolute URL, hostname not in sys_domain, no trailing slash' => array('http://badhost.tld'),
00188             'absolute URL, subdomain in sys_domain, but main domain not, trailing slash' => array('http://domainhostname.tld.badhost.tld/'),
00189             'absolute URL, subdomain in sys_domain, but main domain not, no trailing slash' => array('http://domainhostname.tld.badhost.tld'),
00190             'non http absolute URL 1' => array('its://domainhostname.tld/itunes/'),
00191             'non http absolute URL 2' => array('ftp://domainhostname.tld/download/'),
00192 
00193             'XSS attempt 1' => array('javascript:alert(123)'),
00194             'XSS attempt 2' => array('" onmouseover="alert(123)"'),
00195             'invalid URL, HTML break out attempt' => array('" >blabuubb'),
00196             'invalid URL, UNC path' => array('\\\\foo\\bar\\'),
00197             'invalid URL, backslashes in path' => array('http://domainhostname.tld\\bla\\blupp'),
00198             'invalid URL, linefeed in path' => array("http://domainhostname.tld/bla/blupp\n"),
00199             'invalid URL, only one slash after scheme' => array("http:/domainhostname.tld/bla/blupp"),
00200             'invalid URL, illegal chars' => array("http://(<>domainhostname).tld/bla/blupp"),
00201 
00202         );
00203     }
00204 
00205     /**
00206      * @test
00207      * @dataProvider variousUrlsDataProviderForMalicousUrlsWillBeCleared
00208      */
00209     public function malicousUrlsWillBeCleared($url) {
00210         $this->setUpDatabaseMock();
00211         $this->assertEquals('', $this->txFelogin->validateRedirectUrl($url));
00212     }
00213 
00214     /**
00215      * Data provider for cleanUrlsAreKept
00216      *
00217      * @see cleanUrlsAreKept
00218      */
00219     public function variousUrlsDataProviderForCleanUrlsAreKept() {
00220         return array(
00221             'sane absolute URL' => array('http://domainhostname.tld/'),
00222             'sane absolute URL with script' => array('http://domainhostname.tld/index.php?id=1'),
00223             'sane absolute URL with realurl' => array('http://domainhostname.tld/foo/bar/foo.html'),
00224             'sane absolute URL with homedir' => array('http://domainhostname.tld/~user/'),
00225             'sane absolute URL with some strange chars encoded' => array('http://domainhostname.tld/~user/a%cc%88o%cc%88%c3%9fa%cc%82/foo.html'),
00226 
00227             'sane absolute URL (domain record with path)' => array('http://otherhostname.tld/path/'),
00228             'sane absolute URL with script (domain record with path)' => array('http://otherhostname.tld/path/index.php?id=1'),
00229             'sane absolute URL with realurl (domain record with path)' => array('http://otherhostname.tld/path/foo/bar/foo.html'),
00230 
00231             'sane absolute URL (domain record with path and slash)' => array('http://sub.domainhostname.tld/path/'),
00232             'sane absolute URL with script (domain record with path slash)' => array('http://sub.domainhostname.tld/path/index.php?id=1'),
00233             'sane absolute URL with realurl (domain record with path slash)' => array('http://sub.domainhostname.tld/path/foo/bar/foo.html'),
00234 
00235             'relative URL, no leading slash 1' => array('index.php?id=1'),
00236             'relative URL, no leading slash 2' => array('foo/bar/index.php?id=2'),
00237             'relative URL, leading slash, no realurl' => array('/index.php?id=1'),
00238             'relative URL, leading slash, realurl' => array('/de/service/imprint.html'),
00239         );
00240     }
00241 
00242     /**
00243      * @test
00244      * @dataProvider variousUrlsDataProviderForCleanUrlsAreKept
00245      */
00246     public function cleanUrlsAreKept($url) {
00247         $this->setUpDatabaseMock();
00248         $this->assertEquals($url, $this->txFelogin->validateRedirectUrl($url));
00249     }
00250 
00251     /**
00252      * Data provider for malicousUrlsWillBeClearedTypo3InSubdirectory
00253      *
00254      * @see malicousUrlsWillBeClearedTypo3InSubdirectory
00255      */
00256     public function variousUrlsDataProviderForMalicousUrlsWillBeClearedTypo3InSubdirectory() {
00257         return array(
00258             'absolute URL, missing subdirectory' => array('http://hostname.tld/'),
00259             'absolute URL, wrong subdirectory' => array('http://hostname.tld/hacker/index.php'),
00260             'absolute URL, correct subdirectory, no trailing slash' => array('http://hostname.tld/subdir'),
00261             'absolute URL, correct subdirectory of sys_domain record, no trailing slash' => array('http://otherhostname.tld/path'),
00262             'absolute URL, correct subdirectory of sys_domain record, no trailing slash' => array('http://sub.domainhostname.tld/path'),
00263 
00264             'relative URL, leading slash, no path' => array('/index.php?id=1'),
00265             'relative URL, leading slash, wrong path' => array('/de/sub/site.html'),
00266             'relative URL, leading slash, slash only' => array('/'),
00267         );
00268     }
00269 
00270     /**
00271      * @test
00272      * @dataProvider variousUrlsDataProviderForMalicousUrlsWillBeClearedTypo3InSubdirectory
00273      */
00274     public function malicousUrlsWillBeClearedTypo3InSubdirectory($url) {
00275         $this->testSitePath = '/subdir/';
00276         $this->setUpFakeSitePathAndHost();
00277 
00278         $this->setUpDatabaseMock();
00279         $this->assertEquals('', $this->txFelogin->validateRedirectUrl($url));
00280     }
00281 
00282     /**
00283      * Data provider for cleanUrlsAreKeptTypo3InSubdirectory
00284      *
00285      * @see cleanUrlsAreKeptTypo3InSubdirectory
00286      */
00287     public function variousUrlsDataProviderForCleanUrlsAreKeptTypo3InSubdirectory() {
00288         return array(
00289             'absolute URL, correct subdirectory' => array('http://hostname.tld/subdir/'),
00290             'absolute URL, correct subdirectory, realurl' => array('http://hostname.tld/subdir/de/imprint.html'),
00291             'absolute URL, correct subdirectory, no realurl' => array('http://hostname.tld/subdir/index.php?id=10'),
00292 
00293             'absolute URL, correct subdirectory of sys_domain record' => array('http://otherhostname.tld/path/'),
00294             'absolute URL, correct subdirectory of sys_domain record' => array('http://sub.domainhostname.tld/path/'),
00295 
00296             'relative URL, no leading slash, realurl' => array('de/service/imprint.html'),
00297             'relative URL, no leading slash, no realurl' => array('index.php?id=1'),
00298             'relative URL, no leading slash, no realurl' => array('foo/bar/index.php?id=2'),
00299         );
00300     }
00301 
00302     /**
00303      * @test
00304      * @dataProvider variousUrlsDataProviderForCleanUrlsAreKeptTypo3InSubdirectory
00305      */
00306     public function cleanUrlsAreKeptTypo3InSubdirectory($url) {
00307         $this->testSitePath = '/subdir/';
00308         $this->setUpFakeSitePathAndHost();
00309 
00310         $this->setUpDatabaseMock();
00311         $this->assertEquals($url, $this->txFelogin->validateRedirectUrl($url));
00312     }
00313 
00314 
00315 
00316 }
00317 ?>