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.

211 lines
6.3KB

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