/** * @param string $login * @param string $password * @param int $accountId * @param string $scalrCaptcha * @return Scalr_Account_User * @throws Exception * @throws Scalr_Exception_Core * @throws \Scalr\System\Config\Exception\YamlException */ private function loginUserGet($login, $password, $accountId, $scalrCaptcha) { if ($login != '' && $password != '') { $isAdminLogin = $this->db->GetOne('SELECT * FROM account_users WHERE email = ? AND account_id = 0', array($login)); if ($this->getContainer()->config->get('scalr.auth_mode') == 'ldap' && !$isAdminLogin) { $ldap = $this->getContainer()->ldap($login, $password); $this->response->setHeader('X-Scalr-LDAP-Login', $login); $tldap = 0; $start = microtime(true); $result = $ldap->isValidUser(); $tldap = microtime(true) - $start; if ($result) { try { //Tries to retrieve user's email address from LDAP or provides that login is always with domain suffix if (($pos = strpos($login, '@')) === false) { $login = $ldap->getEmail(); } $start = microtime(true); $groups = $ldap->getUserGroups(); $gtime = microtime(true) - $start; $tldap += $gtime; $this->response->setHeader('X-Scalr-LDAP-G-Query-Time', sprintf('%0.4f sec', $gtime)); $this->response->setHeader('X-Scalr-LDAP-Query-Time', sprintf('%0.4f sec', $tldap)); $this->response->setHeader('X-Scalr-LDAP-CLogin', $login); $this->ldapGroups = $groups; } catch (Exception $e) { throw new Exception($e->getMessage() . $ldap->getLog()); } foreach ($groups as $key => $name) { $groups[$key] = $this->db->qstr($name); } $userAvailableAccounts = array(); if ($ldap->getConfig()->debug) { $this->response->setHeader('X-Scalr-LDAP-Debug', json_encode($ldap->getLog())); } // System users are not members of any group so if there is no groups then skip this. if (count($groups) > 0) { foreach ($this->db->GetAll(' SELECT clients.id, clients.name FROM clients JOIN client_environments ON client_environments.client_id = clients.id JOIN account_team_envs ON account_team_envs.env_id = client_environments.id JOIN account_teams ON account_teams.id = account_team_envs.team_id WHERE account_teams.name IN(' . join(',', $groups) . ')') as $value) { $userAvailableAccounts[$value['id']] = $value; } } foreach ($this->db->GetAll("\n SELECT clients.id, clients.name, clients.org, clients.dtadded\n FROM clients\n JOIN account_users ON account_users.account_id = clients.id\n WHERE account_users.email = ? AND account_users.type = ?", array($login, Scalr_Account_User::TYPE_ACCOUNT_OWNER)) as $value) { $value['dtadded'] = Scalr_Util_DateTime::convertTz($value['dtadded'], 'M j, Y'); $userAvailableAccounts[$value['id']] = $value; } $userAvailableAccounts = array_values($userAvailableAccounts); if (empty($userAvailableAccounts)) { throw new Scalr_Exception_Core('You don\'t have access to any account. ' . $ldap->getLog()); } elseif (count($userAvailableAccounts) == 1) { $accountId = $userAvailableAccounts[0]['id']; } else { $ids = array(); foreach ($userAvailableAccounts as $value) { $ids[] = $value['id']; } if (!$accountId && !in_array($accountId, $ids)) { $this->response->data(array('accounts' => $userAvailableAccounts)); throw new Exception(); } } $user = new Scalr_Account_User(); $user = $user->loadByEmail($login, $accountId); if (!$user) { $user = new Scalr_Account_User(); $user->type = Scalr_Account_User::TYPE_TEAM_USER; $user->status = Scalr_Account_User::STATUS_ACTIVE; $user->create($login, $accountId); } if (!$user->fullname) { $user->fullname = $ldap->getFullName(); $user->save(); } if ($ldap->getUsername() != $ldap->getEmail()) { $user->setSetting(Scalr_Account_User::SETTING_LDAP_EMAIL, $ldap->getEmail()); $user->setSetting(Scalr_Account_User::SETTING_LDAP_USERNAME, $ldap->getUsername()); } else { $user->setSetting(Scalr_Account_User::SETTING_LDAP_EMAIL, ''); } } else { throw new Exception("Incorrect login or password (1) " . $ldap->getLog()); } } else { $userAvailableAccounts = $this->db->GetAll(' SELECT account_users.id AS userId, clients.id, clients.name, clients.org, clients.dtadded, au.email AS `owner` FROM account_users LEFT JOIN clients ON clients.id = account_users.account_id LEFT JOIN account_users au ON account_users.account_id = au.account_id WHERE account_users.email = ? AND (au.type = ? OR account_users.type = ? OR account_users.type = ?) GROUP BY userId ', array($login, Scalr_Account_User::TYPE_ACCOUNT_OWNER, Scalr_Account_User::TYPE_SCALR_ADMIN, Scalr_Account_User::TYPE_FIN_ADMIN)); foreach ($userAvailableAccounts as &$ac) { $ac['dtadded'] = Scalr_Util_DateTime::convertTz($ac['dtadded'], 'M j, Y'); } if (count($userAvailableAccounts) == 1) { $user = new Scalr_Account_User(); $user->loadById($userAvailableAccounts[0]['userId']); } elseif (count($userAvailableAccounts) > 1) { if ($accountId) { foreach ($userAvailableAccounts as $acc) { if ($acc['id'] == $accountId) { $user = new Scalr_Account_User(); $user->loadById($acc['userId']); break; } } } else { $this->response->data(array('accounts' => $userAvailableAccounts)); throw new Exception(); } } else { throw new Exception("Incorrect login or password (3)"); } if ($user) { if ($user->status != User::STATUS_ACTIVE) { throw new Exception('User account has been deactivated. Please contact your account owner.'); } // kaptcha if ($user->loginattempts > 3 && $this->getContainer()->config->get('scalr.ui.recaptcha.private_key')) { if (!$scalrCaptcha || ($r = $this->validateReCaptcha($scalrCaptcha)) !== true) { $this->response->data(array('loginattempts' => $user->loginattempts, 'scalrCaptchaError' => isset($r) ? $r : 'empty-value')); throw new Exception(); } } if (!$user->checkPassword($password)) { $attempts = (int) $this->getContainer()->config->get('scalr.security.user.suspension.failed_login_attempts'); if ($attempts > 0 && $user->loginattempts >= $attempts && $user->getEmail() != 'admin') { $user->status = User::STATUS_INACTIVE; $user->loginattempts = 0; $user->save(); throw new Exception('User account has been deactivated. Please contact your account owner.'); } if ($this->getContainer()->config->get('scalr.ui.recaptcha.private_key')) { $this->response->data(array('loginattempts' => $user->loginattempts)); } throw new Exception("Incorrect login or password (1)"); } } else { throw new Exception("Incorrect login or password (2)"); } } // valid user, other checks $whitelist = $user->getVar(Scalr_Account_User::VAR_SECURITY_IP_WHITELIST); if ($whitelist) { $subnets = unserialize($whitelist); if (!Scalr_Util_Network::isIpInSubnets($this->request->getRemoteAddr(), $subnets)) { throw new Exception('The IP address you are attempting to log in from isn\'t authorized'); } } return $user; } else { throw new Exception('Incorrect login or password (0)'); } }
private function loginUserGet($login, $password, $accountId, $scalrCaptcha, $scalrCaptchaChallenge) { if ($login != '' && $password != '') { $isAdminLogin = $this->db->GetOne('SELECT * FROM account_users WHERE email = ? AND account_id = 0', array($login)); if ($this->getContainer()->config->get('scalr.auth_mode') == 'ldap' && !$isAdminLogin) { $ldap = $this->getContainer()->ldap($login, $password); $this->response->setHeader('X-Scalr-LDAP-Login', $login); $tldap = 0; $start = microtime(true); $result = $ldap->isValidUser(); $tldap = microtime(true) - $start; if ($result) { try { //Tries to retrieve user's email address from LDAP or provides that login is always with domain suffix if (($pos = strpos($login, '@')) === false) { $login = $ldap->getEmail(); } $start = microtime(true); $groups = $ldap->getUserGroups(); $gtime = microtime(true) - $start; $tldap += $gtime; $this->response->setHeader('X-Scalr-LDAP-G-Query-Time', sprintf('%0.4f sec', $gtime)); $this->response->setHeader('X-Scalr-LDAP-Query-Time', sprintf('%0.4f sec', $tldap)); $this->response->setHeader('X-Scalr-LDAP-CLogin', $login); $this->ldapGroups = $groups; } catch (Exception $e) { throw new Exception($e->getMessage() . $ldap->getLog()); } foreach ($groups as $key => $name) { $groups[$key] = $this->db->qstr($name); } $userAvailableAccounts = array(); if ($ldap->getConfig()->debug) { $this->response->varDump($groups); $this->response->setHeader('X-Scalr-LDAP-Debug', json_encode($ldap->getLog())); } // System users are not members of any group so if there is no groups then skip this. if (count($groups) > 0) { foreach ($this->db->GetAll(' SELECT clients.id, clients.name FROM clients JOIN client_environments ON client_environments.client_id = clients.id JOIN account_team_envs ON account_team_envs.env_id = client_environments.id JOIN account_teams ON account_teams.id = account_team_envs.team_id WHERE account_teams.name IN(' . join(',', $groups) . ')') as $value) { $userAvailableAccounts[$value['id']] = $value; } } foreach ($this->db->GetAll("\n SELECT clients.id, clients.name, clients.org, clients.dtadded\n FROM clients\n JOIN account_users ON account_users.account_id = clients.id\n WHERE account_users.email = ? AND account_users.type = ?", array($login, Scalr_Account_User::TYPE_ACCOUNT_OWNER)) as $value) { $value['dtadded'] = Scalr_Util_DateTime::convertTz($value['dtadded'], 'M j, Y'); $userAvailableAccounts[$value['id']] = $value; } $userAvailableAccounts = array_values($userAvailableAccounts); if (count($userAvailableAccounts) == 0) { throw new Scalr_Exception_Core('You don\'t have access to any account. ' . $ldap->getLog()); } if (count($userAvailableAccounts) == 1) { $accountId = $userAvailableAccounts[0]['id']; } else { $ids = array(); foreach ($userAvailableAccounts as $value) { $ids[] = $value['id']; } if (!$accountId && !in_array($accountId, $ids)) { $this->response->data(array('accounts' => $userAvailableAccounts)); throw new Exception(); } } $user = new Scalr_Account_User(); $user = $user->loadByEmail($login, $accountId); if (!$user) { $user = new Scalr_Account_User(); $user->type = Scalr_Account_User::TYPE_TEAM_USER; $user->status = Scalr_Account_User::STATUS_ACTIVE; $user->create($login, $accountId); } if (!$user->fullname) { $user->fullname = $ldap->getFullName(); $user->save(); } if ($ldap->getUsername() != $ldap->getEmail()) { $user->setSetting(Scalr_Account_User::SETTING_LDAP_EMAIL, $ldap->getEmail()); } else { $user->setSetting(Scalr_Account_User::SETTING_LDAP_EMAIL, ''); } } else { throw new Exception("Incorrect login or password (1) " . $ldap->getLog()); } } else { $userAvailableAccounts = $this->db->GetAll(' SELECT account_users.id AS userId, clients.id, clients.name, clients.org, clients.dtadded, au.email AS `owner` FROM account_users LEFT JOIN clients ON clients.id = account_users.account_id LEFT JOIN account_users au ON account_users.account_id = au.account_id WHERE account_users.email = ? AND (au.type = ? OR account_users.type = ? OR account_users.type = ?) GROUP BY userId ', array($login, Scalr_Account_User::TYPE_ACCOUNT_OWNER, Scalr_Account_User::TYPE_SCALR_ADMIN, Scalr_Account_User::TYPE_FIN_ADMIN)); foreach ($userAvailableAccounts as &$ac) { $ac['dtadded'] = Scalr_Util_DateTime::convertTz($ac['dtadded'], 'M j, Y'); } if (count($userAvailableAccounts) == 1) { $user = new Scalr_Account_User(); $user->loadById($userAvailableAccounts[0]['userId']); } else { if (count($userAvailableAccounts) > 1) { if ($accountId) { foreach ($userAvailableAccounts as $acc) { if ($acc['id'] == $accountId) { $user = new Scalr_Account_User(); $user->loadById($acc['userId']); break; } } } else { $this->response->data(array('accounts' => $userAvailableAccounts)); throw new Exception(); } } else { throw new Exception("Incorrect login or password (3)"); } } if ($user) { // kaptcha if ($user->loginattempts > 2 && $this->getContainer()->config->get('scalr.ui.recaptcha.private_key')) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, 'http://www.google.com/recaptcha/api/verify'); curl_setopt($curl, CURLOPT_POST, true); $post = 'privatekey=' . urlencode($this->getContainer()->config->get('scalr.ui.recaptcha.private_key')) . '&remoteip=' . urlencode($this->request->getRemoteAddr()) . '&challenge=' . urlencode($scalrCaptchaChallenge) . '&response=' . urlencode($scalrCaptcha); curl_setopt($curl, CURLOPT_POSTFIELDS, $post); curl_setopt($curl, CURLOPT_TIMEOUT, 10); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLINFO_HEADER_OUT, true); $response = curl_exec($curl); curl_close($curl); $responseStrings = explode("\n", $response); if ($responseStrings[0] !== 'true') { $this->response->data(array('loginattempts' => $user->loginattempts, 'kaptchaError' => $response)); throw new Exception(); } } if (!$user->checkPassword($password)) { if ($this->getContainer()->config->get('scalr.ui.recaptcha.private_key')) { $this->response->data(array('loginattempts' => $user->loginattempts)); } throw new Exception("Incorrect login or password (1)"); } } else { throw new Exception("Incorrect login or password (2)"); } } // valid user, other checks $whitelist = $user->getVar(Scalr_Account_User::VAR_SECURITY_IP_WHITELIST); if ($whitelist) { $subnets = unserialize($whitelist); if (!Scalr_Util_Network::isIpInSubnets($this->request->getRemoteAddr(), $subnets)) { throw new Exception('The IP address you are attempting to log in from isn\'t authorized'); } } return $user; } else { throw new Exception('Incorrect login or password (0)'); } }
public function BuildRestServer($request) { try { $Reflect = new ReflectionObject($this); if ($Reflect->hasMethod($request['Action'])) { //Authenticate if (isset($request["AuthType"]) && $request['AuthType'] == 'ldap') { $this->AuthenticateLdap($request); } else { $authVersion = isset($request['AuthVersion']) ? intval($request['AuthVersion']) : 0; switch ($authVersion) { case 2: $this->AuthenticateRESTv2($request); break; case 3: $this->AuthenticateRESTv3($request); break; default: $this->AuthenticateREST($request); } if ($this->user->getSetting(Scalr_Account_User::SETTING_API_ENABLED) != 1) { throw new Exception(_("Your API keys are currently disabled. You can enable access at Settings > API access.")); } //Check IP Addresses if ($this->user->getVar(Scalr_Account_User::VAR_API_IP_WHITELIST)) { $ips = explode(",", $this->user->getVar(Scalr_Account_User::VAR_API_IP_WHITELIST)); if (!$this->IPAccessCheck($ips)) { throw new Exception(sprintf(_("Access to the API is not allowed from your IP '%s'"), $_SERVER['REMOTE_ADDR'])); } } } //Check limit if ($this->Environment->getPlatformConfigValue(Scalr_Environment::SETTING_API_LIMIT_ENABLED, false) == 1) { $hour = $this->Environment->getPlatformConfigValue(Scalr_Environment::SETTING_API_LIMIT_HOUR, false); $limit = $this->Environment->getPlatformConfigValue(Scalr_Environment::SETTING_API_LIMIT_REQPERHOUR, false); $usage = $this->Environment->getPlatformConfigValue(Scalr_Environment::SETTING_API_LIMIT_USAGE, false); if ($usage >= $limit && $hour == date("YmdH")) { //$reset = 60 - (int)date("i"); header("HTTP/1.0 429 Too Many Requests"); exit; //throw new Exception(sprintf("Hourly API requests limit (%s) exceeded. Limit will be reset within %s minutes", $limit, $reset)); } if (date("YmdH") > $hour) { $hour = date("YmdH"); $usage = 0; } $this->Environment->setPlatformConfig(array(Scalr_Environment::SETTING_API_LIMIT_USAGE => $usage + 1, Scalr_Environment::SETTING_API_LIMIT_HOUR => $hour), false); } //Execute API call $ReflectMethod = $Reflect->getMethod($request['Action']); $args = []; foreach ($ReflectMethod->getParameters() as $param) { $paramName = $param->getName(); if (isset($request[$paramName])) { $args[$paramName] = $param->isArray() ? (array) $request[$paramName] : $request[$paramName]; } elseif (!$param->isOptional()) { throw new BadRequestException(sprintf("Missing required parameter '%s'", $paramName)); } else { $args[$paramName] = $param->isArray() ? [] : null; } } $result = $ReflectMethod->invokeArgs($this, $args); $this->LastTransactionID = $result->TransactionID; // Create response $DOMDocument = new DOMDocument('1.0', 'UTF-8'); $DOMDocument->loadXML("<{$request['Action']}Response></{$request['Action']}Response>"); $this->ObjectToXML($result, $DOMDocument->documentElement, $DOMDocument); $retval = $DOMDocument->saveXML(); } else { throw new Exception(sprintf("Action '%s' is not defined", $request['Action'])); } } catch (Exception $e) { if (empty($this->LastTransactionID)) { $this->LastTransactionID = Scalr::GenerateUID(); } $retval = "<?xml version=\"1.0\"?>\n" . "<Error>\n" . "\t<TransactionID>{$this->LastTransactionID}</TransactionID>\n" . "\t<Message>{$e->getMessage()}</Message>\n" . "</Error>\n"; } if (isset($this->user)) { $this->LogRequest($this->LastTransactionID, $request['Action'], $_SERVER['REMOTE_ADDR'], $request, $retval); } header("Content-type: text/xml"); header("Content-length: " . strlen($retval)); header("Access-Control-Allow-Origin: *"); print $retval; }