From 46ba59a1d2ab7909c38e66601e7a79ec4dfa81a1 Mon Sep 17 00:00:00 2001 From: Sebastian Marcet Date: Thu, 29 Dec 2016 00:16:59 -0300 Subject: [PATCH] Removed TLD validation in the past we received several complains about restrictive openstackid validation related to TLD now that validation was removed, bc not added to much value on security. Change-Id: I47a842416ad898b9508831ee5f6e0d59e4bf3e5e --- .../OpenId/Exceptions/InvalidTLDException.php | 26 ---- app/libs/OpenId/Helpers/OpenIdUriHelper.php | 82 +++++------ .../Requests/OpenIdAuthenticationRequest.php | 47 +++++-- tests/OpenIdProtocolTest.php | 133 ++++++++++++++++++ 4 files changed, 199 insertions(+), 89 deletions(-) delete mode 100644 app/libs/OpenId/Exceptions/InvalidTLDException.php diff --git a/app/libs/OpenId/Exceptions/InvalidTLDException.php b/app/libs/OpenId/Exceptions/InvalidTLDException.php deleted file mode 100644 index bdb6e88e..00000000 --- a/app/libs/OpenId/Exceptions/InvalidTLDException.php +++ /dev/null @@ -1,26 +0,0 @@ - 2; } } @@ -425,9 +406,10 @@ final class OpenIdUriHelper return false; } - $required_parts = array('scheme', 'host'); - $forbidden_parts = array('user', 'pass', 'fragment'); - $keys = array_keys($parts); + $required_parts = ['scheme', 'host']; + $forbidden_parts = ['user', 'pass', 'fragment']; + $keys = array_keys($parts); + if (array_intersect($keys, $required_parts) != $required_parts) { return false; } @@ -440,15 +422,18 @@ final class OpenIdUriHelper return false; } - $scheme = strtolower($parts['scheme']); - $allowed_schemes = array('http', 'https'); + $scheme = strtolower($parts['scheme']); + $allowed_schemes = ['http', 'https']; + if (!in_array($scheme, $allowed_schemes)) { return false; } + $parts['scheme'] = $scheme; - $host = strtolower($parts['host']); + $host = strtolower($parts['host']); $hostparts = explode('*', $host); + switch (count($hostparts)) { case 1: $parts['wildcard'] = false; @@ -485,7 +470,6 @@ final class OpenIdUriHelper $parts['port'] = false; } - $parts['unparsed'] = $trust_root; return $parts; diff --git a/app/libs/OpenId/Requests/OpenIdAuthenticationRequest.php b/app/libs/OpenId/Requests/OpenIdAuthenticationRequest.php index 213148ed..32d55a91 100644 --- a/app/libs/OpenId/Requests/OpenIdAuthenticationRequest.php +++ b/app/libs/OpenId/Requests/OpenIdAuthenticationRequest.php @@ -71,30 +71,49 @@ class OpenIdAuthenticationRequest extends OpenIdRequest */ public function isValid() { - $return_to = $this->getReturnTo(); - $claimed_id = $this->getClaimedId(); - $identity = $this->getIdentity(); - $mode = $this->getMode(); - $realm = $this->getRealm(); - $valid_id = $this->isValidIdentifier($claimed_id, $identity); - $valid_return_to = OpenIdUriHelper::checkReturnTo($return_to); - $valid_realm = OpenIdUriHelper::checkRealm($realm, $return_to); + $return_to = $this->getReturnTo(); + $claimed_id = $this->getClaimedId(); + $identity = $this->getIdentity(); + $mode = $this->getMode(); + $realm = $this->getRealm(); + $valid_id = $this->isValidIdentifier($claimed_id, $identity); + $valid_realm = OpenIdUriHelper::isValidRealm($realm); + $valid_return_to_against_realm = OpenIdUriHelper::checkRealm($realm, $return_to); + $valid_return_to = OpenIdUriHelper::checkReturnTo($return_to); if (empty($return_to)) { throw new InvalidOpenIdMessageException('return_to is empty.'); } - if (!$valid_return_to) { - throw new InvalidOpenIdMessageException(sprintf('invalid return_to %s', $return_to)); - } - if (empty($realm)) { throw new InvalidOpenIdMessageException('realm is empty.'); } if (!$valid_realm) { - throw new InvalidOpenIdMessageException(sprintf('realm check is not valid realm %s - return_to %s.', $realm, - $return_to)); + throw new InvalidOpenIdMessageException + ( + sprintf + ( + 'realm is not valid ( %s )', + $realm + ) + ); + } + + if (!$valid_return_to_against_realm) { + throw new InvalidOpenIdMessageException + ( + sprintf + ( + 'return to url check against provided realm is not valid ( realm %s - return_to %s).', + $realm, + $return_to + ) + ); + } + + if (!$valid_return_to) { + throw new InvalidOpenIdMessageException(sprintf('invalid return_to url ( %s )', $return_to)); } if (empty($claimed_id)) { diff --git a/tests/OpenIdProtocolTest.php b/tests/OpenIdProtocolTest.php index 9064a9b9..78170d32 100644 --- a/tests/OpenIdProtocolTest.php +++ b/tests/OpenIdProtocolTest.php @@ -260,6 +260,139 @@ class OpenIdProtocolTest extends OpenStackIDBaseTest $this->assertTrue($openid_response['is_valid'] === 'true'); } + public function testInvalidTLD_Wilcard_COM_UK() + { + $params = array( + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType, + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::SetupMode, + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "https://*.com.uk", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "https://devbranch.openstack.com.uk/return_to.php", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "http://specs.openid.net/auth/2.0/identifier_select", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "http://specs.openid.net/auth/2.0/identifier_select", + ); + + $response = $this->action("POST", "OpenId\OpenIdProviderController@endpoint", $params); + + $this->assertResponseStatus(302); + + $url = $response->getTargetUrl(); + $parsed_url = @parse_url($url); + $query = isset($parsed_url['query']) ? $parsed_url['query']: null; + $this->assertTrue(!empty($query)); + parse_str($query, $query_array); + $this->assertTrue(isset($query_array['openid_error'])); + $error = $query_array['openid_error']; + $this->assertTrue(str_contains($error,"Invalid OpenId Message : realm is not valid" )); + } + + public function testInvalidTLD_Wilcard_UK() + { + $params = array( + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType, + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::SetupMode, + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "https://*.uk", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "https://devbranch.openstack.com.uk/return_to.php", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "http://specs.openid.net/auth/2.0/identifier_select", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "http://specs.openid.net/auth/2.0/identifier_select", + ); + + $response = $this->action("POST", "OpenId\OpenIdProviderController@endpoint", $params); + + $this->assertResponseStatus(302); + + $url = $response->getTargetUrl(); + $parsed_url = @parse_url($url); + $query = isset($parsed_url['query']) ? $parsed_url['query']: null; + $this->assertTrue(!empty($query)); + parse_str($query, $query_array); + $this->assertTrue(isset($query_array['openid_error'])); + $error = $query_array['openid_error']; + $this->assertTrue(str_contains($error,"Invalid OpenId Message : realm is not valid" )); + } + + public function testValidTLD_Wilcard() + { + $params = array( + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType, + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::SetupMode, + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "https://*.openstack.org", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "https://devbranch.openstack.org/return_to.php", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "http://specs.openid.net/auth/2.0/identifier_select", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "http://specs.openid.net/auth/2.0/identifier_select", + ); + + $response = $this->action("POST", "OpenId\OpenIdProviderController@endpoint", $params); + + $this->assertResponseStatus(302); + + $url = $response->getTargetUrl(); + $parsed_url = @parse_url($url); + $this->assertTrue(!isset($parsed_url['query'])); + $this->assertTrue(str_contains($url, "https://local.openstackid.openstack.org/accounts/user/consent")); + } + + public function testValidTLD_SameDomain() + { + $params = array( + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType, + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::SetupMode, + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "https://devbranch.openstack.org", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "https://devbranch.openstack.org/return_to.php", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "http://specs.openid.net/auth/2.0/identifier_select", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "http://specs.openid.net/auth/2.0/identifier_select", + ); + + $response = $this->action("POST", "OpenId\OpenIdProviderController@endpoint", $params); + + $this->assertResponseStatus(302); + + $url = $response->getTargetUrl(); + $parsed_url = @parse_url($url); + $this->assertTrue(!isset($parsed_url['query'])); + $this->assertTrue(str_contains($url, "https://local.openstackid.openstack.org/accounts/user/consent")); + } + + public function testValidTLD_SingleLevelDomain() + { + $params = array( + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType, + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::SetupMode, + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "https://myrefstack", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "https://myrefstack/return_to.php", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "http://specs.openid.net/auth/2.0/identifier_select", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "http://specs.openid.net/auth/2.0/identifier_select", + ); + + $response = $this->action("POST", "OpenId\OpenIdProviderController@endpoint", $params); + + $this->assertResponseStatus(302); + + $url = $response->getTargetUrl(); + $parsed_url = @parse_url($url); + $this->assertTrue(!isset($parsed_url['query'])); + $this->assertTrue(str_contains($url, "https://local.openstackid.openstack.org/accounts/user/consent")); + } + + public function testValidTLD_IPDomain() + { + $params = array( + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType, + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::SetupMode, + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "https://192.0.0.1", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "https://192.0.0.1/return_to.php", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "http://specs.openid.net/auth/2.0/identifier_select", + OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "http://specs.openid.net/auth/2.0/identifier_select", + ); + + $response = $this->action("POST", "OpenId\OpenIdProviderController@endpoint", $params); + + $this->assertResponseStatus(302); + + $url = $response->getTargetUrl(); + $parsed_url = @parse_url($url); + $this->assertTrue(!isset($parsed_url['query'])); + $this->assertTrue(str_contains($url, "https://local.openstackid.openstack.org/accounts/user/consent")); + } public function testAuthenticationSetupModeSessionAssociationDHSha256() {