PageRenderTime 149ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/code/ryzom/tools/server/www/login/r2_login.php

https://bitbucket.org/Krolock/ryzom-contribution
PHP | 534 lines | 344 code | 61 blank | 129 comment | 62 complexity | 505d9a07e74635ed8977959d5ecf5b55 MD5 | raw file
Possible License(s): AGPL-3.0, GPL-3.0, LGPL-2.1
  1. <?php
  2. error_reporting(E_ERROR | E_PARSE);
  3. set_error_handler('err_callback');
  4. // For error handling, buffer all output
  5. ob_start('ob_callback_r2login');
  6. include_once('config.php');
  7. include_once('login_translations.php');
  8. include_once('../tools/nel_message.php');
  9. include_once('../tools/domain_info.php');
  10. include_once('login_service_itf.php');
  11. include_once('../ring/join_shard.php');
  12. // see errorMsg
  13. function errorMsgBlock($errNum=GENERIC_ERROR_NUM) // $mixedArgs
  14. {
  15. $args = func_get_args();
  16. return '0:'.call_user_func_array('errorMsg', $args);
  17. }
  18. class LoginCb extends CLoginServiceWeb
  19. {
  20. // receive the login result sent back by the LS
  21. function loginResult($userId, $cookie, $resultCode, $errorString)
  22. {
  23. global $RingWebHost, $RingWebHostPHP;
  24. global $domainId;
  25. if ($resultCode == 0 && $cookie != "")
  26. {
  27. // gather the domain informations (server version, patch urls and backup patch url
  28. global $DBHost, $DBUserName, $DBPassword, $DBName, $AutoInsertInRing;
  29. $link = mysql_connect($DBHost, $DBUserName, $DBPassword) or die (errorMsgBlock(3004, 'main', $DBHost, $DBUserName));
  30. mysql_select_db ($DBName) or die (errorMsgBlock(3005, 'main', $DBName, $DBHost, $DBUserName));
  31. $query = "SELECT * FROM domain WHERE domain_id=$domainId";
  32. $result = mysql_query ($query) or die (errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysql_error()));
  33. if( mysql_num_rows($result) != 1)
  34. {
  35. die(errorMsgBlock(3001, $domainId));
  36. }
  37. $row = mysql_fetch_array($result);
  38. // set the cookie
  39. setcookie ( "ryzomId" , $cookie, 0, "/");
  40. $_COOKIE["ryzomId"] = $cookie; // make it available immediately
  41. // Auto-join an available mainland shard
  42. global $FSHostLuaMode, $FSHostResultStr;
  43. $FSHostLuaMode = false;
  44. $res = joinMainland($userId, $domainId, $row["domain_name"]);
  45. if ($res)
  46. {
  47. // return the cookie to the user, il will then be used as an auth to browse the site and to connect to the shard
  48. //echo "1#".$cookie."#http://".$RingWebHost."/ring/web_start.php\n";
  49. // use this line to use woopra stats
  50. // echo "1#".$cookie."#".$FSHostResultStr."#http://".$RingWebHost."/ring/web_start.php#http://".$RingWebHostPHP."/ring/#1\n";
  51. echo "1#".$cookie."#".$FSHostResultStr."#http://".$RingWebHost."/ring/web_start.php#http://".$RingWebHostPHP."/ring/\n";
  52. // return the ring domain information
  53. echo $row["patch_version"]."#".$row["backup_patch_url"]."#".$row["patch_urls"];
  54. }
  55. else
  56. {
  57. global $JoinSessionResultCode, $JoinSessionResultMsg;
  58. echo errorMsgBlock(BASE_TRANSLATED_RSM_ERROR_NUM + $JoinSessionResultCode, $JoinSessionResultCode, $JoinSessionResultMsg, $userId);
  59. }
  60. }
  61. else
  62. {
  63. // empty cookie, this mean the user id can't be validated by the LS
  64. echo errorMsgBlock(BASE_TRANSLATED_LS_ERROR_NUM + $resultCode, $resultCode, $errorString, $userId);
  65. }
  66. }
  67. }
  68. class CWwwLog
  69. {
  70. //function CWwwLog() {}
  71. /*
  72. * Return the log directory. Create it if it does not exist, or return false if creation failed.
  73. */
  74. function getSafeLogDir()
  75. {
  76. // Examples:
  77. // __FILE__ = r:\code\ryzom\www\login\config.php
  78. // $_SERVER['PATH_TRANSLATED'] = 'r:/code/ryzom/www/login//r2_login.php'
  79. // $_SERVER['SCRIPT_FILENAME'] = 'r:/code/ryzom/www/login//r2_login.php'
  80. global $LogRelativePath;
  81. $pathInfo = pathinfo(__FILE__);
  82. $logPath = $pathInfo['dirname'].'/'.$LogRelativePath;
  83. if (!is_dir($logPath))
  84. {
  85. $res = mkdir($LogPath, 0700);
  86. return $res ? $logPath : false;
  87. }
  88. return $logPath;
  89. }
  90. function logStr($str)
  91. {
  92. $logPath = $this->getSafeLogDir();
  93. if ($logPath !== false)
  94. {
  95. $fp = fopen($logPath.'/r2_login_'.date('Y-m-d').'.log', 'a');
  96. fwrite($fp, date('Y-m-d H:i:s').' ('.$_SERVER['REMOTE_ADDR'].':'.$_SERVER['REQUEST_URI']."): $str\n");
  97. fclose($fp);
  98. }
  99. }
  100. }
  101. // Callback called on end of output buffering
  102. function ob_callback_r2login($buffer)
  103. {
  104. // Log only in case of error or malformed result string
  105. $blockHd = substr($buffer, 0, 2);
  106. if ($blockHd != '1:')
  107. {
  108. $logFile = new CWwwLog();
  109. $logFile->logStr(str_replace("\n",'\n',$buffer));
  110. }
  111. return $buffer; // sent to output
  112. }
  113. // Callback called on error
  114. function err_callback($errno, $errmsg, $filename, $linenum, $vars)
  115. {
  116. $logFile = new CWwwLog();
  117. $logFile->logStr("PHP ERROR/$errno $errmsg ($filename:$linenum)");
  118. // Never die after an error
  119. }
  120. if (!isset($_GET['cmd']))
  121. {
  122. die (errorMsgBlock(3002));
  123. }
  124. // check for 'clear password' tag
  125. if (!isset($_GET['cp']))
  126. {
  127. $cp = 0;
  128. }
  129. else
  130. {
  131. $cp = $_GET['cp'];
  132. }
  133. $submittedLang = isset($_GET['lg']) ? $_GET['lg'] : 'unknown';
  134. if (isset($_GET['dbg']) && ($_GET['dbg'] == 1))
  135. $DisplayDbg = true;
  136. switch($_GET['cmd'])
  137. {
  138. case 'ask':
  139. // client ask for a login salt
  140. askSalt($_GET['login'], $submittedLang);
  141. die();
  142. case 'login':
  143. $domainId = -1;
  144. // client sent is login info
  145. if (!checkUserValidity($_GET['login'], $_GET['password'], $_GET['clientApplication'], $cp, $id, $reason, $priv, $extended, $domainId, $submittedLang))
  146. {
  147. echo '0:'.$reason;
  148. }
  149. else
  150. {
  151. // retreive the domain info
  152. $domainInfo = getDomainInfo($domainId);
  153. // if we need to create missing ring info
  154. if ($AutoCreateRingInfo)
  155. {
  156. ////////////// Temporary code alpha 0 only /////////////////////////////////////
  157. // check if the ring user exist, and create it if not
  158. $ringDb = mysql_connect($DBHost, $RingDBUserName, $RingDBPassword) or die(errorMsgBlock(3004, 'Ring', $DBHost, $RingDBUserName));
  159. mysql_select_db ($domainInfo['ring_db_name'], $ringDb) or die(errorMsgBlock(3005, 'Ring', $domainInfo['ring_db_name'], $DBHost, $RingDBUserName));
  160. $query = "SELECT user_id FROM ring_users where user_id = '".$id."'";
  161. $result = mysql_query ($query) or die(errorMsgBlock(3006, $query, 'Ring', $domainInfo['ring_db_name'], $DBHost, $RingDBUserName, mysql_error()));
  162. if (mysql_num_rows($result) == 0)
  163. {
  164. // no ring user record, build one
  165. $query = "INSERT INTO ring_users SET user_id = '".$id."', user_name = '".$_GET["login"]."', user_type='ut_pioneer'";
  166. $result = mysql_query ($query) or die(errorMsgBlock(3006, $query, 'Ring', $domainInfo['ring_db_name'], $DBHost, $RingDBUserName, mysql_error()));
  167. }
  168. // // check that there is a character record (deprecated)
  169. // $query = "SELECT user_id FROM characters where user_id = '".$id."'";
  170. // $result = mysql_query ($query) or die("Query ".$query." failed");
  171. // if (mysql_num_rows($result) == 0)
  172. // {
  173. // // no characters record, build a default one
  174. // $charId = ($id * 16);
  175. // $query = "INSERT INTO characters SET char_id='".$charId."', char_name='".$_GET["login"]."_default', user_id = '".$id."'";
  176. // $result = mysql_query ($query) or die("Query ".$query." failed");
  177. // }
  178. }
  179. // // check domain status
  180. // if ($domainInfo['status'] == "ds_close")
  181. // {
  182. // // the domain is closed
  183. // echo "0:Server is currently closed";
  184. // die;
  185. // }
  186. // else if ($domainInfo['status'] == "ds_dev" && strstr($priv, ":DEV:") == false)
  187. // {
  188. // // the domain is open to dev only
  189. // echo "0:You are not allowed to connect now, retry later";
  190. // die;
  191. // }
  192. // else if ($domainInfo['status'] == "ds_restricted")
  193. // {
  194. // // check for one of the needed privilege
  195. // if ( strstr($priv, ":DEV:") == false
  196. // && strstr($priv, ":SGM:") == false
  197. // && strstr($priv, ":GM:") == false
  198. // && strstr($priv, ":EG:") == false)
  199. // {
  200. // // the domain is open to privileged user only
  201. // echo "0:You are not allowed to connect now, retry later";
  202. // die;
  203. // }
  204. // }
  205. // store the web host for this domain
  206. global $RingWebHost, $RingWebHostPHP;
  207. $RingWebHost = $domainInfo['web_host'];
  208. $RingWebHostPHP = $domainInfo['web_host_php'];
  209. $LSaddr = split(":", $domainInfo['login_address']);
  210. // ask for a session cookie to the login service
  211. $login = new LoginCb;
  212. $res = "";
  213. $login->connect($LSaddr[0], $LSaddr[1], $res);
  214. // $lsProxy = new CLoginServiceWebProxy;
  215. $login->login($id, $_SERVER["REMOTE_ADDR"], $domainId);
  216. // wait for the return message
  217. // $lsSkel = new CLoginServiceWebSkel;
  218. if (!$login->waitCallback())
  219. {
  220. die(errorMsgBlock(3003));
  221. }
  222. //the rest of the process is done in the callback function
  223. }
  224. }
  225. // no more to do (other global statement are old garbage)
  226. die();
  227. // ----------------------------------------------------------------------------------------
  228. // Functions
  229. // ----------------------------------------------------------------------------------------
  230. // $reason contains the reason why the check failed or success
  231. // return true if the check is ok
  232. function checkUserValidity ($login, $password, $clientApplication, $cp, &$id, &$reason, &$priv, &$extended, &$domainId, $lang)
  233. {
  234. global $DBHost, $DBUserName, $DBPassword, $DBName, $AcceptUnknownUser;
  235. setMsgLanguage($lang);
  236. // we map the client application to the domain name
  237. $domainName = $clientApplication;
  238. $link = mysql_connect($DBHost, $DBUserName, $DBPassword) or die (errorMsgBlock(3004, 'main', $DBHost, $DBUserName));
  239. mysql_select_db ($DBName) or die (errorMsgBlock(3005, 'main', $DBName, $DBHost, $DBUserName));
  240. // retreive the domain id
  241. $query = "SELECT domain_id FROM domain WHERE domain_name='$domainName'";
  242. $result = mysql_query ($query) or die (errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysql_error()));
  243. if (mysql_num_rows($result) == 0)
  244. {
  245. // unrecoverable error, we must giveup
  246. $reason = errorMsg(3007, $domainName);
  247. mysql_close($link);
  248. return false;
  249. }
  250. $row = mysql_fetch_array($result);
  251. $domainId = $row[0];
  252. // retreive the domain info
  253. $domainInfo = getDomainInfo($domainId);
  254. // convert the domain status enum into the privilege access set
  255. $accessPriv = strtoupper(substr($domainInfo['status'], 3));
  256. // now, retrieve the user infos
  257. $query = "SELECT * FROM user where Login='$login'";
  258. $result = mysql_query ($query) or die (errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysql_error()));
  259. if (mysql_num_rows ($result) == 0)
  260. {
  261. if ($AcceptUnknownUser)
  262. {
  263. // login doesn't exist, create it
  264. $query = "INSERT INTO user (Login, Password) VALUES ('$login', '$password')";
  265. $result = mysql_query ($query) or die (errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysql_error()));
  266. // get the user to have his UId
  267. $query = "SELECT * FROM user WHERE Login='$login'";
  268. $result = mysql_query ($query) or die (errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysql_error()));
  269. if (mysql_num_rows ($result) == 1)
  270. {
  271. $reason = errorMsg(3008, $login);
  272. $row = mysql_fetch_array ($result);
  273. $id = $row["UId"];
  274. $priv = $row["Privilege"];
  275. $extended = $row["ExtendedPrivilege"];
  276. // add the default permission
  277. $query = "INSERT INTO permission (UId, ClientApplication, AccessPrivilege) VALUES ('$id', 'r2', '$accessPriv')";
  278. $result = mysql_query ($query) or die (errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysql_error()));
  279. $res = false;
  280. }
  281. else
  282. {
  283. $reason = errorMsg(3009, $login);
  284. $res = false;
  285. }
  286. }
  287. else
  288. {
  289. // Check if this is not an unconfirmed account
  290. $query = "SELECT GamePassword, Email, Language FROM signup_data WHERE login='$login'";
  291. $result = mysql_query($query) or die (errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysql_error()));
  292. if (mysql_num_rows($result) == 0)
  293. {
  294. $reason = errorMsg(2001, $login, 'checkUserValidity');
  295. $res = false;
  296. }
  297. else
  298. {
  299. // Check password to avoid revealing email address to third-party
  300. $passwordMatchedRow = false;
  301. while ($row = mysql_fetch_array($result))
  302. {
  303. $salt = substr($row['GamePassword'],0,2);
  304. if (($cp && $row['GamePassword'] == $password) || (!$cp && $row['GamePassword'] == crypt($password, $salt)))
  305. {
  306. $passwordMatchedRow = $row;
  307. break;
  308. }
  309. }
  310. if ($passwordMatchedRow !== false)
  311. {
  312. if ($lang == 'unknown')
  313. setMsgLanguage($passwordMatchedRow['Language']);
  314. $reason = errorMsg(2002, $passwordMatchedRow['Email']);
  315. }
  316. else
  317. $reason = errorMsg(2004, 'db signup_data');
  318. $res = false;
  319. }
  320. }
  321. }
  322. else
  323. {
  324. $row = mysql_fetch_array ($result);
  325. $salt = substr($row["Password"],0,2);
  326. if (($cp && $row["Password"] == $password) || (!$cp && $row["Password"] == crypt($password, $salt)))
  327. {
  328. // Store the real login (with correct case)
  329. $_GET['login'] = $row['Login'];
  330. // check if the user can use this application
  331. $query = "SELECT * FROM permission WHERE UId='".$row["UId"]."' AND ClientApplication='$clientApplication'";
  332. $result = mysql_query ($query) or die (errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysql_error()));
  333. if (mysql_num_rows ($result) == 0)
  334. {
  335. if ($AcceptUnknownUser)
  336. {
  337. // add default permission
  338. $query = "INSERT INTO permission (UId, ClientApplication, ShardId, AccessPrivilege) VALUES ('".$row["UId"]."', '$clientApplication', -1, '$domainStatus')";
  339. $result = mysql_query ($query) or die (errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysql_error()));
  340. $reason = errorMsg(3010);
  341. $res = false;
  342. }
  343. else
  344. {
  345. // no permission
  346. $reason = errorMsg(3011, $clientApplication, $domainName);
  347. $res = false;
  348. }
  349. }
  350. else
  351. {
  352. // check that the access privilege for the domain
  353. $permission = mysql_fetch_array($result);
  354. if (!strstr($permission['AccessPrivilege'], $accessPriv))
  355. {
  356. // no right to connect
  357. if ($AcceptUnknownUser)
  358. {
  359. // set an additionnal privilege for this player
  360. $query = "UPDATE permission set AccessPrivilege='".$permission['AccessPrivilege'].",$accessPriv' WHERE prim=".$permission['prim'];
  361. $result = mysql_query ($query) or die (errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysql_error()));
  362. $reason = errorMsg(3012, $accessPriv);
  363. $res = false;
  364. }
  365. else
  366. {
  367. // no permission
  368. $reason = errorMsg(3013, $clientApplication, $domainName, $accessPriv);
  369. $res = false;
  370. }
  371. }
  372. else
  373. {
  374. // // check if the user not already online
  375. //
  376. // if ($row["State"] != "Offline")
  377. // {
  378. // $reason = "$login is already online and ";
  379. // // ask the LS to remove the client
  380. // if (disconnectClient ($row["ShardId"], $row["UId"], $tempres))
  381. // {
  382. // $reason = $reason."was just disconnected. Now you can retry the identification (error code 54)";
  383. //
  384. // $query = "update shard set NbPlayers=NbPlayers-1 where ShardId=".$row["ShardId"];
  385. // $result = mysql_query ($query) or die ("Can't execute the query: '$query' errno:".mysql_errno().": ".mysql_error());
  386. //
  387. // $query = "update user set ShardId=-1, State='Offline' where UId=".$row["UId"];
  388. // $result = mysql_query ($query) or die ("Can't execute the query: '$query' errno:".mysql_errno().": ".mysql_error());
  389. // }
  390. // else
  391. // {
  392. // $reason = $reason."can't be disconnected: $tempres (error code 55)";
  393. // }
  394. // $res = false;
  395. // }
  396. // else
  397. // {
  398. $id = $row["UId"];
  399. $priv = $row["Privilege"];
  400. $extended = $row["ExtendedPrivilege"];
  401. $res = true;
  402. // }
  403. }
  404. }
  405. }
  406. else
  407. {
  408. $reason = errorMsg(2004, 'user');
  409. $res = false;
  410. }
  411. }
  412. mysql_close($link);
  413. return $res;
  414. }
  415. function askSalt($login, $lang)
  416. {
  417. global $PHP_SELF;
  418. global $DBHost, $DBUserName, $DBPassword, $DBName;
  419. global $AcceptUnknownUser;
  420. setMsgLanguage($lang);
  421. $link = mysql_connect($DBHost, $DBUserName, $DBPassword) or die (errorMsgBlock(3004, 'main', $DBHost, $DBUserName));
  422. mysql_select_db ($DBName) or die (errorMsgBlock(3005, 'main', $DBName, $DBHost, $DBUserName));
  423. $query = "SELECT Password FROM user WHERE Login='$login'";
  424. $result = mysql_query ($query) or die (errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysql_error()));
  425. if (mysql_num_rows ($result) != 1)
  426. {
  427. if ($AcceptUnknownUser)
  428. {
  429. // just accept the client and return a default salk
  430. echo "1:AA";
  431. die;
  432. }
  433. else
  434. {
  435. // Check if this is not an unconfirmed account
  436. $query = "SELECT GamePassword, Language FROM signup_data WHERE login='$login'";
  437. $result = mysql_query($query) or die (errorMsgBlock(3006, $query, 'main', $DBName, $DBHost, $DBUserName, mysql_error()));
  438. if (mysql_num_rows($result) == 0)
  439. {
  440. // no user record, reject it
  441. die (errorMsgBlock(2001, $login, 'askSalt'));
  442. }
  443. else if (mysql_num_rows($result) == 1)
  444. {
  445. // one unconfirmed record, let the client send the encrypted password to get the corresponding email address
  446. $row = mysql_fetch_array($result);
  447. $salt = substr($row['GamePassword'], 0, 2);
  448. }
  449. else
  450. {
  451. if ($lang == 'unknown')
  452. {
  453. // several matching records => display a multi-language message now
  454. $languages = array();
  455. while ($row = mysql_fetch_array($result))
  456. {
  457. $languages[$row['Language']] = true;
  458. }
  459. setMsgLanguage(array_keys($languages));
  460. }
  461. die (errorMsgBlock(2003));
  462. }
  463. }
  464. }
  465. else
  466. {
  467. $res_array = mysql_fetch_array($result);
  468. $salt = substr($res_array['Password'], 0, 2);
  469. }
  470. echo "1:".$salt;
  471. mysql_close($link);
  472. }
  473. ?>