65535)) { auth_error(lang('Connecting to privileged ports is not allowed.')); } } /** * @param string $server * @param string $username * @param string $password * @param string $defaultServer * @param int|null $defaultPort * @return string */ function build_http_url($server, $username, $password, $defaultServer, $defaultPort = null) { if (!preg_match('~^(https?://)?([^:]*)(:\d+)?$~', rtrim($server, '/'), $matches)) { $this->error = lang('Invalid server or credentials.'); return false; } return ($matches[1] ?: "http://") . ($username !== "" || $password !== "" ? "$username:$password@" : "") . ($matches[2] !== "" ? $matches[2] : $defaultServer) . (isset($matches[3]) ? $matches[3] : ($defaultPort ? ":$defaultPort" : "")); } function add_invalid_login() { global $adminer; $fp = file_open_lock(get_temp_dir() . "/adminer.invalid"); if (!$fp) { return; } $invalids = unserialize(stream_get_contents($fp)); $time = time(); if ($invalids) { foreach ($invalids as $ip => $val) { if ($val[0] < $time) { unset($invalids[$ip]); } } } $invalid = &$invalids[$adminer->bruteForceKey()]; if (!$invalid) { $invalid = array($time + 30*60, 0); // active for 30 minutes } $invalid[1]++; file_write_unlock($fp, serialize($invalids)); } function check_invalid_login() { global $adminer; $invalids = unserialize(@file_get_contents(get_temp_dir() . "/adminer.invalid")); // @ - may not exist $invalid = ($invalids ? $invalids[$adminer->bruteForceKey()] : array()); if ($invalid === null) { return; } $next_attempt = ($invalid[1] > 29 ? $invalid[0] - time() : 0); // allow 30 invalid attempts if ($next_attempt > 0) { //! do the same with permanent login auth_error(lang('Too many unsuccessful logins, try again in %d minute(s).', ceil($next_attempt / 60))); } } $auth = $_POST["auth"]; if ($auth) { session_regenerate_id(); // defense against session fixation $vendor = $auth["driver"]; $server = trim($auth["server"]); $username = $auth["username"]; $password = (string) $auth["password"]; $db = $auth["db"]; set_password($vendor, $server, $username, $password); $_SESSION["db"][$vendor][$server][$username][$db] = true; if ($auth["permanent"]) { $key = base64_encode($vendor) . "-" . base64_encode($server) . "-" . base64_encode($username) . "-" . base64_encode($db); $private = $adminer->permanentLogin(true); $permanent[$key] = "$key:" . base64_encode($private ? encrypt_string($password, $private) : ""); cookie("adminer_permanent", implode(" ", $permanent)); } if (count($_POST) == 1 // 1 - auth || DRIVER != $vendor || SERVER != $server || $_GET["username"] !== $username // "0" == "00" || DB != $db ) { redirect(auth_url($vendor, $server, $username, $db)); } } elseif ($_POST["logout"] && (!$has_token || verify_token())) { foreach (array("pwds", "db", "dbs", "queries") as $key) { set_session($key, null); } unset_permanent(); redirect(substr(preg_replace('~\b(username|db|ns)=[^&]*&~', '', ME), 0, -1), lang('Logout successful.')); } elseif ($permanent && !$_SESSION["pwds"]) { session_regenerate_id(); $private = $adminer->permanentLogin(); foreach ($permanent as $key => $val) { list(, $cipher) = explode(":", $val); list($vendor, $server, $username, $db) = array_map('base64_decode', explode("-", $key)); set_password($vendor, $server, $username, decrypt_string(base64_decode($cipher), $private)); $_SESSION["db"][$vendor][$server][$username][$db] = true; } } function unset_permanent() { global $permanent; foreach ($permanent as $key => $val) { list($vendor, $server, $username, $db) = array_map('base64_decode', explode("-", $key)); if ($vendor == DRIVER && $server == SERVER && $username == $_GET["username"] && $db == DB) { unset($permanent[$key]); } } cookie("adminer_permanent", implode(" ", $permanent)); } /** Renders an error message and a login form * @param string plain text * @return null exits */ function auth_error($error) { global $adminer, $has_token; $session_name = session_name(); if (isset($_GET["username"])) { header("HTTP/1.1 403 Forbidden"); // 401 requires sending WWW-Authenticate header if (($_COOKIE[$session_name] || $_GET[$session_name]) && !$has_token) { $error = lang('Session expired, please login again.'); } else { restart_session(); add_invalid_login(); $password = get_password(); if ($password !== null) { if ($password === false) { $error .= ($error ? '
' : '') . lang('Master password expired. Implement %s method to make it permanent.', target_blank(), 'permanentLogin()'); } set_password(DRIVER, SERVER, $_GET["username"], null); } unset_permanent(); } } if (!$_COOKIE[$session_name] && $_GET[$session_name] && ini_bool("session.use_only_cookies")) { $error = lang('Session support must be enabled.'); } $params = session_get_cookie_params(); cookie("adminer_key", ($_COOKIE["adminer_key"] ? $_COOKIE["adminer_key"] : rand_string()), $params["lifetime"]); page_header(lang('Login'), $error, null); echo "
\n"; echo "
"; if (hidden_fields($_POST, array("auth"))) { // expired session echo "

" . lang('The action will be performed after successful login with the same credentials.') . "\n"; } echo "

\n"; $adminer->loginForm(); echo "
\n"; page_footer("auth"); exit; } if (isset($_GET["username"]) && !class_exists("Min_DB")) { unset($_SESSION["pwds"][DRIVER]); unset_permanent(); page_header(lang('No extension'), lang('None of the supported PHP extensions (%s) are available.', implode(", ", $possible_drivers)), false); page_footer("auth"); exit; } stop_session(true); if (isset($_GET["username"]) && is_string(get_password())) { validate_server_input(); check_invalid_login(); $connection = connect(); $driver = new Min_Driver($connection); } $login = null; if (!is_object($connection) || ($login = $adminer->login($_GET["username"], get_password())) !== true) { $error = (is_string($connection) ? h($connection) : (is_string($login) ? $login : lang('Invalid server or credentials.'))); auth_error($error . (preg_match('~^ | $~', get_password()) ? '
' . lang('There is a space in the input password which might be the cause.') : '')); } if ($_POST["logout"] && $has_token && !verify_token()) { page_header(lang('Logout'), lang('Invalid CSRF token. Send the form again.')); page_footer("db"); exit; } if ($auth && $_POST["token"]) { $_POST["token"] = $token; // reset token after explicit login } $error = ''; ///< @var string if ($_POST) { if (!verify_token()) { $ini = "max_input_vars"; $max_vars = ini_get($ini); if (extension_loaded("suhosin")) { foreach (array("suhosin.request.max_vars", "suhosin.post.max_vars") as $key) { $val = ini_get($key); if ($val && (!$max_vars || $val < $max_vars)) { $ini = $key; $max_vars = $val; } } } $error = (!$_POST["token"] && $max_vars ? lang('Maximum number of allowed fields exceeded. Please increase %s.', "'$ini'") : lang('Invalid CSRF token. Send the form again.') . ' ' . lang('If you did not send this request from Adminer then close this page.') ); } } elseif ($_SERVER["REQUEST_METHOD"] == "POST") { // posted form with no data means that post_max_size exceeded because Adminer always sends token at least $error = lang('Too big POST data. Reduce the data or increase the %s configuration directive.', "'post_max_size'"); if (isset($_GET["sql"])) { $error .= ' ' . lang('You can upload a big SQL file via FTP and import it from server.'); } }