diff --git a/code/web/public_php/login/class/ConnectionHandler.php b/code/web/public_php/login/class/ConnectionHandler.php new file mode 100644 index 000000000..d0886f841 --- /dev/null +++ b/code/web/public_php/login/class/ConnectionHandler.php @@ -0,0 +1,292 @@ +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(); + } + + private function askSalt($login, $lang) + { + setMsgLanguage($lang); + $escaped_login = $mysqli->escape_string($login); + $result = mysqli_query($link, $query) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); + if ($stmt = mysqli_prepare('SELECT TOP 1 Password FROM user WHERE Login=\'?\'')) { + $stmt->bind_param("s", $escaped_login); + $stmt->execute(); + $stmt->bind_result($password) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); + if ($stmt->num_rows == 1 && $stmt->fetch()) { + $salt = get_salt($password); + } else { + die(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 '1:' . askSalt($command->login, $command->submittedLang); + break; + case 'login-https': + $salt = askSalt($command->login, $command->submittedLang); + $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 TOP 1 domain_id FROM domain WHERE domain_name='?'")) { + $stmt->bind_param("s", $domainName); + $stmt->execute(); + $stmt->bind_result($result) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); + $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($result) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); + $stmt->fetch(); + $numrows = $stmt->num_rows; + $stmt->close(); + } + + if ($numrows >= 0) { + $row = $mysqli->fetch_assoc(); + $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 right to connect + if ($AcceptUnknownUser) { + // set an additionnal privilege for this player + $query = "UPDATE permission set AccessPrivilege='" . $permission['AccessPrivilege'] . ",$accessPriv' WHERE PermissionId=" . $permission['PermissionId']; + $result = mysqli_query($link, $query) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); + $reason = errorMsg(3012, $accessPriv); + } else { + // 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'); + } + } + $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/nel_command.php b/code/web/public_php/login/class/nel_command.php index da0754fb5..1641ee149 100644 --- a/code/web/public_php/login/class/nel_command.php +++ b/code/web/public_php/login/class/nel_command.php @@ -6,7 +6,7 @@ class NelCommand public $password; public $clientApplication; public $cp; - public $lg; + public $submittedLang; public function __construct($getParams) { diff --git a/code/web/public_php/login/r2_login.php b/code/web/public_php/login/r2_login.php index 94c83cc25..564ba9177 100755 --- a/code/web/public_php/login/r2_login.php +++ b/code/web/public_php/login/r2_login.php @@ -1,19 +1,5 @@ connect($DBHost, $DBUserName, $DBPassword, $DBName); $connection_handler->process_command($nel_command); - -// ---------------------------------------------------------------------------------------- -// Functions -// ---------------------------------------------------------------------------------------- - -function get_salt($password) -{ - return $password[0] == '$' ? substr($password, 0, 19) : substr($password, 0, 2); -} - -// see errorMsg -// $mixedArgsx -function errorMsgBlock($errNum = GENERIC_ERROR_NUM) -{ - return '0:' . call_user_func_array('errorMsg', func_get_args()); -} - -// Callback called on end of output buffering -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 -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 $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 - */ -function checkUserValidity($login, $password, $clientApplication, $cp, &$id, &$reason, &$priv, &$extended, &$domainId, $lang) -{ - global $DBHost; - global $DBUserName; - global $DBPassword; - global $DBName; - global $AcceptUnknownUser; - setMsgLanguage($lang); - $res = false; - $mysqli = new mysqli($DBHost, $DBUserName, $DBPassword) or die(errorMsgBlock(3004, 'main', $DBHost, $DBUserName)); - $mysqli->select_db($DBName) or die(errorMsgBlock(3005, 'main', $DBName, $DBHost, $DBUserName)); - $domainName = $mysqli->escape_string($clientApplication); - - $numrows = 0; - if ($stmt = $mysqli->prepare("SELECT TOP 1 domain_id FROM domain WHERE domain_name='?'")) { - $stmt->bind_param("s", $domainName); - $stmt->execute(); - $stmt->bind_result($result) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); - $stmt->fetch(); - $numrows = $stmt->num_rows; - $stmt->close(); - } - - if ($numrows == 0) { - // unrecoverable error, we must giveup - $reason = errorMsg(3007, $domainName); - $mysqli->close(); - return false; - } - - // 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($result) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); - $stmt->fetch(); - $numrows = $stmt->num_rows; - $stmt->close(); - } - - if ($numrows == 0) { - if ($AcceptUnknownUser) { - // login doesn't exist, create it - $escaped_password = $mysqli->escape_string($password); - $query = "INSERT INTO user (Login, Password) VALUES ('$login', '$escaped_password')"; - $result = mysqli_query($link, $query) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); - - // get the user to have his UId - $query = "SELECT * FROM user WHERE Login='$login'"; - $result = mysqli_query($link, $query) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); - - if (mysqli_num_rows($result) == 1) { - $reason = errorMsg(3008, $login); - $row = mysqli_fetch_assoc($result); - $id = $row["UId"]; - $priv = $row["Privilege"]; - $extended = $row["ExtendedPrivilege"]; - - // add the default permission - $query = "INSERT INTO permission (UId, DomainId, AccessPrivilege) VALUES ('$id', '$domainId', '$accessPriv')"; - $result = mysqli_query($link, $query) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); - - $res = false; - } else { - $reason = errorMsg(3009, $login); - $res = false; - } - } else { - $reason = errorMsg(2001, $login, 'checkUserValidity'); - } - } else { - $row = $mysqli->fetch_assoc(); - $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 right to connect - if ($AcceptUnknownUser) { - // set an additionnal privilege for this player - $query = "UPDATE permission set AccessPrivilege='" . $permission['AccessPrivilege'] . ",$accessPriv' WHERE PermissionId=" . $permission['PermissionId']; - $result = mysqli_query($link, $query) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); - $reason = errorMsg(3012, $accessPriv); - } else { - // 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'); - } - } - $mysqli->close(); - return $res; -} - -function askSalt($login, $lang) -{ - global $PHP_SELF; - global $DBHost, $DBUserName, $DBPassword, $DBName; - global $AcceptUnknownUser; - - setMsgLanguage($lang); - - $link = mysqli_connect($DBHost, $DBUserName, $DBPassword) or die(errorMsgBlock(3004, 'main', $DBHost, $DBUserName)); - mysqli_select_db($link, $DBName) or die(errorMsgBlock(3005, 'main', $DBName, $DBHost, $DBUserName)); - - $login = mysqli_real_escape_string($link, $login); - $query = "SELECT Password FROM user WHERE Login='$login'"; - $result = mysqli_query($link, $query) or die(errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); - - if (mysqli_num_rows($result) != 1) { - if ($AcceptUnknownUser) { - // just accept the client and return a default salk - echo "1:AA"; - die; - } else { - die(errorMsgBlock(2001, $login, 'askSalt')); - // Check if this is not an unconfirmed account - /*$query = "SELECT GamePassword, Language FROM signup_data WHERE login='$login'"; - $result = mysqli_query($link, $query) or die (errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysqli_error($link))); - - if (mysqli_num_rows($result) == 0) - { - // no user record, reject it - die (errorMsgBlock(2001, $login, 'askSalt')); - } - else if (mysqli_num_rows($result) == 1) - { - // one unconfirmed record, let the client send the encrypted password to get the corresponding email address - $row = mysqli_fetch_assoc($result); - $salt = substr($row['GamePassword'], 0, 2); - } - else - { - if ($lang == 'unknown') - { - // several matching records => display a multi-language message now - $languages = array(); - while ($row = mysqli_fetch_assoc($result)) - { - $languages[$row['Language']] = true; - } - setMsgLanguage(array_keys($languages)); - } - die (errorMsgBlock(2003)); - }*/ - } - } else { - $res_array = mysqli_fetch_assoc($result); - $salt = get_salt($res_array['Password']); - } - - mysqli_close($link); - return $salt; -}