#90508 by Heine and the security team. Every form gets a token.
parent
2c2f33e60b
commit
0accf8fe1e
|
@ -1507,6 +1507,48 @@ function drupal_urlencode($text) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the private key variable used to generate tokens is set.
|
||||
*
|
||||
* @return
|
||||
* The private key
|
||||
*/
|
||||
function drupal_get_private_key() {
|
||||
if (!($key = variable_get('drupal_private_key', 0))) {
|
||||
$key = md5(uniqid(mt_rand(), true)) . md5(uniqid(mt_rand(), true));
|
||||
variable_set('drupal_private_key', $key);
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a token based on $value, the current user session and private key.
|
||||
*
|
||||
* @param $value
|
||||
* An additional value to base the token on
|
||||
*/
|
||||
function drupal_get_token($value = '') {
|
||||
$private_key = drupal_get_private_key();
|
||||
return md5(session_id() . $value . $private_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a token based on $value, the current user session and private key.
|
||||
*
|
||||
* @param $token
|
||||
* The token to be validated.
|
||||
* @param $value
|
||||
* An additional value to base the token on.
|
||||
* @param $skip_anonymous
|
||||
* Set to true to skip token validation for anonymous users.
|
||||
* @return
|
||||
* True for a valid token, false for an invalid token. When $skip_anonymous is true, the return value will always be true for anonymous users.
|
||||
*/
|
||||
function drupal_valid_token($token, $value = '', $skip_anonymous = FALSE) {
|
||||
global $user;
|
||||
return (($skip_anonymous && $user->uid == 0) || ($token == md5(session_id() . $value . variable_get('drupal_private_key', ''))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs one or more XML-RPC request(s).
|
||||
*
|
||||
|
|
|
@ -264,6 +264,8 @@ function drupal_process_form($form_id, &$form) {
|
|||
* An associative array containing the structure of the form.
|
||||
*/
|
||||
function drupal_prepare_form($form_id, &$form) {
|
||||
global $user;
|
||||
|
||||
$form['#type'] = 'form';
|
||||
|
||||
if (!isset($form['#post'])) {
|
||||
|
@ -292,22 +294,27 @@ function drupal_prepare_form($form_id, &$form) {
|
|||
$base = $form['#base'];
|
||||
}
|
||||
|
||||
// Add a token, based on either #token or form_id, to any form displayed to authenticated users.
|
||||
// This ensures that any submitted form was actually requested previously by the user and protects against
|
||||
// cross site request forgeries.
|
||||
|
||||
if (isset($form['#token'])) {
|
||||
// If the page cache is on and an anonymous user issues a GET request,
|
||||
// unset the token because the token in the cached page would not match,
|
||||
// because the token is based on the session ID.
|
||||
if (variable_get('cache', 0) && !$user->uid && $_SERVER['REQUEST_METHOD'] == 'GET') {
|
||||
if ($form['#token'] === FALSE || $user->uid == 0 || $form['#programmed']) {
|
||||
unset($form['#token']);
|
||||
}
|
||||
else {
|
||||
// Make sure that a private key is set:
|
||||
if (!variable_get('drupal_private_key', '')) {
|
||||
variable_set('drupal_private_key', mt_rand());
|
||||
}
|
||||
|
||||
$form['form_token'] = array('#type' => 'hidden', '#default_value' => md5(session_id() . $form['#token'] . variable_get('drupal_private_key', '')));
|
||||
$form['form_token'] = array('#type' => 'token', '#default_value' => drupal_get_token($form['#token']));
|
||||
}
|
||||
}
|
||||
else if ($user->uid && !$form['#programmed']) {
|
||||
$form['#token'] = $form_id;
|
||||
$form['form_token'] = array(
|
||||
'#id' => 'edit-'. str_replace('_', '-', $form_id) .'-form-token',
|
||||
'#type' => 'token',
|
||||
'#default_value' => drupal_get_token($form['#token']),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if (isset($form_id)) {
|
||||
$form['form_id'] = array('#type' => 'hidden', '#value' => $form_id, '#id' => str_replace('_', '-', "edit-$form_id"));
|
||||
|
@ -369,7 +376,7 @@ function drupal_validate_form($form_id, $form) {
|
|||
// If the session token was set by drupal_prepare_form(), ensure that it
|
||||
// matches the current user's session
|
||||
if (isset($form['#token'])) {
|
||||
if ($form_values['form_token'] != md5(session_id() . $form['#token'] . variable_get('drupal_private_key', ''))) {
|
||||
if (!drupal_valid_token($form_values['form_token'], $form['#token'])) {
|
||||
// setting this error will cause the form to fail validation
|
||||
form_set_error('form_token', t('Validation error, please try again. If this error persists, please contact the site administrator.'));
|
||||
}
|
||||
|
@ -670,6 +677,10 @@ function form_builder($form_id, $form) {
|
|||
}
|
||||
break;
|
||||
|
||||
case 'token':
|
||||
$form['#value'] = (string)$edit;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isset($edit)) {
|
||||
$form['#value'] = $edit;
|
||||
|
@ -1256,6 +1267,10 @@ function theme_hidden($element) {
|
|||
return '<input type="hidden" name="'. $element['#name'] . '" id="'. $element['#id'] . '" value="'. check_plain($element['#value']) ."\" " . drupal_attributes($element['#attributes']) ." />\n";
|
||||
}
|
||||
|
||||
function theme_token($element) {
|
||||
return theme('hidden', $element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a textfield.
|
||||
*
|
||||
|
|
|
@ -315,7 +315,7 @@ function theme_block_admin_display($form) {
|
|||
$last_region = '';
|
||||
$last_status = 1;
|
||||
foreach (element_children($form) as $i) {
|
||||
$block = $form[$i];
|
||||
$block = &$form[$i];
|
||||
// Only take form elements that are blocks.
|
||||
if (is_array($block['info'])) {
|
||||
// Fetch values
|
||||
|
@ -358,10 +358,8 @@ function theme_block_admin_display($form) {
|
|||
$header[] = array('data' => t('Operations'), 'colspan' => 2);
|
||||
|
||||
$output = theme('table', $header, $rows, array('id' => 'blocks'));
|
||||
$output .= drupal_render($form['submit']);
|
||||
// Also render the form_id as there is no drupal_render($form) call (as drupal_render does not appear to handle the
|
||||
// multi-dimensional block form array very well).
|
||||
$output .= drupal_render($form['form_id']);
|
||||
|
||||
$output .= drupal_render($form);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ function system_elements() {
|
|||
$type['value'] = array('#input' => TRUE);
|
||||
$type['markup'] = array('#prefix' => '', '#suffix' => '');
|
||||
$type['fieldset'] = array('#collapsible' => FALSE, '#collapsed' => FALSE);
|
||||
$type['token'] = array('#input'=> TRUE);
|
||||
return $type;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue