pictcode / lib / Cake / Test / Case / Controller / Component / SecurityComponentTest.php @ 787484d2
履歴 | 表示 | アノテート | ダウンロード (42.957 KB)
| 1 | 635eef61 | spyder1211 | <?php
 | 
      
|---|---|---|---|
| 2 | /**
 | 
      ||
| 3 |  * SecurityComponentTest file
 | 
      ||
| 4 |  *
 | 
      ||
| 5 |  * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
 | 
      ||
| 6 |  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 | 
      ||
| 7 |  *
 | 
      ||
| 8 |  * Licensed under The MIT License
 | 
      ||
| 9 |  * For full copyright and license information, please see the LICENSE.txt
 | 
      ||
| 10 |  * Redistributions of files must retain the above copyright notice
 | 
      ||
| 11 |  *
 | 
      ||
| 12 |  * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 | 
      ||
| 13 |  * @link          http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
 | 
      ||
| 14 |  * @package       Cake.Test.Case.Controller.Component
 | 
      ||
| 15 |  * @since         CakePHP(tm) v 1.2.0.5435
 | 
      ||
| 16 |  * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 | 
      ||
| 17 |  */
 | 
      ||
| 18 | |||
| 19 | App::uses('SecurityComponent', 'Controller/Component');  | 
      ||
| 20 | App::uses('Controller', 'Controller');  | 
      ||
| 21 | |||
| 22 | /**
 | 
      ||
| 23 |  * TestSecurityComponent
 | 
      ||
| 24 |  *
 | 
      ||
| 25 |  * @package       Cake.Test.Case.Controller.Component
 | 
      ||
| 26 |  */
 | 
      ||
| 27 | class TestSecurityComponent extends SecurityComponent {  | 
      ||
| 28 | |||
| 29 | /**
 | 
      ||
| 30 |  * validatePost method
 | 
      ||
| 31 |  *
 | 
      ||
| 32 |  * @param Controller $controller
 | 
      ||
| 33 |  * @return bool
 | 
      ||
| 34 |  */
 | 
      ||
| 35 | public function validatePost(Controller $controller) {  | 
      ||
| 36 | return $this->_validatePost($controller);  | 
      ||
| 37 | }  | 
      ||
| 38 | |||
| 39 | }  | 
      ||
| 40 | |||
| 41 | /**
 | 
      ||
| 42 |  * SecurityTestController
 | 
      ||
| 43 |  *
 | 
      ||
| 44 |  * @package       Cake.Test.Case.Controller.Component
 | 
      ||
| 45 |  */
 | 
      ||
| 46 | class SecurityTestController extends Controller {  | 
      ||
| 47 | |||
| 48 | /**
 | 
      ||
| 49 |  * components property
 | 
      ||
| 50 |  *
 | 
      ||
| 51 |  * @var array
 | 
      ||
| 52 |  */
 | 
      ||
| 53 | public $components = array('Session', 'TestSecurity');  | 
      ||
| 54 | |||
| 55 | /**
 | 
      ||
| 56 |  * failed property
 | 
      ||
| 57 |  *
 | 
      ||
| 58 |  * @var bool
 | 
      ||
| 59 |  */
 | 
      ||
| 60 | public $failed = false;  | 
      ||
| 61 | |||
| 62 | /**
 | 
      ||
| 63 |  * Used for keeping track of headers in test
 | 
      ||
| 64 |  *
 | 
      ||
| 65 |  * @var array
 | 
      ||
| 66 |  */
 | 
      ||
| 67 | public $testHeaders = array();  | 
      ||
| 68 | |||
| 69 | /**
 | 
      ||
| 70 |  * fail method
 | 
      ||
| 71 |  *
 | 
      ||
| 72 |  * @return void
 | 
      ||
| 73 |  */
 | 
      ||
| 74 | public function fail() {  | 
      ||
| 75 | $this->failed = true;  | 
      ||
| 76 | }  | 
      ||
| 77 | |||
| 78 | /**
 | 
      ||
| 79 |  * redirect method
 | 
      ||
| 80 |  *
 | 
      ||
| 81 |  * @param string|array $url
 | 
      ||
| 82 |  * @param mixed $code
 | 
      ||
| 83 |  * @param mixed $exit
 | 
      ||
| 84 |  * @return void
 | 
      ||
| 85 |  */
 | 
      ||
| 86 | public function redirect($url, $status = null, $exit = true) {  | 
      ||
| 87 | return $status;  | 
      ||
| 88 | }  | 
      ||
| 89 | |||
| 90 | /**
 | 
      ||
| 91 |  * Convenience method for header()
 | 
      ||
| 92 |  *
 | 
      ||
| 93 |  * @param string $status
 | 
      ||
| 94 |  * @return void
 | 
      ||
| 95 |  */
 | 
      ||
| 96 | public function header($status) {  | 
      ||
| 97 | $this->testHeaders[] = $status;  | 
      ||
| 98 | }  | 
      ||
| 99 | |||
| 100 | }  | 
      ||
| 101 | |||
| 102 | class BrokenCallbackController extends Controller {  | 
      ||
| 103 | |||
| 104 | public $name = 'UncallableCallback';  | 
      ||
| 105 | |||
| 106 | public $components = array('Session', 'TestSecurity');  | 
      ||
| 107 | |||
| 108 | public function index() {  | 
      ||
| 109 | }  | 
      ||
| 110 | |||
| 111 | protected function _fail() {  | 
      ||
| 112 | }  | 
      ||
| 113 | |||
| 114 | }  | 
      ||
| 115 | |||
| 116 | /**
 | 
      ||
| 117 |  * SecurityComponentTest class
 | 
      ||
| 118 |  *
 | 
      ||
| 119 |  * @package       Cake.Test.Case.Controller.Component
 | 
      ||
| 120 |  */
 | 
      ||
| 121 | class SecurityComponentTest extends CakeTestCase {  | 
      ||
| 122 | |||
| 123 | /**
 | 
      ||
| 124 |  * Controller property
 | 
      ||
| 125 |  *
 | 
      ||
| 126 |  * @var SecurityTestController
 | 
      ||
| 127 |  */
 | 
      ||
| 128 | public $Controller;  | 
      ||
| 129 | |||
| 130 | /**
 | 
      ||
| 131 |  * oldSalt property
 | 
      ||
| 132 |  *
 | 
      ||
| 133 |  * @var string
 | 
      ||
| 134 |  */
 | 
      ||
| 135 | public $oldSalt;  | 
      ||
| 136 | |||
| 137 | /**
 | 
      ||
| 138 |  * setUp method
 | 
      ||
| 139 |  *
 | 
      ||
| 140 |  * @return void
 | 
      ||
| 141 |  */
 | 
      ||
| 142 | public function setUp() {  | 
      ||
| 143 |                 parent::setUp();
 | 
      ||
| 144 | |||
| 145 | $request = $this->getMock('CakeRequest', array('here'), array('posts/index', false));  | 
      ||
| 146 | $request->addParams(array('controller' => 'posts', 'action' => 'index'));  | 
      ||
| 147 | $request->expects($this->any())  | 
      ||
| 148 |                         ->method('here')
 | 
      ||
| 149 | ->will($this->returnValue('/posts/index'));  | 
      ||
| 150 | |||
| 151 | $this->Controller = new SecurityTestController($request);  | 
      ||
| 152 | $this->Controller->Components->init($this->Controller);  | 
      ||
| 153 | $this->Controller->Security = $this->Controller->TestSecurity;  | 
      ||
| 154 | $this->Controller->Security->blackHoleCallback = 'fail';  | 
      ||
| 155 | $this->Security = $this->Controller->Security;  | 
      ||
| 156 | $this->Security->csrfCheck = false;  | 
      ||
| 157 | |||
| 158 | Configure::write('Security.salt', 'foo!');  | 
      ||
| 159 | }  | 
      ||
| 160 | |||
| 161 | /**
 | 
      ||
| 162 |  * Tear-down method. Resets environment state.
 | 
      ||
| 163 |  *
 | 
      ||
| 164 |  * @return void
 | 
      ||
| 165 |  */
 | 
      ||
| 166 | public function tearDown() {  | 
      ||
| 167 |                 parent::tearDown();
 | 
      ||
| 168 | $this->Controller->Session->delete('_Token');  | 
      ||
| 169 | unset($this->Controller->Security);  | 
      ||
| 170 | unset($this->Controller->Component);  | 
      ||
| 171 | unset($this->Controller);  | 
      ||
| 172 | }  | 
      ||
| 173 | |||
| 174 | /**
 | 
      ||
| 175 |  * Test that requests are still blackholed when controller has incorrect
 | 
      ||
| 176 |  * visibility keyword in the blackhole callback
 | 
      ||
| 177 |  *
 | 
      ||
| 178 |  * @expectedException BadRequestException
 | 
      ||
| 179 |  * @return void
 | 
      ||
| 180 |  */
 | 
      ||
| 181 | public function testBlackholeWithBrokenCallback() {  | 
      ||
| 182 | $request = new CakeRequest('posts/index', false);  | 
      ||
| 183 | $request->addParams(array(  | 
      ||
| 184 | 'controller' => 'posts', 'action' => 'index')  | 
      ||
| 185 | );  | 
      ||
| 186 | $this->Controller = new BrokenCallbackController($request);  | 
      ||
| 187 | $this->Controller->Components->init($this->Controller);  | 
      ||
| 188 | $this->Controller->Security = $this->Controller->TestSecurity;  | 
      ||
| 189 | $this->Controller->Security->blackHoleCallback = '_fail';  | 
      ||
| 190 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 191 | $this->Controller->Security->blackHole($this->Controller, 'csrf');  | 
      ||
| 192 | }  | 
      ||
| 193 | |||
| 194 | /**
 | 
      ||
| 195 |  * Ensure that directly requesting the blackholeCallback as the controller
 | 
      ||
| 196 |  * action results in an exception.
 | 
      ||
| 197 |  *
 | 
      ||
| 198 |  * @return void
 | 
      ||
| 199 |  */
 | 
      ||
| 200 | public function testExceptionWhenActionIsBlackholeCallback() {  | 
      ||
| 201 | $this->Controller->request->addParams(array(  | 
      ||
| 202 | 'controller' => 'posts',  | 
      ||
| 203 | 'action' => 'fail'  | 
      ||
| 204 | ));  | 
      ||
| 205 | $this->assertFalse($this->Controller->failed);  | 
      ||
| 206 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 207 | $this->assertTrue($this->Controller->failed, 'Request was blackholed.');  | 
      ||
| 208 | }  | 
      ||
| 209 | |||
| 210 | /**
 | 
      ||
| 211 |  * test that initialize can set properties.
 | 
      ||
| 212 |  *
 | 
      ||
| 213 |  * @return void
 | 
      ||
| 214 |  */
 | 
      ||
| 215 | public function testConstructorSettingProperties() {  | 
      ||
| 216 | $settings = array(  | 
      ||
| 217 | 'requirePost' => array('edit', 'update'),  | 
      ||
| 218 | 'requireSecure' => array('update_account'),  | 
      ||
| 219 | 'requireGet' => array('index'),  | 
      ||
| 220 | 'validatePost' => false,  | 
      ||
| 221 | );  | 
      ||
| 222 | $Security = new SecurityComponent($this->Controller->Components, $settings);  | 
      ||
| 223 | $this->Controller->Security->initialize($this->Controller, $settings);  | 
      ||
| 224 | $this->assertEquals($Security->requirePost, $settings['requirePost']);  | 
      ||
| 225 | $this->assertEquals($Security->requireSecure, $settings['requireSecure']);  | 
      ||
| 226 | $this->assertEquals($Security->requireGet, $settings['requireGet']);  | 
      ||
| 227 | $this->assertEquals($Security->validatePost, $settings['validatePost']);  | 
      ||
| 228 | }  | 
      ||
| 229 | |||
| 230 | /**
 | 
      ||
| 231 |  * testStartup method
 | 
      ||
| 232 |  *
 | 
      ||
| 233 |  * @return void
 | 
      ||
| 234 |  */
 | 
      ||
| 235 | public function testStartup() {  | 
      ||
| 236 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 237 | $result = $this->Controller->params['_Token']['key'];  | 
      ||
| 238 | $this->assertNotNull($result);  | 
      ||
| 239 | $this->assertTrue($this->Controller->Session->check('_Token'));  | 
      ||
| 240 | }  | 
      ||
| 241 | |||
| 242 | /**
 | 
      ||
| 243 |  * testRequirePostFail method
 | 
      ||
| 244 |  *
 | 
      ||
| 245 |  * @return void
 | 
      ||
| 246 |  */
 | 
      ||
| 247 | public function testRequirePostFail() {  | 
      ||
| 248 | $_SERVER['REQUEST_METHOD'] = 'GET';  | 
      ||
| 249 | $this->Controller->request['action'] = 'posted';  | 
      ||
| 250 | $this->Controller->Security->requirePost(array('posted'));  | 
      ||
| 251 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 252 | $this->assertTrue($this->Controller->failed);  | 
      ||
| 253 | }  | 
      ||
| 254 | |||
| 255 | /**
 | 
      ||
| 256 |  * testRequirePostSucceed method
 | 
      ||
| 257 |  *
 | 
      ||
| 258 |  * @return void
 | 
      ||
| 259 |  */
 | 
      ||
| 260 | public function testRequirePostSucceed() {  | 
      ||
| 261 | $_SERVER['REQUEST_METHOD'] = 'POST';  | 
      ||
| 262 | $this->Controller->request['action'] = 'posted';  | 
      ||
| 263 | $this->Controller->Security->requirePost('posted');  | 
      ||
| 264 | $this->Security->startup($this->Controller);  | 
      ||
| 265 | $this->assertFalse($this->Controller->failed);  | 
      ||
| 266 | }  | 
      ||
| 267 | |||
| 268 | /**
 | 
      ||
| 269 |  * testRequireSecureFail method
 | 
      ||
| 270 |  *
 | 
      ||
| 271 |  * @return void
 | 
      ||
| 272 |  */
 | 
      ||
| 273 | public function testRequireSecureFail() {  | 
      ||
| 274 | $_SERVER['HTTPS'] = 'off';  | 
      ||
| 275 | $_SERVER['REQUEST_METHOD'] = 'POST';  | 
      ||
| 276 | $this->Controller->request['action'] = 'posted';  | 
      ||
| 277 | $this->Controller->Security->requireSecure(array('posted'));  | 
      ||
| 278 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 279 | $this->assertTrue($this->Controller->failed);  | 
      ||
| 280 | }  | 
      ||
| 281 | |||
| 282 | /**
 | 
      ||
| 283 |  * testRequireSecureSucceed method
 | 
      ||
| 284 |  *
 | 
      ||
| 285 |  * @return void
 | 
      ||
| 286 |  */
 | 
      ||
| 287 | public function testRequireSecureSucceed() {  | 
      ||
| 288 | $_SERVER['REQUEST_METHOD'] = 'Secure';  | 
      ||
| 289 | $this->Controller->request['action'] = 'posted';  | 
      ||
| 290 | $_SERVER['HTTPS'] = 'on';  | 
      ||
| 291 | $this->Controller->Security->requireSecure('posted');  | 
      ||
| 292 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 293 | $this->assertFalse($this->Controller->failed);  | 
      ||
| 294 | }  | 
      ||
| 295 | |||
| 296 | /**
 | 
      ||
| 297 |  * testRequireAuthFail method
 | 
      ||
| 298 |  *
 | 
      ||
| 299 |  * @return void
 | 
      ||
| 300 |  */
 | 
      ||
| 301 | public function testRequireAuthFail() {  | 
      ||
| 302 | $_SERVER['REQUEST_METHOD'] = 'AUTH';  | 
      ||
| 303 | $this->Controller->request['action'] = 'posted';  | 
      ||
| 304 | $this->Controller->request->data = array('username' => 'willy', 'password' => 'somePass');  | 
      ||
| 305 | $this->Controller->Security->requireAuth(array('posted'));  | 
      ||
| 306 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 307 | $this->assertTrue($this->Controller->failed);  | 
      ||
| 308 | |||
| 309 | $this->Controller->Session->write('_Token', array('allowedControllers' => array()));  | 
      ||
| 310 | $this->Controller->request->data = array('username' => 'willy', 'password' => 'somePass');  | 
      ||
| 311 | $this->Controller->request['action'] = 'posted';  | 
      ||
| 312 | $this->Controller->Security->requireAuth('posted');  | 
      ||
| 313 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 314 | $this->assertTrue($this->Controller->failed);  | 
      ||
| 315 | |||
| 316 | $this->Controller->Session->write('_Token', array(  | 
      ||
| 317 | 'allowedControllers' => array('SecurityTest'), 'allowedActions' => array('posted2')  | 
      ||
| 318 | ));  | 
      ||
| 319 | $this->Controller->request->data = array('username' => 'willy', 'password' => 'somePass');  | 
      ||
| 320 | $this->Controller->request['action'] = 'posted';  | 
      ||
| 321 | $this->Controller->Security->requireAuth('posted');  | 
      ||
| 322 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 323 | $this->assertTrue($this->Controller->failed);  | 
      ||
| 324 | }  | 
      ||
| 325 | |||
| 326 | /**
 | 
      ||
| 327 |  * testRequireAuthSucceed method
 | 
      ||
| 328 |  *
 | 
      ||
| 329 |  * @return void
 | 
      ||
| 330 |  */
 | 
      ||
| 331 | public function testRequireAuthSucceed() {  | 
      ||
| 332 | $_SERVER['REQUEST_METHOD'] = 'AUTH';  | 
      ||
| 333 | $this->Controller->Security->unlockedActions = array('posted');  | 
      ||
| 334 | $this->Controller->request['action'] = 'posted';  | 
      ||
| 335 | $this->Controller->Security->requireAuth('posted');  | 
      ||
| 336 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 337 | $this->assertFalse($this->Controller->failed);  | 
      ||
| 338 | |||
| 339 | $this->Controller->Security->Session->write('_Token', array(  | 
      ||
| 340 | 'allowedControllers' => array('SecurityTest'),  | 
      ||
| 341 | 'allowedActions' => array('posted')  | 
      ||
| 342 | ));  | 
      ||
| 343 | $this->Controller->request['controller'] = 'SecurityTest';  | 
      ||
| 344 | $this->Controller->request['action'] = 'posted';  | 
      ||
| 345 | |||
| 346 | $this->Controller->request->data = array(  | 
      ||
| 347 | 'username' => 'willy',  | 
      ||
| 348 | 'password' => 'somePass',  | 
      ||
| 349 | '_Token' => ''  | 
      ||
| 350 | );  | 
      ||
| 351 | $this->Controller->action = 'posted';  | 
      ||
| 352 | $this->Controller->Security->requireAuth('posted');  | 
      ||
| 353 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 354 | $this->assertFalse($this->Controller->failed);  | 
      ||
| 355 | }  | 
      ||
| 356 | |||
| 357 | /**
 | 
      ||
| 358 |  * testRequirePostSucceedWrongMethod method
 | 
      ||
| 359 |  *
 | 
      ||
| 360 |  * @return void
 | 
      ||
| 361 |  */
 | 
      ||
| 362 | public function testRequirePostSucceedWrongMethod() {  | 
      ||
| 363 | $_SERVER['REQUEST_METHOD'] = 'GET';  | 
      ||
| 364 | $this->Controller->request['action'] = 'getted';  | 
      ||
| 365 | $this->Controller->Security->requirePost('posted');  | 
      ||
| 366 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 367 | $this->assertFalse($this->Controller->failed);  | 
      ||
| 368 | }  | 
      ||
| 369 | |||
| 370 | /**
 | 
      ||
| 371 |  * testRequireGetFail method
 | 
      ||
| 372 |  *
 | 
      ||
| 373 |  * @return void
 | 
      ||
| 374 |  */
 | 
      ||
| 375 | public function testRequireGetFail() {  | 
      ||
| 376 | $_SERVER['REQUEST_METHOD'] = 'POST';  | 
      ||
| 377 | $this->Controller->request['action'] = 'getted';  | 
      ||
| 378 | $this->Controller->Security->requireGet(array('getted'));  | 
      ||
| 379 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 380 | $this->assertTrue($this->Controller->failed);  | 
      ||
| 381 | }  | 
      ||
| 382 | |||
| 383 | /**
 | 
      ||
| 384 |  * testRequireGetSucceed method
 | 
      ||
| 385 |  *
 | 
      ||
| 386 |  * @return void
 | 
      ||
| 387 |  */
 | 
      ||
| 388 | public function testRequireGetSucceed() {  | 
      ||
| 389 | $_SERVER['REQUEST_METHOD'] = 'GET';  | 
      ||
| 390 | $this->Controller->request['action'] = 'getted';  | 
      ||
| 391 | $this->Controller->Security->requireGet('getted');  | 
      ||
| 392 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 393 | $this->assertFalse($this->Controller->failed);  | 
      ||
| 394 | }  | 
      ||
| 395 | |||
| 396 | /**
 | 
      ||
| 397 |  * testRequireGetSucceedWrongMethod method
 | 
      ||
| 398 |  *
 | 
      ||
| 399 |  * @return void
 | 
      ||
| 400 |  */
 | 
      ||
| 401 | public function testRequireGetSucceedWrongMethod() {  | 
      ||
| 402 | $_SERVER['REQUEST_METHOD'] = 'POST';  | 
      ||
| 403 | $this->Controller->request['action'] = 'posted';  | 
      ||
| 404 | $this->Security->requireGet('getted');  | 
      ||
| 405 | $this->Security->startup($this->Controller);  | 
      ||
| 406 | $this->assertFalse($this->Controller->failed);  | 
      ||
| 407 | }  | 
      ||
| 408 | |||
| 409 | /**
 | 
      ||
| 410 |  * testRequirePutFail method
 | 
      ||
| 411 |  *
 | 
      ||
| 412 |  * @return void
 | 
      ||
| 413 |  */
 | 
      ||
| 414 | public function testRequirePutFail() {  | 
      ||
| 415 | $_SERVER['REQUEST_METHOD'] = 'POST';  | 
      ||
| 416 | $this->Controller->request['action'] = 'putted';  | 
      ||
| 417 | $this->Controller->Security->requirePut(array('putted'));  | 
      ||
| 418 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 419 | $this->assertTrue($this->Controller->failed);  | 
      ||
| 420 | }  | 
      ||
| 421 | |||
| 422 | /**
 | 
      ||
| 423 |  * testRequirePutSucceed method
 | 
      ||
| 424 |  *
 | 
      ||
| 425 |  * @return void
 | 
      ||
| 426 |  */
 | 
      ||
| 427 | public function testRequirePutSucceed() {  | 
      ||
| 428 | $_SERVER['REQUEST_METHOD'] = 'PUT';  | 
      ||
| 429 | $this->Controller->request['action'] = 'putted';  | 
      ||
| 430 | $this->Controller->Security->requirePut('putted');  | 
      ||
| 431 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 432 | $this->assertFalse($this->Controller->failed);  | 
      ||
| 433 | }  | 
      ||
| 434 | |||
| 435 | /**
 | 
      ||
| 436 |  * testRequirePutSucceedWrongMethod method
 | 
      ||
| 437 |  *
 | 
      ||
| 438 |  * @return void
 | 
      ||
| 439 |  */
 | 
      ||
| 440 | public function testRequirePutSucceedWrongMethod() {  | 
      ||
| 441 | $_SERVER['REQUEST_METHOD'] = 'POST';  | 
      ||
| 442 | $this->Controller->request['action'] = 'posted';  | 
      ||
| 443 | $this->Controller->Security->requirePut('putted');  | 
      ||
| 444 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 445 | $this->assertFalse($this->Controller->failed);  | 
      ||
| 446 | }  | 
      ||
| 447 | |||
| 448 | /**
 | 
      ||
| 449 |  * testRequireDeleteFail method
 | 
      ||
| 450 |  *
 | 
      ||
| 451 |  * @return void
 | 
      ||
| 452 |  */
 | 
      ||
| 453 | public function testRequireDeleteFail() {  | 
      ||
| 454 | $_SERVER['REQUEST_METHOD'] = 'POST';  | 
      ||
| 455 | $this->Controller->request['action'] = 'deleted';  | 
      ||
| 456 | $this->Controller->Security->requireDelete(array('deleted', 'other_method'));  | 
      ||
| 457 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 458 | $this->assertTrue($this->Controller->failed);  | 
      ||
| 459 | }  | 
      ||
| 460 | |||
| 461 | /**
 | 
      ||
| 462 |  * testRequireDeleteSucceed method
 | 
      ||
| 463 |  *
 | 
      ||
| 464 |  * @return void
 | 
      ||
| 465 |  */
 | 
      ||
| 466 | public function testRequireDeleteSucceed() {  | 
      ||
| 467 | $_SERVER['REQUEST_METHOD'] = 'DELETE';  | 
      ||
| 468 | $this->Controller->request['action'] = 'deleted';  | 
      ||
| 469 | $this->Controller->Security->requireDelete('deleted');  | 
      ||
| 470 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 471 | $this->assertFalse($this->Controller->failed);  | 
      ||
| 472 | }  | 
      ||
| 473 | |||
| 474 | /**
 | 
      ||
| 475 |  * testRequireDeleteSucceedWrongMethod method
 | 
      ||
| 476 |  *
 | 
      ||
| 477 |  * @return void
 | 
      ||
| 478 |  */
 | 
      ||
| 479 | public function testRequireDeleteSucceedWrongMethod() {  | 
      ||
| 480 | $_SERVER['REQUEST_METHOD'] = 'POST';  | 
      ||
| 481 | $this->Controller->request['action'] = 'posted';  | 
      ||
| 482 | $this->Controller->Security->requireDelete('deleted');  | 
      ||
| 483 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 484 | $this->assertFalse($this->Controller->failed);  | 
      ||
| 485 | }  | 
      ||
| 486 | |||
| 487 | /**
 | 
      ||
| 488 |  * Test that validatePost fires on GET with request data.
 | 
      ||
| 489 |  * This could happen when method overriding is used.
 | 
      ||
| 490 |  *
 | 
      ||
| 491 |  * @return void
 | 
      ||
| 492 |  * @triggers Controller.startup $this->Controller
 | 
      ||
| 493 |  */
 | 
      ||
| 494 | public function testValidatePostOnGetWithData() {  | 
      ||
| 495 | $_SERVER['REQUEST_METHOD'] = 'GET';  | 
      ||
| 496 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 497 | |||
| 498 | $fields = 'an-invalid-token';  | 
      ||
| 499 | $unlocked = '';  | 
      ||
| 500 | |||
| 501 | $this->Controller->request->data = [  | 
      ||
| 502 | 'Model' => array('username' => 'nate', 'password' => 'foo', 'valid' => '0'),  | 
      ||
| 503 | '_Token' => compact('fields', 'unlocked')  | 
      ||
| 504 | ];  | 
      ||
| 505 | $this->assertFalse($this->Controller->failed, 'Should not be failed yet');  | 
      ||
| 506 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 507 | $this->assertTrue($this->Controller->failed, 'Should fail because of validatePost.');  | 
      ||
| 508 | }  | 
      ||
| 509 | |||
| 510 | /**
 | 
      ||
| 511 |  * Simple hash validation test
 | 
      ||
| 512 |  *
 | 
      ||
| 513 |  * @return void
 | 
      ||
| 514 |  */
 | 
      ||
| 515 | public function testValidatePost() {  | 
      ||
| 516 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 517 | |||
| 518 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 519 | $fields = '01c1f6dbba02ac6f21b229eab1cc666839b14303%3AModel.valid';  | 
      ||
| 520 | $unlocked = '';  | 
      ||
| 521 | |||
| 522 | $this->Controller->request->data = array(  | 
      ||
| 523 | 'Model' => array('username' => 'nate', 'password' => 'foo', 'valid' => '0'),  | 
      ||
| 524 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 525 | );  | 
      ||
| 526 | $this->assertTrue($this->Controller->Security->validatePost($this->Controller));  | 
      ||
| 527 | }  | 
      ||
| 528 | |||
| 529 | /**
 | 
      ||
| 530 |  * Test that validatePost fails if you are missing the session information.
 | 
      ||
| 531 |  *
 | 
      ||
| 532 |  * @return void
 | 
      ||
| 533 |  */
 | 
      ||
| 534 | public function testValidatePostNoSession() {  | 
      ||
| 535 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 536 | $this->Controller->Session->delete('_Token');  | 
      ||
| 537 | |||
| 538 | $key = $this->Controller->params['_Token']['key'];  | 
      ||
| 539 | $fields = 'a5475372b40f6e3ccbf9f8af191f20e1642fd877%3AModel.valid';  | 
      ||
| 540 | |||
| 541 | $this->Controller->data = array(  | 
      ||
| 542 | 'Model' => array('username' => 'nate', 'password' => 'foo', 'valid' => '0'),  | 
      ||
| 543 | '_Token' => compact('key', 'fields')  | 
      ||
| 544 | );  | 
      ||
| 545 | $this->assertFalse($this->Controller->Security->validatePost($this->Controller));  | 
      ||
| 546 | }  | 
      ||
| 547 | |||
| 548 | /**
 | 
      ||
| 549 |  * test that validatePost fails if any of its required fields are missing.
 | 
      ||
| 550 |  *
 | 
      ||
| 551 |  * @return void
 | 
      ||
| 552 |  */
 | 
      ||
| 553 | public function testValidatePostFormHacking() {  | 
      ||
| 554 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 555 | $key = $this->Controller->params['_Token']['key'];  | 
      ||
| 556 | $unlocked = '';  | 
      ||
| 557 | |||
| 558 | $this->Controller->request->data = array(  | 
      ||
| 559 | 'Model' => array('username' => 'nate', 'password' => 'foo', 'valid' => '0'),  | 
      ||
| 560 | '_Token' => compact('key', 'unlocked')  | 
      ||
| 561 | );  | 
      ||
| 562 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 563 | $this->assertFalse($result, 'validatePost passed when fields were missing. %s');  | 
      ||
| 564 | }  | 
      ||
| 565 | |||
| 566 | /**
 | 
      ||
| 567 |  * Test that objects can't be passed into the serialized string. This was a vector for RFI and LFI
 | 
      ||
| 568 |  * attacks. Thanks to Felix Wilhelm
 | 
      ||
| 569 |  *
 | 
      ||
| 570 |  * @return void
 | 
      ||
| 571 |  */
 | 
      ||
| 572 | public function testValidatePostObjectDeserialize() {  | 
      ||
| 573 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 574 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 575 | $fields = 'a5475372b40f6e3ccbf9f8af191f20e1642fd877';  | 
      ||
| 576 | $unlocked = '';  | 
      ||
| 577 | |||
| 578 |                 // a corrupted serialized object, so we can see if it ever gets to deserialize
 | 
      ||
| 579 | $attack = 'O:3:"App":1:{s:5:"__map";a:1:{s:3:"foo";s:7:"Hacked!";s:1:"fail"}}';  | 
      ||
| 580 | $fields .= urlencode(':' . str_rot13($attack));  | 
      ||
| 581 | |||
| 582 | $this->Controller->request->data = array(  | 
      ||
| 583 | 'Model' => array('username' => 'mark', 'password' => 'foo', 'valid' => '0'),  | 
      ||
| 584 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 585 | );  | 
      ||
| 586 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 587 | $this->assertFalse($result, 'validatePost passed when key was missing. %s');  | 
      ||
| 588 | }  | 
      ||
| 589 | |||
| 590 | /**
 | 
      ||
| 591 |  * Tests validation of checkbox arrays
 | 
      ||
| 592 |  *
 | 
      ||
| 593 |  * @return void
 | 
      ||
| 594 |  */
 | 
      ||
| 595 | public function testValidatePostArray() {  | 
      ||
| 596 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 597 | |||
| 598 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 599 | $fields = '38504e4a341d4e6eadb437217efd91270e558d55%3A';  | 
      ||
| 600 | $unlocked = '';  | 
      ||
| 601 | |||
| 602 | $this->Controller->request->data = array(  | 
      ||
| 603 | 'Model' => array('multi_field' => array('1', '3')),  | 
      ||
| 604 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 605 | );  | 
      ||
| 606 | $this->assertTrue($this->Controller->Security->validatePost($this->Controller));  | 
      ||
| 607 | }  | 
      ||
| 608 | |||
| 609 | /**
 | 
      ||
| 610 |  * testValidatePostNoModel method
 | 
      ||
| 611 |  *
 | 
      ||
| 612 |  * @return void
 | 
      ||
| 613 |  */
 | 
      ||
| 614 | public function testValidatePostNoModel() {  | 
      ||
| 615 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 616 | |||
| 617 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 618 | $fields = 'c5bc49a6c938c820e7e538df3d8ab7bffbc97ef9%3A';  | 
      ||
| 619 | $unlocked = '';  | 
      ||
| 620 | |||
| 621 | $this->Controller->request->data = array(  | 
      ||
| 622 | 'anything' => 'some_data',  | 
      ||
| 623 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 624 | );  | 
      ||
| 625 | |||
| 626 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 627 | $this->assertTrue($result);  | 
      ||
| 628 | }  | 
      ||
| 629 | |||
| 630 | /**
 | 
      ||
| 631 |  * testValidatePostSimple method
 | 
      ||
| 632 |  *
 | 
      ||
| 633 |  * @return void
 | 
      ||
| 634 |  */
 | 
      ||
| 635 | public function testValidatePostSimple() {  | 
      ||
| 636 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 637 | |||
| 638 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 639 | $fields = '5415d31b4483c1e09ddb58d2a91ba9650b12aa83%3A';  | 
      ||
| 640 | $unlocked = '';  | 
      ||
| 641 | |||
| 642 | $this->Controller->request->data = array(  | 
      ||
| 643 | 'Model' => array('username' => '', 'password' => ''),  | 
      ||
| 644 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 645 | );  | 
      ||
| 646 | |||
| 647 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 648 | $this->assertTrue($result);  | 
      ||
| 649 | }  | 
      ||
| 650 | |||
| 651 | /**
 | 
      ||
| 652 |  * Tests hash validation for multiple records, including locked fields
 | 
      ||
| 653 |  *
 | 
      ||
| 654 |  * @return void
 | 
      ||
| 655 |  */
 | 
      ||
| 656 | public function testValidatePostComplex() {  | 
      ||
| 657 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 658 | |||
| 659 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 660 | $fields = 'b72a99e923687687bb5e64025d3cc65e1cecced4%3AAddresses.0.id%7CAddresses.1.id';  | 
      ||
| 661 | $unlocked = '';  | 
      ||
| 662 | |||
| 663 | $this->Controller->request->data = array(  | 
      ||
| 664 | 'Addresses' => array(  | 
      ||
| 665 | '0' => array(  | 
      ||
| 666 | 'id' => '123456', 'title' => '', 'first_name' => '', 'last_name' => '',  | 
      ||
| 667 | 'address' => '', 'city' => '', 'phone' => '', 'primary' => ''  | 
      ||
| 668 | ),  | 
      ||
| 669 | '1' => array(  | 
      ||
| 670 | 'id' => '654321', 'title' => '', 'first_name' => '', 'last_name' => '',  | 
      ||
| 671 | 'address' => '', 'city' => '', 'phone' => '', 'primary' => ''  | 
      ||
| 672 | )  | 
      ||
| 673 | ),  | 
      ||
| 674 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 675 | );  | 
      ||
| 676 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 677 | $this->assertTrue($result);  | 
      ||
| 678 | }  | 
      ||
| 679 | |||
| 680 | /**
 | 
      ||
| 681 |  * test ValidatePost with multiple select elements.
 | 
      ||
| 682 |  *
 | 
      ||
| 683 |  * @return void
 | 
      ||
| 684 |  */
 | 
      ||
| 685 | public function testValidatePostMultipleSelect() {  | 
      ||
| 686 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 687 | |||
| 688 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 689 | $fields = '8a764bdb989132c1d46f9a45f64ce2da5f9eebb9%3A';  | 
      ||
| 690 | $unlocked = '';  | 
      ||
| 691 | |||
| 692 | $this->Controller->request->data = array(  | 
      ||
| 693 | 'Tag' => array('Tag' => array(1, 2)),  | 
      ||
| 694 | '_Token' => compact('key', 'fields', 'unlocked'),  | 
      ||
| 695 | );  | 
      ||
| 696 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 697 | $this->assertTrue($result);  | 
      ||
| 698 | |||
| 699 | $this->Controller->request->data = array(  | 
      ||
| 700 | 'Tag' => array('Tag' => array(1, 2, 3)),  | 
      ||
| 701 | '_Token' => compact('key', 'fields', 'unlocked'),  | 
      ||
| 702 | );  | 
      ||
| 703 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 704 | $this->assertTrue($result);  | 
      ||
| 705 | |||
| 706 | $this->Controller->request->data = array(  | 
      ||
| 707 | 'Tag' => array('Tag' => array(1, 2, 3, 4)),  | 
      ||
| 708 | '_Token' => compact('key', 'fields', 'unlocked'),  | 
      ||
| 709 | );  | 
      ||
| 710 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 711 | $this->assertTrue($result);  | 
      ||
| 712 | |||
| 713 | $fields = '722de3615e63fdff899e86e85e6498b11c50bb66%3A';  | 
      ||
| 714 | $this->Controller->request->data = array(  | 
      ||
| 715 | 'User.password' => 'bar', 'User.name' => 'foo', 'User.is_valid' => '1',  | 
      ||
| 716 | 'Tag' => array('Tag' => array(1)),  | 
      ||
| 717 | '_Token' => compact('key', 'fields', 'unlocked'),  | 
      ||
| 718 | );  | 
      ||
| 719 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 720 | $this->assertTrue($result);  | 
      ||
| 721 | }  | 
      ||
| 722 | |||
| 723 | /**
 | 
      ||
| 724 |  * testValidatePostCheckbox method
 | 
      ||
| 725 |  *
 | 
      ||
| 726 |  * First block tests un-checked checkbox
 | 
      ||
| 727 |  * Second block tests checked checkbox
 | 
      ||
| 728 |  *
 | 
      ||
| 729 |  * @return void
 | 
      ||
| 730 |  */
 | 
      ||
| 731 | public function testValidatePostCheckbox() {  | 
      ||
| 732 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 733 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 734 | $fields = '01c1f6dbba02ac6f21b229eab1cc666839b14303%3AModel.valid';  | 
      ||
| 735 | $unlocked = '';  | 
      ||
| 736 | |||
| 737 | $this->Controller->request->data = array(  | 
      ||
| 738 | 'Model' => array('username' => '', 'password' => '', 'valid' => '0'),  | 
      ||
| 739 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 740 | );  | 
      ||
| 741 | |||
| 742 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 743 | $this->assertTrue($result);  | 
      ||
| 744 | |||
| 745 | $fields = 'efbcf463a2c31e97c85d95eedc41dff9e9c6a026%3A';  | 
      ||
| 746 | |||
| 747 | $this->Controller->request->data = array(  | 
      ||
| 748 | 'Model' => array('username' => '', 'password' => '', 'valid' => '0'),  | 
      ||
| 749 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 750 | );  | 
      ||
| 751 | |||
| 752 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 753 | $this->assertTrue($result);  | 
      ||
| 754 | |||
| 755 | $this->Controller->request->data = array();  | 
      ||
| 756 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 757 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 758 | |||
| 759 | $this->Controller->request->data = array(  | 
      ||
| 760 | 'Model' => array('username' => '', 'password' => '', 'valid' => '0'),  | 
      ||
| 761 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 762 | );  | 
      ||
| 763 | |||
| 764 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 765 | $this->assertTrue($result);  | 
      ||
| 766 | }  | 
      ||
| 767 | |||
| 768 | /**
 | 
      ||
| 769 |  * testValidatePostHidden method
 | 
      ||
| 770 |  *
 | 
      ||
| 771 |  * @return void
 | 
      ||
| 772 |  */
 | 
      ||
| 773 | public function testValidatePostHidden() {  | 
      ||
| 774 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 775 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 776 | $fields = 'baaf832a714b39a0618238ac89c7065fc8ec853e%3AModel.hidden%7CModel.other_hidden';  | 
      ||
| 777 | $unlocked = '';  | 
      ||
| 778 | |||
| 779 | $this->Controller->request->data = array(  | 
      ||
| 780 | 'Model' => array(  | 
      ||
| 781 | 'username' => '', 'password' => '', 'hidden' => '0',  | 
      ||
| 782 | 'other_hidden' => 'some hidden value'  | 
      ||
| 783 | ),  | 
      ||
| 784 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 785 | );  | 
      ||
| 786 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 787 | $this->assertTrue($result);  | 
      ||
| 788 | }  | 
      ||
| 789 | |||
| 790 | /**
 | 
      ||
| 791 |  * testValidatePostWithDisabledFields method
 | 
      ||
| 792 |  *
 | 
      ||
| 793 |  * @return void
 | 
      ||
| 794 |  */
 | 
      ||
| 795 | public function testValidatePostWithDisabledFields() {  | 
      ||
| 796 | $this->Controller->Security->disabledFields = array('Model.username', 'Model.password');  | 
      ||
| 797 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 798 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 799 | $fields = 'aa7f254ebd8bf2ef118bc5ca1e191d1ae96857f5%3AModel.hidden';  | 
      ||
| 800 | $unlocked = '';  | 
      ||
| 801 | |||
| 802 | $this->Controller->request->data = array(  | 
      ||
| 803 | 'Model' => array(  | 
      ||
| 804 | 'username' => '', 'password' => '', 'hidden' => '0'  | 
      ||
| 805 | ),  | 
      ||
| 806 | '_Token' => compact('fields', 'key', 'unlocked')  | 
      ||
| 807 | );  | 
      ||
| 808 | |||
| 809 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 810 | $this->assertTrue($result);  | 
      ||
| 811 | }  | 
      ||
| 812 | |||
| 813 | /**
 | 
      ||
| 814 |  * test validating post data with posted unlocked fields.
 | 
      ||
| 815 |  *
 | 
      ||
| 816 |  * @return void
 | 
      ||
| 817 |  */
 | 
      ||
| 818 | public function testValidatePostDisabledFieldsInData() {  | 
      ||
| 819 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 820 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 821 | $unlocked = 'Model.username';  | 
      ||
| 822 | $fields = array('Model.hidden', 'Model.password');  | 
      ||
| 823 | $fields = urlencode(Security::hash(  | 
      ||
| 824 |                         '/posts/index' .
 | 
      ||
| 825 | serialize($fields) .  | 
      ||
| 826 |                         $unlocked .
 | 
      ||
| 827 | Configure::read('Security.salt'))  | 
      ||
| 828 | );  | 
      ||
| 829 | |||
| 830 | $this->Controller->request->data = array(  | 
      ||
| 831 | 'Model' => array(  | 
      ||
| 832 | 'username' => 'mark',  | 
      ||
| 833 | 'password' => 'sekret',  | 
      ||
| 834 | 'hidden' => '0'  | 
      ||
| 835 | ),  | 
      ||
| 836 | '_Token' => compact('fields', 'key', 'unlocked')  | 
      ||
| 837 | );  | 
      ||
| 838 | |||
| 839 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 840 | $this->assertTrue($result);  | 
      ||
| 841 | }  | 
      ||
| 842 | |||
| 843 | /**
 | 
      ||
| 844 |  * test that missing 'unlocked' input causes failure
 | 
      ||
| 845 |  *
 | 
      ||
| 846 |  * @return void
 | 
      ||
| 847 |  */
 | 
      ||
| 848 | public function testValidatePostFailNoDisabled() {  | 
      ||
| 849 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 850 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 851 | $fields = array('Model.hidden', 'Model.password', 'Model.username');  | 
      ||
| 852 | $fields = urlencode(Security::hash(serialize($fields) . Configure::read('Security.salt')));  | 
      ||
| 853 | |||
| 854 | $this->Controller->request->data = array(  | 
      ||
| 855 | 'Model' => array(  | 
      ||
| 856 | 'username' => 'mark',  | 
      ||
| 857 | 'password' => 'sekret',  | 
      ||
| 858 | 'hidden' => '0'  | 
      ||
| 859 | ),  | 
      ||
| 860 | '_Token' => compact('fields', 'key')  | 
      ||
| 861 | );  | 
      ||
| 862 | |||
| 863 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 864 | $this->assertFalse($result);  | 
      ||
| 865 | }  | 
      ||
| 866 | |||
| 867 | /**
 | 
      ||
| 868 |  * Test that validatePost fails when unlocked fields are changed.
 | 
      ||
| 869 |  *
 | 
      ||
| 870 |  * @return void
 | 
      ||
| 871 |  */
 | 
      ||
| 872 | public function testValidatePostFailDisabledFieldTampering() {  | 
      ||
| 873 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 874 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 875 | $unlocked = 'Model.username';  | 
      ||
| 876 | $fields = array('Model.hidden', 'Model.password');  | 
      ||
| 877 | $fields = urlencode(Security::hash(serialize($fields) . $unlocked . Configure::read('Security.salt')));  | 
      ||
| 878 | |||
| 879 |                 // Tamper the values.
 | 
      ||
| 880 | $unlocked = 'Model.username|Model.password';  | 
      ||
| 881 | |||
| 882 | $this->Controller->request->data = array(  | 
      ||
| 883 | 'Model' => array(  | 
      ||
| 884 | 'username' => 'mark',  | 
      ||
| 885 | 'password' => 'sekret',  | 
      ||
| 886 | 'hidden' => '0'  | 
      ||
| 887 | ),  | 
      ||
| 888 | '_Token' => compact('fields', 'key', 'unlocked')  | 
      ||
| 889 | );  | 
      ||
| 890 | |||
| 891 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 892 | $this->assertFalse($result);  | 
      ||
| 893 | }  | 
      ||
| 894 | |||
| 895 | /**
 | 
      ||
| 896 |  * testValidateHiddenMultipleModel method
 | 
      ||
| 897 |  *
 | 
      ||
| 898 |  * @return void
 | 
      ||
| 899 |  */
 | 
      ||
| 900 | public function testValidateHiddenMultipleModel() {  | 
      ||
| 901 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 902 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 903 | $fields = '38dd8a37bbb52e67ee4eb812bf1725a6a18b989b%3AModel.valid%7CModel2.valid%7CModel3.valid';  | 
      ||
| 904 | $unlocked = '';  | 
      ||
| 905 | |||
| 906 | $this->Controller->request->data = array(  | 
      ||
| 907 | 'Model' => array('username' => '', 'password' => '', 'valid' => '0'),  | 
      ||
| 908 | 'Model2' => array('valid' => '0'),  | 
      ||
| 909 | 'Model3' => array('valid' => '0'),  | 
      ||
| 910 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 911 | );  | 
      ||
| 912 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 913 | $this->assertTrue($result);  | 
      ||
| 914 | }  | 
      ||
| 915 | |||
| 916 | /**
 | 
      ||
| 917 |  * testValidateHasManyModel method
 | 
      ||
| 918 |  *
 | 
      ||
| 919 |  * @return void
 | 
      ||
| 920 |  */
 | 
      ||
| 921 | public function testValidateHasManyModel() {  | 
      ||
| 922 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 923 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 924 | $fields = 'dcef68de6634c60d2e60484ad0e2faec003456e6%3AModel.0.hidden%7CModel.0.valid';  | 
      ||
| 925 | $fields .= '%7CModel.1.hidden%7CModel.1.valid';  | 
      ||
| 926 | $unlocked = '';  | 
      ||
| 927 | |||
| 928 | $this->Controller->request->data = array(  | 
      ||
| 929 | 'Model' => array(  | 
      ||
| 930 |                                 array(
 | 
      ||
| 931 | 'username' => 'username', 'password' => 'password',  | 
      ||
| 932 | 'hidden' => 'value', 'valid' => '0'  | 
      ||
| 933 | ),  | 
      ||
| 934 |                                 array(
 | 
      ||
| 935 | 'username' => 'username', 'password' => 'password',  | 
      ||
| 936 | 'hidden' => 'value', 'valid' => '0'  | 
      ||
| 937 | )  | 
      ||
| 938 | ),  | 
      ||
| 939 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 940 | );  | 
      ||
| 941 | |||
| 942 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 943 | $this->assertTrue($result);  | 
      ||
| 944 | }  | 
      ||
| 945 | |||
| 946 | /**
 | 
      ||
| 947 |  * testValidateHasManyRecordsPass method
 | 
      ||
| 948 |  *
 | 
      ||
| 949 |  * @return void
 | 
      ||
| 950 |  */
 | 
      ||
| 951 | public function testValidateHasManyRecordsPass() {  | 
      ||
| 952 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 953 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 954 | $fields = '8b6880fbbd4b69279155f899652ecffdd9b4c5a1%3AAddress.0.id%7CAddress.0.primary%7C';  | 
      ||
| 955 | $fields .= 'Address.1.id%7CAddress.1.primary';  | 
      ||
| 956 | $unlocked = '';  | 
      ||
| 957 | |||
| 958 | $this->Controller->request->data = array(  | 
      ||
| 959 | 'Address' => array(  | 
      ||
| 960 | 0 => array(  | 
      ||
| 961 | 'id' => '123',  | 
      ||
| 962 | 'title' => 'home',  | 
      ||
| 963 | 'first_name' => 'Bilbo',  | 
      ||
| 964 | 'last_name' => 'Baggins',  | 
      ||
| 965 | 'address' => '23 Bag end way',  | 
      ||
| 966 | 'city' => 'the shire',  | 
      ||
| 967 | 'phone' => 'N/A',  | 
      ||
| 968 | 'primary' => '1',  | 
      ||
| 969 | ),  | 
      ||
| 970 | 1 => array(  | 
      ||
| 971 | 'id' => '124',  | 
      ||
| 972 | 'title' => 'home',  | 
      ||
| 973 | 'first_name' => 'Frodo',  | 
      ||
| 974 | 'last_name' => 'Baggins',  | 
      ||
| 975 | 'address' => '50 Bag end way',  | 
      ||
| 976 | 'city' => 'the shire',  | 
      ||
| 977 | 'phone' => 'N/A',  | 
      ||
| 978 | 'primary' => '1'  | 
      ||
| 979 | )  | 
      ||
| 980 | ),  | 
      ||
| 981 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 982 | );  | 
      ||
| 983 | |||
| 984 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 985 | $this->assertTrue($result);  | 
      ||
| 986 | }  | 
      ||
| 987 | |||
| 988 | /**
 | 
      ||
| 989 |  * Test that values like Foo.0.1
 | 
      ||
| 990 |  *
 | 
      ||
| 991 |  * @return void
 | 
      ||
| 992 |  */
 | 
      ||
| 993 | public function testValidateNestedNumericSets() {  | 
      ||
| 994 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 995 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 996 | $unlocked = '';  | 
      ||
| 997 | $hashFields = array('TaxonomyData');  | 
      ||
| 998 | $fields = urlencode(  | 
      ||
| 999 | Security::hash(  | 
      ||
| 1000 |                         '/posts/index' .
 | 
      ||
| 1001 | serialize($hashFields) .  | 
      ||
| 1002 |                         $unlocked .
 | 
      ||
| 1003 | Configure::read('Security.salt'), 'sha1')  | 
      ||
| 1004 | );  | 
      ||
| 1005 | |||
| 1006 | $this->Controller->request->data = array(  | 
      ||
| 1007 | 'TaxonomyData' => array(  | 
      ||
| 1008 | 1 => array(array(2)),  | 
      ||
| 1009 | 2 => array(array(3))  | 
      ||
| 1010 | ),  | 
      ||
| 1011 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 1012 | );  | 
      ||
| 1013 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 1014 | $this->assertTrue($result);  | 
      ||
| 1015 | }  | 
      ||
| 1016 | |||
| 1017 | /**
 | 
      ||
| 1018 |  * testValidateHasManyRecords method
 | 
      ||
| 1019 |  *
 | 
      ||
| 1020 |  * validatePost should fail, hidden fields have been changed.
 | 
      ||
| 1021 |  *
 | 
      ||
| 1022 |  * @return void
 | 
      ||
| 1023 |  */
 | 
      ||
| 1024 | public function testValidateHasManyRecordsFail() {  | 
      ||
| 1025 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 1026 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 1027 | $fields = '7a203edb3d345bbf38fe0dccae960da8842e11d7%3AAddress.0.id%7CAddress.0.primary%7C';  | 
      ||
| 1028 | $fields .= 'Address.1.id%7CAddress.1.primary';  | 
      ||
| 1029 | $unlocked = '';  | 
      ||
| 1030 | |||
| 1031 | $this->Controller->request->data = array(  | 
      ||
| 1032 | 'Address' => array(  | 
      ||
| 1033 | 0 => array(  | 
      ||
| 1034 | 'id' => '123',  | 
      ||
| 1035 | 'title' => 'home',  | 
      ||
| 1036 | 'first_name' => 'Bilbo',  | 
      ||
| 1037 | 'last_name' => 'Baggins',  | 
      ||
| 1038 | 'address' => '23 Bag end way',  | 
      ||
| 1039 | 'city' => 'the shire',  | 
      ||
| 1040 | 'phone' => 'N/A',  | 
      ||
| 1041 | 'primary' => '5',  | 
      ||
| 1042 | ),  | 
      ||
| 1043 | 1 => array(  | 
      ||
| 1044 | 'id' => '124',  | 
      ||
| 1045 | 'title' => 'home',  | 
      ||
| 1046 | 'first_name' => 'Frodo',  | 
      ||
| 1047 | 'last_name' => 'Baggins',  | 
      ||
| 1048 | 'address' => '50 Bag end way',  | 
      ||
| 1049 | 'city' => 'the shire',  | 
      ||
| 1050 | 'phone' => 'N/A',  | 
      ||
| 1051 | 'primary' => '1'  | 
      ||
| 1052 | )  | 
      ||
| 1053 | ),  | 
      ||
| 1054 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 1055 | );  | 
      ||
| 1056 | |||
| 1057 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 1058 | $this->assertFalse($result);  | 
      ||
| 1059 | }  | 
      ||
| 1060 | |||
| 1061 | /**
 | 
      ||
| 1062 |  * testFormDisabledFields method
 | 
      ||
| 1063 |  *
 | 
      ||
| 1064 |  * @return void
 | 
      ||
| 1065 |  */
 | 
      ||
| 1066 | public function testFormDisabledFields() {  | 
      ||
| 1067 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 1068 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 1069 | $fields = '216ee717efd1a251a6d6e9efbb96005a9d09f1eb%3An%3A0%3A%7B%7D';  | 
      ||
| 1070 | $unlocked = '';  | 
      ||
| 1071 | |||
| 1072 | $this->Controller->request->data = array(  | 
      ||
| 1073 | 'MyModel' => array('name' => 'some data'),  | 
      ||
| 1074 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 1075 | );  | 
      ||
| 1076 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 1077 | $this->assertFalse($result);  | 
      ||
| 1078 | |||
| 1079 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 1080 | $this->Controller->Security->disabledFields = array('MyModel.name');  | 
      ||
| 1081 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 1082 | |||
| 1083 | $this->Controller->request->data = array(  | 
      ||
| 1084 | 'MyModel' => array('name' => 'some data'),  | 
      ||
| 1085 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 1086 | );  | 
      ||
| 1087 | |||
| 1088 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 1089 | $this->assertTrue($result);  | 
      ||
| 1090 | }  | 
      ||
| 1091 | |||
| 1092 | /**
 | 
      ||
| 1093 |  * testRadio method
 | 
      ||
| 1094 |  *
 | 
      ||
| 1095 |  * @return void
 | 
      ||
| 1096 |  */
 | 
      ||
| 1097 | public function testValidatePostRadio() {  | 
      ||
| 1098 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 1099 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 1100 | $fields = '3be63770e7953c6d2119f5377a9303372040f66f%3An%3A0%3A%7B%7D';  | 
      ||
| 1101 | $unlocked = '';  | 
      ||
| 1102 | |||
| 1103 | $this->Controller->request->data = array(  | 
      ||
| 1104 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 1105 | );  | 
      ||
| 1106 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 1107 | $this->assertFalse($result);  | 
      ||
| 1108 | |||
| 1109 | $this->Controller->request->data = array(  | 
      ||
| 1110 | '_Token' => compact('key', 'fields', 'unlocked'),  | 
      ||
| 1111 | 'Test' => array('test' => '')  | 
      ||
| 1112 | );  | 
      ||
| 1113 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 1114 | $this->assertTrue($result);  | 
      ||
| 1115 | |||
| 1116 | $this->Controller->request->data = array(  | 
      ||
| 1117 | '_Token' => compact('key', 'fields', 'unlocked'),  | 
      ||
| 1118 | 'Test' => array('test' => '1')  | 
      ||
| 1119 | );  | 
      ||
| 1120 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 1121 | $this->assertTrue($result);  | 
      ||
| 1122 | |||
| 1123 | $this->Controller->request->data = array(  | 
      ||
| 1124 | '_Token' => compact('key', 'fields', 'unlocked'),  | 
      ||
| 1125 | 'Test' => array('test' => '2')  | 
      ||
| 1126 | );  | 
      ||
| 1127 | $result = $this->Controller->Security->validatePost($this->Controller);  | 
      ||
| 1128 | $this->assertTrue($result);  | 
      ||
| 1129 | }  | 
      ||
| 1130 | |||
| 1131 | /**
 | 
      ||
| 1132 |  * test validatePost uses here() as a hash input.
 | 
      ||
| 1133 |  *
 | 
      ||
| 1134 |  * @return void
 | 
      ||
| 1135 |  */
 | 
      ||
| 1136 | public function testValidatePostUrlAsHashInput() {  | 
      ||
| 1137 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 1138 | |||
| 1139 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 1140 | $fields = '5415d31b4483c1e09ddb58d2a91ba9650b12aa83%3A';  | 
      ||
| 1141 | $unlocked = '';  | 
      ||
| 1142 | |||
| 1143 | $this->Controller->request->data = array(  | 
      ||
| 1144 | 'Model' => array('username' => '', 'password' => ''),  | 
      ||
| 1145 | '_Token' => compact('key', 'fields', 'unlocked')  | 
      ||
| 1146 | );  | 
      ||
| 1147 | $this->assertTrue($this->Controller->Security->validatePost($this->Controller));  | 
      ||
| 1148 | |||
| 1149 | $request = $this->getMock('CakeRequest', array('here'), array('articles/edit/1', false));  | 
      ||
| 1150 | $request->expects($this->at(0))  | 
      ||
| 1151 |                         ->method('here')
 | 
      ||
| 1152 | ->will($this->returnValue('/posts/index?page=1'));  | 
      ||
| 1153 | $request->expects($this->at(1))  | 
      ||
| 1154 |                         ->method('here')
 | 
      ||
| 1155 | ->will($this->returnValue('/posts/edit/1'));  | 
      ||
| 1156 | |||
| 1157 | $this->Controller->Security->request = $request;  | 
      ||
| 1158 | $this->assertFalse($this->Controller->Security->validatePost($this->Controller));  | 
      ||
| 1159 | $this->assertFalse($this->Controller->Security->validatePost($this->Controller));  | 
      ||
| 1160 | }  | 
      ||
| 1161 | |||
| 1162 | /**
 | 
      ||
| 1163 |  * test that a requestAction's controller will have the _Token appended to
 | 
      ||
| 1164 |  * the params.
 | 
      ||
| 1165 |  *
 | 
      ||
| 1166 |  * @return void
 | 
      ||
| 1167 |  * @see https://cakephp.lighthouseapp.com/projects/42648/tickets/68
 | 
      ||
| 1168 |  */
 | 
      ||
| 1169 | public function testSettingTokenForRequestAction() {  | 
      ||
| 1170 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 1171 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 1172 | |||
| 1173 | $this->Controller->params['requested'] = 1;  | 
      ||
| 1174 | unset($this->Controller->request->params['_Token']);  | 
      ||
| 1175 | |||
| 1176 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 1177 | $this->assertEquals($this->Controller->request->params['_Token']['key'], $key);  | 
      ||
| 1178 | }  | 
      ||
| 1179 | |||
| 1180 | /**
 | 
      ||
| 1181 |  * test that blackhole doesn't delete the _Token session key so repeat data submissions
 | 
      ||
| 1182 |  * stay blackholed.
 | 
      ||
| 1183 |  *
 | 
      ||
| 1184 |  * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/214
 | 
      ||
| 1185 |  * @return void
 | 
      ||
| 1186 |  */
 | 
      ||
| 1187 | public function testBlackHoleNotDeletingSessionInformation() {  | 
      ||
| 1188 | $this->Controller->Security->startup($this->Controller);  | 
      ||
| 1189 | |||
| 1190 | $this->Controller->Security->blackHole($this->Controller, 'auth');  | 
      ||
| 1191 | $this->assertTrue($this->Controller->Security->Session->check('_Token'), '_Token was deleted by blackHole %s');  | 
      ||
| 1192 | }  | 
      ||
| 1193 | |||
| 1194 | /**
 | 
      ||
| 1195 |  * test that csrf checks are skipped for request action.
 | 
      ||
| 1196 |  *
 | 
      ||
| 1197 |  * @return void
 | 
      ||
| 1198 |  */
 | 
      ||
| 1199 | public function testCsrfSkipRequestAction() {  | 
      ||
| 1200 | $_SERVER['REQUEST_METHOD'] = 'POST';  | 
      ||
| 1201 | |||
| 1202 | $this->Security->validatePost = false;  | 
      ||
| 1203 | $this->Security->csrfCheck = true;  | 
      ||
| 1204 | $this->Security->csrfExpires = '+10 minutes';  | 
      ||
| 1205 | $this->Controller->request->params['requested'] = 1;  | 
      ||
| 1206 | $this->Security->startup($this->Controller);  | 
      ||
| 1207 | |||
| 1208 | $this->assertFalse($this->Controller->failed, 'fail() was called.');  | 
      ||
| 1209 | }  | 
      ||
| 1210 | |||
| 1211 | /**
 | 
      ||
| 1212 |  * test setting
 | 
      ||
| 1213 |  *
 | 
      ||
| 1214 |  * @return void
 | 
      ||
| 1215 |  */
 | 
      ||
| 1216 | public function testCsrfSettings() {  | 
      ||
| 1217 | $this->Security->validatePost = false;  | 
      ||
| 1218 | $this->Security->csrfCheck = true;  | 
      ||
| 1219 | $this->Security->csrfExpires = '+10 minutes';  | 
      ||
| 1220 | $this->Security->startup($this->Controller);  | 
      ||
| 1221 | |||
| 1222 | $token = $this->Security->Session->read('_Token');  | 
      ||
| 1223 | $this->assertEquals(1, count($token['csrfTokens']), 'Missing the csrf token.');  | 
      ||
| 1224 | $this->assertEquals(strtotime('+10 minutes'), current($token['csrfTokens']), 'Token expiry does not match');  | 
      ||
| 1225 | $this->assertEquals(array('key', 'unlockedFields'), array_keys($this->Controller->request->params['_Token']), 'Keys don not match');  | 
      ||
| 1226 | }  | 
      ||
| 1227 | |||
| 1228 | /**
 | 
      ||
| 1229 |  * Test setting multiple nonces, when startup() is called more than once, (ie more than one request.)
 | 
      ||
| 1230 |  *
 | 
      ||
| 1231 |  * @return void
 | 
      ||
| 1232 |  */
 | 
      ||
| 1233 | public function testCsrfSettingMultipleNonces() {  | 
      ||
| 1234 | $this->Security->validatePost = false;  | 
      ||
| 1235 | $this->Security->csrfCheck = true;  | 
      ||
| 1236 | $this->Security->csrfExpires = '+10 minutes';  | 
      ||
| 1237 | $csrfExpires = strtotime('+10 minutes');  | 
      ||
| 1238 | $this->Security->startup($this->Controller);  | 
      ||
| 1239 | $this->Security->startup($this->Controller);  | 
      ||
| 1240 | |||
| 1241 | $token = $this->Security->Session->read('_Token');  | 
      ||
| 1242 | $this->assertEquals(2, count($token['csrfTokens']), 'Missing the csrf token.');  | 
      ||
| 1243 | foreach ($token['csrfTokens'] as $expires) {  | 
      ||
| 1244 | $this->assertWithinMargin($expires, $csrfExpires, 2, 'Token expiry does not match');  | 
      ||
| 1245 | }  | 
      ||
| 1246 | }  | 
      ||
| 1247 | |||
| 1248 | /**
 | 
      ||
| 1249 |  * test that nonces are consumed by form submits.
 | 
      ||
| 1250 |  *
 | 
      ||
| 1251 |  * @return void
 | 
      ||
| 1252 |  */
 | 
      ||
| 1253 | public function testCsrfNonceConsumption() {  | 
      ||
| 1254 | $this->Security->validatePost = false;  | 
      ||
| 1255 | $this->Security->csrfCheck = true;  | 
      ||
| 1256 | $this->Security->csrfExpires = '+10 minutes';  | 
      ||
| 1257 | |||
| 1258 | $this->Security->Session->write('_Token.csrfTokens', array('nonce1' => strtotime('+10 minutes')));  | 
      ||
| 1259 | |||
| 1260 | $this->Controller->request->params['action'] = 'index';  | 
      ||
| 1261 | $this->Controller->request->data = array(  | 
      ||
| 1262 | '_Token' => array(  | 
      ||
| 1263 | 'key' => 'nonce1'  | 
      ||
| 1264 | ),  | 
      ||
| 1265 | 'Post' => array(  | 
      ||
| 1266 | 'title' => 'Woot'  | 
      ||
| 1267 | )  | 
      ||
| 1268 | );  | 
      ||
| 1269 | $this->Security->startup($this->Controller);  | 
      ||
| 1270 | $token = $this->Security->Session->read('_Token');  | 
      ||
| 1271 | $this->assertFalse(isset($token['csrfTokens']['nonce1']), 'Token was not consumed');  | 
      ||
| 1272 | }  | 
      ||
| 1273 | |||
| 1274 | /**
 | 
      ||
| 1275 |  * tests that reusable CSRF-token expiry is renewed
 | 
      ||
| 1276 |  */
 | 
      ||
| 1277 | public function testCsrfReusableTokenRenewal() {  | 
      ||
| 1278 | $this->Security->validatePost = false;  | 
      ||
| 1279 | $this->Security->csrfCheck = true;  | 
      ||
| 1280 | $this->Security->csrfUseOnce = false;  | 
      ||
| 1281 | $csrfExpires = '+10 minutes';  | 
      ||
| 1282 | $this->Security->csrfExpires = $csrfExpires;  | 
      ||
| 1283 | |||
| 1284 | $this->Security->Session->write('_Token.csrfTokens', array('token' => strtotime('+1 minutes')));  | 
      ||
| 1285 | |||
| 1286 | $this->Security->startup($this->Controller);  | 
      ||
| 1287 | $tokens = $this->Security->Session->read('_Token.csrfTokens');  | 
      ||
| 1288 | $this->assertWithinMargin($tokens['token'], strtotime($csrfExpires), 2, 'Token expiry was not renewed');  | 
      ||
| 1289 | }  | 
      ||
| 1290 | |||
| 1291 | /**
 | 
      ||
| 1292 |  * test that expired values in the csrfTokens are cleaned up.
 | 
      ||
| 1293 |  *
 | 
      ||
| 1294 |  * @return void
 | 
      ||
| 1295 |  */
 | 
      ||
| 1296 | public function testCsrfNonceVacuum() {  | 
      ||
| 1297 | $this->Security->validatePost = false;  | 
      ||
| 1298 | $this->Security->csrfCheck = true;  | 
      ||
| 1299 | $this->Security->csrfExpires = '+10 minutes';  | 
      ||
| 1300 | |||
| 1301 | $this->Security->Session->write('_Token.csrfTokens', array(  | 
      ||
| 1302 | 'valid' => strtotime('+30 minutes'),  | 
      ||
| 1303 | 'poof' => strtotime('-11 minutes'),  | 
      ||
| 1304 | 'dust' => strtotime('-20 minutes')  | 
      ||
| 1305 | ));  | 
      ||
| 1306 | $this->Security->startup($this->Controller);  | 
      ||
| 1307 | $tokens = $this->Security->Session->read('_Token.csrfTokens');  | 
      ||
| 1308 | $this->assertEquals(2, count($tokens), 'Too many tokens left behind');  | 
      ||
| 1309 | $this->assertNotEmpty('valid', $tokens, 'Valid token was removed.');  | 
      ||
| 1310 | }  | 
      ||
| 1311 | |||
| 1312 | /**
 | 
      ||
| 1313 |  * test that when the key is missing the request is blackHoled
 | 
      ||
| 1314 |  *
 | 
      ||
| 1315 |  * @return void
 | 
      ||
| 1316 |  */
 | 
      ||
| 1317 | public function testCsrfBlackHoleOnKeyMismatch() {  | 
      ||
| 1318 | $this->Security->validatePost = false;  | 
      ||
| 1319 | $this->Security->csrfCheck = true;  | 
      ||
| 1320 | $this->Security->csrfExpires = '+10 minutes';  | 
      ||
| 1321 | |||
| 1322 | $this->Security->Session->write('_Token.csrfTokens', array('nonce1' => strtotime('+10 minutes')));  | 
      ||
| 1323 | |||
| 1324 | $this->Controller->request->params['action'] = 'index';  | 
      ||
| 1325 | $this->Controller->request->data = array(  | 
      ||
| 1326 | '_Token' => array(  | 
      ||
| 1327 | 'key' => 'not the right value'  | 
      ||
| 1328 | ),  | 
      ||
| 1329 | 'Post' => array(  | 
      ||
| 1330 | 'title' => 'Woot'  | 
      ||
| 1331 | )  | 
      ||
| 1332 | );  | 
      ||
| 1333 | $this->Security->startup($this->Controller);  | 
      ||
| 1334 | $this->assertTrue($this->Controller->failed, 'fail() was not called.');  | 
      ||
| 1335 | }  | 
      ||
| 1336 | |||
| 1337 | /**
 | 
      ||
| 1338 |  * test that when the key is missing the request is blackHoled
 | 
      ||
| 1339 |  *
 | 
      ||
| 1340 |  * @return void
 | 
      ||
| 1341 |  */
 | 
      ||
| 1342 | public function testCsrfBlackHoleOnExpiredKey() {  | 
      ||
| 1343 | $this->Security->validatePost = false;  | 
      ||
| 1344 | $this->Security->csrfCheck = true;  | 
      ||
| 1345 | $this->Security->csrfExpires = '+10 minutes';  | 
      ||
| 1346 | |||
| 1347 | $this->Security->Session->write('_Token.csrfTokens', array('nonce1' => strtotime('-5 minutes')));  | 
      ||
| 1348 | |||
| 1349 | $this->Controller->request->params['action'] = 'index';  | 
      ||
| 1350 | $this->Controller->request->data = array(  | 
      ||
| 1351 | '_Token' => array(  | 
      ||
| 1352 | 'key' => 'nonce1'  | 
      ||
| 1353 | ),  | 
      ||
| 1354 | 'Post' => array(  | 
      ||
| 1355 | 'title' => 'Woot'  | 
      ||
| 1356 | )  | 
      ||
| 1357 | );  | 
      ||
| 1358 | $this->Security->startup($this->Controller);  | 
      ||
| 1359 | $this->assertTrue($this->Controller->failed, 'fail() was not called.');  | 
      ||
| 1360 | }  | 
      ||
| 1361 | |||
| 1362 | /**
 | 
      ||
| 1363 |  * test that csrfUseOnce = false works.
 | 
      ||
| 1364 |  *
 | 
      ||
| 1365 |  * @return void
 | 
      ||
| 1366 |  */
 | 
      ||
| 1367 | public function testCsrfNotUseOnce() {  | 
      ||
| 1368 | $this->Security->validatePost = false;  | 
      ||
| 1369 | $this->Security->csrfCheck = true;  | 
      ||
| 1370 | $this->Security->csrfUseOnce = false;  | 
      ||
| 1371 | $this->Security->csrfExpires = '+10 minutes';  | 
      ||
| 1372 | |||
| 1373 |                 // Generate one token
 | 
      ||
| 1374 | $this->Security->startup($this->Controller);  | 
      ||
| 1375 | $token = $this->Security->Session->read('_Token.csrfTokens');  | 
      ||
| 1376 | $this->assertEquals(1, count($token), 'Should only be one token.');  | 
      ||
| 1377 | |||
| 1378 | $this->Security->startup($this->Controller);  | 
      ||
| 1379 | $tokenTwo = $this->Security->Session->read('_Token.csrfTokens');  | 
      ||
| 1380 | $this->assertEquals(1, count($tokenTwo), 'Should only be one token.');  | 
      ||
| 1381 | $this->assertEquals($token, $tokenTwo, 'Tokens should not be different.');  | 
      ||
| 1382 | |||
| 1383 | $key = $this->Controller->request->params['_Token']['key'];  | 
      ||
| 1384 | $this->assertEquals(array($key), array_keys($token), '_Token.key and csrfToken do not match request will blackhole.');  | 
      ||
| 1385 | }  | 
      ||
| 1386 | |||
| 1387 | /**
 | 
      ||
| 1388 |  * ensure that longer session tokens are not consumed
 | 
      ||
| 1389 |  *
 | 
      ||
| 1390 |  * @return void
 | 
      ||
| 1391 |  */
 | 
      ||
| 1392 | public function testCsrfNotUseOnceValidationLeavingToken() {  | 
      ||
| 1393 | $this->Security->validatePost = false;  | 
      ||
| 1394 | $this->Security->csrfCheck = true;  | 
      ||
| 1395 | $this->Security->csrfUseOnce = false;  | 
      ||
| 1396 | $this->Security->csrfExpires = '+10 minutes';  | 
      ||
| 1397 | |||
| 1398 | $this->Security->Session->write('_Token.csrfTokens', array('nonce1' => strtotime('+10 minutes')));  | 
      ||
| 1399 | |||
| 1400 | $this->Controller->request = $this->getMock('CakeRequest', array('is'));  | 
      ||
| 1401 | $this->Controller->request->params['action'] = 'index';  | 
      ||
| 1402 | $this->Controller->request->data = array(  | 
      ||
| 1403 | '_Token' => array(  | 
      ||
| 1404 | 'key' => 'nonce1'  | 
      ||
| 1405 | ),  | 
      ||
| 1406 | 'Post' => array(  | 
      ||
| 1407 | 'title' => 'Woot'  | 
      ||
| 1408 | )  | 
      ||
| 1409 | );  | 
      ||
| 1410 | $this->Security->startup($this->Controller);  | 
      ||
| 1411 | $token = $this->Security->Session->read('_Token');  | 
      ||
| 1412 | $this->assertTrue(isset($token['csrfTokens']['nonce1']), 'Token was consumed');  | 
      ||
| 1413 | }  | 
      ||
| 1414 | |||
| 1415 | /**
 | 
      ||
| 1416 |  * Test generateToken()
 | 
      ||
| 1417 |  *
 | 
      ||
| 1418 |  * @return void
 | 
      ||
| 1419 |  */
 | 
      ||
| 1420 | public function testGenerateToken() {  | 
      ||
| 1421 | $request = $this->Controller->request;  | 
      ||
| 1422 | $this->Security->generateToken($request);  | 
      ||
| 1423 | |||
| 1424 | $this->assertNotEmpty($request->params['_Token']);  | 
      ||
| 1425 | $this->assertTrue(isset($request->params['_Token']['unlockedFields']));  | 
      ||
| 1426 | $this->assertTrue(isset($request->params['_Token']['key']));  | 
      ||
| 1427 | }  | 
      ||
| 1428 | |||
| 1429 | /**
 | 
      ||
| 1430 |  * Test the limiting of CSRF tokens.
 | 
      ||
| 1431 |  *
 | 
      ||
| 1432 |  * @return void
 | 
      ||
| 1433 |  */
 | 
      ||
| 1434 | public function testCsrfLimit() {  | 
      ||
| 1435 | $this->Security->csrfLimit = 3;  | 
      ||
| 1436 | $time = strtotime('+10 minutes');  | 
      ||
| 1437 | $tokens = array(  | 
      ||
| 1438 | '1' => $time,  | 
      ||
| 1439 | '2' => $time,  | 
      ||
| 1440 | '3' => $time,  | 
      ||
| 1441 | '4' => $time,  | 
      ||
| 1442 | '5' => $time,  | 
      ||
| 1443 | );  | 
      ||
| 1444 | $this->Security->Session->write('_Token', array('csrfTokens' => $tokens));  | 
      ||
| 1445 | $this->Security->generateToken($this->Controller->request);  | 
      ||
| 1446 | $result = $this->Security->Session->read('_Token.csrfTokens');  | 
      ||
| 1447 | |||
| 1448 | $this->assertFalse(isset($result['1']));  | 
      ||
| 1449 | $this->assertFalse(isset($result['2']));  | 
      ||
| 1450 | $this->assertFalse(isset($result['3']));  | 
      ||
| 1451 | $this->assertTrue(isset($result['4']));  | 
      ||
| 1452 | $this->assertTrue(isset($result['5']));  | 
      ||
| 1453 | }  | 
      ||
| 1454 | |||
| 1455 | /**
 | 
      ||
| 1456 |  * Test unlocked actions
 | 
      ||
| 1457 |  *
 | 
      ||
| 1458 |  * @return void
 | 
      ||
| 1459 |  */
 | 
      ||
| 1460 | public function testUnlockedActions() {  | 
      ||
| 1461 | $_SERVER['REQUEST_METHOD'] = 'POST';  | 
      ||
| 1462 | $this->Controller->request->data = array('data');  | 
      ||
| 1463 | $this->Controller->Security->unlockedActions = 'index';  | 
      ||
| 1464 | $this->Controller->Security->blackHoleCallback = null;  | 
      ||
| 1465 | $result = $this->Controller->Security->startup($this->Controller);  | 
      ||
| 1466 | $this->assertNull($result);  | 
      ||
| 1467 | }  | 
      ||
| 1468 | }  |