Commit 2afef618 authored by Dave Reid's avatar Dave Reid

Issue #1260244: Fixed possible CSRF with the moderation state change callback.

parent 45def2e6
......@@ -58,6 +58,18 @@ class WorkbenchModerationModerateTabTestCase extends WorkbenchModerationTestCase
$this->drupalLogin($this->moderator_user);
}
/**
* Override DrupalWebTestCase::drupalGetToken() as it does not return the
* correct token for the currently logged-in testing user.
*/
protected function drupalGetToken($value = '') {
$session_id = $this->session_id;
if (empty($session_id) && !empty($this->loggedInUser)) {
$session_id = db_query("SELECT sid FROM {sessions} WHERE uid = :uid ORDER BY timestamp DESC", array(':uid' => $this->loggedInUser->uid))->fetchField();
}
return drupal_hmac_base64($value, $session_id . drupal_get_private_key() . drupal_get_hash_salt());
}
function testModerateTab() {
$is_moderated = workbench_moderation_node_type_moderated($this->content_type);
$this->assertTrue($is_moderated, t('The content type is moderated.'));
......@@ -81,6 +93,18 @@ class WorkbenchModerationModerateTabTestCase extends WorkbenchModerationTestCase
// Make sure the "Moderate" tab is accessible.
$this->drupalGet("node/{$node->nid}/moderation");
// Attempt to change the moderation state without a token in the link.
$this->drupalGet("node/{$node->nid}/moderation/{$node->vid}/change-state/needs_review");
$this->assertResponse(403);
// Run the same state change with a valid token, which should succeed.
$this->drupalGet("node/{$node->nid}/moderation/{$node->vid}/change-state/needs_review", array(
'query' => array('token' => $this->drupalGetToken("{$node->nid}:{$node->vid}:needs_review"))
));
$this->assertResponse(200);
$node = node_load($node->nid, NULL, TRUE);
$this->assertEqual($node->workbench_moderation['current']->state, 'needs_review', 'Node state changed to Needs Review via callback.');
// Publish the node via the moderation form.
$moderate = array('state' => workbench_moderation_state_published());
$this->drupalPost("node/{$node->nid}/moderation", $moderate, t('Apply'));
......
......@@ -1334,14 +1334,14 @@ function workbench_moderation_transition_delete($transition) {
* If the user may moderate a change, return an array of possible state
* changes. Otherwise, return FALSE.
*/
function workbench_moderation_states_next($current_state, $account, $node_type) {
function workbench_moderation_states_next($current_state, $account = NULL, $node_type) {
// Make sure we have a current state.
if (!$current_state) {
$current_state = workbench_moderation_state_none();
}
if (!$account) {
$account = $user;
if (empty($account)) {
$account = $GLOBALS['user'];
}
if (user_access('bypass workbench moderation', $account)) {
......@@ -1517,6 +1517,10 @@ function workbench_moderation_store($node) {
* The new moderation state requested.
*/
function workbench_moderation_moderate_callback($node, $state) {
if (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], "{$node->nid}:{$node->vid}:$state")) {
return MENU_ACCESS_DENIED;
}
workbench_moderation_moderate($node, $state);
drupal_goto(isset($_GET['destination']) ? $_GET['destination'] : 'node/' . $node->nid . '/moderation');
}
......@@ -1533,8 +1537,6 @@ function workbench_moderation_moderate_callback($node, $state) {
* A list of links to display with the revision.
*/
function workbench_moderation_get_moderation_links($node, $url_options = array()) {
global $user;
// Make sure that this node type is moderated.
if (!workbench_moderation_node_type_moderated($node->type)) {
return;
......@@ -1544,12 +1546,14 @@ function workbench_moderation_get_moderation_links($node, $url_options = array()
$links = array();
$my_revision = $node->workbench_moderation['my_revision'];
if ($my_revision->vid == $node->workbench_moderation['current']->vid
&& $next_states = workbench_moderation_states_next($my_revision->state, $user, $node->type)) {
&& $next_states = workbench_moderation_states_next($my_revision->state, NULL, $node->type)) {
foreach ($next_states as $state => $label) {
$links[] = array_merge($url_options, array(
$link = array_merge($url_options, array(
'title' => workbench_moderation_state_label($state),
'href' => "node/{$node->nid}/moderation/{$node->vid}/change-state/{$state}",
));
$link['query']['token'] = drupal_get_token("{$node->nid}:{$node->vid}:{$state}");
$links[] = $link;
}
}
......
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