View source
<?php
namespace Drupal\acquia_search_multi_subs\EventSubscriber;
use Solarium\Core\Event\Events;
use Solarium\Core\Plugin\AbstractPlugin;
use Drupal\Component\Utility\Crypt;
use Symfony\Component\EventDispatcher\Event;
use Solarium\Exception\HttpException;
use Drupal\acquia_connector\CryptConnector;
class SearchSubscriber extends AbstractPlugin {
protected $client;
protected $derived_key = [];
protected $nonce = '';
protected $uri = '';
protected $options = '';
public function initPlugin($client, $options) {
$this->client = $client;
$this->options = $options;
$dispatcher = $this->client
->getEventDispatcher();
$dispatcher
->addListener(Events::PRE_EXECUTE_REQUEST, array(
$this,
'preExecuteRequest',
));
$dispatcher
->addListener(Events::POST_EXECUTE_REQUEST, array(
$this,
'postExecuteRequest',
));
}
public function preExecuteRequest($event) {
$request = $event
->getRequest();
$request
->addParam('request_id', uniqid(), TRUE);
$endpoint = $this->client
->getEndpoint();
$this->uri = $endpoint
->getBaseUri() . $request
->getUri();
$this->nonce = Crypt::randomBytesBase64(24);
$string = $request
->getRawData();
if (!$string) {
$parsed_url = parse_url($this->uri);
$path = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
$query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
$string = $path . $query;
}
$cookie = $this
->calculateAuthCookie($string, $this->nonce, NULL, $this->client
->getEndpoint()
->getOption('core'));
$request
->addHeader('Cookie: ' . $cookie);
$request
->addHeader('User-Agent: ' . 'acquia_search/' . \Drupal::config('acquia_search.settings')
->get('version'));
}
public function postExecuteRequest($event) {
$response = $event
->getResponse();
if ($response
->getStatusCode() != 200) {
throw new HttpException($response
->getStatusMessage());
}
if ($event
->getRequest()
->getHandler() == 'admin/ping') {
return;
}
$this
->authenticateResponse($event
->getResponse(), $this->nonce, $this->uri, NULL, $this->client
->getEndpoint()
->getOption('core'));
}
protected function authenticateResponse($response, $nonce, $url) {
$hmac = $this
->extractHmac($response
->getHeaders());
if (!$this
->validateResponse($hmac, $nonce, $response
->getBody(), NULL, $this->client
->getEndpoint()
->getOption('core'))) {
throw new HttpException('Authentication of search content failed url: ' . $url);
}
return $response;
}
public function extractHmac($headers) {
$reg = array();
if (is_array($headers)) {
foreach ($headers as $value) {
if (stristr($value, 'pragma') && preg_match("/hmac_digest=([^;]+);/i", $value, $reg)) {
return trim($reg[1]);
}
}
}
return '';
}
public function validateResponse($hmac, $nonce, $string, $derived_key = NULL, $env_id = NULL) {
if (empty($derived_key)) {
$derived_key = $this
->getDerivedKey($env_id);
}
return $hmac == hash_hmac('sha1', $nonce . $string, $derived_key);
}
public function getDerivedKey($env_id = NULL) {
if (empty($env_id)) {
$env_id = $this->client
->getEndpoint()
->getKey();
}
if (!isset($this->derived_key[$env_id])) {
$identifier = \Drupal::config('acquia_connector.settings')
->get('identifier');
$key = \Drupal::config('acquia_connector.settings')
->get('key');
$derived_key_salt = $this
->getDerivedKeySalt();
if (empty($derived_key_salt) || empty($key) || empty($identifier)) {
$this->derived_key[$env_id] = '';
}
elseif (!isset($derived_key[$env_id])) {
$this->derived_key[$env_id] = CryptConnector::createDerivedKey($derived_key_salt, $env_id, $key);
}
}
return $this->derived_key[$env_id];
}
public function getDerivedKeySalt() {
$salt = \Drupal::config('acquia_search.settings')
->get('derived_key_salt');
if (!$salt) {
$subscription = \Drupal::config('acquia_connector.settings')
->get('subscription_data');
if (isset($subscription['derived_key_salt'])) {
\Drupal::configFactory()
->getEditable('acquia_search.settings')
->set('derived_key_salt', $subscription['derived_key_salt'])
->save();
$salt = $subscription['derived_key_salt'];
}
}
return $salt;
}
public function calculateAuthCookie($string, $nonce, $derived_key = NULL, $env_id = NULL) {
if (empty($derived_key)) {
$derived_key = $this
->getDerivedKey($env_id);
}
if (empty($derived_key)) {
return '';
}
else {
$time = REQUEST_TIME;
return 'acquia_solr_time=' . $time . '; acquia_solr_nonce=' . $nonce . '; acquia_solr_hmac=' . hash_hmac('sha1', $time . $nonce . $string, $derived_key) . ';';
}
}
}