getDOMChildren() public static method

Deprecation: This method will be removed in SSP 2.0. Please use SimpleSAML\Utils\XML::getDOMChildren() instead.
public static getDOMChildren ( DOMElement $element, $localName, $namespaceURI )
$element DOMElement
 /**
  * Extract the response element from the SOAP response.
  *
  * @param string $soapResponse  The SOAP response.
  * @return string  The <saml1p:Response> element, as a string.
  */
 private static function extractResponse($soapResponse)
 {
     assert('is_string($soapResponse)');
     $doc = new DOMDocument();
     if (!$doc->loadXML($soapResponse)) {
         throw new SimpleSAML_Error_Exception('Error parsing SAML 1 artifact response.');
     }
     $soapEnvelope = $doc->firstChild;
     if (!SimpleSAML_Utilities::isDOMElementOfType($soapEnvelope, 'Envelope', 'http://schemas.xmlsoap.org/soap/envelope/')) {
         throw new SimpleSAML_Error_Exception('Expected artifact response to contain a <soap:Envelope> element.');
     }
     $soapBody = SimpleSAML_Utilities::getDOMChildren($soapEnvelope, 'Body', 'http://schemas.xmlsoap.org/soap/envelope/');
     if (count($soapBody) === 0) {
         throw new SimpleSAML_Error_Exception('Couldn\'t find <soap:Body> in <soap:Envelope>.');
     }
     $soapBody = $soapBody[0];
     $responseElement = SimpleSAML_Utilities::getDOMChildren($soapBody, 'Response', 'urn:oasis:names:tc:SAML:1.0:protocol');
     if (count($responseElement) === 0) {
         throw new SimpleSAML_Error_Exception('Couldn\'t find <saml1p:Response> in <soap:Body>.');
     }
     $responseElement = $responseElement[0];
     /*
      * Save the <saml1p:Response> element. Note that we need to import it
      * into a new document, in order to preserve namespace declarations.
      */
     $newDoc = new DOMDocument();
     $newDoc->appendChild($newDoc->importNode($responseElement, TRUE));
     $responseXML = $newDoc->saveXML();
     return $responseXML;
 }
Esempio n. 2
0
 /**
  * Send an authenticationResponse using HTTP-POST.
  *
  * @param string $response  The response which should be sent.
  * @param array $idpmd  The metadata of the IdP which is sending the response.
  * @param array $spmd  The metadata of the SP which is receiving the response.
  * @param string|NULL $relayState  The relaystate for the SP.
  * @param string $shire  The shire which should receive the response.
  */
 public function sendResponse($response, $idpmd, $spmd, $relayState, $shire)
 {
     SimpleSAML_Utilities::validateXMLDocument($response, 'saml11');
     $privatekey = SimpleSAML_Utilities::loadPrivateKey($idpmd, TRUE);
     $publickey = SimpleSAML_Utilities::loadPublicKey($idpmd, TRUE);
     $responsedom = new DOMDocument();
     $responsedom->loadXML(str_replace("\r", "", $response));
     $responseroot = $responsedom->getElementsByTagName('Response')->item(0);
     $firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0);
     /* Determine what we should sign - either the Response element or the Assertion. The default
      * is to sign the Assertion, but that can be overridden by the 'signresponse' option in the
      * SP metadata or 'saml20.signresponse' in the global configuration.
      */
     $signResponse = FALSE;
     if (array_key_exists('signresponse', $spmd) && $spmd['signresponse'] !== NULL) {
         $signResponse = $spmd['signresponse'];
         if (!is_bool($signResponse)) {
             throw new Exception('Expected the \'signresponse\' option in the metadata of the' . ' SP \'' . $spmd['entityid'] . '\' to be a boolean value.');
         }
     } else {
         $signResponse = $this->configuration->getBoolean('shib13.signresponse', TRUE);
     }
     /* Check if we have an assertion to sign. Force to sign the response if not. */
     if ($firstassertionroot === NULL) {
         $signResponse = TRUE;
     }
     $signer = new SimpleSAML_XML_Signer(array('privatekey_array' => $privatekey, 'publickey_array' => $publickey, 'id' => $signResponse ? 'ResponseID' : 'AssertionID'));
     if (array_key_exists('certificatechain', $idpmd)) {
         $signer->addCertificate($idpmd['certificatechain']);
     }
     if ($signResponse) {
         /* Sign the response - this must be done after encrypting the assertion. */
         /* We insert the signature before the saml2p:Status element. */
         $statusElements = SimpleSAML_Utilities::getDOMChildren($responseroot, 'Status', '@saml1p');
         assert('count($statusElements) === 1');
         $signer->sign($responseroot, $responseroot, $statusElements[0]);
     } else {
         /* Sign the assertion */
         $signer->sign($firstassertionroot, $firstassertionroot);
     }
     $response = $responsedom->saveXML();
     if ($this->configuration->getBoolean('debug', FALSE)) {
         $p = new SimpleSAML_XHTML_Template($this->configuration, 'post-debug.php');
         $p->data['header'] = 'SAML (Shibboleth 1.3) Response Debug-mode';
         $p->data['RelayStateName'] = 'TARGET';
         $p->data['RelayState'] = $relayState;
         $p->data['destination'] = $shire;
         $p->data['response'] = str_replace("\n", "", base64_encode($response));
         $p->data['responseHTML'] = htmlspecialchars(SimpleSAML_Utilities::formatXMLString($response));
         $p->show();
     } else {
         SimpleSAML_Utilities::postRedirect($shire, array('TARGET' => $relayState, 'SAMLResponse' => base64_encode($response)));
     }
 }
Esempio n. 3
0
 /**
  * Send an authenticationResponse using HTTP-POST.
  *
  * @param string $response  The response which should be sent.
  * @param SimpleSAML_Configuration $idpmd  The metadata of the IdP which is sending the response.
  * @param SimpleSAML_Configuration $spmd  The metadata of the SP which is receiving the response.
  * @param string|NULL $relayState  The relaystate for the SP.
  * @param string $shire  The shire which should receive the response.
  */
 public function sendResponse($response, SimpleSAML_Configuration $idpmd, SimpleSAML_Configuration $spmd, $relayState, $shire)
 {
     SimpleSAML_Utilities::validateXMLDocument($response, 'saml11');
     $privatekey = SimpleSAML_Utilities::loadPrivateKey($idpmd, TRUE);
     $publickey = SimpleSAML_Utilities::loadPublicKey($idpmd, TRUE);
     $responsedom = new DOMDocument();
     $responsedom->loadXML(str_replace("\r", "", $response));
     $responseroot = $responsedom->getElementsByTagName('Response')->item(0);
     $firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0);
     /* Determine what we should sign - either the Response element or the Assertion. The default
      * is to sign the Assertion, but that can be overridden by the 'signresponse' option in the
      * SP metadata or 'saml20.signresponse' in the global configuration.
      */
     $signResponse = FALSE;
     if ($spmd->hasValue('signresponse')) {
         $signResponse = $spmd->getBoolean['signresponse'];
     } else {
         $signResponse = $this->configuration->getBoolean('shib13.signresponse', TRUE);
     }
     /* Check if we have an assertion to sign. Force to sign the response if not. */
     if ($firstassertionroot === NULL) {
         $signResponse = TRUE;
     }
     $signer = new SimpleSAML_XML_Signer(array('privatekey_array' => $privatekey, 'publickey_array' => $publickey, 'id' => $signResponse ? 'ResponseID' : 'AssertionID'));
     if ($idpmd->hasValue('certificatechain')) {
         $signer->addCertificate($idpmd->getString('certificatechain'));
     }
     if ($signResponse) {
         /* Sign the response - this must be done after encrypting the assertion. */
         /* We insert the signature before the saml2p:Status element. */
         $statusElements = SimpleSAML_Utilities::getDOMChildren($responseroot, 'Status', '@saml1p');
         assert('count($statusElements) === 1');
         $signer->sign($responseroot, $responseroot, $statusElements[0]);
     } else {
         /* Sign the assertion */
         $signer->sign($firstassertionroot, $firstassertionroot);
     }
     $response = $responsedom->saveXML();
     SimpleSAML_Utilities::debugMessage($response, 'out');
     SimpleSAML_Utilities::postRedirect($shire, array('TARGET' => $relayState, 'SAMLResponse' => base64_encode($response)));
 }
 /**
  * Parse an Extensions element.
  *
  * @param mixed $element  The element which contains the Extensions element.
  */
 private static function processExtensions($element)
 {
     $ret = array('scope' => array(), 'tags' => array());
     foreach ($element->Extensions as $e) {
         if ($e instanceof SAML2_XML_shibmd_Scope) {
             $ret['scope'][] = $e->scope;
             continue;
         }
         if (!$e instanceof SAML2_XML_Chunk) {
             continue;
         }
         if ($e->localName === 'Attribute' && $e->namespaceURI === SAML2_Const::NS_SAML) {
             $attribute = $e->getXML();
             $name = $attribute->getAttribute('Name');
             $values = array_map(array('SimpleSAML_Utilities', 'getDOMText'), SimpleSAML_Utilities::getDOMChildren($attribute, 'AttributeValue', '@saml2'));
             if ($name === 'tags') {
                 foreach ($values as $tagname) {
                     if (!empty($tagname)) {
                         $ret['tags'][] = $tagname;
                     }
                 }
             }
         }
     }
     return $ret;
 }
Esempio n. 5
0
 /**
  * Parse an Extensions element.
  *
  * @param mixed $element  The element which contains the Extensions element.
  */
 private static function processExtensions($element)
 {
     $ret = array('scope' => array(), 'tags' => array(), 'entityAttributes' => array());
     foreach ($element->Extensions as $e) {
         if ($e instanceof SAML2_XML_shibmd_Scope) {
             $ret['scope'][] = $e->scope;
             continue;
         }
         // Entity Attributes are only allowed at entity level extensions
         // and not at RoleDescriptor level
         if ($element instanceof SAML2_XML_md_EntityDescriptor) {
             if ($e instanceof SAML2_XML_mdattr_EntityAttributes) {
                 foreach ($e->children as $attr) {
                     // Only saml:Attribute are currently supported here. The specifications also allows
                     // saml:Assertions, which more complex processing.
                     if ($attr instanceof SAML2_XML_saml_Attribute) {
                         if (empty($attr->Name) || empty($attr->AttributeValue)) {
                             continue;
                         }
                         // Attribute names that is not URI is prefixed as this: '{nameformat}name'
                         $name = $attr->Name;
                         if (empty($attr->NameFormat)) {
                             $name = '{' . SAML2_Const::NAMEFORMAT_UNSPECIFIED . '}' . $attr->Name;
                         } elseif ($attr->NameFormat !== 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri') {
                             $name = '{' . $attr->NameFormat . '}' . $attr->Name;
                         }
                         $values = array();
                         foreach ($attr->AttributeValue as $attrvalue) {
                             $values[] = $attrvalue->getString();
                         }
                         $ret['EntityAttributes'][$name] = $values;
                     }
                 }
             }
         }
         if (!$e instanceof SAML2_XML_Chunk) {
             continue;
         }
         if ($e->localName === 'Attribute' && $e->namespaceURI === SAML2_Const::NS_SAML) {
             $attribute = $e->getXML();
             $name = $attribute->getAttribute('Name');
             $values = array_map(array('SimpleSAML_Utilities', 'getDOMText'), SimpleSAML_Utilities::getDOMChildren($attribute, 'AttributeValue', '@saml2'));
             if ($name === 'tags') {
                 foreach ($values as $tagname) {
                     if (!empty($tagname)) {
                         $ret['tags'][] = $tagname;
                     }
                 }
             }
         }
     }
     return $ret;
 }
Esempio n. 6
0
 /**
  * Parse an Extensions element.
  *
  * @param mixed $element  The element which contains the Extensions element.
  */
 private static function processExtensions($element)
 {
     $ret = array('scope' => array(), 'tags' => array(), 'EntityAttributes' => array(), 'UIInfo' => array(), 'DiscoHints' => array());
     foreach ($element->Extensions as $e) {
         if ($e instanceof SAML2_XML_shibmd_Scope) {
             $ret['scope'][] = $e->scope;
             continue;
         }
         // Entity Attributes are only allowed at entity level extensions
         // and not at RoleDescriptor level
         if ($element instanceof SAML2_XML_md_EntityDescriptor) {
             if ($e instanceof SAML2_XML_mdattr_EntityAttributes && !empty($e->children)) {
                 foreach ($e->children as $attr) {
                     // Only saml:Attribute are currently supported here. The specifications also allows
                     // saml:Assertions, which more complex processing.
                     if ($attr instanceof SAML2_XML_saml_Attribute) {
                         if (empty($attr->Name) || empty($attr->AttributeValue)) {
                             continue;
                         }
                         // Attribute names that is not URI is prefixed as this: '{nameformat}name'
                         $name = $attr->Name;
                         if (empty($attr->NameFormat)) {
                             $name = '{' . SAML2_Const::NAMEFORMAT_UNSPECIFIED . '}' . $attr->Name;
                         } elseif ($attr->NameFormat !== 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri') {
                             $name = '{' . $attr->NameFormat . '}' . $attr->Name;
                         }
                         $values = array();
                         foreach ($attr->AttributeValue as $attrvalue) {
                             $values[] = $attrvalue->getString();
                         }
                         $ret['EntityAttributes'][$name] = $values;
                     }
                 }
             }
         }
         // UIInfo elements are only allowed at RoleDescriptor level extensions
         if ($element instanceof SAML2_XML_md_RoleDescriptor) {
             if ($e instanceof SAML2_XML_mdui_UIInfo) {
                 $ret['UIInfo']['DisplayName'] = $e->DisplayName;
                 $ret['UIInfo']['Description'] = $e->Description;
                 $ret['UIInfo']['InformationURL'] = $e->InformationURL;
                 $ret['UIInfo']['PrivacyStatementURL'] = $e->PrivacyStatementURL;
                 foreach ($e->Keywords as $uiItem) {
                     if (!$uiItem instanceof SAML2_XML_mdui_Keywords || empty($uiItem->Keywords) || empty($uiItem->lang)) {
                         continue;
                     }
                     $ret['UIInfo']['Keywords'][$uiItem->lang] = $uiItem->Keywords;
                 }
                 foreach ($e->Logo as $uiItem) {
                     if (!$uiItem instanceof SAML2_XML_mdui_Logo || empty($uiItem->url) || empty($uiItem->height) || empty($uiItem->width)) {
                         continue;
                     }
                     $logo = array('url' => $uiItem->url, 'height' => $uiItem->height, 'width' => $uiItem->width);
                     if (!empty($uiItem->Lang)) {
                         $logo['lang'] = $uiItem->lang;
                     }
                     $ret['UIInfo']['Logo'][] = $logo;
                 }
             }
         }
         // DiscoHints elements are only allowed at IDPSSODescriptor level extensions
         if ($element instanceof SAML2_XML_md_IDPSSODescriptor) {
             if ($e instanceof SAML2_XML_mdui_DiscoHints) {
                 $ret['DiscoHints']['IPHint'] = $e->IPHint;
                 $ret['DiscoHints']['DomainHint'] = $e->DomainHint;
                 $ret['DiscoHints']['GeolocationHint'] = $e->GeolocationHint;
             }
         }
         if (!$e instanceof SAML2_XML_Chunk) {
             continue;
         }
         if ($e->localName === 'Attribute' && $e->namespaceURI === SAML2_Const::NS_SAML) {
             $attribute = $e->getXML();
             $name = $attribute->getAttribute('Name');
             $values = array_map(array('SimpleSAML_Utilities', 'getDOMText'), SimpleSAML_Utilities::getDOMChildren($attribute, 'AttributeValue', '@saml2'));
             if ($name === 'tags') {
                 foreach ($values as $tagname) {
                     if (!empty($tagname)) {
                         $ret['tags'][] = $tagname;
                     }
                 }
             }
         }
     }
     return $ret;
 }
Esempio n. 7
0
 /**
  * This function parses a KeyDescriptor element. It currently only supports keys with a single
  * X509 certificate.
  *
  * The associative array for a key can contain:
  * - 'encryption': Indicates wheter this key can be used for encryption.
  * - 'signing': Indicates wheter this key can be used for signing.
  * - 'type: The type of the key. 'X509Certificate' is the only key type we support.
  * - 'X509Certificate': The contents of the first X509Certificate element (if the type is 'X509Certificate ').
  *
  * @param $kd  The KeyDescriptor element.
  * @return Associative array describing the key, or NULL if this is an unsupported key.
  */
 private static function parseKeyDescriptor($kd)
 {
     assert('$kd instanceof DOMElement');
     $r = array();
     if ($kd->hasAttribute('use')) {
         $use = $kd->getAttribute('use');
         if ($use === 'encryption') {
             $r['encryption'] = TRUE;
             $r['signing'] = FALSE;
         } elseif ($use === 'signing') {
             $r['encryption'] = FALSE;
             $r['signing'] = TRUE;
         } else {
             throw new Exception('Invalid use-value for KeyDescriptor: ' . $use);
         }
     } else {
         $r['encryption'] = TRUE;
         $r['signing'] = TRUE;
     }
     $keyInfo = SimpleSAML_Utilities::getDOMChildren($kd, 'KeyInfo', '@ds');
     if (count($keyInfo) === 0) {
         throw new Exception('Missing required KeyInfo field for KeyDescriptor.');
     }
     $keyInfo = $keyInfo[0];
     $X509Data = SimpleSAML_Utilities::getDOMChildren($keyInfo, 'X509Data', '@ds');
     if (count($X509Data) === 0) {
         return NULL;
     }
     $X509Data = $X509Data[0];
     $X509Certificate = SimpleSAML_Utilities::getDOMChildren($X509Data, 'X509Certificate', '@ds');
     if (count($X509Certificate) === 0) {
         return NULL;
     }
     $X509Certificate = $X509Certificate[0];
     $r['type'] = 'X509Certificate';
     $r['X509Certificate'] = SimpleSAML_Utilities::getDOMText($X509Certificate);
     return $r;
 }