Use request tokens to protect POST requests from CSFR
| | |
| | | |
| | | |
| | | /** |
| | | * Generate a unique token to be used in a form request |
| | | * |
| | | * @param string Request identifier |
| | | * @return string The request token |
| | | */ |
| | | public function get_request_token($key) |
| | | { |
| | | if (!$this->request_tokens[$key]) |
| | | $_SESSION['request_tokens'][$key] = $this->request_tokens[$key] = md5(uniqid($key . rand(), true)); |
| | | |
| | | return $this->request_tokens[$key]; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Check if the current request contains a valid token |
| | | * |
| | | * @param string Request identifier |
| | | * @return boolean True if request token is valid false if not |
| | | */ |
| | | public function check_request($key, $mode = RCUBE_INPUT_POST) |
| | | { |
| | | $token = get_input_value('_token', $mode); |
| | | $valid = !(empty($token) || $_SESSION['request_tokens'][$key] != $token); |
| | | |
| | | if ($valid) |
| | | unset($_SESSION['request_tokens'][$key]); |
| | | |
| | | return $valid; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Create unique authorization hash |
| | | * |
| | | * @param string Session ID |
| | |
| | | */ |
| | | public function form_tag($attrib, $content = null) |
| | | { |
| | | if ($this->framed) { |
| | | if ($this->framed || !empty($_REQUEST['_framed'])) { |
| | | $hiddenfield = new html_hiddenfield(array('name' => '_framed', 'value' => '1')); |
| | | $hidden = $hiddenfield->show(); |
| | | } |
| | |
| | | |
| | | return html::tag('form', |
| | | $attrib + array('action' => "./", 'method' => "get"), |
| | | $hidden . $content); |
| | | $hidden . $content, |
| | | array('id','class','style','name','method','action','enctype','onsubmit')); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Build a form tag with a unique request token |
| | | * |
| | | * @param array Named tag parameters including 'action' and 'task' values which will be put into hidden fields |
| | | * @param string Form content |
| | | * @return string HTML code for the form |
| | | */ |
| | | public function request_form($attrib, $content) |
| | | { |
| | | $hidden = new html_hiddenfield(); |
| | | if ($attrib['task']) { |
| | | $hidden->add(array('name' => '_task', 'value' => $attrib['task'])); |
| | | } |
| | | if ($attrib['action']) { |
| | | $hidden->add(array('name' => '_action', 'value' => $attrib['action'])); |
| | | } |
| | | |
| | | // generate request token |
| | | $request_key = $attrib['request'] ? $attrib['request'] : $attrib['action']; |
| | | $hidden->add(array('name' => '_token', 'value' => $this->app->get_request_token($request_key))); |
| | | |
| | | unset($attrib['task'], $attrib['request']); |
| | | $attrib['action'] = './'; |
| | | |
| | | // we already have a <form> tag |
| | | if ($attrib['form']) |
| | | return $hidden->show() . $content; |
| | | else |
| | | return $this->form_tag($attrib, $hidden->show() . $content); |
| | | } |
| | | |
| | | |
| | |
| | | $messages['cookiesdisabled'] = 'Ihr Browser akzeptiert keine Cookies'; |
| | | $messages['sessionerror'] = 'Ihre Session ist ungültig oder abgelaufen'; |
| | | $messages['imaperror'] = 'Keine Verbindung zum IMAP Server'; |
| | | $messages['servererror'] = 'Serverfehler!'; |
| | | $messages['invalidrequest'] = 'Ungültige Anfrage! Es wurden keine Daten gespeichert.'; |
| | | $messages['nomessagesfound'] = 'Keine Nachrichten in diesem Ordner'; |
| | | $messages['loggedout'] = 'Sie haben Ihre Session erfolgreich beendet. Auf Wiedersehen!'; |
| | | $messages['mailboxempty'] = 'Ordner ist leer'; |
| | |
| | | $messages['errorsaving'] = 'Beim Speichern ist ein Fehler aufgetreten'; |
| | | $messages['errormoving'] = 'Nachricht konnte nicht verschoben werden'; |
| | | $messages['errordeleting'] = 'Nachricht konnte nicht gelöscht werden'; |
| | | $messages['errormarking'] = 'Nachricht konnte nicht markiert werden'; |
| | | $messages['deletecontactconfirm'] = 'Wollen Sie die ausgewählten Kontakte wirklich löschen'; |
| | | $messages['deletemessagesconfirm'] = 'Wollen Sie die ausgewählten Nachrichten wirklich löschen?'; |
| | | $messages['deletefolderconfirm'] = 'Wollen Sie diesen Ordner wirklich löschen?'; |
| | |
| | | $messages['sessionerror'] = 'Ihre Session ist ungültig oder abgelaufen'; |
| | | $messages['imaperror'] = 'Keine Verbindung zum IMAP-Server'; |
| | | $messages['servererror'] = 'Serverfehler!'; |
| | | $messages['invalidrequest'] = 'Ungültige Anfrage! Es wurden keine Daten gespeichert.'; |
| | | $messages['nomessagesfound'] = 'Keine Nachrichten in diesem Ordner'; |
| | | $messages['loggedout'] = 'Sie haben Ihre Session erfolgreich beendet. Auf Wiedersehen!'; |
| | | $messages['mailboxempty'] = 'Ordner ist leer'; |
| | |
| | | $messages['sessionerror'] = 'Your session is invalid or expired'; |
| | | $messages['imaperror'] = 'Connection to IMAP server failed'; |
| | | $messages['servererror'] = 'Server Error!'; |
| | | $messages['invalidrequest'] = 'Invalid request! No data was saved.'; |
| | | $messages['nomessagesfound'] = 'No messages found in this mailbox'; |
| | | $messages['loggedout'] = 'You have successfully terminated the session. Good bye!'; |
| | | $messages['mailboxempty'] = 'Mailbox is empty'; |
| | |
| | | { |
| | | global $CONTACTS, $EDIT_FORM, $RCMAIL; |
| | | |
| | | $result = $CONTACTS->get_result(); |
| | | $form_start = ''; |
| | | if (!strlen($EDIT_FORM)) |
| | | { |
| | | $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $RCMAIL->task)); |
| | | $hiddenfields->add(array('name' => '_action', 'value' => 'save')); |
| | | $hiddenfields->add(array('name' => '_source', 'value' => get_input_value('_source', RCUBE_INPUT_GPC))); |
| | | $hiddenfields->add(array('name' => '_framed', 'value' => (empty($_REQUEST['_framed']) ? 0 : 1))); |
| | | $form_start = $form_end = ''; |
| | | |
| | | if (empty($EDIT_FORM)) { |
| | | $hiddenfields = new html_hiddenfield(array('name' => '_source', 'value' => get_input_value('_source', RCUBE_INPUT_GPC))); |
| | | |
| | | if (($result = $CONTACTS->get_result()) && ($record = $result->first())) |
| | | $hiddenfields->add(array('name' => '_cid', 'value' => $record['ID'])); |
| | | |
| | | $form_start = !strlen($attrib['form']) ? $RCMAIL->output->form_tag(array('name' => "form", 'method' => "post")) : ''; |
| | | $form_start .= $hiddenfields->show(); |
| | | $form_start = $RCMAIL->output->request_form(array('name' => "form", 'method' => "post", 'task' => $RCMAIL->task, 'action' => 'save', 'request' => 'save.'.intval($record['ID']), 'noclose' => true) + $attrib, $hiddenfields->show()); |
| | | $form_end = !strlen($attrib['form']) ? '</form>' : ''; |
| | | |
| | | $EDIT_FORM = !empty($attrib['form']) ? $attrib['form'] : 'form'; |
| | | $RCMAIL->output->add_gui_object('editform', $EDIT_FORM); |
| | | } |
| | | |
| | | $form_end = (strlen($EDIT_FORM) && !strlen($attrib['form'])) ? '</form>' : ''; |
| | | $form_name = strlen($attrib['form']) ? $attrib['form'] : 'form'; |
| | | |
| | | if (!strlen($EDIT_FORM)) |
| | | $RCMAIL->output->add_gui_object('editform', $form_name); |
| | | |
| | | $EDIT_FORM = $form_name; |
| | | |
| | | return array($form_start, $form_end); |
| | | } |
| | |
| | | |
| | | */ |
| | | |
| | | $cid = get_input_value('_cid', RCUBE_INPUT_POST); |
| | | $return_action = empty($cid) ? 'add' : 'show'; |
| | | |
| | | // check request token and exit if invalid |
| | | if (!$RCMAIL->check_request('save.'.intval($cid), RCUBE_INPUT_POST)) |
| | | { |
| | | $OUTPUT->show_message('invalidrequest', 'error'); |
| | | rcmail_overwrite_action($return_action); |
| | | return; |
| | | } |
| | | |
| | | // cannot edit record |
| | | if ($CONTACTS->readonly) |
| | | { |
| | | $OUTPUT->show_message('contactreadonly', 'error'); |
| | | rcmail_overwrite_action(empty($_POST['_cid']) ? 'add' : 'show'); |
| | | rcmail_overwrite_action($return_action); |
| | | return; |
| | | } |
| | | |
| | |
| | | if ((!get_input_value('_name', RCUBE_INPUT_POST) || !get_input_value('_email', RCUBE_INPUT_POST))) |
| | | { |
| | | $OUTPUT->show_message('formincomplete', 'warning'); |
| | | rcmail_overwrite_action(empty($_POST['_cid']) ? 'add' : 'show'); |
| | | rcmail_overwrite_action($return_action); |
| | | return; |
| | | } |
| | | |
| | |
| | | // setup some vars we need |
| | | $a_save_cols = array('name', 'firstname', 'surname', 'email'); |
| | | $a_record = array(); |
| | | $cid = get_input_value('_cid', RCUBE_INPUT_POST); |
| | | |
| | | // read POST values into hash array |
| | | foreach ($a_save_cols as $col) |
| | |
| | | $t_rows = !empty($attrib['textarearows']) ? $attrib['textarearows'] : 6; |
| | | $t_cols = !empty($attrib['textareacols']) ? $attrib['textareacols'] : 40; |
| | | |
| | | list($form_start, $form_end) = get_form_tags($attrib, 'save-identity', array('name' => '_iid', 'value' => $IDENTITY_RECORD['identity_id'])); |
| | | list($form_start, $form_end) = get_form_tags($attrib, 'save-identity', intval($IDENTITY_RECORD['identity_id']), array('name' => '_iid', 'value' => $IDENTITY_RECORD['identity_id'])); |
| | | unset($attrib['form']); |
| | | |
| | | // list of available cols |
| | |
| | | |
| | | |
| | | // similar function as in /steps/addressbook/edit.inc |
| | | function get_form_tags($attrib, $action, $add_hidden=array()) |
| | | function get_form_tags($attrib, $action, $id = null, $hidden = null) |
| | | { |
| | | global $EDIT_FORM, $RCMAIL; |
| | | |
| | | $form_start = ''; |
| | | if (!strlen($EDIT_FORM)) |
| | | { |
| | | $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $RCMAIL->task)); |
| | | $hiddenfields->add(array('name' => '_action', 'value' => $action)); |
| | | $form_start = $form_end = ''; |
| | | |
| | | if ($add_hidden) |
| | | $hiddenfields->add($add_hidden); |
| | | if (empty($EDIT_FORM)) { |
| | | $request_key = $action . (isset($id) ? '.'.$id : ''); |
| | | $form_start = $RCMAIL->output->request_form(array('name' => "form", 'method' => "post", 'task' => $RCMAIL->task, 'action' => $action, 'request' => $request_key, 'noclose' => true) + $attrib); |
| | | |
| | | $form_start = !strlen($attrib['form']) ? $RCMAIL->output->form_tag(array('name' => "form", 'method' => "post")) : ''; |
| | | if (is_array($hidden)) { |
| | | $hiddenfields = new html_hiddenfield($hidden); |
| | | $form_start .= $hiddenfields->show(); |
| | | } |
| | | |
| | | $form_end = (!strlen($EDIT_FORM) && !strlen($attrib['form'])) ? '</form>' : ''; |
| | | $form_name = strlen($attrib['form']) ? $attrib['form'] : 'form'; |
| | | $form_end = !strlen($attrib['form']) ? '</form>' : ''; |
| | | |
| | | if (!strlen($EDIT_FORM)) |
| | | $RCMAIL->output->add_gui_object('editform', $form_name); |
| | | |
| | | $EDIT_FORM = $form_name; |
| | | $EDIT_FORM = !empty($attrib['form']) ? $attrib['form'] : 'form'; |
| | | $RCMAIL->output->add_gui_object('editform', $EDIT_FORM); |
| | | } |
| | | |
| | | return array($form_start, $form_end); |
| | | } |
| | |
| | | $a_boolean_cols = array('standard', 'html_signature'); |
| | | $updated = $default_id = false; |
| | | |
| | | // check request token |
| | | if (!$RCMAIL->check_request('save-identity.'.intval(get_input_value('_iid', RCUBE_INPUT_POST)), RCUBE_INPUT_POST)) { |
| | | $OUTPUT->show_message('invalidrequest', 'error'); |
| | | rcmail_overwrite_action('identities'); |
| | | return; |
| | | } |
| | | // check input |
| | | if (empty($_POST['_name']) || (empty($_POST['_email']) && IDENTITIES_LEVEL != 1 && IDENTITIES_LEVEL != 3)) |
| | | { |
| | |
| | | |
| | | */ |
| | | |
| | | // check request token and exit if invalid |
| | | if (!$RCMAIL->check_request('save-prefs', RCUBE_INPUT_POST)) { |
| | | $OUTPUT->show_message('invalidrequest', 'error'); |
| | | rcmail_overwrite_action('preferences'); |
| | | return; |
| | | } |
| | | |
| | | $a_user_prefs = array( |
| | | 'language' => isset($_POST['_language']) ? get_input_value('_language', RCUBE_INPUT_POST) : $CONFIG['language'], |
| | | 'timezone' => isset($_POST['_timezone']) ? (is_numeric($_POST['_timezone']) ? floatval($_POST['_timezone']) : get_input_value('_timezone', RCUBE_INPUT_POST)) : $CONFIG['timezone'], |