/** * Setter for cookie encryption secret */ function set_secret($secret = null) { // generate random hash and store in session if (!$secret) { if (!empty($_SESSION['auth_secret'])) { $secret = $_SESSION['auth_secret']; } else { $secret = rcube_utils::random_bytes(strlen($this->key)); } } $_SESSION['auth_secret'] = $secret; }
/** * Create configuration file that contains parameters * that differ from default values. * * @return string The complete config file content */ function create_config() { $config = array(); foreach ($this->config as $prop => $default) { $is_default = !isset($_POST["_{$prop}"]); $value = !$is_default || $this->bool_config_props[$prop] ? $_POST["_{$prop}"] : $default; // always disable installer if ($prop == 'enable_installer') { $value = false; } // reset useragent to default (keeps version up-to-date) if ($prop == 'useragent' && stripos($value, 'Roundcube Webmail/') !== false) { $value = $this->defaults[$prop]; } // generate new encryption key, never use the default value if ($prop == 'des_key' && $value == $this->defaults[$prop]) { $value = rcube_utils::random_bytes(24); } // convert some form data if ($prop == 'debug_level' && !$is_default) { if (is_array($value)) { $val = 0; foreach ($value as $dbgval) { $val += intval($dbgval); } $value = $val; } } else { if ($prop == 'db_dsnw' && !empty($_POST['_dbtype'])) { if ($_POST['_dbtype'] == 'sqlite') { $value = sprintf('%s://%s?mode=0646', $_POST['_dbtype'], $_POST['_dbname'][0] == '/' ? '/' . $_POST['_dbname'] : $_POST['_dbname']); } else { if ($_POST['_dbtype']) { $value = sprintf('%s://%s:%s@%s/%s', $_POST['_dbtype'], rawurlencode($_POST['_dbuser']), rawurlencode($_POST['_dbpass']), $_POST['_dbhost'], $_POST['_dbname']); } } } else { if ($prop == 'smtp_auth_type' && $value == '0') { $value = ''; } else { if ($prop == 'default_host' && is_array($value)) { $value = self::_clean_array($value); if (count($value) <= 1) { $value = $value[0]; } } else { if ($prop == 'mail_pagesize' || $prop == 'addressbook_pagesize') { $value = max(2, intval($value)); } else { if ($prop == 'smtp_user' && !empty($_POST['_smtp_user_u'])) { $value = '%u'; } else { if ($prop == 'smtp_pass' && !empty($_POST['_smtp_user_u'])) { $value = '%p'; } else { if (is_bool($default)) { $value = (bool) $value; } else { if (is_numeric($value)) { $value = intval($value); } else { if ($prop == 'plugins' && !empty($_POST['submit'])) { $value = array(); foreach (array_keys($_POST) as $key) { if (preg_match('/^_plugins_*/', $key)) { array_push($value, $_POST[$key]); } } } } } } } } } } } } // skip this property if ($value == $this->defaults[$prop] && !in_array($prop, $this->local_config) || in_array($prop, array_merge($this->obsolete_config, array_keys($this->replaced_config))) || preg_match('/^db_(table|sequence)_/', $prop)) { continue; } // save change $this->config[$prop] = $value; $config[$prop] = $value; } $out = "<?php\n\n"; $out .= "/* Local configuration for Roundcube Webmail */\n\n"; foreach ($config as $prop => $value) { // copy option descriptions from existing config or defaults.inc.php $out .= $this->comments[$prop]; $out .= "\$config['{$prop}'] = " . self::_dump_var($value, $prop) . ";\n\n"; } return $out; }
/** * rcube:utils::random_bytes() */ function test_random_bytes() { $this->assertSame(15, strlen(rcube_utils::random_bytes(15))); $this->assertSame(15, strlen(rcube_utils::random_bytes(15, true))); $this->assertSame(1, strlen(rcube_utils::random_bytes(1))); $this->assertSame(0, strlen(rcube_utils::random_bytes(0))); $this->assertSame(0, strlen(rcube_utils::random_bytes(-1))); }
/** * Generate a unique token to be used in a form request * * @return string The request token */ public function get_request_token() { if (empty($_SESSION['request_token'])) { $plugin = $this->plugins->exec_hook('request_token', array('value' => rcube_utils::random_bytes(32))); $_SESSION['request_token'] = $plugin['value']; } return $_SESSION['request_token']; }
/** * Generate a unique hash to identify this user whith */ function get_hash() { $prefs = $this->get_prefs(); // generate a random hash and store it in user prefs if (empty($prefs['client_hash'])) { $prefs['client_hash'] = rcube_utils::random_bytes(16); $this->save_prefs(array('client_hash' => $prefs['client_hash'])); } return $prefs['client_hash']; }
/** * 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 = rcube_utils::random_bytes($length); $plugin = $this->plugins->exec_hook('secure_token', array('value' => $token, 'length' => $length)); $_SESSION['secure_token'] = $plugin['value']; } return $_SESSION['secure_token']; } return false; }
/** * Hashes a password and returns the hash based on the specified method * * Parts of the code originally from the phpLDAPadmin development team * http://phpldapadmin.sourceforge.net/ * * @param string Clear password * @param string Hashing method * @param bool|string Prefix string or TRUE to add a default prefix * * @return string Hashed password */ static function hash_password($password, $method = '', $prefixed = true) { $method = strtolower($method); $rcmail = rcmail::get_instance(); $prefix = ''; $crypted = ''; $default = false; if (empty($method) || $method == 'default') { $method = $rcmail->config->get('password_algorithm'); $prefixed = $rcmail->config->get('password_algorithm_prefix'); $default = true; } else { if ($method == 'crypt') { // deprecated if (!($method = $rcmail->config->get('password_crypt_hash'))) { $method = 'md5'; } if (!strpos($method, '-crypt')) { $method .= '-crypt'; } } } switch ($method) { case 'des': case 'des-crypt': $crypted = crypt($password, rcube_utils::random_bytes(2)); $prefix = '{CRYPT}'; break; case 'ext_des': // for BC // for BC case 'ext-des-crypt': $crypted = crypt($password, '_' . rcube_utils::random_bytes(8)); $prefix = '{CRYPT}'; break; case 'md5crypt': // for BC // for BC case 'md5-crypt': $crypted = crypt($password, '$1$' . rcube_utils::random_bytes(9)); $prefix = '{CRYPT}'; break; case 'sha256-crypt': $rounds = (int) $rcmail->config->get('password_crypt_rounds'); $prefix = '$5$'; if ($rounds > 1000) { $prefix .= 'rounds=' . $rounds . '$'; } $crypted = crypt($password, $prefix . rcube_utils::random_bytes(16)); $prefix = '{CRYPT}'; break; case 'sha512-crypt': $rounds = (int) $rcmail->config->get('password_crypt_rounds'); $prefix = '$6$'; if ($rounds > 1000) { $prefix .= 'rounds=' . $rounds . '$'; } $crypted = crypt($password, $prefix . rcube_utils::random_bytes(16)); $prefix = '{CRYPT}'; break; case 'blowfish': // for BC // for BC case 'blowfish-crypt': $cost = (int) $rcmail->config->get('password_blowfish_cost'); $cost = $cost < 4 || $cost > 31 ? 12 : $cost; $prefix = sprintf('$2a$%02d$', $cost); $crypted = crypt($password, $prefix . rcube_utils::random_bytes(22)); $prefix = '{CRYPT}'; break; case 'md5': $crypted = base64_encode(pack('H*', md5($password))); $prefix = '{MD5}'; break; case 'sha': if (function_exists('sha1')) { $crypted = pack('H*', sha1($password)); } else { if (function_exists('hash')) { $crypted = hash('sha1', $password, true); } else { if (function_exists('mhash')) { $crypted = mhash(MHASH_SHA1, $password); } else { rcube::raise_error(array('code' => 600, 'file' => __FILE__, 'line' => __LINE__, 'message' => "Password plugin: Your PHP install does not have the mhash()/hash() nor sha1() function"), true, true); } } } $crypted = base64_encode($crypted); $prefix = '{SHA}'; break; case 'ssha': $salt = rcube_utils::random_bytes(8); if (function_exists('mhash') && function_exists('mhash_keygen_s2k')) { $salt = mhash_keygen_s2k(MHASH_SHA1, $password, $salt, 4); $crypted = mhash(MHASH_SHA1, $password . $salt); } else { if (function_exists('sha1')) { $salt = substr(pack("H*", sha1($salt . $password)), 0, 4); $crypted = sha1($password . $salt, true); } else { if (function_exists('hash')) { $salt = substr(pack("H*", hash('sha1', $salt . $password)), 0, 4); $crypted = hash('sha1', $password . $salt, true); } else { rcube::raise_error(array('code' => 600, 'file' => __FILE__, 'line' => __LINE__, 'message' => "Password plugin: Your PHP install does not have the mhash()/hash() nor sha1() function"), true, true); } } } $crypted = base64_encode($crypted . $salt); $prefix = '{SSHA}'; break; case 'smd5': $salt = rcube_utils::random_bytes(8); if (function_exists('mhash') && function_exists('mhash_keygen_s2k')) { $salt = mhash_keygen_s2k(MHASH_MD5, $password, $salt, 4); $crypted = mhash(MHASH_MD5, $password . $salt); } else { if (function_exists('hash')) { $salt = substr(pack("H*", hash('md5', $salt . $password)), 0, 4); $crypted = hash('md5', $password . $salt, true); } else { $salt = substr(pack("H*", md5($salt . $password)), 0, 4); $crypted = md5($password . $salt, true); } } $crypted = base64_encode($crypted . $salt); $prefix = '{SMD5}'; break; case 'samba': if (function_exists('hash')) { $crypted = hash('md4', rcube_charset::convert($password, RCUBE_CHARSET, 'UTF-16LE')); $crypted = strtoupper($crypted); } else { rcube::raise_error(array('code' => 600, 'file' => __FILE__, 'line' => __LINE__, 'message' => "Password plugin: Your PHP install does not have hash() function"), true, true); } break; case 'ad': $crypted = rcube_charset::convert('"' . $password . '"', RCUBE_CHARSET, 'UTF-16LE'); break; case 'cram-md5': // deprecated require_once __DIR__ . '/../helpers/dovecot_hmacmd5.php'; $crypted = dovecot_hmacmd5($password); $prefix = '{CRAM-MD5}'; break; case 'dovecot': if (!($dovecotpw = $rcmail->config->get('password_dovecotpw'))) { $dovecotpw = 'dovecotpw'; } if (!($method = $rcmail->config->get('password_dovecotpw_method'))) { $method = 'CRAM-MD5'; } $spec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('file', '/dev/null', 'a')); $pipe = proc_open("{$dovecotpw} -s '{$method}'", $spec, $pipes); if (!is_resource($pipe)) { return false; } fwrite($pipes[0], $password . "\n", 1 + strlen($password)); usleep(1000); fwrite($pipes[0], $password . "\n", 1 + strlen($password)); $crypted = trim(stream_get_contents($pipes[1]), "\n"); fclose($pipes[0]); fclose($pipes[1]); proc_close($pipe); if (!preg_match('/^\\{' . $method . '\\}/', $crypted)) { return false; } if (!$default) { $prefixed = (bool) $rcmail->config->get('password_dovecotpw_with_method'); } if (!$prefixed) { $crypted = trim(str_replace('{' . $method . '}', '', $crypted)); } $prefixed = false; break; case 'hash': // deprecated if (!extension_loaded('hash')) { rcube::raise_error(array('code' => 600, 'file' => __FILE__, 'line' => __LINE__, 'message' => "Password plugin: 'hash' extension not loaded!"), true, true); } if (!($hash_algo = strtolower($rcmail->config->get('password_hash_algorithm')))) { $hash_algo = 'sha1'; } $crypted = hash($hash_algo, $password); if ($rcmail->config->get('password_hash_base64')) { $crypted = base64_encode(pack('H*', $crypted)); } break; case 'clear': $crypted = $password; } if ($crypted === null || $crypted === false) { return false; } if ($prefixed && $prefixed !== true) { $prefix = $prefixed; $prefixed = true; } if ($prefixed === true && $prefix) { $crypted = $prefix . $crypted; } return $crypted; }
/** * rcube:utils::random_bytes() */ function test_random_bytes() { $this->assertRegexp('/^[a-zA-Z0-9]{15}$/', rcube_utils::random_bytes(15)); $this->assertSame(15, strlen(rcube_utils::random_bytes(15, true))); $this->assertSame(1, strlen(rcube_utils::random_bytes(1))); $this->assertSame(0, strlen(rcube_utils::random_bytes(0))); $this->assertSame(0, strlen(rcube_utils::random_bytes(-1))); }