protected function _sendHTTPPost($message, $remoteEntity)
 {
     $name = $message['__']['paramname'];
     $extra = "";
     if ($message['__']['ProtocolBinding'] == 'JSON-POST') {
         if ($relayState = $message['__']['RelayState']) {
             $relayState = "&RelayState={$relayState}";
         }
         $name = 'j' . $name;
         $encodedMessage = json_encode($message);
         $signatureHTMLValue = htmlspecialchars(base64_encode(sha1($remoteEntity['sharedkey'] . sha1("{$name}={$message}{$relayState}"))));
         $extra .= '<input type="hidden" name="Signature" value="' . $signatureHTMLValue . '">';
     } else {
         // Determine if we should sign the message
         $wantRequestsSigned = isset($remoteEntity['AuthnRequestsSigned']) && $remoteEntity['AuthnRequestsSigned'] || $this->_server->getCurrentEntitySetting('WantsAuthnRequestsSigned');
         if ($name == 'SAMLRequest' && $wantRequestsSigned) {
             $this->_server->getSessionLog()->debug("HTTP-Redirect: (Re-)Signing");
             $message = $this->_server->sign($message);
         } else {
             if ($name == 'SAMLResponse' && isset($remoteEntity['WantsAssertionsSigned']) && $remoteEntity['WantsAssertionsSigned']) {
                 $this->_server->getSessionLog()->debug("HTTP-Redirect: (Re-)Signing Assertion");
                 $message['saml:Assertion']['__t'] = 'saml:Assertion';
                 $message['saml:Assertion']['_xmlns:saml'] = "urn:oasis:names:tc:SAML:2.0:assertion";
                 $message['saml:Assertion']['ds:Signature'] = '__placeholder__';
                 uksort($message['saml:Assertion'], array(__CLASS__, '_usortAssertion'));
                 $message['saml:Assertion'] = $this->_server->sign($message['saml:Assertion']);
                 #$enc = docrypt(certs::$server_crt, $message['saml:Assertion'], 'saml:EncryptedAssertion');
             } else {
                 if ($name == 'SAMLResponse' && isset($remoteEntity['WantsResponsesSigned']) && $remoteEntity['WantsResponsesSigned']) {
                     $this->_server->getSessionLog()->debug("HTTP-Redirect: (Re-)Signing");
                     uksort($message['saml:Assertion'], array(__CLASS__, '_usortAssertion'));
                     $message = $this->_server->sign($message);
                 }
             }
         }
         $encodedMessage = Corto_XmlToArray::array2xml($message);
         $schemaUrl = 'http://docs.oasis-open.org/security/saml/v2.0/saml-schema-protocol-2.0.xsd';
         if ($this->_server->getConfig('debug') && ini_get('allow_url_fopen') && file_exists($schemaUrl)) {
             $dom = new DOMDocument();
             $dom->loadXML($encodedMessage);
             if (!$dom->schemaValidate($schemaUrl)) {
                 //echo '<pre>'.htmlentities(Corto_XmlToArray::formatXml($encodedMessage)).'</pre>';
                 //throw new Exception('Message XML doesnt validate against XSD at Oasis-open.org?!');
             }
         }
     }
     $extra .= isset($message['__']['RelayState']) ? '<input type="hidden" name="RelayState" value="' . htmlspecialchars($message['__']['RelayState']) . '">' : '';
     $extra .= isset($message['__']['return']) ? '<input type="hidden" name="return" value="' . htmlspecialchars($message['__']['return']) . '">' : '';
     $encodedMessage = htmlspecialchars(base64_encode($encodedMessage));
     $action = $message['_Destination'] . (isset($message['_Recipient']) ? $message['_Recipient'] : '');
     $this->_server->getSessionLog()->debug("HTTP-Post: Sending Message: " . var_export($message, true));
     $output = $this->_server->renderTemplate('form', array('action' => $action, 'message' => $encodedMessage, 'xtra' => $extra, 'name' => $name, 'trace' => $this->_server->getConfig('debug', false) ? htmlentities(Corto_XmlToArray::formatXml(Corto_XmlToArray::array2xml($message))) : ''));
     $this->_server->sendOutput($output);
 }
 public function idPsMetadataService()
 {
     $entitiesDescriptor = array(Corto_XmlToArray::TAG_NAME_PFX => 'md:EntitiesDescriptor', '_xmlns:md' => 'urn:oasis:names:tc:SAML:2.0:metadata', '_xmlns:mdui' => 'urn:oasis:names:tc:SAML:metadata:ui', '_ID' => $this->_server->getNewId(), 'ds:Signature' => '__placeholder__', 'md:EntityDescriptor' => array());
     // Fetch SP Entity Descriptor for the SP Entity ID that is fetched from the request
     $request = EngineBlock_ApplicationSingleton::getInstance()->getHttpRequest();
     $spEntityId = $request->getQueryParameter('sp-entity-id');
     if ($spEntityId) {
         $spEntityDescriptor = $this->_getSpEntityDescriptor($spEntityId);
         $spEntity = $this->_server->getRemoteEntity($spEntityId);
         if ($spEntityDescriptor) {
             $entitiesDescriptor['md:EntityDescriptor'][] = $spEntityDescriptor;
         }
     }
     foreach ($this->_server->getRemoteEntities() as $entityID => $entity) {
         if (!isset($entity['SingleSignOnService'])) {
             continue;
         }
         $entityDescriptor = array('_validUntil' => $this->_server->timeStamp($this->_server->getCurrentEntitySetting('idpMetadataValidUntilSeconds', 86400)), '_entityID' => $entityID, 'md:IDPSSODescriptor' => array('_protocolSupportEnumeration' => "urn:oasis:names:tc:SAML:2.0:protocol"));
         if (isset($entity['DisplayName'])) {
             if (!isset($entityDescriptor['md:IDPSSODescriptor']['md:Extensions'])) {
                 $entityDescriptor['md:IDPSSODescriptor']['md:Extensions'] = array();
             }
             if (!isset($entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'])) {
                 $entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'] = array(0 => array());
             }
             foreach ($entity['DisplayName'] as $lang => $name) {
                 if (trim($name) === '') {
                     continue;
                 }
                 if (!isset($entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'][0]['mdui:DisplayName'])) {
                     $entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'][0]['mdui:DisplayName'] = array();
                 }
                 $entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'][0]['mdui:DisplayName'][] = array('_xml:lang' => $lang, '__v' => $name);
             }
         }
         if (isset($entity['Description'])) {
             if (!isset($entityDescriptor['md:IDPSSODescriptor']['md:Extensions'])) {
                 $entityDescriptor['md:IDPSSODescriptor']['md:Extensions'] = array();
             }
             if (!isset($entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'])) {
                 $entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'] = array(0 => array());
             }
             foreach ($entity['Description'] as $lang => $name) {
                 if (trim($name) === '') {
                     continue;
                 }
                 if (!isset($entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'][0]['mdui:Description'])) {
                     $entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'][0]['mdui:Description'] = array();
                 }
                 $entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'][0]['mdui:Description'][] = array('_xml:lang' => $lang, '__v' => $name);
             }
         }
         $hasLogoHeight = isset($entity['Logo']['Height']) && $entity['Logo']['Height'];
         $hasLogoWidth = isset($entity['Logo']['Width']) && $entity['Logo']['Width'];
         if (isset($entity['Logo']) && $hasLogoHeight && $hasLogoWidth) {
             if (!isset($entityDescriptor['md:IDPSSODescriptor']['md:Extensions'])) {
                 $entityDescriptor['md:IDPSSODescriptor']['md:Extensions'] = array();
             }
             if (!isset($entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'])) {
                 $entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'] = array(0 => array());
             }
             $entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'][0]['mdui:Logo'] = array(array('_height' => $entity['Logo']['Height'], '_width' => $entity['Logo']['Width'], '__v' => $entity['Logo']['URL']));
         }
         if (isset($entity['GeoLocation']) && !empty($entity['GeoLocation'])) {
             if (!isset($entityDescriptor['md:IDPSSODescriptor']['md:Extensions'])) {
                 $entityDescriptor['md:IDPSSODescriptor']['md:Extensions'] = array();
             }
             if (!isset($entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:DiscoHints'])) {
                 $entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:DiscoHints'] = array(0 => array());
             }
             $entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:DiscoHints'][0]['mdui:GeolocationHint'] = array(array('__v' => $entity['GeoLocation']));
         }
         if (isset($entity['Keywords'])) {
             if (!isset($entityDescriptor['md:IDPSSODescriptor']['md:Extensions'])) {
                 $entityDescriptor['md:IDPSSODescriptor']['md:Extensions'] = array();
             }
             if (!isset($entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'])) {
                 $entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'] = array(0 => array());
             }
             $uiInfo =& $entityDescriptor['md:IDPSSODescriptor']['md:Extensions']['mdui:UIInfo'][0];
             foreach ($entity['Keywords'] as $lang => $name) {
                 if (trim($name) === '') {
                     continue;
                 }
                 if (!isset($uiInfo['mdui:Keywords'])) {
                     $uiInfo['mdui:Keywords'] = array();
                 }
                 $uiInfo['mdui:Keywords'][] = array(array('_xml:lang' => $lang, '__v' => $name));
             }
         }
         // Check if an alternative Public & Private key have been set for a SP
         // If yes, use these in the metadata of Engineblock
         if (isset($spEntity) && $spEntity['AlternatePrivateKey'] && $spEntity['AlternatePublicKey']) {
             $publicCertificate = $spEntity['AlternatePublicKey'];
         } else {
             $certificates = $this->_server->getCurrentEntitySetting('certificates', array());
             $publicCertificate = $certificates['public'];
         }
         if (isset($publicCertificate)) {
             $entityDescriptor['md:IDPSSODescriptor']['md:KeyDescriptor'] = array(array('_xmlns:ds' => 'http://www.w3.org/2000/09/xmldsig#', '_use' => 'signing', 'ds:KeyInfo' => array('ds:X509Data' => array('ds:X509Certificate' => array('__v' => $this->_server->getCertDataFromPem($publicCertificate))))), array('_xmlns:ds' => 'http://www.w3.org/2000/09/xmldsig#', '_use' => 'encryption', 'ds:KeyInfo' => array('ds:X509Data' => array('ds:X509Certificate' => array('__v' => $this->_server->getCertDataFromPem($publicCertificate))))));
         }
         $entityDescriptor['md:IDPSSODescriptor']['md:NameIDFormat'] = array('__v' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient');
         $entityDescriptor['md:IDPSSODescriptor']['md:SingleSignOnService'] = array('_Binding' => self::DEFAULT_REQUEST_BINDING, '_Location' => $this->_server->getCurrentEntityUrl('singleSignOnService', $entityID));
         $entitiesDescriptor['md:EntityDescriptor'][] = $entityDescriptor;
     }
     $alternatePublicKey = isset($spEntity['AlternatePublicKey']) ? $spEntity['AlternatePublicKey'] : null;
     $alternatePrivateKey = isset($spEntity['AlternatePublicKey']) ? $spEntity['AlternatePublicKey'] : null;
     $entitiesDescriptor = $this->_server->sign($entitiesDescriptor, $alternatePublicKey, $alternatePrivateKey);
     $xml = Corto_XmlToArray::array2xml($entitiesDescriptor);
     $schemaUrl = 'http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd';
     if ($this->_server->getConfig('debug', false) && ini_get('allow_url_fopen') && file_exists($schemaUrl)) {
         $dom = new DOMDocument();
         $dom->loadXML($xml);
         if (!$dom->schemaValidate($schemaUrl)) {
             echo '<pre>' . htmlentities(Corto_XmlToArray::formatXml($xml)) . '</pre>';
             throw new Exception('Metadata XML doesnt validate against XSD at Oasis-open.org?!');
         }
     }
     $this->_server->sendHeader('Content-Type', 'application/xml');
     //$this->_server->sendHeader('Content-Type', 'application/samlmetadata+xml');
     $this->_server->sendOutput($xml);
 }
 /**
  * Validates xml against oasis SAML 2 spec
  *
  * @param string $xml
  * @return void
  * @throws Exception in case validating itself fails or if xml does not validate
  */
 protected function _validateXml($xml)
 {
     $inDebugModus = $this->_server->getConfig('debug', false);
     if ($inDebugModus) {
         if (!ini_get('allow_url_fopen')) {
             throw new Exception('Failed validating XML, url_fopen is not allowed');
         }
         // Load schema
         $schemaUrl = 'http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd';
         $schemaXml = @file_get_contents($schemaUrl);
         if ($schemaXml === false) {
             throw new Exception('Failed validating XML, schema url could not be opened: "' . $schemaUrl . '"');
         }
         $schemaXml = $this->_absolutizeSchemaLocations($schemaXml, $schemaUrl);
         $dom = new DOMDocument();
         $dom->loadXML($xml);
         if (!@$dom->schemaValidateSource($schemaXml)) {
             $errorInfo = error_get_last();
             $errorMessage = $errorInfo['message'];
             // @todo improve parsing message by creating custom exceptions for which know that structure of messages
             $parsedErrorMessage = preg_replace('/\\{[^}]*\\}/', '', $errorMessage);
             echo '<pre>' . htmlentities(Corto_XmlToArray::formatXml($xml)) . '</pre>';
             throw new Exception('Metadata XML doesnt validate against XSD at Oasis-open.org: ' . $parsedErrorMessage);
         }
     }
 }