Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.583 diff -u -Ffunction -r1.583 common.inc --- includes/common.inc 23 Oct 2006 06:45:17 -0000 1.583 +++ includes/common.inc 28 Oct 2006 12:09:39 -0000 @@ -1508,6 +1508,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). * * @param $url Index: includes/form.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/form.inc,v retrieving revision 1.157 diff -u -Ffunction -r1.157 form.inc --- includes/form.inc 20 Oct 2006 20:55:03 -0000 1.157 +++ includes/form.inc 28 Oct 2006 12:09:16 -0000 @@ -264,6 +264,8 @@ * theming, and hook_form_alter functi * 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 @@ // forms with different $form_ids to t $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, // 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; @@ -1253,6 +1264,10 @@ function theme_hidden($element) { return '\n"; } +function theme_token($element) { + return theme('hidden', $element); +} + /** * Format a textfield. * Index: modules/block/block.module =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.module,v retrieving revision 1.230 diff -u -Ffunction -r1.230 block.module --- modules/block/block.module 22 Oct 2006 08:28:44 -0000 1.230 +++ modules/block/block.module 28 Oct 2006 12:09:16 -0000 @@ -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; } Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.386 diff -u -Ffunction -r1.386 system.module --- modules/system/system.module 26 Oct 2006 22:07:03 -0000 1.386 +++ modules/system/system.module 28 Oct 2006 12:09:16 -0000 @@ -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; }