/**
  * Tests that a new token seed is generated upon first use.
  *
  * @covers ::get
  */
 public function testGenerateSeedOnGet()
 {
     $key = Crypt::randomBytesBase64();
     $this->privateKey->expects($this->any())->method('get')->will($this->returnValue($key));
     $this->sessionMetadata->expects($this->once())->method('getCsrfTokenSeed')->will($this->returnValue(NULL));
     $this->sessionMetadata->expects($this->once())->method('setCsrfTokenSeed')->with($this->isType('string'));
     $this->assertInternalType('string', $this->generator->get());
 }
예제 #2
0
 /**
  * {@inheritdoc}
  */
 function setUp()
 {
     parent::setUp();
     $this->key = Crypt::randomBytesBase64(55);
     $this->privateKey = $this->getMockBuilder('Drupal\\Core\\PrivateKey')->disableOriginalConstructor()->setMethods(array('get'))->getMock();
     $this->privateKey->expects($this->any())->method('get')->will($this->returnValue($this->key));
     $settings = array('hash_salt' => $this->randomName());
     new Settings($settings);
     $this->generator = new CsrfTokenGenerator($this->privateKey);
 }
예제 #3
0
 /**
  * Generates a hash that uniquely identifies the user's permissions.
  *
  * @param \Drupal\user\Entity\Role[] $roles
  *   The user's roles.
  *
  * @return string
  *   The permissions hash.
  */
 protected function doGenerate(array $roles)
 {
     // @todo Once Drupal gets rid of user_role_permissions(), we should be able
     // to inject the user role controller and call a method on that instead.
     $permissions_by_role = user_role_permissions($roles);
     foreach ($permissions_by_role as $role => $permissions) {
         sort($permissions);
         $permissions_by_role[$role] = $permissions;
     }
     return hash('sha256', $this->privateKey->get() . Settings::getHashSalt() . serialize($permissions_by_role));
 }
 /**
  * {@inheritdoc}
  */
 protected function setUp()
 {
     parent::setUp();
     new Settings(array('hash_salt' => 'test'));
     // The mocked super user account, with the same roles as Account 2.
     $this->account1 = $this->getMockBuilder('Drupal\\user\\Entity\\User')->disableOriginalConstructor()->setMethods(array('getRoles', 'id'))->getMock();
     $this->account1->expects($this->any())->method('id')->willReturn(1);
     $this->account1->expects($this->never())->method('getRoles');
     // Account 2: 'administrator' and 'authenticated' roles.
     $roles_1 = array('administrator', 'authenticated');
     $this->account2 = $this->getMockBuilder('Drupal\\user\\Entity\\User')->disableOriginalConstructor()->setMethods(array('getRoles', 'id'))->getMock();
     $this->account2->expects($this->any())->method('getRoles')->will($this->returnValue($roles_1));
     $this->account2->expects($this->any())->method('id')->willReturn(2);
     // Account 3: 'authenticated' and 'administrator' roles (different order).
     $roles_3 = array('authenticated', 'administrator');
     $this->account3 = $this->getMockBuilder('Drupal\\user\\Entity\\User')->disableOriginalConstructor()->setMethods(array('getRoles', 'id'))->getMock();
     $this->account3->expects($this->any())->method('getRoles')->will($this->returnValue($roles_3));
     $this->account3->expects($this->any())->method('id')->willReturn(3);
     // Updated account 2: now also 'editor' role.
     $roles_2_updated = array('editor', 'administrator', 'authenticated');
     $this->account2Updated = $this->getMockBuilder('Drupal\\user\\Entity\\User')->disableOriginalConstructor()->setMethods(array('getRoles', 'id'))->getMock();
     $this->account2Updated->expects($this->any())->method('getRoles')->will($this->returnValue($roles_2_updated));
     $this->account2Updated->expects($this->any())->method('id')->willReturn(2);
     // Mocked private key + cache services.
     $random = Crypt::randomBytesBase64(55);
     $this->privateKey = $this->getMockBuilder('Drupal\\Core\\PrivateKey')->disableOriginalConstructor()->setMethods(array('get'))->getMock();
     $this->privateKey->expects($this->any())->method('get')->will($this->returnValue($random));
     $this->cache = $this->getMockBuilder('Drupal\\Core\\Cache\\CacheBackendInterface')->disableOriginalConstructor()->getMock();
     $this->staticCache = $this->getMockBuilder('Drupal\\Core\\Cache\\CacheBackendInterface')->disableOriginalConstructor()->getMock();
     $this->permissionsHash = new PermissionsHashGenerator($this->privateKey, $this->cache, $this->staticCache);
 }
예제 #5
0
 /**
  * {@inheritdoc}
  */
 public function processFetchTask($project)
 {
     global $base_url;
     // This can be in the middle of a long-running batch, so REQUEST_TIME won't
     // necessarily be valid.
     $request_time_difference = time() - REQUEST_TIME;
     if (empty($this->failed)) {
         // If we have valid data about release history XML servers that we have
         // failed to fetch from on previous attempts, load that.
         $this->failed = $this->tempStore->get('fetch_failures');
     }
     $max_fetch_attempts = $this->updateSettings->get('fetch.max_attempts');
     $success = FALSE;
     $available = array();
     $site_key = Crypt::hmacBase64($base_url, $this->privateKey->get());
     $fetch_url_base = $this->updateFetcher->getFetchBaseUrl($project);
     $project_name = $project['name'];
     if (empty($this->failed[$fetch_url_base]) || $this->failed[$fetch_url_base] < $max_fetch_attempts) {
         $data = $this->updateFetcher->fetchProjectData($project, $site_key);
     }
     if (!empty($data)) {
         $available = $this->parseXml($data);
         // @todo: Purge release data we don't need. See
         //   https://www.drupal.org/node/238950.
         if (!empty($available)) {
             // Only if we fetched and parsed something sane do we return success.
             $success = TRUE;
         }
     } else {
         $available['project_status'] = 'not-fetched';
         if (empty($this->failed[$fetch_url_base])) {
             $this->failed[$fetch_url_base] = 1;
         } else {
             $this->failed[$fetch_url_base]++;
         }
     }
     $frequency = $this->updateSettings->get('check.interval_days');
     $available['last_fetch'] = REQUEST_TIME + $request_time_difference;
     $this->availableReleasesTempStore->setWithExpire($project_name, $available, $request_time_difference + 60 * 60 * 24 * $frequency);
     // Stash the $this->failed data back in the DB for the next 5 minutes.
     $this->tempStore->setWithExpire('fetch_failures', $this->failed, $request_time_difference + 60 * 5);
     // Whether this worked or not, we did just (try to) check for updates.
     $this->stateStore->set('update.last_check', REQUEST_TIME + $request_time_difference);
     // Now that we processed the fetch task for this project, clear out the
     // record for this task so we're willing to fetch again.
     $this->fetchTaskStore->delete($project_name);
     return $success;
 }
예제 #6
0
 /**
  * Tests PrivateKey::setPrivateKey().
  */
 public function testSet()
 {
     $random_name = $this->randomMachineName();
     $this->state->expects($this->once())->method('set')->with('system.private_key', $random_name)->will($this->returnValue(TRUE));
     $this->privateKey->set($random_name);
 }
예제 #7
0
 /**
  * Generates a token based on $value, the token seed, and the private key.
  *
  * @param string $seed
  *   The per-session token seed.
  * @param string $value
  *   (optional) An additional value to base the token on.
  *
  * @return string
  *   A 43-character URL-safe token for validation, based on the token seed,
  *   the hash salt provided by Settings::getHashSalt(), and the
  *   'drupal_private_key' configuration variable.
  *
  * @see \Drupal\Core\Site\Settings::getHashSalt()
  */
 protected function computeToken($seed, $value = '')
 {
     return Crypt::hmacBase64($value, $seed . $this->privateKey->get() . Settings::getHashSalt());
 }
예제 #8
0
 /**
  * Hashes the given string.
  *
  * @param string $identifier
  *   The string to be hashed.
  *
  * @return string
  *   The hash.
  */
 protected function hash($identifier)
 {
     return hash('sha256', $this->privateKey->get() . Settings::getHashSalt() . $identifier);
 }
예제 #9
0
 /**
  * {@inheritdoc}
  */
 public function buildForm(array $form, FormStateInterface $form_state)
 {
     $config = $this->config('acquia_connector.settings');
     $identifier = $config->get('identifier');
     $key = $config->get('key');
     $subscription = $config->get('subscription_name');
     if (empty($identifier) && empty($key)) {
         return new RedirectResponse($this->url('acquia_connector.start'));
     }
     // Check our connection to the Acquia Network and validity of the credentials.
     try {
         $this->client->getSubscription($identifier, $key);
     } catch (ConnectorException $e) {
         $error_message = acquia_connector_connection_error_message($e->getCustomMessage('code', FALSE));
         $ssl_available = in_array('ssl', stream_get_transports(), TRUE) && !defined('ACQUIA_DEVELOPMENT_NOSSL') && $config->get('spi.ssl_verify');
         if (empty($error_message) && $ssl_available) {
             $error_message = $this->t('There was an error in validating your subscription credentials. You may want to try disabling SSL peer verification by setting the variable acquia_connector.settings:spi.ssl_verify to false.');
         }
         drupal_set_message($error_message, 'error', FALSE);
     }
     $form['connected'] = array('#markup' => $this->t('<h3>Connected to the Acquia Network</h3>'));
     if (!empty($subscription)) {
         $form['subscription'] = array('#markup' => $this->t('Subscription: @sub <a href="@url">change</a>', array('@sub' => $subscription, '@url' => $this->url('acquia_connector.setup'))));
     }
     $form['connection'] = array('#type' => 'fieldset', '#title' => $this->t('Acquia Subscription Settings'), '#collapsible' => FALSE);
     $form['migrate'] = array('#type' => 'details', '#title' => $this->t('Acquia Cloud Migrate'), '#description' => $this->t('Transfer a fully-functional copy of your site to Acquia Cloud. <a href="@url">Learn more</a>.', array('@url' => Url::fromUri('https://docs.acquia.com/cloud/site/import/connector')->getUri())), '#open' => !\Drupal::request()->server->has('AH_SITE_GROUP'));
     $form['migrate']['submit'] = array('#type' => 'submit', '#value' => $this->t('Migrate'), '#submit' => ['::submitMigrateGoForm']);
     $last_migration = \Drupal::state()->get('migrate.cloud', []);
     if (!empty($last_migration['db_file']) || !empty($last_migration['tar_file']) || !empty($last_migration['dir'])) {
         // Replace Upload button with Cleanup.
         unset($form['migrate']['#description']);
         $form['migrate']['#prefix'] = '<div class="messages error">' . $this->t('Temporary files were leftover from last migration attempt.') . '</div>';
         $form['migrate']['submit']['#value'] = $this->t('Cleanup files');
         $form['migrate']['submit']['#submit'] = ['::submitMigrateCleanupForm'];
     }
     // Help documentation is local unless the Help module is disabled.
     if ($this->moduleHandler->moduleExists('help')) {
         $help_url = \Drupal::url('help.page', array('name' => 'acquia_connector'));
     } else {
         $help_url = Url::fromUri('https://docs.acquia.com/network/install')->getUri();
     }
     if (!empty($identifier) && !empty($key)) {
         $ssl_available = in_array('ssl', stream_get_transports(), TRUE) && !defined('ACQUIA_DEVELOPMENT_NOSSL');
         $form['connection']['spi'] = array('#prefix' => '<div class="acquia-spi">', '#suffix' => '</div>', '#weight' => 0);
         $form['connection']['description']['#markup'] = $this->t('Allow collection and examination of the following items. <a href="@url">Learn more</a>.', array('@url' => $help_url));
         $form['connection']['description']['#weight'] = '-1';
         $form['connection']['spi']['admin_priv'] = array('#type' => 'checkbox', '#title' => $this->t('Admin privileges'), '#default_value' => $config->get('spi.admin_priv'));
         $form['connection']['spi']['send_node_user'] = array('#type' => 'checkbox', '#title' => $this->t('Nodes and users'), '#default_value' => $config->get('spi.send_node_user'));
         $form['connection']['spi']['send_watchdog'] = array('#type' => 'checkbox', '#title' => $this->t('Watchdog logs'), '#default_value' => $config->get('spi.send_watchdog'));
         $form['connection']['spi']['module_diff_data'] = array('#type' => 'checkbox', '#title' => t('Source code'), '#default_value' => (int) $config->get('spi.module_diff_data') && $ssl_available, '#description' => $this->t('Source code analysis requires a SSL connection and for your site to be publicly accessible. <a href="@url">Learn more</a>.', array('@url' => $help_url)), '#disabled' => !$ssl_available);
         $form['connection']['acquia_dynamic_banner'] = array('#type' => 'checkbox', '#title' => $this->t('Receive updates from Acquia Subscription'), '#default_value' => $config->get('spi.dynamic_banner'));
         $form['connection']['alter_variables'] = array('#type' => 'checkbox', '#title' => $this->t('Allow Insight to update list of approved variables.'), '#default_value' => (int) $config->get('spi.set_variables_override'), '#description' => $this->t('Insight can set variables on your site to recommended values at your approval, but only from a specific list of variables. Check this box to allow Insight to update the list of approved variables. <a href="@url">Learn more</a>.', array('@url' => $help_url)));
         $use_cron = $config->get('spi.use_cron');
         $form['connection']['use_cron'] = array('#type' => 'checkbox', '#title' => $this->t('Send via Drupal cron'), '#default_value' => $use_cron);
         $form['#attached']['library'][] = 'acquia_connector/acquia_connector.form';
         $key = sha1($this->privateKey->get());
         $url = Url::fromRoute('acquia_connector.send', [], ['query' => ['key' => $key], 'absolute' => TRUE])->toString();
         $form['connection']['use_cron_url'] = array('#type' => 'container', '#children' => $this->t('Enter the following URL in your server\'s crontab to send SPI data:<br /><em>@url</em>', array('@url' => $url)), '#states' => array('visible' => array(':input[name="use_cron"]' => array('checked' => FALSE))));
     }
     return parent::buildForm($form, $form_state);
 }