summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris McCafferty2017-03-15 16:50:50 -0400
committerChris McCafferty2017-03-15 16:50:50 -0400
commit7b55855e70fe7015f1c55fd781ac72502700c11b (patch)
treec15b9e4500438d149c443fc49fb4cc7f5eea5244
parentd20187f47396f75c5309781f87d1e1c53af44feb (diff)
SA-CORE-2017-001 by alexpott, benjy, Berdir, casey, cilefen, dawehner, Heine, klausi, larowlan, Mixologic, mlhess, pwolanin, samuel.mortenson, Wim Leers, xjm, YesCT
-rw-r--r--composer.lock10
-rw-r--r--core/composer.json2
-rw-r--r--core/modules/block/block.routing.yml2
-rw-r--r--core/modules/block/src/Tests/BlockUiTest.php14
-rw-r--r--core/modules/editor/editor.module4
-rw-r--r--core/modules/editor/tests/src/Functional/EditorPrivateFileReferenceFilterTest.php42
-rw-r--r--core/modules/search/search.routing.yml3
-rw-r--r--core/modules/search/src/Form/SearchBlockForm.php13
-rw-r--r--core/modules/search/src/Tests/SearchConfigSettingsFormTest.php36
-rw-r--r--core/modules/simpletest/src/WebTestBase.php4
10 files changed, 109 insertions, 21 deletions
diff --git a/composer.lock b/composer.lock
index 81ca12d..44d2f9a 100644
--- a/composer.lock
+++ b/composer.lock
@@ -3642,16 +3642,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "4.8.27",
+ "version": "4.8.28",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90"
+ "reference": "558a3a0d28b4cb7e4a593a4fbd2220e787076225"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c062dddcb68e44b563f66ee319ddae2b5a322a90",
- "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/558a3a0d28b4cb7e4a593a4fbd2220e787076225",
+ "reference": "558a3a0d28b4cb7e4a593a4fbd2220e787076225",
"shasum": ""
},
"require": {
@@ -3710,7 +3710,7 @@
"testing",
"xunit"
],
- "time": "2016-07-21T06:48:14+00:00"
+ "time": "2016-11-14T06:25:28+00:00"
},
{
"name": "phpunit/phpunit-mock-objects",
diff --git a/core/composer.json b/core/composer.json
index 503704c..d2a41c0 100644
--- a/core/composer.json
+++ b/core/composer.json
@@ -42,7 +42,7 @@
"jcalderonzumba/gastonjs": "~1.0.2",
"jcalderonzumba/mink-phantomjs-driver": "~0.3.1",
"mikey179/vfsStream": "~1.2",
- "phpunit/phpunit": "~4.8",
+ "phpunit/phpunit": ">=4.8.28 <5",
"symfony/css-selector": "~2.8"
},
"replace": {
diff --git a/core/modules/block/block.routing.yml b/core/modules/block/block.routing.yml
index e12cd8b..83648b9 100644
--- a/core/modules/block/block.routing.yml
+++ b/core/modules/block/block.routing.yml
@@ -32,6 +32,7 @@ entity.block.enable:
op: enable
requirements:
_entity_access: 'block.enable'
+ _csrf_token: 'TRUE'
entity.block.disable:
path: '/admin/structure/block/manage/{block}/disable'
@@ -40,6 +41,7 @@ entity.block.disable:
op: disable
requirements:
_entity_access: 'block.disable'
+ _csrf_token: 'TRUE'
block.admin_display:
path: '/admin/structure/block'
diff --git a/core/modules/block/src/Tests/BlockUiTest.php b/core/modules/block/src/Tests/BlockUiTest.php
index 899f9bb..d4ebda4 100644
--- a/core/modules/block/src/Tests/BlockUiTest.php
+++ b/core/modules/block/src/Tests/BlockUiTest.php
@@ -312,4 +312,18 @@ class BlockUiTest extends WebTestBase {
$this->assertTrue($error_class, 'Plugin error class found in parent form.');
}
+ /**
+ * Tests that the enable/disable routes are protected from CSRF.
+ */
+ public function testRouteProtection() {
+ // Get the first block generated in our setUp method.
+ /** @var \Drupal\block\BlockInterface $block */
+ $block = reset($this->blocks);
+ // Ensure that the enable and disable routes are protected.
+ $this->drupalGet('admin/structure/block/manage/' . $block->id() . '/disable');
+ $this->assertResponse(403);
+ $this->drupalGet('admin/structure/block/manage/' . $block->id() . '/enable');
+ $this->assertResponse(403);
+ }
+
}
diff --git a/core/modules/editor/editor.module b/core/modules/editor/editor.module
index 04e4cd5..dccf823 100644
--- a/core/modules/editor/editor.module
+++ b/core/modules/editor/editor.module
@@ -520,8 +520,8 @@ function editor_file_download($uri) {
if ($file->isPermanent()) {
$referencing_entity_is_accessible = FALSE;
$references = empty($usage_list['editor']) ? [] : $usage_list['editor'];
- foreach ($references as $entity_type => $entity_ids) {
- $referencing_entities = entity_load_multiple($entity_type, $entity_ids);
+ foreach ($references as $entity_type => $entity_ids_usage_count) {
+ $referencing_entities = entity_load_multiple($entity_type, array_keys($entity_ids_usage_count));
/** @var \Drupal\Core\Entity\EntityInterface $referencing_entity */
foreach ($referencing_entities as $referencing_entity) {
if ($referencing_entity->access('view', NULL, TRUE)->isAllowed()) {
diff --git a/core/modules/editor/tests/src/Functional/EditorPrivateFileReferenceFilterTest.php b/core/modules/editor/tests/src/Functional/EditorPrivateFileReferenceFilterTest.php
index 3e3f3d1..816de5d 100644
--- a/core/modules/editor/tests/src/Functional/EditorPrivateFileReferenceFilterTest.php
+++ b/core/modules/editor/tests/src/Functional/EditorPrivateFileReferenceFilterTest.php
@@ -68,9 +68,18 @@ class EditorPrivateFileReferenceFilterTest extends BrowserTestBase {
$file->setPermanent();
$file->save();
+ // Create some nodes to ensure file usage count does not match the ID's
+ // of the nodes we are going to check.
+ for ($i = 0; $i < 5; $i++) {
+ $this->drupalCreateNode([
+ 'type' => 'page',
+ 'uid' => $author->id(),
+ ]);
+ }
+
// Create a node with its body field properly pointing to the just-created
// file.
- $node = $this->drupalCreateNode([
+ $published_node = $this->drupalCreateNode([
'type' => 'page',
'body' => [
'value' => '<img alt="alt" data-entity-type="file" data-entity-uuid="' . $file->uuid() . '" src="' . $src . '" />',
@@ -79,19 +88,44 @@ class EditorPrivateFileReferenceFilterTest extends BrowserTestBase {
'uid' => $author->id(),
]);
+ // Create an unpublished node with its body field properly pointing to the
+ // just-created file.
+ $unpublished_node = $this->drupalCreateNode([
+ 'type' => 'page',
+ 'status' => NODE_NOT_PUBLISHED,
+ 'body' => [
+ 'value' => '<img alt="alt" data-entity-type="file" data-entity-uuid="' . $file->uuid() . '" src="' . $src . '" />',
+ 'format' => 'private_images',
+ ],
+ 'uid' => $author->id(),
+ ]);
+
// Do the actual test. The image should be visible for anonymous users,
- // because they can view the referencing entity.
- $this->drupalGet($node->toUrl());
+ // because they can view the published node. Even though they can't view
+ // the unpublished node.
+ $this->drupalGet($published_node->toUrl());
$this->assertSession()->statusCodeEquals(200);
+ $this->drupalGet($unpublished_node->toUrl());
+ $this->assertSession()->statusCodeEquals(403);
$this->drupalGet($src);
$this->assertSession()->statusCodeEquals(200);
+ // When the published node is also unpublished, the image should also
+ // become inaccessible to anonymous users.
+ $published_node->setPublished(FALSE)->save();
+
+ $this->drupalGet($published_node->toUrl());
+ $this->assertSession()->statusCodeEquals(403);
+ $this->drupalGet($src);
+ $this->assertSession()->statusCodeEquals(403);
+
// Disallow anonymous users to view the entity, which then should also
// disallow them to view the image.
+ $published_node->setPublished(TRUE)->save();
Role::load(RoleInterface::ANONYMOUS_ID)
->revokePermission('access content')
->save();
- $this->drupalGet($node->toUrl());
+ $this->drupalGet($published_node->toUrl());
$this->assertSession()->statusCodeEquals(403);
$this->drupalGet($src);
$this->assertSession()->statusCodeEquals(403);
diff --git a/core/modules/search/search.routing.yml b/core/modules/search/search.routing.yml
index ec273f1..98969a6 100644
--- a/core/modules/search/search.routing.yml
+++ b/core/modules/search/search.routing.yml
@@ -37,6 +37,7 @@ entity.search_page.enable:
op: 'enable'
requirements:
_entity_access: 'search_page.update'
+ _csrf_token: 'TRUE'
entity.search_page.disable:
path: '/admin/config/search/pages/manage/{search_page}/disable'
@@ -45,6 +46,7 @@ entity.search_page.disable:
op: 'disable'
requirements:
_entity_access: 'search_page.disable'
+ _csrf_token: 'TRUE'
entity.search_page.set_default:
path: '/admin/config/search/pages/manage/{search_page}/set-default'
@@ -52,6 +54,7 @@ entity.search_page.set_default:
_controller: '\Drupal\search\Controller\SearchController::setAsDefault'
requirements:
_entity_access: 'search_page.update'
+ _csrf_token: 'TRUE'
entity.search_page.delete_form:
path: '/admin/config/search/pages/manage/{search_page}/delete'
diff --git a/core/modules/search/src/Form/SearchBlockForm.php b/core/modules/search/src/Form/SearchBlockForm.php
index 5d77b7c..652bf73 100644
--- a/core/modules/search/src/Form/SearchBlockForm.php
+++ b/core/modules/search/src/Form/SearchBlockForm.php
@@ -75,6 +75,16 @@ class SearchBlockForm extends FormBase {
public function buildForm(array $form, FormStateInterface $form_state) {
// Set up the form to submit using GET to the correct search page.
$entity_id = $this->searchPageRepository->getDefaultSearchPage();
+
+ $form = [];
+
+ // SearchPageRepository::getDefaultSearchPage() depends on search.settings.
+ // The dependency needs to be added before the conditional return, otherwise
+ // the block would get cached without the necessary cacheablity metadata in
+ // case there is no default search page and would not be invalidated if that
+ // changes.
+ $this->renderer->addCacheableDependency($form, $this->configFactory->get('search.settings'));
+
if (!$entity_id) {
$form['message'] = [
'#markup' => $this->t('Search is currently disabled'),
@@ -103,9 +113,6 @@ class SearchBlockForm extends FormBase {
'#name' => '',
];
- // SearchPageRepository::getDefaultSearchPage() depends on search.settings.
- $this->renderer->addCacheableDependency($form, $this->configFactory->get('search.settings'));
-
return $form;
}
diff --git a/core/modules/search/src/Tests/SearchConfigSettingsFormTest.php b/core/modules/search/src/Tests/SearchConfigSettingsFormTest.php
index b5021d9..191e0cf 100644
--- a/core/modules/search/src/Tests/SearchConfigSettingsFormTest.php
+++ b/core/modules/search/src/Tests/SearchConfigSettingsFormTest.php
@@ -154,8 +154,7 @@ class SearchConfigSettingsFormTest extends SearchTestBase {
// Test each plugin if it's enabled as the only search plugin.
foreach ($entities as $entity_id => $entity) {
- // Set this as default.
- $this->drupalGet("admin/config/search/pages/manage/$entity_id/set-default");
+ $this->setDefaultThroughUi($entity_id);
// Run a search from the correct search URL.
$info = $plugin_info[$entity_id];
@@ -187,13 +186,16 @@ class SearchConfigSettingsFormTest extends SearchTestBase {
$entity->disable()->save();
}
+ // Set the node search as default.
+ $this->setDefaultThroughUi('node_search');
+
// Test with all search plugins enabled. When you go to the search
// page or run search, all plugins should be shown.
foreach ($entities as $entity) {
$entity->enable()->save();
}
- // Set the node search as default.
- $this->drupalGet('admin/config/search/pages/manage/node_search/set-default');
+
+ \Drupal::service('router.builder')->rebuild();
$paths = [
['path' => 'search/node', 'options' => ['query' => ['keys' => 'pizza']]],
@@ -317,6 +319,19 @@ class SearchConfigSettingsFormTest extends SearchTestBase {
}
/**
+ * Tests that the enable/disable/default routes are protected from CSRF.
+ */
+ public function testRouteProtection() {
+ // Ensure that the enable and disable routes are protected.
+ $this->drupalGet('admin/config/search/pages/manage/node_search/enable');
+ $this->assertResponse(403);
+ $this->drupalGet('admin/config/search/pages/manage/node_search/disable');
+ $this->assertResponse(403);
+ $this->drupalGet('admin/config/search/pages/manage/node_search/set-default');
+ $this->assertResponse(403);
+ }
+
+ /**
* Checks that the search page operations match expectations.
*
* @param string $id
@@ -373,4 +388,17 @@ class SearchConfigSettingsFormTest extends SearchTestBase {
$this->assertIdentical($search_page_repository->getDefaultSearchPage(), $expected, $message, $group);
}
+ /**
+ * Sets a search page as the default in the UI.
+ *
+ * @param string $entity_id
+ * The search page entity ID to enable.
+ */
+ protected function setDefaultThroughUi($entity_id) {
+ $this->drupalGet('admin/config/search/pages');
+ preg_match('|href="([^"]+' . $entity_id . '/set-default[^"]+)"|', $this->getRawContent(), $matches);
+
+ $this->drupalGet($this->getAbsoluteUrl($matches[1]));
+ }
+
}
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index 986410d..2491bc8 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -901,7 +901,7 @@ abstract class WebTestBase extends TestBase {
}
if ($path instanceof Url) {
- $path = $path->toString();
+ $path = $path->setAbsolute()->toString(TRUE)->getGeneratedUrl();
}
$verbose = 'GET request to: ' . $path .
@@ -2127,7 +2127,7 @@ abstract class WebTestBase extends TestBase {
$url_options = $path->getOptions();
$options = $url_options + $options;
$path->setOptions($options);
- return $path->setAbsolute()->toString();
+ return $path->setAbsolute()->toString(TRUE)->getGeneratedUrl();
}
// The URL generator service is not necessarily available yet; e.g., in
// interactive installer tests.