Commit b158c354 authored by catch's avatar catch

Issue #2421503 by lauriii, larowlan, Wim Leers, dawehner, tim.plunkett:...

Issue #2421503 by lauriii, larowlan, Wim Leers, dawehner, tim.plunkett: SA-CORE-2014-002 forward port only checks internal cache
parent 6b7039c8
......@@ -29,18 +29,3 @@ function page_cache_help($route_name, RouteMatchInterface $route_match) {
return $output;
}
}
/**
* Implements hook_form_alter().
*/
function page_cache_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// If the page that's being built is cacheable, set the 'immutable' flag, to
// ensure that when the form is used, a new form build ID is generated when
// appropriate, to prevent information disclosure.
$request_policy = \Drupal::service('page_cache_request_policy');
$request = \Drupal::requestStack()->getCurrentRequest();
$request_is_cacheable = $request_policy->check($request) === RequestPolicyInterface::ALLOW;
if ($request_is_cacheable) {
$form_state->addBuildInfo('immutable', TRUE);
}
}
......@@ -384,17 +384,25 @@ public function testFormImmutability() {
// Install the module that provides the test form.
$this->container->get('module_installer')
->install(['page_cache_form_test']);
// Uninstall the page_cache module to verify that form is immutable
// regardless of the internal page cache module.
$this->container->get('module_installer')->uninstall(['page_cache']);
\Drupal::service('router.builder')->rebuild();
$this->drupalGet('page_cache_form_test_immutability');
$this->assertText("Immutable: TRUE", "Form is immutable.");
// Uninstall the page_cache module, verify the flag is not set.
$this->container->get('module_installer')->uninstall(['page_cache']);
// The immutable flag is set unconditionally by system_form_alter(), set
// a flag to tell page_cache_form_test_module_implements_alter() to disable
// that implementation.
\Drupal::state()->set('page_cache_bypass_form_immutability', TRUE);
\Drupal::moduleHandler()->resetImplementations();
\Drupal::cache('render')->deleteAll();
$this->drupalGet('page_cache_form_test_immutability');
$this->assertText("Immutable: FALSE", "Form is not immutable,");
}
}
......@@ -11,10 +11,30 @@
* Implements hook_form_FORM_ID_alter().
*/
function page_cache_form_test_form_page_cache_form_test_alter(&$form, FormStateInterface $form_state, $form_id) {
// This runs earlier than system_form_alter() so we fore-go the immutability
// check to the process callback, by which time system_form_alter() has run.
$form['#process'][] = 'page_cache_form_test_form_page_cache_form_test_process';
}
/**
* Process callback to check immutability.
*/
function page_cache_form_test_form_page_cache_form_test_process($form, FormStateInterface $form_state) {
if (isset($form_state->getBuildInfo()['immutable']) && $form_state->getBuildInfo()['immutable']) {
$form['#suffix'] = 'Immutable: TRUE';
}
else {
$form['#suffix'] = 'Immutable: FALSE';
}
return $form;
}
/**
* Implements hook_module_implements_alter().
*/
function page_cache_form_test_module_implements_alter(&$implementations, $hook) {
if ($hook === 'form_alter' && \Drupal::state()->get('page_cache_bypass_form_immutability', FALSE)) {
// Disable system_form_alter
unset($implementations['system']);
}
}
......@@ -12,6 +12,7 @@
use Drupal\Core\Extension\ExtensionDiscovery;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\KeyValueStore\KeyValueDatabaseExpirableFactory;
use Drupal\Core\PageCache\RequestPolicyInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Menu\MenuTreeParameters;
......@@ -695,6 +696,29 @@ function system_js_settings_alter(&$settings, AttachedAssetsInterface $assets) {
}
}
/**
* Implements hook_form_alter().
*/
function system_form_alter(&$form, FormStateInterface $form_state) {
// If the page that's being built is cacheable, set the 'immutable' flag, to
// ensure that when the form is used, a new form build ID is generated when
// appropriate, to prevent information disclosure.
// Note: This code just wants to know whether cache response headers are set,
// not whether page_cache module will be active.
// \Drupal\Core\EventSubscriber\FinishResponseSubscriber::onRespond will
// send those headers, in case $request_policy->check($request) succeeds. In
// that case we need to ensure that the immutable flag is sot, so future POST
// request won't take over the form state of another user.
/** @var \Drupal\Core\PageCache\RequestPolicyInterface $request_policy */
$request_policy = \Drupal::service('page_cache_request_policy');
$request = \Drupal::requestStack()->getCurrentRequest();
$request_is_cacheable = $request_policy->check($request) === RequestPolicyInterface::ALLOW;
if ($request_is_cacheable) {
$form_state->addBuildInfo('immutable', TRUE);
}
}
/**
* Implements hook_form_FORM_ID_alter().
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment