/** * Attempt a login * * @param int iOnExit What action to take if the user is not logged on (one of the class constants EXIT_...) * @return int One of the class constants EXIT_CODE_... */ protected static function Login($iOnExit) { if (self::SecureConnectionRequired() && !utils::IsConnectionSecure()) { // Non secured URL... request for a secure connection throw new Exception('Secure connection required!'); } $aAllowedLoginTypes = MetaModel::GetConfig()->GetAllowedLoginTypes(); if (isset($_SESSION['auth_user'])) { //echo "User: "******"\n"; // Already authentified UserRights::Login($_SESSION['auth_user']); // Login & set the user's language return self::EXIT_CODE_OK; } else { $index = 0; $sLoginMode = ''; $sAuthentication = 'internal'; while ($sLoginMode == '' && $index < count($aAllowedLoginTypes)) { $sLoginType = $aAllowedLoginTypes[$index]; switch ($sLoginType) { case 'cas': utils::InitCASClient(); // check CAS authentication if (phpCAS::isAuthenticated()) { $sAuthUser = phpCAS::getUser(); $sAuthPwd = ''; $sLoginMode = 'cas'; $sAuthentication = 'external'; } break; case 'form': // iTop standard mode: form based authentication $sAuthUser = utils::ReadPostedParam('auth_user', '', false, 'raw_data'); $sAuthPwd = utils::ReadPostedParam('auth_pwd', null, false, 'raw_data'); if ($sAuthUser != '' && $sAuthPwd !== null) { $sLoginMode = 'form'; } break; case 'basic': // Standard PHP authentication method, works with Apache... // Case 1) Apache running in CGI mode + rewrite rules in .htaccess if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION'])) { list($sAuthUser, $sAuthPwd) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6))); $sLoginMode = 'basic'; } else { if (isset($_SERVER['PHP_AUTH_USER'])) { $sAuthUser = $_SERVER['PHP_AUTH_USER']; // Unfortunately, the RFC is not clear about the encoding... // IE and FF supply the user and password encoded in ISO-8859-1 whereas Chrome provides them encoded in UTF-8 // So let's try to guess if it's an UTF-8 string or not... fortunately all encodings share the same ASCII base if (!self::LooksLikeUTF8($sAuthUser)) { // Does not look like and UTF-8 string, try to convert it from iso-8859-1 to UTF-8 // Supposed to be harmless in case of a plain ASCII string... $sAuthUser = iconv('iso-8859-1', 'utf-8', $sAuthUser); } $sAuthPwd = $_SERVER['PHP_AUTH_PW']; if (!self::LooksLikeUTF8($sAuthPwd)) { // Does not look like and UTF-8 string, try to convert it from iso-8859-1 to UTF-8 // Supposed to be harmless in case of a plain ASCII string... $sAuthPwd = iconv('iso-8859-1', 'utf-8', $sAuthPwd); } $sLoginMode = 'basic'; } } break; case 'external': // Web server supplied authentication $bExternalAuth = false; $sExtAuthVar = MetaModel::GetConfig()->GetExternalAuthenticationVariable(); // In which variable is the info passed ? eval('$sAuthUser = isset(' . $sExtAuthVar . ') ? ' . $sExtAuthVar . ' : false;'); // Retrieve the value if ($sAuthUser && strlen($sAuthUser) > 0) { $sAuthPwd = ''; // No password in this case the web server already authentified the user... $sLoginMode = 'external'; $sAuthentication = 'external'; } break; case 'url': // Credentials passed directly in the url $sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data'); $sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data'); if ($sAuthUser != '' && $sAuthPwd !== null) { $sLoginMode = 'url'; } break; } $index++; } //echo "\nsLoginMode: $sLoginMode (user: $sAuthUser / pwd: $sAuthPwd\n)"; if ($sLoginMode == '') { // First connection $sDesiredLoginMode = utils::ReadParam('login_mode'); if (in_array($sDesiredLoginMode, $aAllowedLoginTypes)) { $sLoginMode = $sDesiredLoginMode; } else { $sLoginMode = $aAllowedLoginTypes[0]; // First in the list... } if (array_key_exists('HTTP_X_COMBODO_AJAX', $_SERVER)) { // X-Combodo-Ajax is a special header automatically added to all ajax requests // Let's reply that we're currently logged-out header('HTTP/1.0 401 Unauthorized'); exit; } if ($iOnExit == self::EXIT_HTTP_401 || $sLoginMode == 'basic') { header('WWW-Authenticate: Basic realm="' . Dict::Format('UI:iTopVersion:Short', ITOP_VERSION)); header('HTTP/1.0 401 Unauthorized'); header('Content-type: text/html; charset=iso-8859-1'); exit; } else { if ($iOnExit == self::EXIT_RETURN) { if ($sAuthUser !== '' && $sAuthPwd === null) { return self::EXIT_CODE_MISSINGPASSWORD; } else { return self::EXIT_CODE_MISSINGLOGIN; } } else { $oPage = self::NewLoginWebPage(); $oPage->DisplayLoginForm($sLoginMode, false); $oPage->output(); exit; } } } else { if (!UserRights::CheckCredentials($sAuthUser, $sAuthPwd, $sLoginMode, $sAuthentication)) { //echo "Check Credentials returned false for user $sAuthUser!"; self::ResetSession(); if ($iOnExit == self::EXIT_HTTP_401 || $sLoginMode == 'basic') { header('WWW-Authenticate: Basic realm="' . Dict::Format('UI:iTopVersion:Short', ITOP_VERSION)); header('HTTP/1.0 401 Unauthorized'); header('Content-type: text/html; charset=iso-8859-1'); exit; } else { if ($iOnExit == self::EXIT_RETURN) { return self::EXIT_CODE_WRONGCREDENTIALS; } else { $oPage = self::NewLoginWebPage(); $oPage->DisplayLoginForm($sLoginMode, true); $oPage->output(); exit; } } } else { // User is Ok, let's save it in the session and proceed with normal login UserRights::Login($sAuthUser, $sAuthentication); // Login & set the user's language if (MetaModel::GetConfig()->Get('log_usage')) { $oLog = new EventLoginUsage(); $oLog->Set('userinfo', UserRights::GetUser()); $oLog->Set('user_id', UserRights::GetUserObject()->GetKey()); $oLog->Set('message', 'Successful login'); $oLog->DBInsertNoReload(); } $_SESSION['auth_user'] = $sAuthUser; $_SESSION['login_mode'] = $sLoginMode; UserRights::_InitSessionCache(); } } } return self::EXIT_CODE_OK; }