Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
6.9 KiB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
  1. <?php
  2. require_once('include/security.php');
  3. require_once('include/datetime.php');
  4. // When the "Friendica" cookie is set, take the value to authenticate and renew the cookie.
  5. if (isset($_COOKIE["Friendica"])) {
  6. $data = json_decode($_COOKIE["Friendica"]);
  7. if (isset($data->uid)) {
  8. $r = q("SELECT `user`.*, `user`.`pubkey` as `upubkey`, `user`.`prvkey` as `uprvkey`
  9. FROM `user` WHERE `uid` = %d AND NOT `blocked` AND NOT `account_expired` AND NOT `account_removed` AND `verified` LIMIT 1",
  10. intval($data->uid)
  11. );
  12. if ($r) {
  13. if ($data->hash != cookie_hash($r[0])) {
  14. logger("Hash for user ".$data->uid." doesn't fit.");
  15. nuke_session();
  16. goaway(z_root());
  17. }
  18. // Renew the cookie
  19. new_cookie(604800, $r[0]);
  20. // Do the authentification if not done by now
  21. if (!isset($_SESSION) OR !isset($_SESSION['authenticated'])) {
  22. authenticate_success($r[0]);
  23. if (get_config('system','paranoia'))
  24. $_SESSION['addr'] = $data->ip;
  25. }
  26. }
  27. }
  28. }
  29. // login/logout
  30. if (isset($_SESSION) && x($_SESSION,'authenticated') && (!x($_POST,'auth-params') || ($_POST['auth-params'] !== 'login'))) {
  31. if ((x($_POST,'auth-params') && ($_POST['auth-params'] === 'logout')) || ($a->module === 'logout')) {
  32. // process logout request
  33. call_hooks("logging_out");
  34. nuke_session();
  35. info(t('Logged out.').EOL);
  36. goaway(z_root());
  37. }
  38. if (x($_SESSION,'visitor_id') && !x($_SESSION,'uid')) {
  39. $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1",
  40. intval($_SESSION['visitor_id'])
  41. );
  42. if (dbm::is_result($r)) {
  43. $a->contact = $r[0];
  44. }
  45. }
  46. if (x($_SESSION,'uid')) {
  47. // already logged in user returning
  48. $check = get_config('system','paranoia');
  49. // extra paranoia - if the IP changed, log them out
  50. if ($check && ($_SESSION['addr'] != $_SERVER['REMOTE_ADDR'])) {
  51. logger('Session address changed. Paranoid setting in effect, blocking session. '.
  52. $_SESSION['addr'].' != '.$_SERVER['REMOTE_ADDR']);
  53. nuke_session();
  54. goaway(z_root());
  55. }
  56. $r = q("SELECT `user`.*, `user`.`pubkey` as `upubkey`, `user`.`prvkey` as `uprvkey`
  57. FROM `user` WHERE `uid` = %d AND NOT `blocked` AND NOT `account_expired` AND NOT `account_removed` AND `verified` LIMIT 1",
  58. intval($_SESSION['uid'])
  59. );
  60. if (!dbm::is_result($r)) {
  61. nuke_session();
  62. goaway(z_root());
  63. }
  64. // Make sure to refresh the last login time for the user if the user
  65. // stays logged in for a long time, e.g. with "Remember Me"
  66. $login_refresh = false;
  67. if (!x($_SESSION['last_login_date'])) {
  68. $_SESSION['last_login_date'] = datetime_convert('UTC','UTC');
  69. }
  70. if (strcmp(datetime_convert('UTC','UTC','now - 12 hours'), $_SESSION['last_login_date']) > 0) {
  71. $_SESSION['last_login_date'] = datetime_convert('UTC','UTC');
  72. $login_refresh = true;
  73. }
  74. authenticate_success($r[0], false, false, $login_refresh);
  75. }
  76. } else {
  77. session_unset();
  78. if (x($_POST,'password') && strlen($_POST['password']))
  79. $encrypted = hash('whirlpool',trim($_POST['password']));
  80. else {
  81. if ((x($_POST,'openid_url')) && strlen($_POST['openid_url']) ||
  82. (x($_POST,'username')) && strlen($_POST['username'])) {
  83. $noid = get_config('system','no_openid');
  84. $openid_url = trim((strlen($_POST['openid_url'])?$_POST['openid_url']:$_POST['username']));
  85. // validate_url alters the calling parameter
  86. $temp_string = $openid_url;
  87. // if it's an email address or doesn't resolve to a URL, fail.
  88. if ($noid || strpos($temp_string,'@') || !validate_url($temp_string)) {
  89. $a = get_app();
  90. notice(t('Login failed.').EOL);
  91. goaway(z_root());
  92. // NOTREACHED
  93. }
  94. // Otherwise it's probably an openid.
  95. try {
  96. require_once('library/openid.php');
  97. $openid = new LightOpenID;
  98. $openid->identity = $openid_url;
  99. $_SESSION['openid'] = $openid_url;
  100. $openid->returnUrl = App::get_baseurl(true).'/openid';
  101. goaway($openid->authUrl());
  102. } catch (Exception $e) {
  103. notice(t('We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID.').'<br /><br >'.t('The error message was:').' '.$e->getMessage());
  104. }
  105. // NOTREACHED
  106. }
  107. }
  108. if (x($_POST,'auth-params') && $_POST['auth-params'] === 'login') {
  109. $record = null;
  110. $addon_auth = array(
  111. 'username' => trim($_POST['username']),
  112. 'password' => trim($_POST['password']),
  113. 'authenticated' => 0,
  114. 'user_record' => null
  115. );
  116. /**
  117. *
  118. * A plugin indicates successful login by setting 'authenticated' to non-zero value and returning a user record
  119. * Plugins should never set 'authenticated' except to indicate success - as hooks may be chained
  120. * and later plugins should not interfere with an earlier one that succeeded.
  121. *
  122. */
  123. call_hooks('authenticate', $addon_auth);
  124. if ($addon_auth['authenticated'] && count($addon_auth['user_record']))
  125. $record = $addon_auth['user_record'];
  126. else {
  127. // process normal login request
  128. $r = q("SELECT `user`.*, `user`.`pubkey` as `upubkey`, `user`.`prvkey` as `uprvkey`
  129. FROM `user` WHERE (`email` = '%s' OR `nickname` = '%s')
  130. AND `password` = '%s' AND NOT `blocked` AND NOT `account_expired` AND NOT `account_removed` AND `verified` LIMIT 1",
  131. dbesc(trim($_POST['username'])),
  132. dbesc(trim($_POST['username'])),
  133. dbesc($encrypted)
  134. );
  135. if (dbm::is_result($r))
  136. $record = $r[0];
  137. }
  138. if (!$record || !count($record)) {
  139. logger('authenticate: failed login attempt: '.notags(trim($_POST['username'])).' from IP '.$_SERVER['REMOTE_ADDR']);
  140. notice(t('Login failed.').EOL);
  141. goaway(z_root());
  142. }
  143. // If the user specified to remember the authentication, then set a cookie
  144. // that expires after one week (the default is when the browser is closed).
  145. // The cookie will be renewed automatically.
  146. // The week ensures that sessions will expire after some inactivity.
  147. if ($_POST['remember'])
  148. new_cookie(604800, $r[0]);
  149. else
  150. new_cookie(0); // 0 means delete on browser exit
  151. // if we haven't failed up this point, log them in.
  152. $_SESSION['last_login_date'] = datetime_convert('UTC','UTC');
  153. authenticate_success($record, true, true);
  154. }
  155. }
  156. /**
  157. * @brief Kills the "Friendica" cookie and all session data
  158. */
  159. function nuke_session() {
  160. new_cookie(-3600); // make sure cookie is deleted on browser close, as a security measure
  161. session_unset();
  162. session_destroy();
  163. }
  164. /**
  165. * @brief Calculate the hash that is needed for the "Friendica" cookie
  166. *
  167. * @param array $user Record from "user" table
  168. *
  169. * @return string Hashed data
  170. */
  171. function cookie_hash($user) {
  172. return(hash("sha256", get_config("system", "site_prvkey").
  173. $user["uprvkey"].
  174. $user["password"]));
  175. }
  176. /**
  177. * @brief Set the "Friendica" cookie
  178. *
  179. * @param int $time
  180. * @param array $user Record from "user" table
  181. */
  182. function new_cookie($time, $user = array()) {
  183. if ($time != 0)
  184. $time = $time + time();
  185. if ($user)
  186. $value = json_encode(array("uid" => $user["uid"],
  187. "hash" => cookie_hash($user),
  188. "ip" => $_SERVER['REMOTE_ADDR']));
  189. else
  190. $value = "";
  191. setcookie("Friendica", $value, $time, "/", "",
  192. (get_config('system', 'ssl_policy') == SSL_POLICY_FULL), true);
  193. }