public function __doRequest($request, $location, $action, $version, $one_way = null)
{
$certKey = openssl_get_privatekey($this->privateKey, '');
$wsse = new \DOMDocument('1.0', 'UTF-8');
$wsse->loadXML($request);
$envelope = $wsse->documentElement;
$ns = $envelope->namespaceURI;
$prefix = $envelope->prefix;
$xpath = new \DOMXPath($wsse);
$xpath->registerNamespace('wssoap', $ns);
$xpath->registerNamespace('wswsse', self::WSSENS);
//Sets security header
$setActor = null;
$headers = $xpath->query('//wssoap:Envelope/wssoap:Header');
$header = $headers->item(0);
if (!$header) {
$header = $wsse->createElementNS($ns, $prefix . ':Header');
$envelope->insertBefore($header, $envelope->firstChild);
}
$secNodes = $xpath->query('./wswsse:Security', $header);
$security = null;
foreach ($secNodes as $node) {
$actor = $node->getAttributeNS($ns, 'actor');
if ($actor == $setActor) {
$security = $node;
break;
}
}
if (!$security) {
$security = $wsse->createElementNS(self::WSSENS, self::WSSEPFX . ':Security');
$header->appendChild($security);
$security->setAttributeNS($ns, $prefix . ':mustUnderstand', '1');
if (!empty($setActor)) {
$security->setAttributeNS($ns, $prefix . ':actor', $setActor);
}
}
//Sets timestamp
$timestamp = $wsse->createElementNS(self::WSUNS, self::WSUPFX . ':Timestamp');
$security->insertBefore($timestamp, $security->firstChild);
$currentTime = time();
$created = $wsse->createElementNS(self::WSUNS, self::WSUPFX . ':Created', gmdate('Y-m-d\\TH:i:s', $currentTime) . 'Z');
$timestamp->appendChild($created);
$expire = $wsse->createElementNS(self::WSUNS, self::WSUPFX . ':Expires', gmdate('Y-m-d\\TH:i:s', $currentTime + 3600) . 'Z');
$timestamp->appendChild($expire);
//Signs document
$arNodes = array();
foreach ($security->childNodes as $node) {
if ($node->nodeType == \XML_ELEMENT_NODE) {
$arNodes[] = $node;
}
}
foreach ($envelope->childNodes as $node) {
if ($node->namespaceURI == $ns && $node->localName == 'Body') {
$arNodes[] = $node;
break;
}
}
$arOptions = array('prefix' => self::WSUPFX, 'prefix_ns' => self::WSUNS);
try {
$sigdoc = new \DOMDocument();
$sigdoc->loadXML(self::SIGN_TPL);
$this->sigNode = $sigdoc->documentElement;
$sigXpath = new \DOMXPath($this->sigNode->ownerDocument);
$sigXpath->registerNamespace('secdsig', self::XMLDSIGNS);
$query = './secdsig:SignedInfo';
$nodeset = $sigXpath->query($query);
if ($sinfo = $nodeset->item(0)) {
$canonNode = $this->_createNewSignNode('CanonicalizationMethod');
$sinfo->insertBefore($canonNode, $sinfo->firstChild);
$canonNode->setAttribute('Algorithm', $this->canonicalMethod);
}
$nodeset = $sigXpath->query("./secdsig:SignedInfo");
if ($sInfo = $nodeset->item(0)) {
foreach ($arNodes as $node) {
$this->_addRefInternal($sInfo, $node, self::SHA1, null, $arOptions);
}
}
$nodeset = $sigXpath->query("./secdsig:SignedInfo");
if ($sInfo = $nodeset->item(0)) {
$nodeset = $sigXpath->query("./secdsig:SignatureMethod", $sInfo);
$sMethod = $nodeset->item(0);
$sMethod->setAttribute('Algorithm', "http://www.w3.org/2000/09/xmldsig#rsa-sha1");
$data = $this->_canonicalizeData($sInfo, $this->canonicalMethod);
$algo = OPENSSL_ALGO_SHA1;
if (!openssl_sign($data, $signature, $certKey, $algo)) {
throw new \Exception('Failure Signing Data: ' . openssl_error_string() . ' - ' . $algo);
return;
}
$sigValue = base64_encode($signature);
$sigValueNode = $this->_createNewSignNode('SignatureValue', $sigValue);
if ($infoSibling = $sInfo->nextSibling) {
$infoSibling->parentNode->insertBefore($sigValueNode, $infoSibling);
} else {
$this->sigNode->appendChild($sigValueNode);
}
}
$this->_insertSignature($security, $security->firstChild);
} catch (\Exception $e) {
throw new \Exception("Unable to sign AWS API request. Please, check your X.509 certificate and private key. ");
}
$token = $wsse->createElementNS(self::WSSENS, self::WSSEPFX . ':BinarySecurityToken', self::_get509XCert($this->certificate, true));
$security->insertBefore($token, $security->firstChild);
$token->setAttribute('EncodingType', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary');
$token->setAttributeNS(self::WSUNS, self::WSUPFX . ':Id', self::_generateGuid());
$token->setAttribute('ValueType', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3');
$sigdoc = new \DOMDocument();
$sigdoc->loadXML(self::SIGN_TPL);
$this->sigNode = $sigdoc->documentElement;
$sigXpath = new \DOMXPath($this->sigNode->ownerDocument);
$sigXpath->registerNamespace('secdsig', self::XMLDSIGNS);
if ($objDSig = $this->_locateSignature($wsse)) {
$tokenURI = '#' . $token->getAttributeNS(self::WSUNS, "Id");
$xpath->registerNamespace('secdsig', self::XMLDSIGNS);
$nodeset = $xpath->query("./secdsig:KeyInfo", $objDSig);
$keyInfo = $nodeset->item(0);
if (!$keyInfo) {
$keyInfo = $this->_createNewSignNode('KeyInfo');
$objDSig->appendChild($keyInfo);
}
$tokenRef = $wsse->createElementNS(self::WSSENS, self::WSSEPFX . ':SecurityTokenReference');
$keyInfo->appendChild($tokenRef);
$reference = $wsse->createElementNS(self::WSSENS, self::WSSEPFX . ':Reference');
$reference->setAttribute("URI", $tokenURI);
$tokenRef->appendChild($reference);
} else {
throw new \Exception('Unable to locate digital signature');
}
$retval = parent::__doRequest($wsse->saveXML(), $location, $action, $version, $one_way);
if ($retval instanceof \SoapFault && stristr($retval->faultstring, "Could not connect to host")) {
throw new \Exception($retval->getMessage());
}
return $retval;
}