2010-11-20 16:25:08 +01:00
< ? php
/* Copyright ( C ) 2010 Laurent Destailleur < eldy @ users . sourceforge . net >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
2013-01-16 15:36:08 +01:00
* the Free Software Foundation ; either version 3 of the License , or
2010-11-20 16:25:08 +01:00
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2019-09-23 21:55:30 +02:00
* along with this program . If not , see < https :// www . gnu . org / licenses />.
* or see https :// www . gnu . org /
2010-11-20 16:25:08 +01:00
*/
/**
* \file test / phpunit / SecurityTest . php
* \ingroup test
* \brief PHPUnit test
* \remarks To run this script as CLI : phpunit filename . php
*/
global $conf , $user , $langs , $db ;
//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver
2014-05-01 19:57:53 +02:00
//require_once 'PHPUnit/Autoload.php';
2010-11-20 16:25:08 +01:00
require_once dirname ( __FILE__ ) . '/../../htdocs/master.inc.php' ;
2011-10-24 10:45:06 +02:00
require_once dirname ( __FILE__ ) . '/../../htdocs/core/lib/security.lib.php' ;
2012-02-12 17:41:28 +01:00
require_once dirname ( __FILE__ ) . '/../../htdocs/core/lib/security2.lib.php' ;
2010-11-20 16:25:08 +01:00
2019-01-27 13:07:22 +01:00
if ( ! defined ( 'NOREQUIREUSER' )) define ( 'NOREQUIREUSER' , '1' );
if ( ! defined ( 'NOREQUIREDB' )) define ( 'NOREQUIREDB' , '1' );
if ( ! defined ( 'NOREQUIRESOC' )) define ( 'NOREQUIRESOC' , '1' );
if ( ! defined ( 'NOREQUIRETRAN' )) define ( 'NOREQUIRETRAN' , '1' );
if ( ! defined ( 'NOCSRFCHECK' )) define ( 'NOCSRFCHECK' , '1' );
if ( ! defined ( 'NOTOKENRENEWAL' )) define ( 'NOTOKENRENEWAL' , '1' );
if ( ! defined ( 'NOREQUIREMENU' )) define ( 'NOREQUIREMENU' , '1' ); // If there is no menu to show
if ( ! defined ( 'NOREQUIREHTML' )) define ( 'NOREQUIREHTML' , '1' ); // If we don't need to load the html.form.class.php
if ( ! defined ( 'NOREQUIREAJAX' )) define ( 'NOREQUIREAJAX' , '1' );
if ( ! defined ( " NOLOGIN " )) define ( " NOLOGIN " , '1' ); // If this page is public (can be called outside logged session)
2010-11-20 16:25:08 +01:00
2012-02-12 18:30:50 +01:00
if ( empty ( $user -> id ))
{
print " Load permissions for admin user nb 1 \n " ;
$user -> fetch ( 1 );
$user -> getrights ();
}
$conf -> global -> MAIN_DISABLE_ALL_MAILS = 1 ;
2010-11-20 16:25:08 +01:00
/**
2011-09-23 14:21:00 +02:00
* Class for PHPUnit tests
2010-11-20 16:25:08 +01:00
*
* @ backupGlobals disabled
* @ backupStaticAttributes enabled
* @ remarks backupGlobals must be disabled to have db , conf , user and lang not erased .
*/
2019-07-05 21:28:27 +02:00
class SecurityTest extends PHPUnit\Framework\TestCase
2010-11-20 16:25:08 +01:00
{
protected $savconf ;
protected $savuser ;
protected $savlangs ;
protected $savdb ;
/**
* Constructor
* We save global variables into local variables
*
2011-03-29 11:12:18 +02:00
* @ return SecurityTest
2010-11-20 16:25:08 +01:00
*/
2019-02-25 00:56:48 +01:00
public function __construct ()
2010-11-20 16:25:08 +01:00
{
2018-09-02 14:10:06 +02:00
parent :: __construct ();
2010-11-20 16:25:08 +01:00
//$this->sharedFixture
global $conf , $user , $langs , $db ;
$this -> savconf = $conf ;
$this -> savuser = $user ;
$this -> savlangs = $langs ;
$this -> savdb = $db ;
print __METHOD__ . " db->type= " . $db -> type . " user->id= " . $user -> id ;
//print " - db ".$db->db;
print " \n " ;
}
2020-05-03 22:47:43 +02:00
/**
* setUpBeforeClass
*
* @ return void
*/
2019-02-25 00:56:48 +01:00
public static function setUpBeforeClass ()
2010-11-20 16:25:08 +01:00
{
global $conf , $user , $langs , $db ;
$db -> begin (); // This is to have all actions inside a transaction even if test launched without suite.
print __METHOD__ . " \n " ;
}
2015-01-06 17:54:36 +01:00
2020-05-03 22:47:43 +02:00
/**
* tearDownAfterClass
*
* @ return void
*/
2010-11-20 16:25:08 +01:00
public static function tearDownAfterClass ()
{
global $conf , $user , $langs , $db ;
$db -> rollback ();
print __METHOD__ . " \n " ;
}
/**
2012-02-15 13:41:05 +01:00
* Init phpunit tests
*
* @ return void
2010-11-20 16:25:08 +01:00
*/
protected function setUp ()
{
global $conf , $user , $langs , $db ;
$conf = $this -> savconf ;
$user = $this -> savuser ;
$langs = $this -> savlangs ;
$db = $this -> savdb ;
print __METHOD__ . " \n " ;
}
2011-09-23 14:21:00 +02:00
2010-11-20 16:25:08 +01:00
/**
2012-02-15 13:41:05 +01:00
* End phpunit tests
*
* @ return void
2010-11-20 16:25:08 +01:00
*/
protected function tearDown ()
{
print __METHOD__ . " \n " ;
}
2019-09-24 13:54:52 +02:00
/**
* testSetLang
*
* @ return string
*/
public function testSetLang ()
{
global $conf ;
$conf = $this -> savconf ;
$tmplangs = new Translate ( '' , $conf );
$_SERVER [ 'HTTP_ACCEPT_LANGUAGE' ] = " ' malicious text with quote " ;
$tmplangs -> setDefaultLang ( 'auto' );
print __METHOD__ . ' $tmplangs->defaultlang=' . $tmplangs -> defaultlang . " \n " ;
$this -> assertEquals ( $tmplangs -> defaultlang , 'malicioustextwithquote_MALICIOUSTEXTWITHQUOTE' );
}
2010-11-20 16:25:08 +01:00
/**
2012-02-12 17:41:28 +01:00
* testGETPOST
*
* @ return string
2010-11-20 16:25:08 +01:00
*/
public function testGETPOST ()
{
global $conf , $user , $langs , $db ;
$conf = $this -> savconf ;
$user = $this -> savuser ;
$langs = $this -> savlangs ;
$db = $this -> savdb ;
$_COOKIE [ " id " ] = 111 ;
$_GET [ " param1 " ] = " 222 " ;
$_POST [ " param1 " ] = " 333 " ;
$_GET [ " param2 " ] = 'a/b#e(pr)qq-rr\cc' ;
2020-09-19 03:25:25 +02:00
$_GET [ " param3 " ] = '"na/b#e(pr)qq-rr\cc' ; // Same than param2 + " and n
2012-02-29 11:48:03 +01:00
$_GET [ " param4 " ] = '../dir' ;
2017-05-10 11:47:34 +02:00
$_GET [ " param5 " ] = " a_1-b " ;
2020-09-19 03:25:25 +02:00
$_POST [ " param6 " ] = " "><svg onload='console.log("123")'> " ;
$_GET [ " param7 " ] = '"c:\this is a path~1\aaan" abc<bad>def</bad>' ;
$_POST [ " param8 " ] = " Hacker<svg onload='console.log("123")' " ; // html tag is not closed so it is not detected as html tag but is still harmfull
2017-11-05 03:03:17 +01:00
2017-05-10 11:47:34 +02:00
// Test int
2019-01-27 13:07:22 +01:00
$result = GETPOST ( 'id' , 'int' ); // Must return nothing
2010-11-20 16:25:08 +01:00
print __METHOD__ . " result= " . $result . " \n " ;
2019-01-27 13:07:22 +01:00
$this -> assertEquals ( $result , '' );
2010-11-20 16:25:08 +01:00
2019-01-27 13:07:22 +01:00
$result = GETPOST ( " param1 " , 'int' );
2010-11-20 16:25:08 +01:00
print __METHOD__ . " result= " . $result . " \n " ;
2019-01-27 13:07:22 +01:00
$this -> assertEquals ( $result , 222 );
2010-11-20 16:25:08 +01:00
2019-01-27 13:07:22 +01:00
$result = GETPOST ( " param1 " , 'int' , 2 );
2010-11-20 16:25:08 +01:00
print __METHOD__ . " result= " . $result . " \n " ;
2019-01-27 13:07:22 +01:00
$this -> assertEquals ( $result , 333 );
2010-11-20 16:25:08 +01:00
2017-05-10 11:47:34 +02:00
// Test alpha
2019-01-27 13:07:22 +01:00
$result = GETPOST ( " param2 " , 'alpha' );
2010-11-20 16:25:08 +01:00
print __METHOD__ . " result= " . $result . " \n " ;
2019-01-27 13:07:22 +01:00
$this -> assertEquals ( $result , $_GET [ " param2 " ]);
2010-11-20 16:25:08 +01:00
2020-02-20 14:07:25 +01:00
$result = GETPOST ( " param3 " , 'alpha' ); // Must return string sanitized from char "
2010-11-20 16:25:08 +01:00
print __METHOD__ . " result= " . $result . " \n " ;
2020-09-19 03:25:25 +02:00
$this -> assertEquals ( $result , 'na/b#e(pr)qq-rr\cc' );
2010-11-20 16:25:08 +01:00
2020-02-20 14:07:25 +01:00
$result = GETPOST ( " param4 " , 'alpha' ); // Must return string sanitized from ../
2012-02-29 11:48:03 +01:00
print __METHOD__ . " result= " . $result . " \n " ;
2020-02-20 14:07:25 +01:00
$this -> assertEquals ( $result , 'dir' );
2012-02-29 11:48:03 +01:00
2017-05-10 11:47:34 +02:00
// Test aZ09
2020-02-20 14:07:25 +01:00
$result = GETPOST ( " param1 " , 'aZ09' );
2017-05-10 11:47:34 +02:00
print __METHOD__ . " result= " . $result . " \n " ;
2019-01-27 13:07:22 +01:00
$this -> assertEquals ( $result , $_GET [ " param1 " ]);
2017-11-05 03:03:17 +01:00
2020-02-20 14:07:25 +01:00
$result = GETPOST ( " param2 " , 'aZ09' ); // Must return '' as string contains car not in aZ09 definition
2017-05-10 11:47:34 +02:00
print __METHOD__ . " result= " . $result . " \n " ;
2019-01-27 13:07:22 +01:00
$this -> assertEquals ( $result , '' );
2017-11-05 03:03:17 +01:00
2020-02-20 14:07:25 +01:00
$result = GETPOST ( " param3 " , 'aZ09' ); // Must return '' as string contains car not in aZ09 definition
2017-05-10 11:47:34 +02:00
print __METHOD__ . " result= " . $result . " \n " ;
2019-01-27 13:07:22 +01:00
$this -> assertEquals ( $result , '' );
2017-11-05 03:03:17 +01:00
2020-02-20 14:07:25 +01:00
$result = GETPOST ( " param4 " , 'aZ09' ); // Must return '' as string contains car not in aZ09 definition
2017-05-10 11:47:34 +02:00
print __METHOD__ . " result= " . $result . " \n " ;
2020-09-17 21:09:16 +02:00
$this -> assertEquals ( '' , $result );
2017-11-05 03:03:17 +01:00
2019-01-27 13:07:22 +01:00
$result = GETPOST ( " param5 " , 'aZ09' );
2017-05-10 11:47:34 +02:00
print __METHOD__ . " result= " . $result . " \n " ;
2020-09-17 21:09:16 +02:00
$this -> assertEquals ( $_GET [ " param5 " ], $result );
$result = GETPOST ( " param6 " , 'nohtml' );
print __METHOD__ . " result= " . $result . " \n " ;
$this -> assertEquals ( '">' , $result );
2017-05-10 11:47:34 +02:00
2020-09-19 03:25:25 +02:00
// With restricthtml we must remove html open/close tag and content but not htmlentities like n
2020-09-18 01:01:01 +02:00
$result = GETPOST ( " param7 " , 'restricthtml' );
print __METHOD__ . " result= " . $result . " \n " ;
2020-09-19 03:25:25 +02:00
$this -> assertEquals ( '"c:\this is a path~1\aaan" abcdef' , $result );
// With alphanohtml, we must convert the html entities like n
$result = GETPOST ( " param8 " , 'alphanohtml' );
print __METHOD__ . " result= " . $result . " \n " ;
$this -> assertEquals ( " Hacker<svg onload='console.log(123)' " , $result );
2020-09-18 01:01:01 +02:00
2012-02-29 11:48:03 +01:00
return $result ;
2010-11-20 16:25:08 +01:00
}
2011-09-23 14:21:00 +02:00
/**
2012-02-12 17:41:28 +01:00
* testCheckLoginPassEntity
*
* @ return void
2011-09-23 14:21:00 +02:00
*/
public function testCheckLoginPassEntity ()
{
2019-01-27 13:07:22 +01:00
$login = checkLoginPassEntity ( 'loginbidon' , 'passwordbidon' , 1 , array ( 'dolibarr' ));
2011-09-23 14:21:00 +02:00
print __METHOD__ . " login= " . $login . " \n " ;
2019-01-27 13:07:22 +01:00
$this -> assertEquals ( $login , '' );
2011-09-23 14:21:00 +02:00
2019-01-27 13:07:22 +01:00
$login = checkLoginPassEntity ( 'admin' , 'passwordbidon' , 1 , array ( 'dolibarr' ));
2011-09-23 14:21:00 +02:00
print __METHOD__ . " login= " . $login . " \n " ;
2019-01-27 13:07:22 +01:00
$this -> assertEquals ( $login , '' );
2011-09-23 14:21:00 +02:00
2019-01-27 13:07:22 +01:00
$login = checkLoginPassEntity ( 'admin' , 'admin' , 1 , array ( 'dolibarr' )); // Should works because admin/admin exists
2011-09-23 14:21:00 +02:00
print __METHOD__ . " login= " . $login . " \n " ;
2019-01-27 13:07:22 +01:00
$this -> assertEquals ( $login , 'admin' );
2011-09-23 14:21:00 +02:00
2019-01-27 13:07:22 +01:00
$login = checkLoginPassEntity ( 'admin' , 'admin' , 1 , array ( 'http' , 'dolibarr' )); // Should work because of second authetntication method
2011-09-23 14:21:00 +02:00
print __METHOD__ . " login= " . $login . " \n " ;
2019-01-27 13:07:22 +01:00
$this -> assertEquals ( $login , 'admin' );
2011-09-23 14:21:00 +02:00
2019-01-27 13:07:22 +01:00
$login = checkLoginPassEntity ( 'admin' , 'admin' , 1 , array ( 'forceuser' ));
2011-09-23 14:21:00 +02:00
print __METHOD__ . " login= " . $login . " \n " ;
2019-01-27 13:07:22 +01:00
$this -> assertEquals ( $login , '' ); // Expected '' because should failed because login 'auto' does not exists
2011-09-23 14:21:00 +02:00
}
2010-11-20 16:25:08 +01:00
/**
2012-02-12 17:41:28 +01:00
* testEncodeDecode
*
* @ return number
2010-11-20 16:25:08 +01:00
*/
2011-09-24 15:44:35 +02:00
public function testEncodeDecode ()
2010-11-20 16:25:08 +01:00
{
2018-04-19 12:03:42 +02:00
$stringtotest = " This is a string to test encode/decode. This is a string to test encode/decode. This is a string to test encode/decode. " ;
2010-11-20 16:25:08 +01:00
2011-09-24 15:44:35 +02:00
$encodedstring = dol_encode ( $stringtotest );
$decodedstring = dol_decode ( $encodedstring );
print __METHOD__ . " encodedstring= " . $encodedstring . " " . base64_encode ( $stringtotest ) . " \n " ;
2019-01-27 13:07:22 +01:00
$this -> assertEquals ( $stringtotest , $decodedstring , 'Use dol_encode/decode with no parameter' );
2018-04-19 12:03:42 +02:00
$encodedstring = dol_encode ( $stringtotest , 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' );
$decodedstring = dol_decode ( $encodedstring , 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' );
print __METHOD__ . " encodedstring= " . $encodedstring . " " . base64_encode ( $stringtotest ) . " \n " ;
2019-01-27 13:07:22 +01:00
$this -> assertEquals ( $stringtotest , $decodedstring , 'Use dol_encode/decode with a key parameter' );
2010-11-20 16:25:08 +01:00
2011-12-05 19:41:38 +01:00
return 0 ;
2011-09-24 15:44:35 +02:00
}
2020-10-15 19:36:08 +02:00
/**
* testDolStringOnlyTheseHtmlTags
*
* @ return number
*/
public function testDolHTMLEntityDecode ()
{
$stringtotest = 'a : b " c ' d ' e é' ;
$decodedstring = dol_html_entity_decode ( $stringtotest , ENT_QUOTES );
$this -> assertEquals ( 'a : b " c \' d ' e é' , $decodedstring , 'Function did not sanitize correclty' );
$stringtotest = 'a : b " c ' d ' e é' ;
$decodedstring = dol_html_entity_decode ( $stringtotest , ENT_QUOTES | ENT_HTML5 );
$this -> assertEquals ( 'a : b " c \' d \' e é' , $decodedstring , 'Function did not sanitize correclty' );
return 0 ;
}
/**
* testDolStringOnlyTheseHtmlTags
*
* @ return number
*/
public function testDolStringOnlyTheseHtmlTags ()
{
$stringtotest = '<a href="javascript:aaa">bbbڴ' ;
$decodedstring = dol_string_onlythesehtmltags ( $stringtotest , 1 , 1 , 1 );
$this -> assertEquals ( '<a href="aaa">bbbڴ' , $decodedstring , 'Function did not sanitize correclty with test 1' );
$stringtotest = '<a href="java' . chr ( 0 ) . 'script:aaa">bbbڴ' ;
$decodedstring = dol_string_onlythesehtmltags ( $stringtotest , 1 , 1 , 1 );
$this -> assertEquals ( '<a href="aaa">bbbڴ' , $decodedstring , 'Function did not sanitize correclty with test 2' );
$stringtotest = '<a href="javascript:aaa">bbbڴ' ;
$decodedstring = dol_string_onlythesehtmltags ( $stringtotest , 1 , 1 , 1 );
$this -> assertEquals ( '<a href="aaa">bbbڴ' , $decodedstring , 'Function did not sanitize correclty with test 3' );
return 0 ;
}
2011-09-24 15:44:35 +02:00
/**
2012-02-12 17:41:28 +01:00
* testGetRandomPassword
*
* @ return number
2011-09-24 15:44:35 +02:00
*/
public function testGetRandomPassword ()
{
global $conf ;
2018-12-21 09:56:31 +01:00
$genpass1 = getRandomPassword ( true ); // Should be a string return by dol_hash (if no option set, will be md5)
print __METHOD__ . " genpass1= " . $genpass1 . " \n " ;
$this -> assertEquals ( strlen ( $genpass1 ), 32 );
$genpass1 = getRandomPassword ( true , array ( 'I' )); // Should be a string return by dol_hash (if no option set, will be md5)
2011-09-24 15:44:35 +02:00
print __METHOD__ . " genpass1= " . $genpass1 . " \n " ;
2017-11-05 03:03:17 +01:00
$this -> assertEquals ( strlen ( $genpass1 ), 32 );
2011-09-24 15:44:35 +02:00
$conf -> global -> USER_PASSWORD_GENERATED = 'None' ;
2018-12-21 09:56:31 +01:00
$genpass2 = getRandomPassword ( false ); // Should return an empty string
2011-09-24 15:44:35 +02:00
print __METHOD__ . " genpass2= " . $genpass2 . " \n " ;
2017-11-05 03:03:17 +01:00
$this -> assertEquals ( $genpass2 , '' );
2011-09-24 15:44:35 +02:00
$conf -> global -> USER_PASSWORD_GENERATED = 'Standard' ;
2020-08-07 14:59:22 +02:00
$genpass3 = getRandomPassword ( false ); // Should return a password of 10 chars
2011-09-24 15:44:35 +02:00
print __METHOD__ . " genpass3= " . $genpass3 . " \n " ;
2020-08-07 14:59:22 +02:00
$this -> assertEquals ( strlen ( $genpass3 ), 10 );
2010-11-20 16:25:08 +01:00
2011-12-05 19:41:38 +01:00
return 0 ;
2010-11-20 16:25:08 +01:00
}
2012-02-12 17:41:28 +01:00
/**
2012-02-12 18:30:50 +01:00
* testRestrictedArea
2012-02-12 17:41:28 +01:00
*
2012-02-12 18:30:50 +01:00
* @ return void
2012-02-12 17:41:28 +01:00
*/
public function testRestrictedArea ()
{
2012-02-12 18:30:50 +01:00
global $conf , $user , $langs , $db ;
$conf = $this -> savconf ;
$user = $this -> savuser ;
$langs = $this -> savlangs ;
$db = $this -> savdb ;
2012-02-12 17:41:28 +01:00
2012-02-12 18:30:50 +01:00
//$dummyuser=new User($db);
//$result=restrictedArea($dummyuser,'societe');
2012-02-12 17:41:28 +01:00
2019-01-27 13:07:22 +01:00
$result = restrictedArea ( $user , 'societe' );
$this -> assertEquals ( 1 , $result );
2012-02-12 17:41:28 +01:00
}
2020-10-27 15:06:16 +01:00
/**
* testGetRandomPassword
*
* @ return number
*/
public function testGetURLContent ()
{
global $conf ;
include_once DOL_DOCUMENT_ROOT . '/core/lib/geturl.lib.php' ;
$url = 'ftp://aaaa' ;
$tmp = getURLContent ( $url );
print __METHOD__ . " url= " . $url . " \n " ;
$this -> assertGreaterThan ( 0 , strpos ( $tmp [ 'curl_error_msg' ], 'not supported' )); // Test error if return does not contains 'not supported'
$url = 'https://www.dolibarr.fr' ; // This is a redirect 301 page
$tmp = getURLContent ( $url , 'GET' , '' , 0 ); // We do NOT follow
print __METHOD__ . " url= " . $url . " \n " ;
$this -> assertEquals ( 301 , $tmp [ 'http_code' ], 'GET url 301 without following -> 301' );
$url = 'https://www.dolibarr.fr' ; // This is a redirect 301 page
$tmp = getURLContent ( $url ); // We DO follow
print __METHOD__ . " url= " . $url . " \n " ;
//var_dump($tmp);
$this -> assertEquals ( 200 , $tmp [ 'http_code' ], 'GET url 301 with following -> 200' ); // Test error if return does not contains 'not supported'
return 0 ;
}
2010-11-20 16:25:08 +01:00
}