diff --git a/code/web/public_php/login/class/ConnectionHandler.php b/code/web/public_php/login/class/ConnectionHandler.php deleted file mode 100644 index 2b14e21a8..000000000 --- a/code/web/public_php/login/class/ConnectionHandler.php +++ /dev/null @@ -1,283 +0,0 @@ -db_Connection = new mysqli($dbhost, $dbusername, $dbpassword) or die(errorMsgBlock(3004, 'main', $DBHost, $DBUserName)); - $this->db_Connection->select_db($dbname) or die(errorMsgBlock(3005, 'main', $dbname, $dbhost, $dbusername)); - } - - public function __destruct() - { - if ($this->db_Connection != null) { - $this->db_Connection->close(); - } - } - - private function askSalt($login, $lang) - { - setMsgLanguage($lang); - $escaped_login = $this->db_Connection->escape_string($login); - if ($stmt = $this->db_Connection->prepare('SELECT Password FROM user WHERE Login=\'?\' LIMIT 1')) { - $stmt->bind_param("s", $escaped_login); - $stmt->execute(); - $stmt->bind_result($password) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, $this->db_Connection->error)); - if ($stmt->fetch() && $stmt->num_rows == 1) { - $salt = '1:' . get_salt($password); - } else { - $salt = errorMsgBlock(2001, $login, 'askSalt'); - } - $stmt->close(); - } - return $salt; - } - - private function Login($login, $password, $clientApplication, $cp, $submittedLang) - { - $res = false; - $domainId = -1; - // client sent is login info - if (!checkUserValidity($login, $password, $clientApplication, $cp, $id, $reason, $priv, $extended, $domainId, $submittedLang)) { - echo '0:' . $reason; - } else { - - // retreive the domain info - $domainInfo = getDomainInfo($domainId); - - // if we need to create missing ring info - if ($AutoCreateRingInfo) { - // check if the ring user exist, and create it if not - $ringDb = mysqli_connect($DBHost, $RingDBUserName, $RingDBPassword) or die(errorMsgBlock(3004, 'Ring', $DBHost, $RingDBUserName)); - mysqli_select_db($ringDb, $domainInfo['ring_db_name']) or die(errorMsgBlock(3005, 'Ring', $domainInfo['ring_db_name'], $DBHost, $RingDBUserName)); - $query = "SELECT user_id FROM ring_users where user_id = '" . $id . "'"; - $result = mysqli_query($ringDb, $query) or die(errorMsgBlock(3006, $query, 'Ring', $domainInfo['ring_db_name'], $DBHost, $RingDBUserName, mysqli_error($ringDb))); - - if (mysqli_num_rows($result) == 0) { - // no ring user record, build one - $login = mysqli_real_escape_string($ringDb, $_GET['login']); - $query = "INSERT INTO ring_users SET user_id = '$id', user_name = '$login', user_type='ut_pioneer'"; - $result = mysqli_query($ringDb, $query) or die(errorMsgBlock(3006, $query, 'Ring', $domainInfo['ring_db_name'], $DBHost, $RingDBUserName, mysqli_error($ringDb))); - } - } - - // store the web host for this domain - global $RingWebHost, $RingWebHostPHP; - $RingWebHost = $domainInfo['web_host']; - $RingWebHostPHP = $domainInfo['web_host_php']; - - $LSaddr = explode(":", $domainInfo['login_address']); - - // ask for a session cookie to the login service - $login = new LoginCb; - $res = ""; - $login->connect($LSaddr[0], $LSaddr[1], $res); - $login->login($id, $_SERVER["REMOTE_ADDR"], $domainId); - - // wait for the return message - if (!$login->waitCallback()) { - die(errorMsgBlock(3003)); - } - //the rest of the process is done in the callback function - } - } - - /** - * @param NelCommand - * the command you got from the client - */ - public function process_command($command) - { - switch ($command->cmd) { - case 'ask': - echo askSalt($command->login, $command->submittedLang); - break; - case 'login-https': - $salt = substr(askSalt($command->login, $command->submittedLang), 2); - $generated_password = crypt($command->password, sprintf('$6$rounds=%d$%s$', 5000, $salt)); - login($command->login, $generated_password, $command->clientApplication, $command->cp, $command->submittedLang); - break; - case 'login': - login($command->login, $command->password, $command->clientApplication, $command->cp, $command->submittedLang); - break; - default: - break; - } - } - - /** - * @param string $login - * The user login. - * @todo: This should become the password. - * @param string $password - * The user's password. - * @param string $clientApplication - * @param ? $cp - * @param int $id - * @param string $id - * @param string $priv - * @param string $extended - * @param string $domainId - * @param string $lang - * @return true if the User is valid - */ - public function checkUserValidity($login, $password, $clientApplication, $cp, &$id, &$reason, &$priv, &$extended, &$domainId, $lang) - { - $res = false; - setMsgLanguage($lang); - $domainName = $mysqli->escape_string($clientApplication); - - if ($stmt = $mysqli->prepare('SELECT domain_id FROM domain WHERE domain_name=\'?\' LIMIT 1')) { - $stmt->bind_param("s", $domainName); - $stmt->execute(); - $stmt->bind_result($result) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, $db_Connection->error)); - $stmt->fetch(); - if ($stmt->num_rows == 0) { - // unrecoverable error, we must giveup - $reason = errorMsg(3007, $domainName); - $mysqli->close(); - return $res; - } - $stmt->close(); - } - - // retrieve the domain info - $domainInfo = getDomainInfo($domainId); - - // convert the domain status enum into the privilege access set - $accessPriv = strtoupper(substr($domainInfo['status'], 3)); - - // now, retrieve the user infos - $login = $mysqli->escape_string($login); - $numrows = 0; - if ($stmt = mysqli_prepare("SELECT 1 FROM user WHERE Login='?'")) { - $stmt->bind_param("s", $login); - $stmt->execute(); - $stmt->bind_result($row) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); - $stmt->fetch(); - if ($stmt->num_rows) { - $salt = get_salt($row["Password"]); - if (($cp && $row["Password"] == $password) || (!$cp && $row["Password"] == crypt($password, $salt))) { - // Store the real login (with correct case) - $_GET['login'] = $row['Login']; - // check if the user can use this application - - $clientApplication = mysqli_real_escape_string($link, $clientApplication); - $query = "SELECT * FROM permission WHERE UId='" . $row["UId"] . "' AND DomainId='$domainId'"; - $result = mysqli_query($link, $query) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); - if (mysqli_num_rows($result) == 0) { - if ($AcceptUnknownUser) { - // add default permission - $query = "INSERT INTO permission (UId, DomainId, ShardId, AccessPrivilege) VALUES ('" . $row["UId"] . "', '$domainId', -1, '$domainStatus')"; - $result = mysqli_query($link, $query) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); - - $reason = errorMsg(3010); - $res = false; - } else { - // no permission - $reason = errorMsg(3011, $clientApplication, $domainName); - $res = false; - } - } else { - // check that the access privilege for the domain - $permission = mysqli_fetch_assoc($result); - - if (!strstr($permission['AccessPrivilege'], $accessPriv)) { - // no permission - $reason = errorMsg(3013, $clientApplication, $domainName, $accessPriv); - } else { - // // check if the user not already online - // if ($row["State"] != "Offline") { - // $reason = "$login is already online and "; - // // ask the LS to remove the client - // if (disconnectClient($row["ShardId"], $row["UId"], $tempres)) { - // $reason = $reason . "was just disconnected. Now you can retry the identification (error code 54)"; - - // $query = "update shard set NbPlayers=NbPlayers-1 where ShardId=" . $row["ShardId"]; - // $result = mysqli_query($link, $query) or die("Can't execute the query: '$query' errno:" . mysqli_errno($link) . ": " . mysqli_error($link)); - - // $query = "update user set ShardId=-1, State='Offline' where UId=" . $row["UId"]; - // $result = mysqli_query($link, $query) or die("Can't execute the query: '$query' errno:" . mysqli_errno($link) . ": " . mysqli_error($link)); - // } else { - // $reason = $reason . "can't be disconnected: $tempres (error code 55)"; - // } - // $res = false; - // } else { - $id = $row["UId"]; - $priv = $row["Privilege"]; - $extended = $row["ExtendedPrivilege"]; - $res = true; - // } - } - } - } else { - $reason = errorMsg(2004, 'user'); - } - } - $stmt->close(); - } - - $mysqli->close(); - return $res; - } - - public function errorMsgBlock($errNum = GENERIC_ERROR_NUM) - { - return '0:' . call_user_func_array('errorMsg', func_get_args()); - } - - /** - * Callback called on end of output buffering - */ - public function ob_callback_r2login($buffer) - { - // Log only in case of error or malformed result string - $blockHd = substr($buffer, 0, 2); - if ($blockHd != '1:') { - $logFile = new CWwwLog(); - $logFile->logStr(str_replace("\n", '\n', $buffer)); - } - return $buffer; // sent to output - } - - // Callback called on error - public function err_callback($errno, $errmsg, $filename, $linenum, $vars) - { - $logFile = new CWwwLog(); - $logFile->logStr("PHP ERROR/$errno $errmsg ($filename:$linenum)"); - $logFile->logStr("PHP CALLSTACK/" . print_r(debug_backtrace(), true)); - // Never die after an error - } - - /** - * @param string - * the password to extract the salt from. - * @return string the salting prefix - */ - public function get_salt($password) - { - return $password[0] == '$' ? substr($password, 0, 19) : substr($password, 0, 2); - } -} diff --git a/code/web/public_php/login/class/connection_handler.php b/code/web/public_php/login/class/connection_handler.php index d3307dee9..fcb1b92b4 100644 --- a/code/web/public_php/login/class/connection_handler.php +++ b/code/web/public_php/login/class/connection_handler.php @@ -1,5 +1,19 @@ db_Connection = new mysqli($dbhost, $dbusername, $dbpassword) or die(errorMsgBlock(3004, 'main', $DBHost, $DBUserName)); + $this->db_Connection->select_db($dbname) or die(errorMsgBlock(3005, 'main', $dbname, $dbhost, $dbusername)); } public function __destruct() { - $db_Connection->close(); + if ($this->db_Connection != null) { + $this->db_Connection->close(); + } + } + + private function askSalt($login, $lang) + { + setMsgLanguage($lang); + $escaped_login = $this->db_Connection->escape_string($login); + if ($stmt = $this->db_Connection->prepare('SELECT Password FROM user WHERE Login=\'?\' LIMIT 1')) { + $stmt->bind_param('s', $escaped_login); + $stmt->execute(); + $stmt->bind_result($password) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, $this->db_Connection->error)); + $stmt->fetch(); + if ($stmt->num_rows == 1) { + $salt = '1:' . get_salt($password); + } else { + $salt = errorMsgBlock(2001, $login, 'askSalt'); + } + $stmt->close(); + } + return $salt; + } + + private function Login($login, $password, $clientApplication, $cp, $submittedLang) + { + $res = false; + $domainId = -1; + // Client sent his login info + if (checkUserValidity($login, $password, $clientApplication, $cp, $id, $reason, $priv, $extended, $domainId, $submittedLang)) { + echo '0:' . $reason; + } else { + + // retreive the domain info + $domainInfo = getDomainInfo($domainId); + + // if we need to create missing ring info + if ($AutoCreateRingInfo) { + // check if the ring user exist, and create it if not + $ringDb = mysqli_connect($DBHost, $RingDBUserName, $RingDBPassword) or die(errorMsgBlock(3004, 'Ring', $DBHost, $RingDBUserName)); + mysqli_select_db($ringDb, $domainInfo['ring_db_name']) or die(errorMsgBlock(3005, 'Ring', $domainInfo['ring_db_name'], $DBHost, $RingDBUserName)); + $query = "SELECT user_id FROM ring_users where user_id = '" . $id . "'"; + $result = mysqli_query($ringDb, $query) or die(errorMsgBlock(3006, $query, 'Ring', $domainInfo['ring_db_name'], $DBHost, $RingDBUserName, mysqli_error($ringDb))); + + if (mysqli_num_rows($result) == 0) { + // no ring user record, build one + $login = mysqli_real_escape_string($ringDb, $_GET['login']); + $query = "INSERT INTO ring_users SET user_id = '$id', user_name = '$login', user_type='ut_pioneer'"; + $result = mysqli_query($ringDb, $query) or die(errorMsgBlock(3006, $query, 'Ring', $domainInfo['ring_db_name'], $DBHost, $RingDBUserName, mysqli_error($ringDb))); + } + } + + // store the web host for this domain + global $RingWebHost, $RingWebHostPHP; + $RingWebHost = $domainInfo['web_host']; + $RingWebHostPHP = $domainInfo['web_host_php']; + + $LSaddr = explode(":", $domainInfo['login_address']); + + // ask for a session cookie to the login service + $login = new LoginCb; + $res = ""; + $login->connect($LSaddr[0], $LSaddr[1], $res); + $login->login($id, $_SERVER["REMOTE_ADDR"], $domainId); + + // wait for the return message + if (!$login->waitCallback()) { + die(errorMsgBlock(3003)); + } + //the rest of the process is done in the callback function + } } /** @@ -23,59 +113,167 @@ class ConnectionHandler { switch ($command->cmd) { case 'ask': - echo '1:' . askSalt($command->login, $command->lg); + echo askSalt($command->login, $command->submittedLang); break; case 'login-https': - $salt = askSalt($command->login, $command->lg); - crypt($command->password, sprintf('$6$rounds=%d$%s$', 5000, $salt)); + $salt = substr(askSalt($command->login, $command->submittedLang), 2); + $generated_password = crypt($command->password, sprintf('$6$rounds=%d$%s$', 5000, $salt)); + login($command->login, $generated_password, $command->clientApplication, $command->cp, $command->submittedLang); + break; case 'login': - $domainId = -1; - // client sent is login info - if (!checkUserValidity($_GET['login'], $_GET['password'], $_GET['clientApplication'], $cp, $id, $reason, $priv, $extended, $domainId, $submittedLang)) { - echo '0:' . $reason; - } else { - - // retreive the domain info - $domainInfo = getDomainInfo($domainId); - - // if we need to create missing ring info - if ($AutoCreateRingInfo) { - // check if the ring user exist, and create it if not - $ringDb = mysqli_connect($DBHost, $RingDBUserName, $RingDBPassword) or die(errorMsgBlock(3004, 'Ring', $DBHost, $RingDBUserName)); - mysqli_select_db($ringDb, $domainInfo['ring_db_name']) or die(errorMsgBlock(3005, 'Ring', $domainInfo['ring_db_name'], $DBHost, $RingDBUserName)); - $query = "SELECT user_id FROM ring_users where user_id = '" . $id . "'"; - $result = mysqli_query($ringDb, $query) or die(errorMsgBlock(3006, $query, 'Ring', $domainInfo['ring_db_name'], $DBHost, $RingDBUserName, mysqli_error($ringDb))); - - if (mysqli_num_rows($result) == 0) { - // no ring user record, build one - $login = mysqli_real_escape_string($ringDb, $_GET['login']); - $query = "INSERT INTO ring_users SET user_id = '$id', user_name = '$login', user_type='ut_pioneer'"; - $result = mysqli_query($ringDb, $query) or die(errorMsgBlock(3006, $query, 'Ring', $domainInfo['ring_db_name'], $DBHost, $RingDBUserName, mysqli_error($ringDb))); - } - } - - // store the web host for this domain - global $RingWebHost, $RingWebHostPHP; - $RingWebHost = $domainInfo['web_host']; - $RingWebHostPHP = $domainInfo['web_host_php']; - - $LSaddr = explode(":", $domainInfo['login_address']); - - // ask for a session cookie to the login service - $login = new LoginCb; - $res = ""; - $login->connect($LSaddr[0], $LSaddr[1], $res); - $login->login($id, $_SERVER["REMOTE_ADDR"], $domainId); - - // wait for the return message - if (!$login->waitCallback()) { - die(errorMsgBlock(3003)); - } - //the rest of the process is done in the callback function - } + login($command->login, $command->password, $command->clientApplication, $command->cp, $command->submittedLang); break; default: break; } } + + /** + * @param string $login + * The user login. + * @todo: This should become the password. + * @param string $password + * The user's password. + * @param string $clientApplication + * @param ? $cp + * @param int $id + * @param string $id + * @param string $priv + * @param string $extended + * @param string $domainId + * @param string $lang + * @return true if the User is valid + */ + public function checkUserValidity($login, $password, $clientApplication, $cp, &$id, &$reason, &$priv, &$extended, &$domainId, $lang) + { + $res = false; + setMsgLanguage($lang); + $domainName = $this->db_Connection->escape_string($clientApplication); + + if ($stmt = $this->db_Connection->prepare('SELECT domain_id FROM domain WHERE domain_name=\'?\' LIMIT 1')) { + $stmt->bind_param("s", $domainName); + $stmt->execute(); + $stmt->bind_result($domainId) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, $db_Connection->error)); + $stmt->fetch(); + if ($stmt->num_rows == 0) { + // unrecoverable error, we must giveup + $reason = errorMsg(3007, $domainName); + $mysqli->close(); + return $res; + } + $stmt->close(); + } + + // retrieve the domain info + $domainInfo = getDomainInfo($domainId); + + // convert the domain status enum into the privilege access set + $accessPriv = strtoupper(substr($domainInfo['status'], 3)); + + // now, retrieve the user infos + $login = $this->db_Connection->escape_string($login); + $numrows = 0; + if ($stmt = $this->db_Connection->prepare('SELECT Password, UId FROM user WHERE Login=\'?\' LIMIT 1')) { + $stmt->bind_param('s', $login); + $stmt->execute(); + $stmt->bind_result($dbPassword, $dbUid) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, $this->db_Connection->error)); + $stmt->fetch(); + if ($stmt->num_rows) { + $salt = get_salt($dbPassword); + if (($cp && $dbPassword == $password) || (!$cp && $dbPassword == crypt($password, $salt))) { + if ($stmt2 = $this->db_Connection->prepare('SELECT AccessPrivilege, Privilege, ExtendedPrivilege FROM permission WHERE UId=\'' . $dbUid . '\' AND DomainId=\'$domainId\'')) { + $stmt2->bind_param('i', $dbUid); + $stmt2->execute(); + $stmt2->bind_result($dbAccessPrivilege, $dbPrivilege, $dbExtendedPrivilege) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, $this->db_Connection->error)); + $stmt2->fetch(); + if ($stmt->num_rows == 0) { + // no permission + $reason = errorMsg(3011, $clientApplication, $domainName); + $res = false; + } else { + if (!strstr($dbAccessPrivilege, $accessPriv)) { + // no permission + $reason = errorMsg(3013, $clientApplication, $domainName, $accessPriv); + } else { + if (IsUserOnline()) { + + } else { + $id = $dbUid; + $priv = $dbPrivilege; + $extended = $dbExtendedPrivilege; + $res = true; + } + } + } + $stmt2->close(); + } + } else { + $reason = errorMsg(2004, 'user'); + } + } + $stmt->close(); + } + return $res; + } + + private function IsUserOnline() + { + return false; + // // check if the user not already online + // if ($row["State"] != "Offline") { + // $reason = "$login is already online and "; + // // ask the LS to remove the client + // if (disconnectClient($row["ShardId"], $row["UId"], $tempres)) { + // $reason = $reason . "was just disconnected. Now you can retry the identification (error code 54)"; + + // $query = "update shard set NbPlayers=NbPlayers-1 where ShardId=" . $row["ShardId"]; + // $result = mysqli_query($link, $query) or die("Can't execute the query: '$query' errno:" . mysqli_errno($link) . ": " . mysqli_error($link)); + + // $query = "update user set ShardId=-1, State='Offline' where UId=" . $row["UId"]; + // $result = mysqli_query($link, $query) or die("Can't execute the query: '$query' errno:" . mysqli_errno($link) . ": " . mysqli_error($link)); + // } else { + // $reason = $reason . "can't be disconnected: $tempres (error code 55)"; + // } + // $res = false; + // } + } + + public function errorMsgBlock($errNum = GENERIC_ERROR_NUM) + { + return '0:' . call_user_func_array('errorMsg', func_get_args()); + } + + /** + * Callback called on end of output buffering + */ + public function ob_callback_r2login($buffer) + { + // Log only in case of error or malformed result string + $blockHd = substr($buffer, 0, 2); + if ($blockHd != '1:') { + $logFile = new CWwwLog(); + $logFile->logStr(str_replace("\n", '\n', $buffer)); + } + return $buffer; // sent to output + } + + /** + * Callback called on error + */ + public function err_callback($errno, $errmsg, $filename, $linenum, $vars) + { + $logFile = new CWwwLog(); + $logFile->logStr('PHP ERROR/$errno $errmsg ($filename:$linenum)'); + $logFile->logStr('PHP CALLSTACK/' . print_r(debug_backtrace(), true)); + } + + /** + * @param string + * the password to extract the salt from. + * @return string the salting prefix + */ + public function get_salt($password) + { + return $password[0] == '$' ? substr($password, 0, 19) : substr($password, 0, 2); + } }