From 037af6890fe6fdb84a08d3c86083e847c90ec0ad Mon Sep 17 00:00:00 2001 From: Aleksander Machniak <alec@alec.pl> Date: Tue, 22 Oct 2013 08:17:26 -0400 Subject: [PATCH] Fix vulnerability in handling _session argument of utils/save-prefs (#1489382) --- plugins/managesieve/managesieve.php | 93 ++++++++++++++++++++++++++++++++++------------ 1 files changed, 69 insertions(+), 24 deletions(-) diff --git a/plugins/managesieve/managesieve.php b/plugins/managesieve/managesieve.php index 7f4624e..4e7fdb6 100644 --- a/plugins/managesieve/managesieve.php +++ b/plugins/managesieve/managesieve.php @@ -62,7 +62,7 @@ "x-beenthere", ); - const VERSION = '6.0'; + const VERSION = '6.2'; const PROGNAME = 'Roundcube (Managesieve)'; const PORT = 4190; @@ -200,10 +200,19 @@ $include_path .= ini_get('include_path'); set_include_path($include_path); - $host = rcube_parse_host($this->rc->config->get('managesieve_host', 'localhost')); + // Get connection parameters + $host = $this->rc->config->get('managesieve_host', 'localhost'); + $port = $this->rc->config->get('managesieve_port'); + $tls = $this->rc->config->get('managesieve_usetls', false); + + $host = rcube_parse_host($host); $host = rcube_idn_to_ascii($host); - $port = $this->rc->config->get('managesieve_port'); + // remove tls:// prefix, set TLS flag + if (($host = preg_replace('|^tls://|i', '', $host, 1, $cnt)) && $cnt) { + $tls = true; + } + if (empty($port)) { $port = getservbyname('sieve', 'tcp'); if (empty($port)) { @@ -216,8 +225,8 @@ 'password' => $this->rc->decrypt($_SESSION['password']), 'host' => $host, 'port' => $port, + 'usetls' => $tls, 'auth_type' => $this->rc->config->get('managesieve_auth_type'), - 'usetls' => $this->rc->config->get('managesieve_usetls', false), 'disabled' => $this->rc->config->get('managesieve_disabled_extensions'), 'debug' => $this->rc->config->get('managesieve_debug', false), 'auth_cid' => $this->rc->config->get('managesieve_auth_cid'), @@ -651,6 +660,7 @@ $act_types = get_input_value('_action_type', RCUBE_INPUT_POST, true); $mailboxes = get_input_value('_action_mailbox', RCUBE_INPUT_POST, true); $act_targets = get_input_value('_action_target', RCUBE_INPUT_POST, true); + $domain_targets = get_input_value('_action_target_domain', RCUBE_INPUT_POST); $area_targets = get_input_value('_action_target_area', RCUBE_INPUT_POST, true); $reasons = get_input_value('_action_reason', RCUBE_INPUT_POST, true); $addresses = get_input_value('_action_addresses', RCUBE_INPUT_POST, true); @@ -819,14 +829,13 @@ $i = 0; // actions foreach($act_types as $idx => $type) { - $type = $this->strip_value($type); - $target = $this->strip_value($act_targets[$idx]); + $type = $this->strip_value($type); switch ($type) { case 'fileinto': case 'fileinto_copy': - $mailbox = $this->strip_value($mailboxes[$idx]); + $mailbox = $this->strip_value($mailboxes[$idx], false, false); $this->form['actions'][$i]['target'] = $this->mod_mailbox($mailbox, 'in'); if ($type == 'fileinto_copy') { $type = 'fileinto'; @@ -845,12 +854,25 @@ case 'redirect': case 'redirect_copy': + $target = $this->strip_value($act_targets[$idx]); + $domain = $this->strip_value($domain_targets[$idx]); + + // force one of the configured domains + $domains = (array) $this->rc->config->get('managesieve_domains'); + if (!empty($domains) && !empty($target)) { + if (!$domain || !in_array($domain, $domains)) { + $domain = $domains[0]; + } + + $target .= '@' . $domain; + } + $this->form['actions'][$i]['target'] = $target; - if ($this->form['actions'][$i]['target'] == '') + if ($target == '') $this->errors['actions'][$i]['target'] = $this->gettext('cannotbeempty'); - else if (!check_email($this->form['actions'][$i]['target'])) - $this->errors['actions'][$i]['target'] = $this->gettext('noemailwarning'); + else if (!rcube_utils::check_email($target)) + $this->errors['actions'][$i]['target'] = $this->plugin->gettext(!empty($domains) ? 'forbiddenchars' : 'noemailwarning'); if ($type == 'redirect_copy') { $type = 'redirect'; @@ -958,7 +980,7 @@ $this->rc->output->command('parent.managesieve_updatelist', isset($new) ? 'add' : 'update', array( - 'name' => Q($this->form['name']), + 'name' => $this->form['name'], 'id' => $fid, 'disabled' => $this->form['disabled'] )); @@ -1040,7 +1062,7 @@ foreach ($list as $idx => $set) { $scripts['S'.$idx] = $set; $result[] = array( - 'name' => Q($set), + 'name' => $set, 'id' => 'S'.$idx, 'class' => !in_array($set, $this->active) ? 'disabled' : '', ); @@ -1085,7 +1107,7 @@ $this->rc->output->set_env('blankpage', $attrib['src'] ? $this->rc->output->abs_url($attrib['src']) : 'program/resources/blank.gif'); - return html::tag('iframe', $attrib); + return $this->rc->output->frame($attrib); } function filterset_form($attrib) @@ -1551,11 +1573,34 @@ // actions target inputs $out .= '<td class="rowtargets">'; - // shared targets - $out .= '<input type="text" name="_action_target['.$id.']" id="action_target' .$id. '" ' - .'value="' .($action['type']=='redirect' ? Q($action['target'], 'strict', false) : ''). '" size="35" ' - .'style="display:' .($action['type']=='redirect' ? 'inline' : 'none') .'" ' - . $this->error_class($id, 'action', 'target', 'action_target') .' />'; + + // force domain selection in redirect email input + $domains = (array) $this->rc->config->get('managesieve_domains'); + if (!empty($domains)) { + sort($domains); + + $domain_select = new html_select(array('name' => "_action_target_domain[$id]", 'id' => 'action_target_domain'.$id)); + $domain_select->add(array_combine($domains, $domains)); + + $parts = explode('@', $action['target']); + + if (!empty($parts)) { + $action['domain'] = array_pop($parts); + $action['target'] = implode('@', $parts); + } + } + + // redirect target + $out .= '<span id="redirect_target' . $id . '" style="white-space:nowrap;' + . ' display:' . ($action['type'] == 'redirect' ? 'inline' : 'none') . '">' + . '<input type="text" name="_action_target['.$id.']" id="action_target' .$id. '"' + . ' value="' .($action['type'] == 'redirect' ? Q($action['target'], 'strict', false) : '') . '"' + . (!empty($domains) ? ' size="20"' : ' size="35"') + . $this->error_class($id, 'action', 'target', 'action_target') .' />' + . (!empty($domains) ? ' @ ' . $domain_select->show($action['domain']) : '') + . '</span>'; + + // (e)reject target $out .= '<textarea name="_action_target_area['.$id.']" id="action_target_area' .$id. '" ' .'rows="3" cols="35" '. $this->error_class($id, 'action', 'targetarea', 'action_target_area') .'style="display:' .(in_array($action['type'], array('reject', 'ereject')) ? 'inline' : 'none') .'">' @@ -1699,16 +1744,16 @@ private function genid() { - $result = preg_replace('/[^0-9]/', '', microtime(true)); - return $result; + return preg_replace('/[^0-9]/', '', microtime(true)); } - private function strip_value($str, $allow_html=false) + private function strip_value($str, $allow_html = false, $trim = true) { - if (!$allow_html) + if (!$allow_html) { $str = strip_tags($str); + } - return trim($str); + return $trim ? trim($str) : $str; } private function error_class($id, $type, $target, $elem_prefix='') @@ -2030,7 +2075,7 @@ $fname = $filter['name'] ? $filter['name'] : "#$i"; $result[] = array( 'id' => $idx, - 'name' => Q($fname), + 'name' => $fname, 'class' => $filter['disabled'] ? 'disabled' : '', ); $i++; -- Gitblit v1.9.1