From 4b91712791225ad3fc6718855509118b06db4267 Mon Sep 17 00:00:00 2001 From: DarkAngelBGE Date: Tue, 13 May 2008 06:27:43 +0000 Subject: [PATCH] bringing security component up to 84% coverage, internationalizing trigger_error for security lib git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6835 3807eeeb-6ff5-0310-8944-8be069107fe0 --- cake/libs/controller/components/security.php | 7 +- cake/libs/security.php | 2 +- .../controller/components/security.test.php | 246 ++++++++++++++++++ 3 files changed, 250 insertions(+), 5 deletions(-) diff --git a/cake/libs/controller/components/security.php b/cake/libs/controller/components/security.php index 87fe4719b..cf1284ec3 100644 --- a/cake/libs/controller/components/security.php +++ b/cake/libs/controller/components/security.php @@ -444,12 +444,11 @@ class SecurityComponent extends Object { return null; } } - $token = $controller->data['__Token']['key']; if ($this->Session->check('_Token')) { $tData = unserialize($this->Session->read('_Token')); - if (!empty($tData['allowedControllers']) && !in_array($controller->params['controller'], $tData['allowedControllers']) ||!empty($tData['allowedActions']) && !in_array($controller->params['action'], $tData['allowedActions'])) { + if (!empty($tData['allowedControllers']) && !in_array($controller->params['controller'], $tData['allowedControllers']) || !empty($tData['allowedActions']) && !in_array($controller->params['action'], $tData['allowedActions'])) { if (!$this->blackHole($controller, 'auth')) { return null; } @@ -638,10 +637,10 @@ class SecurityComponent extends Object { } else { $keys = $value; } - + if (isset($field[$key])) { $field[$key] = array_merge($field[$key], $keys); - } elseif (is_numeric($keys[0])) { + } elseif (is_array($keys) && !empty($keys) && is_numeric($keys[0])) { foreach ($value as $fields) { $merge[] = array_keys($fields); } diff --git a/cake/libs/security.php b/cake/libs/security.php index 797f94cee..90383b78f 100644 --- a/cake/libs/security.php +++ b/cake/libs/security.php @@ -174,7 +174,7 @@ class Security extends Object { */ function cipher($text, $key) { if (empty($key)) { - trigger_error('You cannot use an empty key for Security::cipher()'); + trigger_error(__('You cannot use an empty key for Security::cipher()', true), E_USER_WARNING); return ''; } diff --git a/cake/tests/cases/libs/controller/components/security.test.php b/cake/tests/cases/libs/controller/components/security.test.php index 7bed3e69a..c66944a77 100644 --- a/cake/tests/cases/libs/controller/components/security.test.php +++ b/cake/tests/cases/libs/controller/components/security.test.php @@ -86,6 +86,64 @@ class SecurityComponentTest extends CakeTestCase { $this->assertFalse($this->Controller->failed); } + function testRequireSecureFail() { + $_SERVER['REQUEST_METHOD'] = 'POST'; + $this->Controller->action = 'posted'; + $this->Controller->Security->requireSecure('posted'); + $this->Controller->Security->startup($this->Controller); + $this->assertTrue($this->Controller->failed); + } + + function testRequireSecureSucceed() { + $_SERVER['REQUEST_METHOD'] = 'Secure'; + $this->Controller->action = 'posted'; + $_SERVER['HTTPS'] = true; + $this->Controller->Security->requireSecure('posted'); + $this->Controller->Security->startup($this->Controller); + $this->assertFalse($this->Controller->failed); + } + + function testRequireAuthFail() { + $_SERVER['REQUEST_METHOD'] = 'AUTH'; + $this->Controller->action = 'posted'; + $this->Controller->data = array('username' => 'willy', 'password' => 'somePass'); + $this->Controller->Security->requireAuth('posted'); + $this->Controller->Security->startup($this->Controller); + $this->assertTrue($this->Controller->failed); + + $this->Controller->Session->write('_Token', array('allowedControllers' => array())); + $this->Controller->data = array('username' => 'willy', 'password' => 'somePass'); + $this->Controller->action = 'posted'; + $this->Controller->Security->requireAuth('posted'); + $this->Controller->Security->startup($this->Controller); + $this->assertTrue($this->Controller->failed); + + $this->Controller->Session->write('_Token', array('allowedControllers' => array('SecurityTest'), 'allowedActions' => array('posted2'))); + $this->Controller->data = array('username' => 'willy', 'password' => 'somePass'); + $this->Controller->action = 'posted'; + $this->Controller->Security->requireAuth('posted'); + $this->Controller->Security->startup($this->Controller); + $this->assertTrue($this->Controller->failed); + } + + function testRequireAuthSucceed() { + $_SERVER['REQUEST_METHOD'] = 'AUTH'; + $this->Controller->action = 'posted'; + $this->Controller->Security->requireAuth('posted'); + $this->Controller->Security->startup($this->Controller); + $this->assertFalse($this->Controller->failed); + + $this->Controller->Security->Session->write('_Token', serialize(array('allowedControllers' => array('SecurityTest'), 'allowedActions' => array('posted')))); + $this->Controller->params['controller'] = 'SecurityTest'; + $this->Controller->params['action'] = 'posted'; + + $this->Controller->data = array('username' => 'willy', 'password' => 'somePass', '__Token' => ''); + $this->Controller->action = 'posted'; + $this->Controller->Security->requireAuth('posted'); + $this->Controller->Security->startup($this->Controller); + $this->assertFalse($this->Controller->failed); + } + function testRequirePostSucceedWrongMethod() { $_SERVER['REQUEST_METHOD'] = 'GET'; $this->Controller->action = 'getted'; @@ -110,6 +168,60 @@ class SecurityComponentTest extends CakeTestCase { $this->assertFalse($this->Controller->failed); } + function testRequireLogin() { + $this->Controller->action = 'posted'; + $this->Controller->Security->requireLogin( + 'posted', + array('type' => 'basic', 'users' => array('admin' => 'password')) + ); + $_SERVER['PHP_AUTH_USER'] = 'admin'; + $_SERVER['PHP_AUTH_PW'] = 'password'; + $this->Controller->Security->startup($this->Controller); + $this->assertFalse($this->Controller->failed); + + + $this->Controller->action = 'posted'; + $this->Controller->Security->requireLogin( + 'posted', + array('type' => 'basic', 'users' => array('admin' => 'password')) + ); + $_SERVER['PHP_AUTH_USER'] = 'admin2'; + $_SERVER['PHP_AUTH_PW'] = 'password'; + $this->Controller->Security->startup($this->Controller); + $this->assertTrue($this->Controller->failed); + + $this->Controller->action = 'posted'; + $this->Controller->Security->requireLogin( + 'posted', + array('type' => 'basic', 'users' => array('admin' => 'password')) + ); + $_SERVER['PHP_AUTH_USER'] = 'admin'; + $_SERVER['PHP_AUTH_PW'] = 'password2'; + $this->Controller->Security->startup($this->Controller); + $this->assertTrue($this->Controller->failed); + } + + function testDigestAuth() { + $this->Controller->action = 'posted'; + $_SERVER['PHP_AUTH_DIGEST'] = $digest = <<Controller->Security->requireLogin( + 'posted', + array('type' => 'digest', 'users' => array('Mufasa' => 'password'), 'realm' => 'testrealm@host.com') + ); + $this->Controller->Security->startup($this->Controller); + $this->assertFalse($this->Controller->failed); + } + function testRequireGetSucceedWrongMethod() { $_SERVER['REQUEST_METHOD'] = 'POST'; $this->Controller->action = 'posted'; @@ -274,6 +386,35 @@ class SecurityComponentTest extends CakeTestCase { $this->assertTrue($this->Controller->data == $data); } + function testValidatePostWithDisabledFields() { + $this->Controller->Security->startup($this->Controller); + $this->Controller->Security->disabledFields = array('Model.username', 'Model.password'); + $key = $this->Controller->params['_Token']['key']; + + $data['Model']['username'] = ''; + $data['Model']['password'] = ''; + $data['_Model']['hidden'] = '0'; + $data['__Token']['key'] = $key; + + $fields = array( + 'Model' => array('hidden'), + '_Model' => array('hidden' => '0'), + '__Token' => array('key' => $key) + ); + $fields = $this->__sortFields($fields); + + $fields = urlencode(Security::hash(serialize($fields) . Configure::read('Security.salt'))); + $data['__Token']['fields'] = $fields; + + $this->Controller->data = $data; + $result = $this->Controller->Security->__validatePost($this->Controller); + $this->assertTrue($result); + + unset($data['_Model']); + $data['Model']['hidden'] = '0'; + $this->assertTrue($this->Controller->data == $data); + } + function testValidateHiddenMultipleModel() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->params['_Token']['key']; @@ -354,6 +495,111 @@ class SecurityComponentTest extends CakeTestCase { $this->assertTrue($this->Controller->data == $data); } + function testLoginRequest() { + $this->Controller->Security->startup($this->Controller); + $realm = 'cakephp.org'; + $options = array('realm' => $realm, 'type' => 'basic'); + $result = $this->Controller->Security->loginRequest($options); + $expected = 'WWW-Authenticate: Basic realm="'.$realm.'"'; + $this->assertEqual($result, $expected); + + $this->Controller->Security->startup($this->Controller); + $options = array('realm' => $realm, 'type' => 'digest'); + $result = $this->Controller->Security->loginRequest($options); + $this->assertPattern('/realm="'.$realm.'"/', $result); + $this->assertPattern('/qop="auth"/', $result); + } + + function testGenerateDigestResponseHash() { + $this->Controller->Security->startup($this->Controller); + $realm = 'cakephp.org'; + $loginData = array('realm' => $realm, 'users' => array('Willy Smith' => 'password')); + $this->Controller->Security->requireLogin($loginData); + + $data = array( + 'username' => 'Willy Smith', + 'password' => 'password', + 'nonce' => String::uuid(), + 'nc' => 1, + 'cnonce' => 1, + 'realm' => $realm, + 'uri' => 'path_to_identifier', + 'qop' => 'testme' + ); + $_SERVER['REQUEST_METHOD'] = 'POST'; + + $result = $this->Controller->Security->generateDigestResponseHash($data); + $expected = md5( + md5($data['username'] . ':' . $loginData['realm'].':'.$data['password']) . ':' . $data['nonce'] . ':' . $data['nc'] . ':' . $data['cnonce'] . ':' . $data['qop'] . ':' . + md5(env('REQUEST_METHOD') . ':' . $data['uri'])); + $this->assertIdentical($result, $expected); + } + + function testLoginCredentials() { + $this->Controller->Security->startup($this->Controller); + $_SERVER['PHP_AUTH_USER'] = $user = 'Willy Test'; + $_SERVER['PHP_AUTH_PW'] = $pw = 'some password for the nice test'; + + $result = $this->Controller->Security->loginCredentials('basic'); + $expected = array('username' => $user, 'password' => $pw); + $this->assertIdentical($result, $expected); + + if (version_compare(phpversion(), '5.1') != -1) { + $_SERVER['PHP_AUTH_DIGEST'] = $digest = << 'Mufasa', + 'nonce' => 'dcd98b7102dd2f0e8b11d0f600bfb0c093', + 'uri' => '/dir/index.html', + 'qop' => 'auth', + 'nc' => '00000001', + 'cnonce' => '0a4f113b', + 'response' => '6629fae49393a05397450978507c4ef1', + 'opaque' => '5ccc069c403ebaf9f0171e9517f40e41' + ); + $result = $this->Controller->Security->loginCredentials('digest'); + $this->assertIdentical($result, $expected); + } + } + + function testParseDigestAuthData() { + $this->Controller->Security->startup($this->Controller); + $digest = << 'Mufasa', + 'nonce' => 'dcd98b7102dd2f0e8b11d0f600bfb0c093', + 'uri' => '/dir/index.html', + 'qop' => 'auth', + 'nc' => '00000001', + 'cnonce' => '0a4f113b', + 'response' => '6629fae49393a05397450978507c4ef1', + 'opaque' => '5ccc069c403ebaf9f0171e9517f40e41' + ); + $result = $this->Controller->Security->parseDigestAuthData($digest); + $this->assertIdentical($result, $expected); + + $result = $this->Controller->Security->parseDigestAuthData(''); + $this->assertNull($result); + } function __sortFields($fields) { foreach ($fields as $key => $value) { if(strpos($key, '_') !== 0 && is_array($fields[$key])) {