diff --git a/README.md b/README.md index 802f4b7..dd0a868 100644 --- a/README.md +++ b/README.md @@ -463,7 +463,11 @@ $advancedSettings = array ( False || True (use sp certs) || array ( keyFileName => 'metadata.key', certFileName => 'metadata.crt' - ) + ) + || array ( + 'x509cert' => '', + 'privateKey' => '' + ) */ 'signMetadata' => false, diff --git a/advanced_settings_example.php b/advanced_settings_example.php index 50194ae..99d0c04 100644 --- a/advanced_settings_example.php +++ b/advanced_settings_example.php @@ -2,7 +2,7 @@ $advancedSettings = array ( - // Compression settings + // Compression settings // Handle if the getRequest/getResponse methods will return the Request/Response deflated. // But if we provide a $deflate boolean parameter to the getRequest or getResponse // method it will have priority over the compression settings. @@ -36,7 +36,11 @@ False || True (use sp certs) || array ( keyFileName => 'metadata.key', certFileName => 'metadata.crt' - ) + ) + || array ( + 'x509cert' => '', + 'privateKey' => '' + ) */ 'signMetadata' => false, diff --git a/lib/Saml2/Settings.php b/lib/Saml2/Settings.php index 13e54ff..67410cf 100644 --- a/lib/Saml2/Settings.php +++ b/lib/Saml2/Settings.php @@ -608,9 +608,14 @@ public function checkSPSettings($settings) $errors[] = 'sp_sls_url_invalid'; } - if (isset($security['signMetadata']) && is_array($security['signMetadata']) && - (!isset($security['signMetadata']['keyFileName']) || !isset($security['signMetadata']['certFileName']))) { - $errors[] = 'sp_signMetadata_invalid'; + if (isset($security['signMetadata']) && is_array($security['signMetadata'])) { + if ((!isset($security['signMetadata']['keyFileName']) + || !isset($security['signMetadata']['certFileName'])) && + (!isset($security['signMetadata']['privateKey']) + || !isset($security['signMetadata']['x509cert'])) + ) { + $errors[] = 'sp_signMetadata_invalid'; + } } if (((isset($security['authnRequestsSigned']) && $security['authnRequestsSigned'] == true) @@ -842,40 +847,28 @@ public function getSPMetadata($alwaysPublishEncryptionCert = false, $validUntil } //Sign Metadata - if (isset($this->_security['signMetadata']) && $this->_security['signMetadata'] != false) { + if (isset($this->_security['signMetadata']) && $this->_security['signMetadata'] !== false) { if ($this->_security['signMetadata'] === true) { $keyMetadata = $this->getSPkey(); $certMetadata = $cert; - if (!$keyMetadata) { throw new OneLogin_Saml2_Error( 'SP Private key not found.', OneLogin_Saml2_Error::PRIVATE_KEY_FILE_NOT_FOUND ); } - if (!$certMetadata) { throw new OneLogin_Saml2_Error( 'SP Public cert not found.', OneLogin_Saml2_Error::PUBLIC_CERT_FILE_NOT_FOUND ); } - } else { - if (!isset($this->_security['signMetadata']['keyFileName']) - || !isset($this->_security['signMetadata']['certFileName']) - ) { - throw new OneLogin_Saml2_Error( - 'Invalid Setting: signMetadata value of the sp is not valid', - OneLogin_Saml2_Error::SETTINGS_INVALID_SYNTAX - ); - } + } else if (isset($this->_security['signMetadata']['keyFileName']) && + isset($this->_security['signMetadata']['certFileName'])) { $keyFileName = $this->_security['signMetadata']['keyFileName']; $certFileName = $this->_security['signMetadata']['certFileName']; - $keyMetadataFile = $this->_paths['cert'].$keyFileName; $certMetadataFile = $this->_paths['cert'].$certFileName; - - if (!file_exists($keyMetadataFile)) { throw new OneLogin_Saml2_Error( 'SP Private key file not found: %s', @@ -883,7 +876,6 @@ public function getSPMetadata($alwaysPublishEncryptionCert = false, $validUntil array($keyMetadataFile) ); } - if (!file_exists($certMetadataFile)) { throw new OneLogin_Saml2_Error( 'SP Public cert file not found: %s', @@ -893,6 +885,27 @@ public function getSPMetadata($alwaysPublishEncryptionCert = false, $validUntil } $keyMetadata = file_get_contents($keyMetadataFile); $certMetadata = file_get_contents($certMetadataFile); + } else if (isset($this->_security['signMetadata']['privateKey']) && + isset($this->_security['signMetadata']['x509cert'])) { + $keyMetadata = OneLogin_Saml2_Utils::formatPrivateKey($this->_security['signMetadata']['privateKey']); + $certMetadata = OneLogin_Saml2_Utils::formatCert($this->_security['signMetadata']['x509cert']); + if (!$keyMetadata) { + throw new OneLogin_Saml2_Error( + 'Private key not found.', + OneLogin_Saml2_Error::PRIVATE_KEY_FILE_NOT_FOUND + ); + } + if (!$certMetadata) { + throw new OneLogin_Saml2_Error( + 'Public cert not found.', + OneLogin_Saml2_Error::PUBLIC_CERT_FILE_NOT_FOUND + ); + } + } else { + throw new OneLogin_Saml2_Error( + 'Invalid Setting: signMetadata value of the sp is not valid', + OneLogin_Saml2_Error::SETTINGS_INVALID_SYNTAX + ); } $signatureAlgorithm = $this->_security['signatureAlgorithm']; diff --git a/tests/src/OneLogin/Saml2/SettingsTest.php b/tests/src/OneLogin/Saml2/SettingsTest.php index f23e56c..44bdae5 100644 --- a/tests/src/OneLogin/Saml2/SettingsTest.php +++ b/tests/src/OneLogin/Saml2/SettingsTest.php @@ -391,6 +391,16 @@ public function testCheckSettings() $this->assertContains('organization_not_enought_data', $e->getMessage()); $this->assertContains('contact_type_invalid', $e->getMessage()); } + + $settingsInfo['security']['signMetadata'] = ['privateKey' => file_get_contents(TEST_ROOT . '/data/customPath/certs/metadata.key')]; + try { + $settings = new OneLogin_Saml2_Settings($settingsInfo); + $this->fail('Error was not raised'); + } catch (OneLogin_Saml2_Error $e) { + $this->assertContains('sp_signMetadata_invalid', $e->getMessage()); + $this->assertContains('organization_not_enought_data', $e->getMessage()); + $this->assertContains('contact_type_invalid', $e->getMessage()); + } } /** @@ -588,6 +598,26 @@ public function testGetSPMetadataSigned() $this->assertContains('assertContains('', $metadata2); + $cert = file_get_contents(TEST_ROOT . '/data/customPath/certs/metadata.crt'); + $settingsInfo['security']['signMetadata'] = [ + 'privateKey' => file_get_contents(TEST_ROOT . '/data/customPath/certs/metadata.key'), + 'x509cert' => $cert, + ]; + $settings3 = new OneLogin_Saml2_Settings($settingsInfo); + $metadata3 = $settings3->getSPMetadata(); + $this->assertNotEmpty($metadata3); + $this->assertContains('assertContains('entityID="http://stuff.com/endpoints/metadata.php"', $metadata3); + $this->assertContains('AuthnRequestsSigned="false"', $metadata3); + $this->assertContains('WantAssertionsSigned="false"', $metadata3); + $this->assertContains('', $metadata3); + $this->assertContains('', $metadata3); + $this->assertContains('urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified', $metadata3); + $this->assertContains('', $metadata3); + $this->assertContains('', $metadata3); + $this->assertContains('assertContains('', $metadata3); + $this->assertContains(OneLogin_Saml2_Utils::formatCert($cert, false), $metadata3); } /**