diff options
Diffstat (limited to 'program/lib/Roundcube/rcube.php')
-rw-r--r-- | program/lib/Roundcube/rcube.php | 139 |
1 files changed, 127 insertions, 12 deletions
diff --git a/program/lib/Roundcube/rcube.php b/program/lib/Roundcube/rcube.php index 03f49637c..547e2b4ac 100644 --- a/program/lib/Roundcube/rcube.php +++ b/program/lib/Roundcube/rcube.php @@ -28,9 +28,15 @@ */ class rcube { - const INIT_WITH_DB = 1; + // Init options + const INIT_WITH_DB = 1; const INIT_WITH_PLUGINS = 2; + // Request status + const REQUEST_VALID = 0; + const REQUEST_ERROR_URL = 1; + const REQUEST_ERROR_TOKEN = 2; + /** * Singleton instace of rcube * @@ -101,6 +107,12 @@ class rcube */ public $user; + /** + * Request status + * + * @var int + */ + public $request_status = 0; /* private/protected vars */ protected $texts; @@ -978,6 +990,104 @@ class rcube /** + * Returns session token for secure URLs + * + * @param bool $generate Generate token if not exists in session yet + * + * @return string|bool Token string, False when disabled + */ + public function get_secure_url_token($generate = false) + { + if ($len = $this->config->get('use_secure_urls')) { + if (empty($_SESSION['secure_token']) && $generate) { + // generate x characters long token + $length = $len > 1 ? $len : 16; + $token = openssl_random_pseudo_bytes($length / 2); + $token = bin2hex($token); + + $plugin = $this->plugins->exec_hook('secure_token', + array('value' => $token, 'length' => $length)); + + $_SESSION['secure_token'] = $plugin['value']; + } + + return $_SESSION['secure_token']; + } + + return false; + } + + + /** + * Generate a unique token to be used in a form request + * + * @return string The request token + */ + public function get_request_token() + { + $sess_id = $_COOKIE[ini_get('session.name')]; + if (!$sess_id) { + $sess_id = session_id(); + } + + $plugin = $this->plugins->exec_hook('request_token', array( + 'value' => md5('RT' . $this->get_user_id() . $this->config->get('des_key') . $sess_id))); + + return $plugin['value']; + } + + + /** + * Check if the current request contains a valid token. + * Empty requests aren't checked until use_secure_urls is set. + * + * @param int Request method + * + * @return boolean True if request token is valid false if not + */ + public function check_request($mode = rcube_utils::INPUT_POST) + { + // check secure token in URL if enabled + if ($token = $this->get_secure_url_token()) { + foreach (explode('/', preg_replace('/[?#&].*$/', '', $_SERVER['REQUEST_URI'])) as $tok) { + if ($tok == $token) { + return true; + } + } + + $this->request_status = self::REQUEST_ERROR_URL; + + return false; + } + + $sess_tok = $this->get_request_token(); + + // ajax requests + if (rcube_utils::request_header('X-Roundcube-Request') == $sess_tok) { + return true; + } + + // skip empty requests + if (($mode == rcube_utils::INPUT_POST && empty($_POST)) + || ($mode == rcube_utils::INPUT_GET && empty($_GET)) + ) { + return true; + } + + // default method of securing requests + $token = rcube_utils::get_input_value('_token', $mode); + $sess_id = $_COOKIE[ini_get('session.name')]; + + if (empty($sess_id) || $token != $sess_tok) { + $this->request_status = self::REQUEST_ERROR_TOKEN; + return false; + } + + return true; + } + + + /** * Build a valid URL to this instance of Roundcube * * @param mixed Either a string with the action or url parameters as key-value pairs @@ -1551,7 +1661,7 @@ class rcube // send thru SMTP server using custom SMTP library if ($this->config->get('smtp_server')) { // generate list of recipients - $a_recipients = array($mailto); + $a_recipients = (array) $mailto; if (strlen($headers['Cc'])) $a_recipients[] = $headers['Cc']; @@ -1651,19 +1761,24 @@ class rcube // remove MDN headers after sending unset($headers['Return-Receipt-To'], $headers['Disposition-Notification-To']); - // get all recipients - if ($headers['Cc']) - $mailto .= $headers['Cc']; - if ($headers['Bcc']) - $mailto .= $headers['Bcc']; - if (preg_match_all('/<([^@]+@[^>]+)>/', $mailto, $m)) - $mailto = implode(', ', array_unique($m[1])); - if ($this->config->get('smtp_log')) { + // get all recipient addresses + if (is_array($mailto)) { + $mailto = implode(',', $mailto); + } + if ($headers['Cc']) { + $mailto .= ',' . $headers['Cc']; + } + if ($headers['Bcc']) { + $mailto .= ',' . $headers['Bcc']; + } + + $mailto = rcube_mime::decode_address_list($mailto, null, false, null, true); + self::write_log('sendmail', sprintf("User %s [%s]; Message for %s; %s", $this->user->get_username(), - $_SERVER['REMOTE_ADDR'], - $mailto, + rcube_utils::remote_addr(), + implode(', ', $mailto), !empty($response) ? join('; ', $response) : '')); } } |