From 2f8b1036da42ec3d15a51c6b17a473f9f4df71d3 Mon Sep 17 00:00:00 2001 From: Thomas Bruederli <bruederli@kolabsys.com> Date: Sat, 07 Feb 2015 12:33:24 -0500 Subject: [PATCH] Bump version and copyright year --- program/lib/Roundcube/rcube.php | 188 ++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 163 insertions(+), 25 deletions(-) diff --git a/program/lib/Roundcube/rcube.php b/program/lib/Roundcube/rcube.php index e3e26d8..819c7f8 100644 --- a/program/lib/Roundcube/rcube.php +++ b/program/lib/Roundcube/rcube.php @@ -28,8 +28,14 @@ */ 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 @@ */ public $user; + /** + * Request status + * + * @var int + */ + public $request_status = 0; /* private/protected vars */ protected $texts; @@ -389,8 +401,12 @@ $this->storage->set_options($options); $this->set_storage_prop(); - } + // subscribe to 'storage_connected' hook for session logging + if ($this->config->get('imap_log_session', false)) { + $this->plugins->register_hook('storage_connected', array($this, 'storage_log_session')); + } + } /** * Set storage parameters. @@ -456,6 +472,16 @@ } } + + /** + * Callback for IMAP connection events to log session identifiers + */ + public function storage_log_session($args) + { + if (!empty($args['session']) && session_id()) { + $this->write_log('imap_session', $args['session']); + } + } /** * Create session object and start the session. @@ -828,6 +854,7 @@ * upon decryption; see http://php.net/mcrypt_generic#68082 */ $clear = pack("a*H2", $clear, "80"); + $ckey = $this->config->get_crypto_key($key); if (function_exists('openssl_encrypt')) { $method = 'DES-EDE3-CBC'; @@ -839,7 +866,7 @@ ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, "")) ) { $iv = $this->create_iv(mcrypt_enc_get_iv_size($td)); - mcrypt_generic_init($td, $this->config->get_crypto_key($key), $iv); + mcrypt_generic_init($td, $ckey, $iv); $cipher = $iv . mcrypt_generic($td, $clear); mcrypt_generic_deinit($td); mcrypt_module_close($td); @@ -850,7 +877,7 @@ if (function_exists('des')) { $des_iv_size = 8; $iv = $this->create_iv($des_iv_size); - $cipher = $iv . des($this->config->get_crypto_key($key), $clear, 1, 1, $iv); + $cipher = $iv . des($ckey, $clear, 1, 1, $iv); } else { self::raise_error(array( @@ -881,6 +908,7 @@ } $cipher = $base64 ? base64_decode($cipher) : $cipher; + $ckey = $this->config->get_crypto_key($key); if (function_exists('openssl_decrypt')) { $method = 'DES-EDE3-CBC'; @@ -900,7 +928,7 @@ ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, "")) ) { $iv_size = mcrypt_enc_get_iv_size($td); - $iv = substr($cipher, 0, $iv_size); + $iv = substr($cipher, 0, $iv_size); // session corruption? (#1485970) if (strlen($iv) < $iv_size) { @@ -908,7 +936,7 @@ } $cipher = substr($cipher, $iv_size); - mcrypt_generic_init($td, $this->config->get_crypto_key($key), $iv); + mcrypt_generic_init($td, $ckey, $iv); $clear = mdecrypt_generic($td, $cipher); mcrypt_generic_deinit($td); mcrypt_module_close($td); @@ -918,15 +946,15 @@ if (function_exists('des')) { $des_iv_size = 8; - $iv = substr($cipher, 0, $des_iv_size); + $iv = substr($cipher, 0, $des_iv_size); $cipher = substr($cipher, $des_iv_size); - $clear = des($this->config->get_crypto_key($key), $cipher, 0, 1, $iv); + $clear = des($ckey, $cipher, 0, 1, $iv); } else { self::raise_error(array( 'code' => 500, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Could not perform decryption; make sure Mcrypt is installed or lib/des.inc is available" + 'message' => "Could not perform decryption; make sure OpenSSL or Mcrypt or lib/des.inc is available" ), true, true); } } @@ -958,6 +986,104 @@ } return $iv; + } + + + /** + * 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; } @@ -1138,8 +1264,12 @@ $line = var_export($line, true); } - $date_format = self::$instance ? self::$instance->config->get('log_date_format') : null; - $log_driver = self::$instance ? self::$instance->config->get('log_driver') : null; + $date_format = $log_driver = $session_key = null; + if (self::$instance) { + $date_format = self::$instance->config->get('log_date_format'); + $log_driver = self::$instance->config->get('log_driver'); + $session_key = intval(self::$instance->config->get('log_session_id', 8)); + } if (empty($date_format)) { $date_format = 'd-M-Y H:i:s O'; @@ -1158,8 +1288,8 @@ } // add session ID to the log - if ($sess = session_id()) { - $line = '<' . substr($sess, 0, 8) . '> ' . $line; + if ($session_key > 0 && ($sess = session_id())) { + $line = '<' . substr($sess, 0, $session_key) . '> ' . $line; } if ($log_driver == 'syslog') { @@ -1261,6 +1391,9 @@ } exit(1); + } + else if ($cli) { + fwrite(STDERR, 'ERROR: ' . $arg['message']); } } @@ -1528,7 +1661,7 @@ // 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']; @@ -1573,7 +1706,7 @@ if (!$sent) { self::raise_error(array('code' => 800, 'type' => 'smtp', 'line' => __LINE__, 'file' => __FILE__, - 'message' => "SMTP error: ".join("\n", $response)), TRUE, FALSE); + 'message' => join("\n", $response)), true, false); } } // send mail using PHP's mail() function @@ -1628,19 +1761,24 @@ // 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) : '')); } } -- Gitblit v1.9.1