| | |
| | | */ |
| | | 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 |
| | |
| | | */ |
| | | public $user; |
| | | |
| | | /** |
| | | * Request status |
| | | * |
| | | * @var int |
| | | */ |
| | | public $request_status = 0; |
| | | |
| | | /* private/protected vars */ |
| | | protected $texts; |
| | |
| | | public function get_dbh() |
| | | { |
| | | if (!$this->db) { |
| | | $config_all = $this->config->all(); |
| | | $this->db = rcube_db::factory($config_all['db_dsnw'], $config_all['db_dsnr'], $config_all['db_persistent']); |
| | | $this->db->set_debug((bool)$config_all['sql_debug']); |
| | | $this->db = rcube_db::factory( |
| | | $this->config->get('db_dsnw'), |
| | | $this->config->get('db_dsnr'), |
| | | $this->config->get('db_persistent') |
| | | ); |
| | | |
| | | $this->db->set_debug((bool)$this->config->get('sql_debug')); |
| | | } |
| | | |
| | | return $this->db; |
| | |
| | | |
| | | // set class options |
| | | $options = array( |
| | | 'auth_type' => $this->config->get("{$driver}_auth_type", 'check'), |
| | | 'auth_cid' => $this->config->get("{$driver}_auth_cid"), |
| | | 'auth_pw' => $this->config->get("{$driver}_auth_pw"), |
| | | 'debug' => (bool) $this->config->get("{$driver}_debug"), |
| | | 'force_caps' => (bool) $this->config->get("{$driver}_force_caps"), |
| | | 'disabled_caps' => $this->config->get("{$driver}_disabled_caps"), |
| | | 'timeout' => (int) $this->config->get("{$driver}_timeout"), |
| | | 'skip_deleted' => (bool) $this->config->get('skip_deleted'), |
| | | 'driver' => $driver, |
| | | 'auth_type' => $this->config->get("{$driver}_auth_type", 'check'), |
| | | 'auth_cid' => $this->config->get("{$driver}_auth_cid"), |
| | | 'auth_pw' => $this->config->get("{$driver}_auth_pw"), |
| | | 'debug' => (bool) $this->config->get("{$driver}_debug"), |
| | | 'force_caps' => (bool) $this->config->get("{$driver}_force_caps"), |
| | | 'disabled_caps' => $this->config->get("{$driver}_disabled_caps"), |
| | | 'socket_options' => $this->config->get("{$driver}_conn_options"), |
| | | 'timeout' => (int) $this->config->get("{$driver}_timeout"), |
| | | 'skip_deleted' => (bool) $this->config->get('skip_deleted'), |
| | | 'driver' => $driver, |
| | | ); |
| | | |
| | | if (!empty($_SESSION['storage_host'])) { |
| | |
| | | |
| | | $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. |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 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. |
| | |
| | | * 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('mcrypt_module_open') && |
| | | if (function_exists('openssl_encrypt')) { |
| | | $method = 'DES-EDE3-CBC'; |
| | | $opts = defined('OPENSSL_RAW_DATA') ? OPENSSL_RAW_DATA : true; |
| | | $iv = $this->create_iv(openssl_cipher_iv_length($method)); |
| | | $cipher = $iv . openssl_encrypt($clear, $method, $ckey, $opts, $iv); |
| | | } |
| | | else if (function_exists('mcrypt_module_open') && |
| | | ($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); |
| | |
| | | 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( |
| | | 'code' => 500, 'type' => 'php', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => "Could not perform encryption; make sure Mcrypt is installed or lib/des.inc is available" |
| | | 'message' => "Could not perform encryption; make sure OpenSSL or Mcrypt or lib/des.inc is available" |
| | | ), true, true); |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | $cipher = $base64 ? base64_decode($cipher) : $cipher; |
| | | $ckey = $this->config->get_crypto_key($key); |
| | | |
| | | if (function_exists('mcrypt_module_open') && |
| | | ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, "")) |
| | | ) { |
| | | $iv_size = mcrypt_enc_get_iv_size($td); |
| | | $iv = substr($cipher, 0, $iv_size); |
| | | if (function_exists('openssl_decrypt')) { |
| | | $method = 'DES-EDE3-CBC'; |
| | | $opts = defined('OPENSSL_RAW_DATA') ? OPENSSL_RAW_DATA : true; |
| | | $iv_size = openssl_cipher_iv_length($method); |
| | | $iv = substr($cipher, 0, $iv_size); |
| | | |
| | | // session corruption? (#1485970) |
| | | if (strlen($iv) < $iv_size) { |
| | |
| | | } |
| | | |
| | | $cipher = substr($cipher, $iv_size); |
| | | mcrypt_generic_init($td, $this->config->get_crypto_key($key), $iv); |
| | | $clear = openssl_decrypt($cipher, $method, $ckey, $opts, $iv); |
| | | } |
| | | else if (function_exists('mcrypt_module_open') && |
| | | ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, "")) |
| | | ) { |
| | | $iv_size = mcrypt_enc_get_iv_size($td); |
| | | $iv = substr($cipher, 0, $iv_size); |
| | | |
| | | // session corruption? (#1485970) |
| | | if (strlen($iv) < $iv_size) { |
| | | return ''; |
| | | } |
| | | |
| | | $cipher = substr($cipher, $iv_size); |
| | | mcrypt_generic_init($td, $ckey, $iv); |
| | | $clear = mdecrypt_generic($td, $cipher); |
| | | mcrypt_generic_deinit($td); |
| | | mcrypt_module_close($td); |
| | |
| | | |
| | | 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); |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | |
| | |
| | | $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'; |
| | |
| | | $date = $log['date']; |
| | | if ($log['abort']) |
| | | return true; |
| | | } |
| | | |
| | | // add session ID to the log |
| | | if ($session_key > 0 && ($sess = session_id())) { |
| | | $line = '<' . substr($sess, 0, $session_key) . '> ' . $line; |
| | | } |
| | | |
| | | if ($log_driver == 'syslog') { |
| | |
| | | } |
| | | |
| | | exit(1); |
| | | } |
| | | else if ($cli) { |
| | | fwrite(STDERR, 'ERROR: ' . $arg['message']); |
| | | } |
| | | } |
| | | |
| | |
| | | )); |
| | | |
| | | if ($plugin['abort']) { |
| | | if (!empty($plugin['error'])) { |
| | | $error = $plugin['error']; |
| | | } |
| | | if (!empty($plugin['body_file'])) { |
| | | $body_file = $plugin['body_file']; |
| | | } |
| | | |
| | | return isset($plugin['result']) ? $plugin['result'] : false; |
| | | } |
| | | |
| | |
| | | // 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']; |
| | |
| | | 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 |
| | |
| | | // 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) : '')); |
| | | } |
| | | } |