View source
<?php
class SearchApiAcquiaSearchConnection extends SearchApiSolrConnection {
protected $derivedKey;
function authenticator($string, $nonce, $derived_key = NULL) {
if (empty($derived_key)) {
$derived_key = $this
->getDerivedKey();
}
if (empty($derived_key)) {
return '';
}
else {
$time = time();
$hash = hash_hmac('sha1', $time . $nonce . $string, $derived_key);
return 'acquia_solr_time=' . $time . '; acquia_solr_nonce=' . $nonce . '; acquia_solr_hmac=' . $hash . ';';
}
}
public function setDerivedKey($derived_key) {
$this->derivedKey = $derived_key;
}
public function getDerivedKey() {
if (!isset($this->derivedKey)) {
$key = acquia_agent_settings('acquia_key');
$subscription = acquia_agent_settings('acquia_subscription_data');
$identifier = acquia_agent_settings('acquia_identifier');
if (empty($subscription['active']) || empty($key) || empty($identifier)) {
$this->derivedKey = '';
}
else {
$salt = isset($subscription['derived_key_salt']) ? $subscription['derived_key_salt'] : '';
$derivation_string = $identifier . 'solr' . $salt;
$this->derivedKey = hash_hmac('sha1', str_pad($derivation_string, 80, $derivation_string), $key);
}
}
return $this->derivedKey;
}
public function prepareRequest(&$url, &$options, $use_data = TRUE) {
$id = uniqid();
if (!stristr($url, '?')) {
$url .= "?";
}
else {
$url .= "&";
}
$url .= 'request_id=' . $id;
if (isset($_ENV['HTTP_X_REQUEST_ID'])) {
$xid = empty($_ENV['HTTP_X_REQUEST_ID']) ? '-' : $_ENV['HTTP_X_REQUEST_ID'];
$url .= '&x-request-id=' . rawurlencode($xid);
}
if ($use_data && isset($options['data'])) {
list($cookie, $nonce) = $this
->authCookie($url, $options['data']);
}
else {
list($cookie, $nonce) = $this
->authCookie($url);
}
if (empty($cookie)) {
throw new Exception('Invalid authentication string - subscription keys expired or missing.');
}
$options['headers']['Cookie'] = $cookie;
$options['headers'] += array(
'User-Agent' => 'search_api_acquia/' . variable_get('search_api_acquia_version', '7.x'),
);
$options['context'] = acquia_agent_stream_context_create($url, 'acquia_search');
if (!$options['context']) {
throw new Exception(t("Could not create stream context"));
}
return $nonce;
}
public function authenticateResponse($response, $nonce, $url) {
$hmac = $this
->extractHmac($response->headers);
if (!$this
->validResponse($hmac, $nonce, $response->data)) {
throw new Exception('Authentication of search content failed url: ' . $url);
}
return $response;
}
protected function extractHmac($headers) {
$reg = array();
if (is_array($headers)) {
foreach ($headers as $name => $value) {
if (strtolower($name) == 'pragma' && preg_match("/hmac_digest=([^;]+);/i", $value, $reg)) {
return trim($reg[1]);
}
}
}
return '';
}
protected function validResponse($hmac, $nonce, $string, $derived_key = NULL) {
if (empty($derived_key)) {
$derived_key = $this
->getDerivedKey();
}
return $hmac == hash_hmac('sha1', $nonce . $string, $derived_key);
}
public function makeServletRequest($servlet, array $params = array(), array $options = array()) {
$params += array(
'wt' => 'json',
);
$url = $this
->constructUrl($servlet, $params);
$nonce = $this
->prepareRequest($url, $options, FALSE);
$response = $this
->makeHttpRequest($url, $options);
$response = $this
->checkResponse($response);
return $this
->authenticateResponse($response, $nonce, $url);
}
protected function sendRawGet($url, array $options = array()) {
$nonce = $this
->prepareRequest($url, $options);
$response = $this
->makeHttpRequest($url, $options);
$response = $this
->checkResponse($response);
return $this
->authenticateResponse($response, $nonce, $url);
}
protected function sendRawPost($url, array $options = array()) {
$options['method'] = 'POST';
if (!isset($options['headers']['Content-Type'])) {
$options['headers']['Content-Type'] = 'text/xml; charset=UTF-8';
}
$nonce = $this
->prepareRequest($url, $options);
$response = $this
->makeHttpRequest($url, $options);
$response = $this
->checkResponse($response);
return $this
->authenticateResponse($response, $nonce, $url);
}
function authCookie(&$url, $string = '', $derived_key = NULL) {
$uri = parse_url($url);
if (in_array('ssl', stream_get_transports(), TRUE) && !defined('ACQUIA_DEVELOPMENT_NOSSL')) {
$scheme = 'https://';
$port = '';
}
else {
$scheme = 'http://';
$port = isset($uri['port']) && $uri['port'] != 80 ? ':' . $uri['port'] : '';
}
$path = isset($uri['path']) ? $uri['path'] : '/';
$query = isset($uri['query']) ? '?' . $uri['query'] : '';
$url = $scheme . $uri['host'] . $port . $path . $query;
$nonce = base64_encode(drupal_random_bytes(24));
if ($string) {
$auth_header = $this
->authenticator($string, $nonce, $derived_key);
}
else {
$auth_header = $this
->authenticator($path . $query, $nonce, $derived_key);
}
return array(
$auth_header,
$nonce,
);
}
}