From 47ca5bbf715d36e46ffd9b88956315646c157b75 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 28 Aug 2018 20:44:39 +0000 Subject: [PATCH 01/19] Use item class instead of direct call --- mod/community.php | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/mod/community.php b/mod/community.php index 9c9fb43900..685eda6da0 100644 --- a/mod/community.php +++ b/mod/community.php @@ -11,6 +11,7 @@ use Friendica\Core\L10n; use Friendica\Core\PConfig; use Friendica\Database\DBA; use Friendica\Model\Contact; +use Friendica\Model\Item; function community_init(App $a) { @@ -227,19 +228,12 @@ function community_getitems($start, $itemspage, $content, $accounttype) return DBA::toArray($r); } elseif ($content == 'global') { if (!is_null($accounttype)) { - $sql_accounttype = " AND `owner`.`contact-type` = ?"; - $values = [$accounttype, $start, $itemspage]; + $condition = ["`uid` = ? AND `owner`.`contact-type` = ?", 0, $accounttype]; } else { - $sql_accounttype = ""; - $values = [$start, $itemspage]; + $condition = ['uid' => 0]; } - $r = DBA::p("SELECT `uri` FROM `thread` - INNER JOIN `item` ON `item`.`id` = `thread`.`iid` - INNER JOIN `contact` AS `author` ON `author`.`id`=`item`.`author-id` - INNER JOIN `contact` AS `owner` ON `owner`.`id`=`item`.`owner-id` - WHERE `thread`.`uid` = 0 AND NOT `author`.`hidden` AND NOT `author`.`blocked` $sql_accounttype - ORDER BY `thread`.`commented` DESC LIMIT ?, ?", $values); + $r = Item::selectThreadForUser(0, ['uri'], $condition, ['order' => ['commented' => true], 'limit' => [$start, $itemspage]]); return DBA::toArray($r); } From 05be2db72516ac17dc6b9cccaa6fee458501df53 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Wed, 17 Oct 2018 14:19:58 +0200 Subject: [PATCH 02/19] Move include/security tp /src/Core/Authentication and /src/Util/Security --- include/api.php | 4 +- include/security.php | 457 -------------------------------- mod/admin.php | 53 ++-- mod/attach.php | 4 +- mod/cal.php | 3 +- mod/delegate.php | 5 +- mod/display.php | 4 +- mod/group.php | 17 +- mod/invite.php | 5 +- mod/item.php | 3 +- mod/manage.php | 4 +- mod/openid.php | 4 +- mod/photo.php | 5 +- mod/photos.php | 13 +- mod/profile.php | 6 +- mod/profile_photo.php | 7 +- mod/profiles.php | 19 +- mod/register.php | 5 +- mod/settings.php | 33 +-- mod/subthread.php | 4 +- mod/videos.php | 4 +- src/Content/Widget/TagCloud.php | 4 +- src/Core/Authentication.php | 213 +++++++++++++++ src/Model/Group.php | 3 +- src/Model/Item.php | 2 +- src/Model/Photo.php | 3 +- src/Module/Login.php | 20 +- src/Module/Logout.php | 3 +- src/Object/Thread.php | 5 +- src/Util/Security.php | 273 +++++++++++++++++++ 30 files changed, 613 insertions(+), 572 deletions(-) delete mode 100644 include/security.php create mode 100644 src/Core/Authentication.php create mode 100644 src/Util/Security.php diff --git a/include/api.php b/include/api.php index ff763e9885..51caa9019b 100644 --- a/include/api.php +++ b/include/api.php @@ -12,6 +12,7 @@ use Friendica\Content\Feature; use Friendica\Content\Text\BBCode; use Friendica\Content\Text\HTML; use Friendica\Core\Addon; +use Friendica\Core\Authentication; use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Core\NotificationsManager; @@ -46,7 +47,6 @@ use Friendica\Util\XML; require_once 'include/conversation.php'; require_once 'mod/share.php'; require_once 'mod/item.php'; -require_once 'include/security.php'; require_once 'mod/wall_upload.php'; define('API_METHOD_ANY', '*'); @@ -242,7 +242,7 @@ function api_login(App $a) throw new UnauthorizedException("This API requires login"); } - authenticate_success($record); + Authentication::authenticate_success($record); $_SESSION["allow_api"] = true; diff --git a/include/security.php b/include/security.php deleted file mode 100644 index 2063bdd162..0000000000 --- a/include/security.php +++ /dev/null @@ -1,457 +0,0 @@ - $user["uid"], - "hash" => cookie_hash($user), - "ip" => defaults($_SERVER, 'REMOTE_ADDR', '0.0.0.0')]); - } else { - $value = ""; - } - - setcookie("Friendica", $value, $time, "/", "", (Config::get('system', 'ssl_policy') == SSL_POLICY_FULL), true); -} - -/** - * @brief Sets the provided user's authenticated session - * - * @todo Should be moved to Friendica\Core\Session once it's created - * - * @param type $user_record - * @param type $login_initial - * @param type $interactive - * @param type $login_refresh - */ -function authenticate_success($user_record, $login_initial = false, $interactive = false, $login_refresh = false) -{ - $a = get_app(); - - $_SESSION['uid'] = $user_record['uid']; - $_SESSION['theme'] = $user_record['theme']; - $_SESSION['mobile-theme'] = PConfig::get($user_record['uid'], 'system', 'mobile_theme'); - $_SESSION['authenticated'] = 1; - $_SESSION['page_flags'] = $user_record['page-flags']; - $_SESSION['my_url'] = System::baseUrl() . '/profile/' . $user_record['nickname']; - $_SESSION['my_address'] = $user_record['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3); - $_SESSION['addr'] = defaults($_SERVER, 'REMOTE_ADDR', '0.0.0.0'); - - $a->user = $user_record; - - if ($interactive) { - if ($a->user['login_date'] <= NULL_DATE) { - $_SESSION['return_url'] = 'profile_photo/new'; - $a->module = 'profile_photo'; - info(L10n::t("Welcome ") . $a->user['username'] . EOL); - info(L10n::t('Please upload a profile photo.') . EOL); - } else { - info(L10n::t("Welcome back ") . $a->user['username'] . EOL); - } - } - - $member_since = strtotime($a->user['register_date']); - if (time() < ($member_since + ( 60 * 60 * 24 * 14))) { - $_SESSION['new_member'] = true; - } else { - $_SESSION['new_member'] = false; - } - if (strlen($a->user['timezone'])) { - date_default_timezone_set($a->user['timezone']); - $a->timezone = $a->user['timezone']; - } - - $master_record = $a->user; - - if ((x($_SESSION, 'submanage')) && intval($_SESSION['submanage'])) { - $user = DBA::selectFirst('user', [], ['uid' => $_SESSION['submanage']]); - if (DBA::isResult($user)) { - $master_record = $user; - } - } - - if ($master_record['parent-uid'] == 0) { - // First add our own entry - $a->identities = [['uid' => $master_record['uid'], - 'username' => $master_record['username'], - 'nickname' => $master_record['nickname']]]; - - // Then add all the children - $r = DBA::select('user', ['uid', 'username', 'nickname'], - ['parent-uid' => $master_record['uid'], 'account_removed' => false]); - if (DBA::isResult($r)) { - $a->identities = array_merge($a->identities, DBA::toArray($r)); - } - } else { - // Just ensure that the array is always defined - $a->identities = []; - - // First entry is our parent - $r = DBA::select('user', ['uid', 'username', 'nickname'], - ['uid' => $master_record['parent-uid'], 'account_removed' => false]); - if (DBA::isResult($r)) { - $a->identities = DBA::toArray($r); - } - - // Then add all siblings - $r = DBA::select('user', ['uid', 'username', 'nickname'], - ['parent-uid' => $master_record['parent-uid'], 'account_removed' => false]); - if (DBA::isResult($r)) { - $a->identities = array_merge($a->identities, DBA::toArray($r)); - } - } - - $r = DBA::p("SELECT `user`.`uid`, `user`.`username`, `user`.`nickname` - FROM `manage` - INNER JOIN `user` ON `manage`.`mid` = `user`.`uid` - WHERE `user`.`account_removed` = 0 AND `manage`.`uid` = ?", - $master_record['uid'] - ); - if (DBA::isResult($r)) { - $a->identities = array_merge($a->identities, DBA::toArray($r)); - } - - if ($login_initial) { - logger('auth_identities: ' . print_r($a->identities, true), LOGGER_DEBUG); - } - if ($login_refresh) { - logger('auth_identities refresh: ' . print_r($a->identities, true), LOGGER_DEBUG); - } - - $contact = DBA::selectFirst('contact', [], ['uid' => $_SESSION['uid'], 'self' => true]); - if (DBA::isResult($contact)) { - $a->contact = $contact; - $a->cid = $contact['id']; - $_SESSION['cid'] = $a->cid; - } - - header('X-Account-Management-Status: active; name="' . $a->user['username'] . '"; id="' . $a->user['nickname'] . '"'); - - if ($login_initial || $login_refresh) { - DBA::update('user', ['login_date' => DateTimeFormat::utcNow()], ['uid' => $_SESSION['uid']]); - - // Set the login date for all identities of the user - DBA::update('user', ['login_date' => DateTimeFormat::utcNow()], - ['parent-uid' => $master_record['uid'], 'account_removed' => false]); - } - - if ($login_initial) { - /* - * If the user specified to remember the authentication, then set a cookie - * that expires after one week (the default is when the browser is closed). - * The cookie will be renewed automatically. - * The week ensures that sessions will expire after some inactivity. - */ - if (!empty($_SESSION['remember'])) { - logger('Injecting cookie for remembered user ' . $a->user['nickname']); - new_cookie(604800, $user_record); - unset($_SESSION['remember']); - } - } - - if ($login_initial) { - Addon::callHooks('logged_in', $a->user); - - if (($a->module !== 'home') && isset($_SESSION['return_url'])) { - goaway(System::baseUrl() . '/' . $_SESSION['return_url']); - } - } -} - -function can_write_wall($owner) -{ - static $verified = 0; - - if (!local_user() && !remote_user()) { - return false; - } - - $uid = local_user(); - if ($uid == $owner) { - return true; - } - - if (local_user() && ($owner == 0)) { - return true; - } - - if (remote_user()) { - // use remembered decision and avoid a DB lookup for each and every display item - // DO NOT use this function if there are going to be multiple owners - // We have a contact-id for an authenticated remote user, this block determines if the contact - // belongs to this page owner, and has the necessary permissions to post content - - if ($verified === 2) { - return true; - } elseif ($verified === 1) { - return false; - } else { - $cid = 0; - - if (!empty($_SESSION['remote'])) { - foreach ($_SESSION['remote'] as $visitor) { - if ($visitor['uid'] == $owner) { - $cid = $visitor['cid']; - break; - } - } - } - - if (!$cid) { - return false; - } - - $r = q("SELECT `contact`.*, `user`.`page-flags` FROM `contact` INNER JOIN `user` on `user`.`uid` = `contact`.`uid` - WHERE `contact`.`uid` = %d AND `contact`.`id` = %d AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0 - AND `user`.`blockwall` = 0 AND `readonly` = 0 AND ( `contact`.`rel` IN ( %d , %d ) OR `user`.`page-flags` = %d ) LIMIT 1", - intval($owner), - intval($cid), - intval(Contact::SHARING), - intval(Contact::FRIEND), - intval(Contact::PAGE_COMMUNITY) - ); - - if (DBA::isResult($r)) { - $verified = 2; - return true; - } else { - $verified = 1; - } - } - } - - return false; -} - -/// @TODO $groups should be array -function permissions_sql($owner_id, $remote_verified = false, $groups = null) -{ - $local_user = local_user(); - $remote_user = remote_user(); - - /** - * Construct permissions - * - * default permissions - anonymous user - */ - $sql = " AND allow_cid = '' - AND allow_gid = '' - AND deny_cid = '' - AND deny_gid = '' - "; - - /** - * Profile owner - everything is visible - */ - if ($local_user && $local_user == $owner_id) { - $sql = ''; - /** - * Authenticated visitor. Unless pre-verified, - * check that the contact belongs to this $owner_id - * and load the groups the visitor belongs to. - * If pre-verified, the caller is expected to have already - * done this and passed the groups into this function. - */ - } elseif ($remote_user) { - /* - * Authenticated visitor. Unless pre-verified, - * check that the contact belongs to this $owner_id - * and load the groups the visitor belongs to. - * If pre-verified, the caller is expected to have already - * done this and passed the groups into this function. - */ - - if (!$remote_verified) { - if (DBA::exists('contact', ['id' => $remote_user, 'uid' => $owner_id, 'blocked' => false])) { - $remote_verified = true; - $groups = Group::getIdsByContactId($remote_user); - } - } - - if ($remote_verified) { - $gs = '<<>>'; // should be impossible to match - - if (is_array($groups)) { - foreach ($groups as $g) { - $gs .= '|<' . intval($g) . '>'; - } - } - - $sql = sprintf( - " AND ( NOT (deny_cid REGEXP '<%d>' OR deny_gid REGEXP '%s') - AND ( allow_cid REGEXP '<%d>' OR allow_gid REGEXP '%s' OR ( allow_cid = '' AND allow_gid = '') ) - ) - ", - intval($remote_user), - DBA::escape($gs), - intval($remote_user), - DBA::escape($gs) - ); - } - } - return $sql; -} - -function item_permissions_sql($owner_id, $remote_verified = false, $groups = null) -{ - $local_user = local_user(); - $remote_user = remote_user(); - - /* - * Construct permissions - * - * default permissions - anonymous user - */ - $sql = " AND NOT `item`.`private`"; - - // Profile owner - everything is visible - if ($local_user && ($local_user == $owner_id)) { - $sql = ''; - } elseif ($remote_user) { - /* - * Authenticated visitor. Unless pre-verified, - * check that the contact belongs to this $owner_id - * and load the groups the visitor belongs to. - * If pre-verified, the caller is expected to have already - * done this and passed the groups into this function. - */ - $set = PermissionSet::get($owner_id, $remote_user, $groups); - - if (!empty($set)) { - $sql_set = " OR (`item`.`private` IN (1,2) AND `item`.`wall` AND `item`.`psid` IN (" . implode(',', $set) . "))"; - } else { - $sql_set = ''; - } - - $sql = " AND (NOT `item`.`private`" . $sql_set . ")"; - } - - return $sql; -} - -/* - * Functions used to protect against Cross-Site Request Forgery - * The security token has to base on at least one value that an attacker can't know - here it's the session ID and the private key. - * In this implementation, a security token is reusable (if the user submits a form, goes back and resubmits the form, maybe with small changes; - * or if the security token is used for ajax-calls that happen several times), but only valid for a certain amout of time (3hours). - * The "typename" seperates the security tokens of different types of forms. This could be relevant in the following case: - * A security token is used to protekt a link from CSRF (e.g. the "delete this profile"-link). - * If the new page contains by any chance external elements, then the used security token is exposed by the referrer. - * Actually, important actions should not be triggered by Links / GET-Requests at all, but somethimes they still are, - * so this mechanism brings in some damage control (the attacker would be able to forge a request to a form of this type, but not to forms of other types). - */ -function get_form_security_token($typename = '') -{ - $a = get_app(); - - $timestamp = time(); - $sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $timestamp . $typename); - - return $timestamp . '.' . $sec_hash; -} - -function check_form_security_token($typename = '', $formname = 'form_security_token') -{ - $hash = null; - - if (!empty($_REQUEST[$formname])) { - /// @TODO Careful, not secured! - $hash = $_REQUEST[$formname]; - } - - if (!empty($_SERVER['HTTP_X_CSRF_TOKEN'])) { - /// @TODO Careful, not secured! - $hash = $_SERVER['HTTP_X_CSRF_TOKEN']; - } - - if (empty($hash)) { - return false; - } - - $max_livetime = 10800; // 3 hours - - $a = get_app(); - - $x = explode('.', $hash); - if (time() > (IntVal($x[0]) + $max_livetime)) { - return false; - } - - $sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $x[0] . $typename); - - return ($sec_hash == $x[1]); -} - -function check_form_security_std_err_msg() -{ - return L10n::t("The form security token was not correct. This probably happened because the form has been opened for too long \x28>3 hours\x29 before submitting it.") . EOL; -} - -function check_form_security_token_redirectOnErr($err_redirect, $typename = '', $formname = 'form_security_token') -{ - if (!check_form_security_token($typename, $formname)) { - $a = get_app(); - logger('check_form_security_token failed: user ' . $a->user['guid'] . ' - form element ' . $typename); - logger('check_form_security_token failed: _REQUEST data: ' . print_r($_REQUEST, true), LOGGER_DATA); - notice(check_form_security_std_err_msg()); - goaway(System::baseUrl() . $err_redirect); - } -} - -function check_form_security_token_ForbiddenOnErr($typename = '', $formname = 'form_security_token') -{ - if (!check_form_security_token($typename, $formname)) { - $a = get_app(); - logger('check_form_security_token failed: user ' . $a->user['guid'] . ' - form element ' . $typename); - logger('check_form_security_token failed: _REQUEST data: ' . print_r($_REQUEST, true), LOGGER_DATA); - header('HTTP/1.1 403 Forbidden'); - killme(); - } -} - -/** - * @brief Kills the "Friendica" cookie and all session data - */ -function nuke_session() -{ - new_cookie(-3600); // make sure cookie is deleted on browser close, as a security measure - session_unset(); - session_destroy(); -} diff --git a/mod/admin.php b/mod/admin.php index b02db73bdd..ccadfa525c 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -25,6 +25,7 @@ use Friendica\Util\Arrays; use Friendica\Util\DateTimeFormat; use Friendica\Util\Temporal; use Friendica\Util\Network; +use Friendica\Util\Security; require_once 'include/enotify.php'; require_once 'include/text.php'; @@ -313,7 +314,7 @@ function admin_page_tos(App $a) '$preview' => L10n::t('Privacy Statement Preview'), '$privtext' => $tos->privacy_complete, '$tostext' => ['tostext', L10n::t('The Terms of Service'), Config::get('system', 'tostext'), L10n::t('Enter the Terms of Service for your node here. You can use BBCode. Headers of sections should be [h2] and below.')], - '$form_security_token' => get_form_security_token("admin_tos"), + '$form_security_token' => Security::get_form_security_token("admin_tos"), '$submit' => L10n::t('Save Settings'), ]); } @@ -324,7 +325,7 @@ function admin_page_tos(App $a) */ function admin_page_tos_post(App $a) { - check_form_security_token_redirectOnErr('/admin/tos', 'admin_tos'); + Security::check_form_security_token_redirectOnErr('/admin/tos', 'admin_tos'); if (!x($_POST, "page_tos")) { return; @@ -384,7 +385,7 @@ function admin_page_blocklist(App $a) '$entries' => $blocklistform, '$baseurl' => System::baseUrl(true), '$confirm_delete' => L10n::t('Delete entry from blocklist?'), - '$form_security_token' => get_form_security_token("admin_blocklist") + '$form_security_token' => Security::get_form_security_token("admin_blocklist") ]); } @@ -399,7 +400,7 @@ function admin_page_blocklist_post(App $a) return; } - check_form_security_token_redirectOnErr('/admin/blocklist', 'admin_blocklist'); + Security::check_form_security_token_redirectOnErr('/admin/blocklist', 'admin_blocklist'); if (x($_POST['page_blocklist_save'])) { // Add new item to blocklist @@ -442,7 +443,7 @@ function admin_page_contactblock_post(App $a) $contact_url = x($_POST, 'contact_url') ? $_POST['contact_url'] : ''; $contacts = x($_POST, 'contacts') ? $_POST['contacts'] : []; - check_form_security_token_redirectOnErr('/admin/contactblock', 'admin_contactblock'); + Security::check_form_security_token_redirectOnErr('/admin/contactblock', 'admin_contactblock'); if (x($_POST, 'page_contactblock_block')) { $contact_id = Contact::getIdForURL($contact_url); @@ -499,7 +500,7 @@ function admin_page_contactblock(App $a) '$h_newblock' => L10n::t('Block New Remote Contact'), '$th_contacts' => [L10n::t('Photo'), L10n::t('Name'), L10n::t('Address'), L10n::t('Profile URL')], - '$form_security_token' => get_form_security_token("admin_contactblock"), + '$form_security_token' => Security::get_form_security_token("admin_contactblock"), // values // '$baseurl' => System::baseUrl(true), @@ -534,7 +535,7 @@ function admin_page_deleteitem(App $a) '$intro2' => L10n::t('You need to know the GUID of the item. You can find it e.g. by looking at the display URL. The last part of http://example.com/display/123456 is the GUID, here 123456.'), '$deleteitemguid' => ['deleteitemguid', L10n::t("GUID"), '', L10n::t("The GUID of the item you want to delete."), 'required', 'autofocus'], '$baseurl' => System::baseUrl(), - '$form_security_token' => get_form_security_token("admin_deleteitem") + '$form_security_token' => Security::get_form_security_token("admin_deleteitem") ]); } @@ -552,7 +553,7 @@ function admin_page_deleteitem_post(App $a) return; } - check_form_security_token_redirectOnErr('/admin/deleteitem/', 'admin_deleteitem'); + Security::check_form_security_token_redirectOnErr('/admin/deleteitem/', 'admin_deleteitem'); if (x($_POST['page_deleteitem_submit'])) { $guid = trim(notags($_POST['deleteitemguid'])); @@ -945,7 +946,7 @@ function admin_page_summary(App $a) */ function admin_page_site_post(App $a) { - check_form_security_token_redirectOnErr('/admin/site', 'admin_site'); + Security::check_form_security_token_redirectOnErr('/admin/site', 'admin_site'); if (!empty($_POST['republish_directory'])) { Worker::add(PRIORITY_LOW, 'Directory'); @@ -1541,7 +1542,7 @@ function admin_page_site(App $a) '$relay_server_tags' => ['relay_server_tags', L10n::t("Server tags"), Config::get('system','relay_server_tags'), L10n::t("Comma separated list of tags for the 'tags' subscription.")], '$relay_user_tags' => ['relay_user_tags', L10n::t("Allow user tags"), Config::get('system', 'relay_user_tags', true), L10n::t("If enabled, the tags from the saved searches will used for the 'tags' subscription in addition to the 'relay_server_tags'.")], - '$form_security_token' => get_form_security_token("admin_site"), + '$form_security_token' => Security::get_form_security_token("admin_site"), '$relocate_button' => L10n::t('Start Relocation'), ]); } @@ -1656,7 +1657,7 @@ function admin_page_users_post(App $a) $nu_email = defaults($_POST, 'new_user_email' , ''); $nu_language = Config::get('system', 'language'); - check_form_security_token_redirectOnErr('/admin/users', 'admin_users'); + Security::check_form_security_token_redirectOnErr('/admin/users', 'admin_users'); if (!($nu_name === "") && !($nu_email === "") && !($nu_nickname === "")) { try { @@ -1772,14 +1773,14 @@ function admin_page_users(App $a) } switch ($a->argv[2]) { case "delete": - check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't'); + Security::check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't'); // delete user User::remove($uid); notice(L10n::t("User '%s' deleted", $user['username']) . EOL); break; case "block": - check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't'); + Security::check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't'); q("UPDATE `user` SET `blocked` = %d WHERE `uid` = %s", intval(1 - $user['blocked']), intval($uid) @@ -1930,7 +1931,7 @@ function admin_page_users(App $a) '$confirm_delete_multi' => L10n::t('Selected users will be deleted!\n\nEverything these users had posted on this site will be permanently deleted!\n\nAre you sure?'), '$confirm_delete' => L10n::t('The user {0} will be deleted!\n\nEverything this user has posted on this site will be permanently deleted!\n\nAre you sure?'), - '$form_security_token' => get_form_security_token("admin_users"), + '$form_security_token' => Security::get_form_security_token("admin_users"), // values // '$baseurl' => System::baseUrl(true), @@ -1975,7 +1976,7 @@ function admin_page_addons(App $a) } if (x($_GET, "a") && $_GET['a'] == "t") { - check_form_security_token_redirectOnErr('/admin/addons', 'admin_themes', 't'); + Security::check_form_security_token_redirectOnErr('/admin/addons', 'admin_themes', 't'); // Toggle addon status $idx = array_search($addon, $a->addons); @@ -2037,7 +2038,7 @@ function admin_page_addons(App $a) '$screenshot' => '', '$readme' => $readme, - '$form_security_token' => get_form_security_token("admin_themes"), + '$form_security_token' => Security::get_form_security_token("admin_themes"), ]); } @@ -2045,7 +2046,7 @@ function admin_page_addons(App $a) * List addons */ if (x($_GET, "a") && $_GET['a'] == "r") { - check_form_security_token_redirectOnErr(System::baseUrl() . '/admin/addons', 'admin_themes', 't'); + Security::check_form_security_token_redirectOnErr(System::baseUrl() . '/admin/addons', 'admin_themes', 't'); Addon::reload(); info("Addons reloaded"); goaway(System::baseUrl() . '/admin/addons'); @@ -2088,7 +2089,7 @@ function admin_page_addons(App $a) '$addons' => $addons, '$pcount' => count($addons), '$noplugshint' => L10n::t('There are currently no addons available on your node. You can find the official addon repository at %1$s and might find other interesting addons in the open addon registry at %2$s', 'https://github.com/friendica/friendica-addons', 'http://addons.friendi.ca'), - '$form_security_token' => get_form_security_token("admin_themes"), + '$form_security_token' => Security::get_form_security_token("admin_themes"), ]); } @@ -2223,7 +2224,7 @@ function admin_page_themes(App $a) } if (x($_GET, "a") && $_GET['a'] == "t") { - check_form_security_token_redirectOnErr('/admin/themes', 'admin_themes', 't'); + Security::check_form_security_token_redirectOnErr('/admin/themes', 'admin_themes', 't'); // Toggle theme status @@ -2305,13 +2306,13 @@ function admin_page_themes(App $a) '$screenshot' => $screenshot, '$readme' => $readme, - '$form_security_token' => get_form_security_token("admin_themes"), + '$form_security_token' => Security::get_form_security_token("admin_themes"), ]); } // reload active themes if (x($_GET, "a") && $_GET['a'] == "r") { - check_form_security_token_redirectOnErr(System::baseUrl() . '/admin/themes', 'admin_themes', 't'); + Security::check_form_security_token_redirectOnErr(System::baseUrl() . '/admin/themes', 'admin_themes', 't'); foreach ($themes as $th) { if ($th['allowed']) { Theme::uninstall($th['name']); @@ -2344,7 +2345,7 @@ function admin_page_themes(App $a) '$noplugshint' => L10n::t('No themes found on the system. They should be placed in %1$s', '/view/themes'), '$experimental' => L10n::t('[Experimental]'), '$unsupported' => L10n::t('[Unsupported]'), - '$form_security_token' => get_form_security_token("admin_themes"), + '$form_security_token' => Security::get_form_security_token("admin_themes"), ]); } @@ -2356,7 +2357,7 @@ function admin_page_themes(App $a) function admin_page_logs_post(App $a) { if (x($_POST, "page_logs")) { - check_form_security_token_redirectOnErr('/admin/logs', 'admin_logs'); + Security::check_form_security_token_redirectOnErr('/admin/logs', 'admin_logs'); $logfile = ((x($_POST,'logfile')) ? notags(trim($_POST['logfile'])) : ''); $debugging = ((x($_POST,'debugging')) ? true : false); @@ -2418,7 +2419,7 @@ function admin_page_logs(App $a) '$debugging' => ['debugging', L10n::t("Enable Debugging"), Config::get('system', 'debugging'), ""], '$logfile' => ['logfile', L10n::t("Log file"), Config::get('system', 'logfile'), L10n::t("Must be writable by web server. Relative to your Friendica top-level directory.")], '$loglevel' => ['loglevel', L10n::t("Log level"), Config::get('system', 'loglevel'), "", $log_choices], - '$form_security_token' => get_form_security_token("admin_logs"), + '$form_security_token' => Security::get_form_security_token("admin_logs"), '$phpheader' => L10n::t("PHP logging"), '$phphint' => L10n::t("To temporarily enable logging of PHP errors and warnings you can prepend the following to the index.php file of your installation. The filename set in the 'error_log' line is relative to the friendica top-level directory and must be writeable by the web server. The option '1' for 'log_errors' and 'display_errors' is to enable these options, set to '0' to disable them."), '$phplogcode' => "error_reporting(E_ERROR | E_WARNING | E_PARSE);\nini_set('error_log','php.out');\nini_set('log_errors','1');\nini_set('display_errors', '1');", @@ -2489,7 +2490,7 @@ function admin_page_viewlogs(App $a) */ function admin_page_features_post(App $a) { - check_form_security_token_redirectOnErr('/admin/features', 'admin_manage_features'); + Security::check_form_security_token_redirectOnErr('/admin/features', 'admin_manage_features'); logger('postvars: ' . print_r($_POST, true), LOGGER_DATA); @@ -2554,7 +2555,7 @@ function admin_page_features(App $a) $tpl = get_markup_template('admin/settings_features.tpl'); $o = replace_macros($tpl, [ - '$form_security_token' => get_form_security_token("admin_manage_features"), + '$form_security_token' => Security::get_form_security_token("admin_manage_features"), '$title' => L10n::t('Manage Additional Features'), '$features' => $arr, '$submit' => L10n::t('Save Settings'), diff --git a/mod/attach.php b/mod/attach.php index 99f0fc4600..97eb10997e 100644 --- a/mod/attach.php +++ b/mod/attach.php @@ -6,9 +6,9 @@ use Friendica\App; use Friendica\Core\L10n; use Friendica\Database\DBA; +use Friendica\Util\Security; require_once 'include/dba.php'; -require_once 'include/security.php'; function attach_init(App $a) { @@ -27,7 +27,7 @@ function attach_init(App $a) return; } - $sql_extra = permissions_sql($r['uid']); + $sql_extra = Security::permissions_sql($r['uid']); // Now we'll see if we can access the attachment diff --git a/mod/cal.php b/mod/cal.php index ae1060c47a..cc6973d472 100644 --- a/mod/cal.php +++ b/mod/cal.php @@ -21,6 +21,7 @@ use Friendica\Model\Profile; use Friendica\Protocol\DFRN; use Friendica\Util\DateTimeFormat; use Friendica\Util\Temporal; +use Friendica\Util\Security; function cal_init(App $a) { @@ -141,7 +142,7 @@ function cal_content(App $a) } // get the permissions - $sql_perms = item_permissions_sql($owner_uid, $remote_contact, $groups); + $sql_perms = Security::item_permissions_sql($owner_uid, $remote_contact, $groups); // we only want to have the events of the profile owner $sql_extra = " AND `event`.`cid` = 0 " . $sql_perms; diff --git a/mod/delegate.php b/mod/delegate.php index ed4f854377..f711f593fa 100644 --- a/mod/delegate.php +++ b/mod/delegate.php @@ -9,6 +9,7 @@ use Friendica\Core\Protocol; use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Model\User; +use Friendica\Util\Security; require_once 'mod/settings.php'; @@ -28,7 +29,7 @@ function delegate_post(App $a) return; } - check_form_security_token_redirectOnErr('/delegate', 'delegate'); + Security::check_form_security_token_redirectOnErr('/delegate', 'delegate'); $parent_uid = defaults($_POST, 'parent_user', 0); $parent_password = defaults($_POST, 'parent_password', ''); @@ -162,7 +163,7 @@ function delegate_content(App $a) } $o = replace_macros(get_markup_template('delegate.tpl'), [ - '$form_security_token' => get_form_security_token('delegate'), + '$form_security_token' => Security::get_form_security_token('delegate'), '$parent_header' => L10n::t('Parent User'), '$parent_user' => $parent_user, '$parent_password' => $parent_password, diff --git a/mod/display.php b/mod/display.php index a03b918372..0c1cc90375 100644 --- a/mod/display.php +++ b/mod/display.php @@ -18,6 +18,7 @@ use Friendica\Model\Item; use Friendica\Model\Profile; use Friendica\Protocol\DFRN; use Friendica\Protocol\ActivityPub; +use Friendica\Util\Security; function display_init(App $a) { @@ -200,7 +201,6 @@ function display_content(App $a, $update = false, $update_uid = 0) return; } - require_once 'include/security.php'; require_once 'include/conversation.php'; $o = ''; @@ -325,7 +325,7 @@ function display_content(App $a, $update = false, $update_uid = 0) $o .= status_editor($a, $x, 0, true); } - $sql_extra = item_permissions_sql($a->profile['uid'], $is_remote_contact, $groups); + $sql_extra = Security::item_permissions_sql($a->profile['uid'], $is_remote_contact, $groups); if (local_user() && (local_user() == $a->profile['uid'])) { $condition = ['parent-uri' => $item_parent_uri, 'uid' => local_user(), 'unseen' => true]; diff --git a/mod/group.php b/mod/group.php index f8fefc78f9..09fe676c17 100644 --- a/mod/group.php +++ b/mod/group.php @@ -13,6 +13,7 @@ use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Model; use Friendica\Module; +use Friendica\Util\Security; function group_init(App $a) { if (local_user()) { @@ -28,7 +29,7 @@ function group_post(App $a) { } if (($a->argc == 2) && ($a->argv[1] === 'new')) { - check_form_security_token_redirectOnErr('/group/new', 'group_edit'); + Security::check_form_security_token_redirectOnErr('/group/new', 'group_edit'); $name = notags(trim($_POST['groupname'])); $r = Model\Group::create(local_user(), $name); @@ -46,7 +47,7 @@ function group_post(App $a) { } if (($a->argc == 2) && intval($a->argv[1])) { - check_form_security_token_redirectOnErr('/group', 'group_edit'); + Security::check_form_security_token_redirectOnErr('/group', 'group_edit'); $r = q("SELECT * FROM `group` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($a->argv[1]), @@ -107,7 +108,7 @@ function group_content(App $a) { '$title' => L10n::t('Create a group of contacts/friends.'), '$gname' => ['groupname', L10n::t('Group Name: '), '', ''], '$gid' => 'new', - '$form_security_token' => get_form_security_token("group_edit"), + '$form_security_token' => Security::get_form_security_token("group_edit"), ]); @@ -137,7 +138,7 @@ function group_content(App $a) { if (($a->argc == 3) && ($a->argv[1] === 'drop')) { - check_form_security_token_redirectOnErr('/group', 'group_drop', 't'); + Security::check_form_security_token_redirectOnErr('/group', 'group_drop', 't'); if (intval($a->argv[2])) { $r = q("SELECT `name` FROM `group` WHERE `id` = %d AND `uid` = %d LIMIT 1", @@ -162,7 +163,7 @@ function group_content(App $a) { } if (($a->argc > 2) && intval($a->argv[1]) && intval($a->argv[2])) { - check_form_security_token_ForbiddenOnErr('group_member_change', 't'); + Security::check_form_security_token_ForbiddenOnErr('group_member_change', 't'); $r = q("SELECT `id` FROM `contact` WHERE `id` = %d AND `uid` = %d and `self` = 0 and `blocked` = 0 AND `pending` = 0 LIMIT 1", intval($a->argv[2]), @@ -216,7 +217,7 @@ function group_content(App $a) { $drop_txt = replace_macros($drop_tpl, [ '$id' => $group['id'], '$delete' => L10n::t('Delete Group'), - '$form_security_token' => get_form_security_token("group_drop"), + '$form_security_token' => Security::get_form_security_token("group_drop"), ]); @@ -225,7 +226,7 @@ function group_content(App $a) { '$gname' => ['groupname', L10n::t('Group Name: '), $group['name'], ''], '$gid' => $group['id'], '$drop' => $drop_txt, - '$form_security_token' => get_form_security_token('group_edit'), + '$form_security_token' => Security::get_form_security_token('group_edit'), '$edit_name' => L10n::t('Edit Group Name'), '$editable' => 1, ]; @@ -244,7 +245,7 @@ function group_content(App $a) { 'contacts' => [], ]; - $sec_token = addslashes(get_form_security_token('group_member_change')); + $sec_token = addslashes(Security::get_form_security_token('group_member_change')); // Format the data of the group members foreach ($members as $member) { diff --git a/mod/invite.php b/mod/invite.php index 2a98d19ffc..cd9de6cc0a 100644 --- a/mod/invite.php +++ b/mod/invite.php @@ -14,6 +14,7 @@ use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Protocol\Email; use Friendica\Util\DateTimeFormat; +use Friendica\Util\Security; function invite_post(App $a) { @@ -22,7 +23,7 @@ function invite_post(App $a) return; } - check_form_security_token_redirectOnErr('/', 'send_invite'); + Security::check_form_security_token_redirectOnErr('/', 'send_invite'); $max_invites = intval(Config::get('system', 'max_invites')); if (! $max_invites) { @@ -144,7 +145,7 @@ function invite_content(App $a) { } $o = replace_macros($tpl, [ - '$form_security_token' => get_form_security_token("send_invite"), + '$form_security_token' => Security::get_form_security_token("send_invite"), '$title' => L10n::t('Send invitations'), '$recipients' => ['recipients', L10n::t('Enter email addresses, one per line:')], '$message' => ['message', L10n::t('Your message:'),L10n::t('You are cordially invited to join me and other close friends on Friendica - and help us to create a better social web.') . "\r\n" . "\r\n" diff --git a/mod/item.php b/mod/item.php index 053a00c977..5a665fc7c8 100644 --- a/mod/item.php +++ b/mod/item.php @@ -32,6 +32,7 @@ use Friendica\Protocol\Diaspora; use Friendica\Protocol\Email; use Friendica\Util\DateTimeFormat; use Friendica\Util\Emailer; +use Friendica\Util\Security; require_once 'include/enotify.php'; require_once 'include/text.php'; @@ -162,7 +163,7 @@ function item_post(App $a) { $allow_comment = local_user() && ($profile_uid == 0) && $parent && in_array($parent_item['network'], [Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN]); // Now check that valid personal details have been provided - if (!can_write_wall($profile_uid) && !$allow_comment) { + if (!Security::can_write_wall($profile_uid) && !$allow_comment) { notice(L10n::t('Permission denied.') . EOL) ; if (!empty($_REQUEST['return'])) { diff --git a/mod/manage.php b/mod/manage.php index f81afb09a6..d54b92a3a7 100644 --- a/mod/manage.php +++ b/mod/manage.php @@ -3,6 +3,7 @@ * @file mod/manage.php */ use Friendica\App; +use Friendica\Core\Authentication; use Friendica\Core\Addon; use Friendica\Core\L10n; use Friendica\Core\System; @@ -109,8 +110,7 @@ function manage_post(App $a) { unset($_SESSION['sysmsg_info']); } - require_once('include/security.php'); - authenticate_success($r[0], true, true); + Authentication::authenticate_success($r[0], true, true); if ($limited_id) { $_SESSION['submanage'] = $original_id; diff --git a/mod/openid.php b/mod/openid.php index 63b29684b3..a9930d0448 100644 --- a/mod/openid.php +++ b/mod/openid.php @@ -4,6 +4,7 @@ */ use Friendica\App; +use Friendica\Core\Authentication; use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Core\System; @@ -50,8 +51,7 @@ function openid_content(App $a) { unset($_SESSION['openid']); - require_once('include/security.php'); - authenticate_success($r[0],true,true); + Authentication::authenticate_success($r[0],true,true); // just in case there was no return url set // and we fell through diff --git a/mod/photo.php b/mod/photo.php index b1dd9a5c3a..3a0a199d8c 100644 --- a/mod/photo.php +++ b/mod/photo.php @@ -6,8 +6,7 @@ use Friendica\App; use Friendica\Database\DBA; use Friendica\Object\Image; - -require_once 'include/security.php'; +use Friendica\Util\Security; function photo_init(App $a) { @@ -111,7 +110,7 @@ function photo_init(App $a) intval($resolution) ); if (DBA::isResult($r)) { - $sql_extra = permissions_sql($r[0]['uid']); + $sql_extra = Security::permissions_sql($r[0]['uid']); // Now we'll see if we can access the photo $r = q("SELECT * FROM `photo` WHERE `resource-id` = '%s' AND `scale` <= %d $sql_extra ORDER BY scale DESC LIMIT 1", diff --git a/mod/photos.php b/mod/photos.php index 259209ed40..4208e22754 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -26,9 +26,9 @@ use Friendica\Protocol\DFRN; use Friendica\Util\DateTimeFormat; use Friendica\Util\Map; use Friendica\Util\Temporal; +use Friendica\Util\Security; require_once 'include/items.php'; -require_once 'include/security.php'; function photos_init(App $a) { @@ -948,7 +948,6 @@ function photos_content(App $a) return; } - require_once 'include/security.php'; require_once 'include/conversation.php'; if (empty($a->data['user'])) { @@ -1053,7 +1052,7 @@ function photos_content(App $a) return; } - $sql_extra = permissions_sql($owner_uid, $remote_contact, $groups); + $sql_extra = Security::permissions_sql($owner_uid, $remote_contact, $groups); $o = ""; @@ -1473,7 +1472,7 @@ function photos_content(App $a) $tpl = get_markup_template('photo_item.tpl'); $return_url = $a->cmd; - if ($can_post || can_write_wall($owner_uid)) { + if ($can_post || Security::can_write_wall($owner_uid)) { $like_tpl = get_markup_template('like_noshare.tpl'); $likebuttons = replace_macros($like_tpl, [ '$id' => $link_item['id'], @@ -1485,7 +1484,7 @@ function photos_content(App $a) } if (!DBA::isResult($items)) { - if (($can_post || can_write_wall($owner_uid))) { + if (($can_post || Security::can_write_wall($owner_uid))) { $comments .= replace_macros($cmnt_tpl, [ '$return_path' => '', '$jsreload' => $return_url, @@ -1524,7 +1523,7 @@ function photos_content(App $a) $dislike = format_like($conv_responses['dislike'][$link_item['uri']], $conv_responses['dislike'][$link_item['uri'] . '-l'], 'dislike', $link_item['id']); } - if (($can_post || can_write_wall($owner_uid))) { + if (($can_post || Security::can_write_wall($owner_uid))) { $comments .= replace_macros($cmnt_tpl,[ '$return_path' => '', '$jsreload' => $return_url, @@ -1584,7 +1583,7 @@ function photos_content(App $a) '$comment' => $comment ]); - if (($can_post || can_write_wall($owner_uid))) { + if (($can_post || Security::can_write_wall($owner_uid))) { $comments .= replace_macros($cmnt_tpl, [ '$return_path' => '', '$jsreload' => $return_url, diff --git a/mod/profile.php b/mod/profile.php index aa284d1669..5484beb265 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -20,6 +20,7 @@ use Friendica\Model\Profile; use Friendica\Module\Login; use Friendica\Protocol\DFRN; use Friendica\Util\DateTimeFormat; +use Friendica\Util\Security; use Friendica\Protocol\ActivityPub; function profile_init(App $a) @@ -130,7 +131,6 @@ function profile_content(App $a, $update = 0) return Login::form(); } - require_once 'include/security.php'; require_once 'include/conversation.php'; require_once 'include/items.php'; @@ -210,7 +210,7 @@ function profile_content(App $a, $update = 0) $a->page['aside'] .= Widget::categories(System::baseUrl(true) . '/profile/' . $a->profile['nickname'], (!empty($category) ? xmlify($category) : '')); $a->page['aside'] .= Widget::tagCloud(); - if (can_write_wall($a->profile['profile_uid'])) { + if (Security::can_write_wall($a->profile['profile_uid'])) { $x = [ 'is_owner' => $is_owner, 'allow_location' => ($is_owner || $commvisitor) && $a->profile['allow_location'], @@ -234,7 +234,7 @@ function profile_content(App $a, $update = 0) // Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups - $sql_extra = item_permissions_sql($a->profile['profile_uid'], $remote_contact, $groups); + $sql_extra = Security::item_permissions_sql($a->profile['profile_uid'], $remote_contact, $groups); $sql_extra2 = ''; if ($update) { diff --git a/mod/profile_photo.php b/mod/profile_photo.php index 984ebfed6f..492be7e4ae 100644 --- a/mod/profile_photo.php +++ b/mod/profile_photo.php @@ -13,6 +13,7 @@ use Friendica\Model\Contact; use Friendica\Model\Photo; use Friendica\Model\Profile; use Friendica\Object\Image; +use Friendica\Util\Security; function profile_photo_init(App $a) { @@ -30,7 +31,7 @@ function profile_photo_post(App $a) return; } - check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo'); + Security::check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo'); if (!empty($_POST['cropfinal']) && $_POST['cropfinal'] == 1) { @@ -246,7 +247,7 @@ function profile_photo_content(App $a) '$title' => L10n::t('Upload Profile Photo'), '$submit' => L10n::t('Upload'), '$profiles' => $profiles, - '$form_security_token' => get_form_security_token("profile_photo"), + '$form_security_token' => Security::get_form_security_token("profile_photo"), '$select' => sprintf('%s %s', L10n::t('or'), ($newuser) ? '' . L10n::t('skip this step') . '' : '' . L10n::t('select a photo from your photo albums') . '') ]); @@ -263,7 +264,7 @@ function profile_photo_content(App $a) '$image_url' => System::baseUrl() . '/photo/' . $filename, '$title' => L10n::t('Crop Image'), '$desc' => L10n::t('Please adjust the image cropping for optimum viewing.'), - '$form_security_token' => get_form_security_token("profile_photo"), + '$form_security_token' => Security::get_form_security_token("profile_photo"), '$done' => L10n::t('Done Editing') ]); return $o; diff --git a/mod/profiles.php b/mod/profiles.php index 3e6bd1cb0d..37277f3f24 100644 --- a/mod/profiles.php +++ b/mod/profiles.php @@ -20,6 +20,7 @@ use Friendica\Model\Profile; use Friendica\Network\Probe; use Friendica\Util\DateTimeFormat; use Friendica\Util\Temporal; +use Friendica\Utill\Security; use Friendica\Module\Login; function profiles_init(App $a) { @@ -41,7 +42,7 @@ function profiles_init(App $a) { return; // NOTREACHED } - check_form_security_token_redirectOnErr('/profiles', 'profile_drop', 't'); + Security::check_form_security_token_redirectOnErr('/profiles', 'profile_drop', 't'); // move every contact using this profile as their default to the user default @@ -64,7 +65,7 @@ function profiles_init(App $a) { if (($a->argc > 1) && ($a->argv[1] === 'new')) { - check_form_security_token_redirectOnErr('/profiles', 'profile_new', 't'); + Security::check_form_security_token_redirectOnErr('/profiles', 'profile_new', 't'); $r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d", intval(local_user())); @@ -100,7 +101,7 @@ function profiles_init(App $a) { if (($a->argc > 2) && ($a->argv[1] === 'clone')) { - check_form_security_token_redirectOnErr('/profiles', 'profile_clone', 't'); + Security::check_form_security_token_redirectOnErr('/profiles', 'profile_clone', 't'); $r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d", intval(local_user())); @@ -195,7 +196,7 @@ function profiles_post(App $a) { return; } - check_form_security_token_redirectOnErr('/profiles', 'profile_edit'); + Security::check_form_security_token_redirectOnErr('/profiles', 'profile_edit'); $is_default = (($orig[0]['is-default']) ? 1 : 0); @@ -565,10 +566,10 @@ function profiles_content(App $a) { ], '$multi_profiles' => Feature::isEnabled(local_user(), 'multi_profiles'), - '$form_security_token' => get_form_security_token("profile_edit"), - '$form_security_token_photo' => get_form_security_token("profile_photo"), - '$profile_clone_link' => ((Feature::isEnabled(local_user(), 'multi_profiles')) ? 'profiles/clone/' . $r[0]['id'] . '?t=' . get_form_security_token("profile_clone") : ""), - '$profile_drop_link' => 'profiles/drop/' . $r[0]['id'] . '?t=' . get_form_security_token("profile_drop"), + '$form_security_token' => Security::get_form_security_token("profile_edit"), + '$form_security_token_photo' => Security::get_form_security_token("profile_photo"), + '$profile_clone_link' => ((Feature::isEnabled(local_user(), 'multi_profiles')) ? 'profiles/clone/' . $r[0]['id'] . '?t=' . Security::get_form_security_token("profile_clone") : ""), + '$profile_drop_link' => 'profiles/drop/' . $r[0]['id'] . '?t=' . Security::get_form_security_token("profile_drop"), '$profile_action' => L10n::t('Profile Actions'), '$banner' => L10n::t('Edit Profile Details'), @@ -681,7 +682,7 @@ function profiles_content(App $a) { '$header' => L10n::t('Edit/Manage Profiles'), '$chg_photo' => L10n::t('Change profile photo'), '$cr_new' => L10n::t('Create New Profile'), - '$cr_new_link' => 'profiles/new?t=' . get_form_security_token("profile_new"), + '$cr_new_link' => 'profiles/new?t=' . Security::get_form_security_token("profile_new"), '$profiles' => $profiles ]); } diff --git a/mod/register.php b/mod/register.php index 454062d89b..9a2ad0f482 100644 --- a/mod/register.php +++ b/mod/register.php @@ -15,12 +15,13 @@ use Friendica\Database\DBA; use Friendica\Model\User; use Friendica\Module\Tos; use Friendica\Util\DateTimeFormat; +use Friendica\Util\Security; require_once 'include/enotify.php'; function register_post(App $a) { - check_form_security_token_redirectOnErr('/register', 'register'); + Security::check_form_security_token_redirectOnErr('/register', 'register'); $verified = 0; $blocked = 1; @@ -291,7 +292,7 @@ function register_content(App $a) '$showprivstatement' => Config::get('system', 'tosprivstatement'), '$privstatement' => $tos->privacy_complete, '$baseurl' => System::baseurl(), - '$form_security_token' => get_form_security_token("register"), + '$form_security_token' => Security::get_form_security_token("register"), '$explicit_content' => Config::get('system', 'explicit_content', false), '$explicit_content_note' => L10n::t('Note: This node explicitly contains adult content') ]); diff --git a/mod/settings.php b/mod/settings.php index 5632193e3b..3737aeadac 100644 --- a/mod/settings.php +++ b/mod/settings.php @@ -22,6 +22,7 @@ use Friendica\Model\User; use Friendica\Protocol\Email; use Friendica\Util\Network; use Friendica\Util\Temporal; +use Friendica\Util\Security; use Friendica\Module\Login; function get_theme_config_file($theme) @@ -154,7 +155,7 @@ function settings_post(App $a) $old_page_flags = $a->user['page-flags']; if (($a->argc > 1) && ($a->argv[1] === 'oauth') && x($_POST, 'remove')) { - check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth'); + Security::check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth'); $key = $_POST['remove']; DBA::delete('tokens', ['id' => $key, 'uid' => local_user()]); @@ -163,7 +164,7 @@ function settings_post(App $a) } if (($a->argc > 2) && ($a->argv[1] === 'oauth') && ($a->argv[2] === 'edit'||($a->argv[2] === 'add')) && x($_POST, 'submit')) { - check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth'); + Security::check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth'); $name = defaults($_POST, 'name' , ''); $key = defaults($_POST, 'key' , ''); @@ -209,14 +210,14 @@ function settings_post(App $a) } if (($a->argc > 1) && ($a->argv[1] == 'addon')) { - check_form_security_token_redirectOnErr('/settings/addon', 'settings_addon'); + Security::check_form_security_token_redirectOnErr('/settings/addon', 'settings_addon'); Addon::callHooks('addon_settings_post', $_POST); return; } if (($a->argc > 1) && ($a->argv[1] == 'connectors')) { - check_form_security_token_redirectOnErr('/settings/connectors', 'settings_connectors'); + Security::check_form_security_token_redirectOnErr('/settings/connectors', 'settings_connectors'); if (x($_POST, 'general-submit')) { PConfig::set(local_user(), 'system', 'disable_cw', intval($_POST['disable_cw'])); @@ -298,7 +299,7 @@ function settings_post(App $a) } if (($a->argc > 1) && ($a->argv[1] === 'features')) { - check_form_security_token_redirectOnErr('/settings/features', 'settings_features'); + Security::check_form_security_token_redirectOnErr('/settings/features', 'settings_features'); foreach ($_POST as $k => $v) { if (strpos($k, 'feature_') === 0) { PConfig::set(local_user(), 'feature', substr($k, 8), ((intval($v)) ? 1 : 0)); @@ -309,7 +310,7 @@ function settings_post(App $a) } if (($a->argc > 1) && ($a->argv[1] === 'display')) { - check_form_security_token_redirectOnErr('/settings/display', 'settings_display'); + Security::check_form_security_token_redirectOnErr('/settings/display', 'settings_display'); $theme = x($_POST, 'theme') ? notags(trim($_POST['theme'])) : $a->user['theme']; $mobile_theme = x($_POST, 'mobile_theme') ? notags(trim($_POST['mobile_theme'])) : ''; @@ -373,7 +374,7 @@ function settings_post(App $a) return; // NOTREACHED } - check_form_security_token_redirectOnErr('/settings', 'settings'); + Security::check_form_security_token_redirectOnErr('/settings', 'settings'); if (x($_POST,'resend_relocate')) { Worker::add(PRIORITY_HIGH, 'Notifier', 'relocate', local_user()); @@ -671,7 +672,7 @@ function settings_content(App $a) if (($a->argc > 2) && ($a->argv[2] === 'add')) { $tpl = get_markup_template('settings/oauth_edit.tpl'); $o .= replace_macros($tpl, [ - '$form_security_token' => get_form_security_token("settings_oauth"), + '$form_security_token' => Security::get_form_security_token("settings_oauth"), '$title' => L10n::t('Add application'), '$submit' => L10n::t('Save Settings'), '$cancel' => L10n::t('Cancel'), @@ -697,7 +698,7 @@ function settings_content(App $a) $tpl = get_markup_template('settings/oauth_edit.tpl'); $o .= replace_macros($tpl, [ - '$form_security_token' => get_form_security_token("settings_oauth"), + '$form_security_token' => Security::get_form_security_token("settings_oauth"), '$title' => L10n::t('Add application'), '$submit' => L10n::t('Update'), '$cancel' => L10n::t('Cancel'), @@ -711,7 +712,7 @@ function settings_content(App $a) } if (($a->argc > 3) && ($a->argv[2] === 'delete')) { - check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth', 't'); + Security::check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth', 't'); DBA::delete('clients', ['client_id' => $a->argv[3], 'uid' => local_user()]); goaway(System::baseUrl(true)."/settings/oauth/"); @@ -729,7 +730,7 @@ function settings_content(App $a) $tpl = get_markup_template('settings/oauth.tpl'); $o .= replace_macros($tpl, [ - '$form_security_token' => get_form_security_token("settings_oauth"), + '$form_security_token' => Security::get_form_security_token("settings_oauth"), '$baseurl' => System::baseUrl(true), '$title' => L10n::t('Connected Apps'), '$add' => L10n::t('Add application'), @@ -756,7 +757,7 @@ function settings_content(App $a) $tpl = get_markup_template('settings/addons.tpl'); $o .= replace_macros($tpl, [ - '$form_security_token' => get_form_security_token("settings_addon"), + '$form_security_token' => Security::get_form_security_token("settings_addon"), '$title' => L10n::t('Addon Settings'), '$settings_addons' => $settings_addons ]); @@ -777,7 +778,7 @@ function settings_content(App $a) $tpl = get_markup_template('settings/features.tpl'); $o .= replace_macros($tpl, [ - '$form_security_token' => get_form_security_token("settings_features"), + '$form_security_token' => Security::get_form_security_token("settings_features"), '$title' => L10n::t('Additional Features'), '$features' => $arr, '$submit' => L10n::t('Save Settings'), @@ -836,7 +837,7 @@ function settings_content(App $a) $mail_disabled_message = (($mail_disabled) ? L10n::t('Email access is disabled on this site.') : ''); $o .= replace_macros($tpl, [ - '$form_security_token' => get_form_security_token("settings_connectors"), + '$form_security_token' => Security::get_form_security_token("settings_connectors"), '$title' => L10n::t('Social Networks'), @@ -956,7 +957,7 @@ function settings_content(App $a) $tpl = get_markup_template('settings/display.tpl'); $o = replace_macros($tpl, [ '$ptitle' => L10n::t('Display Settings'), - '$form_security_token' => get_form_security_token("settings_display"), + '$form_security_token' => Security::get_form_security_token("settings_display"), '$submit' => L10n::t('Save Settings'), '$baseurl' => System::baseUrl(true), '$uid' => local_user(), @@ -1185,7 +1186,7 @@ function settings_content(App $a) '$submit' => L10n::t('Save Settings'), '$baseurl' => System::baseUrl(true), '$uid' => local_user(), - '$form_security_token' => get_form_security_token("settings"), + '$form_security_token' => Security::get_form_security_token("settings"), '$nickname_block' => $prof_addr, '$h_pass' => L10n::t('Password Settings'), diff --git a/mod/subthread.php b/mod/subthread.php index 105cf60feb..8bd60e8fef 100644 --- a/mod/subthread.php +++ b/mod/subthread.php @@ -8,8 +8,8 @@ use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Model\Item; +use Friendica\Util\Security; -require_once 'include/security.php'; require_once 'include/items.php'; function subthread_content(App $a) { @@ -32,7 +32,7 @@ function subthread_content(App $a) { $owner_uid = $item['uid']; - if (!can_write_wall($owner_uid)) { + if (!Security::can_write_wall($owner_uid)) { return; } diff --git a/mod/videos.php b/mod/videos.php index e52c78cab1..0d217ef9c4 100644 --- a/mod/videos.php +++ b/mod/videos.php @@ -14,9 +14,9 @@ use Friendica\Model\Group; use Friendica\Model\Item; use Friendica\Model\Profile; use Friendica\Protocol\DFRN; +use Friendica\Util\Security; require_once 'include/items.php'; -require_once 'include/security.php'; function videos_init(App $a) { @@ -302,7 +302,7 @@ function videos_content(App $a) return; } - $sql_extra = permissions_sql($owner_uid, $remote_contact, $groups); + $sql_extra = Security::permissions_sql($owner_uid, $remote_contact, $groups); $o = ""; diff --git a/src/Content/Widget/TagCloud.php b/src/Content/Widget/TagCloud.php index 71872830cb..3a2b01123a 100644 --- a/src/Content/Widget/TagCloud.php +++ b/src/Content/Widget/TagCloud.php @@ -9,9 +9,9 @@ namespace Friendica\Content\Widget; use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Database\DBA; +use Friendica\Util\Security; require_once 'include/dba.php'; -require_once 'include/security.php'; /** * TagCloud widget @@ -73,7 +73,7 @@ class TagCloud */ private static function tagadelic($uid, $count = 0, $owner_id = 0, $flags = '', $type = TERM_HASHTAG) { - $sql_options = item_permissions_sql($uid); + $sql_options = Security::item_permissions_sql($uid); $limit = $count ? sprintf('LIMIT %d', intval($count)) : ''; if ($flags) { diff --git a/src/Core/Authentication.php b/src/Core/Authentication.php new file mode 100644 index 0000000000..3e53a5ae9a --- /dev/null +++ b/src/Core/Authentication.php @@ -0,0 +1,213 @@ + $user["uid"], + "hash" => self::cookie_hash($user), + "ip" => defaults($_SERVER, 'REMOTE_ADDR', '0.0.0.0')]); + } else { + $value = ""; + } + + setcookie("Friendica", $value, $time, "/", "", (Config::get('system', 'ssl_policy') == SSL_POLICY_FULL), true); + } + + /** + * @brief Sets the provided user's authenticated session + * + * @todo Should be moved to Friendica\Core\Session once it's created + * + * @param type $user_record + * @param type $login_initial + * @param type $interactive + * @param type $login_refresh + */ + public static function authenticate_success($user_record, $login_initial = false, $interactive = false, $login_refresh = false) + { + $a = self::getApp(); + + $_SESSION['uid'] = $user_record['uid']; + $_SESSION['theme'] = $user_record['theme']; + $_SESSION['mobile-theme'] = PConfig::get($user_record['uid'], 'system', 'mobile_theme'); + $_SESSION['authenticated'] = 1; + $_SESSION['page_flags'] = $user_record['page-flags']; + $_SESSION['my_url'] = $a->getbaseUrl() . '/profile/' . $user_record['nickname']; + $_SESSION['my_address'] = $user_record['nickname'] . '@' . substr($a->getbaseUrl(), strpos($a->getbaseUrl(), '://') + 3); + $_SESSION['addr'] = defaults($_SERVER, 'REMOTE_ADDR', '0.0.0.0'); + + $a->user = $user_record; + + if ($interactive) { + if ($a->user['login_date'] <= NULL_DATE) { + $_SESSION['return_url'] = 'profile_photo/new'; + $a->module = 'profile_photo'; + info(L10n::t("Welcome ") . $a->user['username'] . EOL); + info(L10n::t('Please upload a profile photo.') . EOL); + } else { + info(L10n::t("Welcome back ") . $a->user['username'] . EOL); + } + } + + $member_since = strtotime($a->user['register_date']); + if (time() < ($member_since + ( 60 * 60 * 24 * 14))) { + $_SESSION['new_member'] = true; + } else { + $_SESSION['new_member'] = false; + } + if (strlen($a->user['timezone'])) { + date_default_timezone_set($a->user['timezone']); + $a->timezone = $a->user['timezone']; + } + + $master_record = $a->user; + + if ((x($_SESSION, 'submanage')) && intval($_SESSION['submanage'])) { + $user = DBA::selectFirst('user', [], ['uid' => $_SESSION['submanage']]); + if (DBA::isResult($user)) { + $master_record = $user; + } + } + + if ($master_record['parent-uid'] == 0) { + // First add our own entry + $a->identities = [['uid' => $master_record['uid'], + 'username' => $master_record['username'], + 'nickname' => $master_record['nickname']]]; + + // Then add all the children + $r = DBA::select('user', ['uid', 'username', 'nickname'], + ['parent-uid' => $master_record['uid'], 'account_removed' => false]); + if (DBA::isResult($r)) { + $a->identities = array_merge($a->identities, DBA::toArray($r)); + } + } else { + // Just ensure that the array is always defined + $a->identities = []; + + // First entry is our parent + $r = DBA::select('user', ['uid', 'username', 'nickname'], + ['uid' => $master_record['parent-uid'], 'account_removed' => false]); + if (DBA::isResult($r)) { + $a->identities = DBA::toArray($r); + } + + // Then add all siblings + $r = DBA::select('user', ['uid', 'username', 'nickname'], + ['parent-uid' => $master_record['parent-uid'], 'account_removed' => false]); + if (DBA::isResult($r)) { + $a->identities = array_merge($a->identities, DBA::toArray($r)); + } + } + + $r = DBA::p("SELECT `user`.`uid`, `user`.`username`, `user`.`nickname` + FROM `manage` + INNER JOIN `user` ON `manage`.`mid` = `user`.`uid` + WHERE `user`.`account_removed` = 0 AND `manage`.`uid` = ?", + $master_record['uid'] + ); + if (DBA::isResult($r)) { + $a->identities = array_merge($a->identities, DBA::toArray($r)); + } + + if ($login_initial) { + logger('auth_identities: ' . print_r($a->identities, true), LOGGER_DEBUG); + } + if ($login_refresh) { + logger('auth_identities refresh: ' . print_r($a->identities, true), LOGGER_DEBUG); + } + + $contact = DBA::selectFirst('contact', [], ['uid' => $_SESSION['uid'], 'self' => true]); + if (DBA::isResult($contact)) { + $a->contact = $contact; + $a->cid = $contact['id']; + $_SESSION['cid'] = $a->cid; + } + + header('X-Account-Management-Status: active; name="' . $a->user['username'] . '"; id="' . $a->user['nickname'] . '"'); + + if ($login_initial || $login_refresh) { + DBA::update('user', ['login_date' => DateTimeFormat::utcNow()], ['uid' => $_SESSION['uid']]); + + // Set the login date for all identities of the user + DBA::update('user', ['login_date' => DateTimeFormat::utcNow()], + ['parent-uid' => $master_record['uid'], 'account_removed' => false]); + } + + if ($login_initial) { + /* + * If the user specified to remember the authentication, then set a cookie + * that expires after one week (the default is when the browser is closed). + * The cookie will be renewed automatically. + * The week ensures that sessions will expire after some inactivity. + */ + if (!empty($_SESSION['remember'])) { + logger('Injecting cookie for remembered user ' . $a->user['nickname']); + self::new_cookie(604800, $user_record); + unset($_SESSION['remember']); + } + } + + if ($login_initial) { + Addon::callHooks('logged_in', $a->user); + + if (($a->module !== 'home') && isset($_SESSION['return_url'])) { + goaway($a->getbaseUrl() . '/' . $_SESSION['return_url']); + } + } + } + + /** + * @brief Kills the "Friendica" cookie and all session data + */ + public static function nuke_session() + { + self::new_cookie(-3600); // make sure cookie is deleted on browser close, as a security measure + session_unset(); + session_destroy(); + } +} + +?> diff --git a/src/Model/Group.php b/src/Model/Group.php index e313842e41..4f6f97c49d 100644 --- a/src/Model/Group.php +++ b/src/Model/Group.php @@ -7,6 +7,7 @@ namespace Friendica\Model; use Friendica\BaseObject; use Friendica\Core\L10n; use Friendica\Database\DBA; +use Friendica\Util\Security; require_once 'boot.php'; require_once 'include/dba.php'; @@ -409,7 +410,7 @@ class Group extends BaseObject '$createtext' => L10n::t('Create a new group'), '$creategroup' => L10n::t('Group Name: '), '$editgroupstext' => L10n::t('Edit groups'), - '$form_security_token' => get_form_security_token('group_edit'), + '$form_security_token' => Security::get_form_security_token('group_edit'), ]); diff --git a/src/Model/Item.php b/src/Model/Item.php index 824e240cc3..9513f4787a 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -3060,7 +3060,7 @@ class Item extends BaseObject $uid = local_user(); } - if (!can_write_wall($uid)) { + if (!Security::can_write_wall($uid)) { logger('like: unable to write on wall ' . $uid); return false; } diff --git a/src/Model/Photo.php b/src/Model/Photo.php index e64158e175..9abd73e762 100644 --- a/src/Model/Photo.php +++ b/src/Model/Photo.php @@ -14,6 +14,7 @@ use Friendica\Database\DBA; use Friendica\Object\Image; use Friendica\Util\DateTimeFormat; use Friendica\Util\Network; +use Friendica\Util\Security; require_once 'include/dba.php'; @@ -226,7 +227,7 @@ class Photo */ public static function getAlbums($uid, $update = false) { - $sql_extra = permissions_sql($uid); + $sql_extra = Security::permissions_sql($uid); $key = "photo_albums:".$uid.":".local_user().":".remote_user(); $albums = Cache::get($key); diff --git a/src/Module/Login.php b/src/Module/Login.php index 15505a38be..3c123b198c 100644 --- a/src/Module/Login.php +++ b/src/Module/Login.php @@ -7,6 +7,7 @@ namespace Friendica\Module; use Exception; use Friendica\BaseModule; use Friendica\Core\Addon; +use Friendica\Core\Authentication; use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Database\DBA; @@ -16,7 +17,6 @@ use Friendica\Util\Network; use LightOpenID; require_once 'boot.php'; -require_once 'include/security.php'; require_once 'include/text.php'; /** @@ -148,13 +148,13 @@ class Login extends BaseModule } if (!$remember) { - new_cookie(0); // 0 means delete on browser exit + Authentication::new_cookie(0); // 0 means delete on browser exit } // if we haven't failed up this point, log them in. $_SESSION['remember'] = $remember; $_SESSION['last_login_date'] = DateTimeFormat::utcNow(); - authenticate_success($record, true, true); + Authentication::authenticate_success($record, true, true); if (x($_SESSION, 'return_url')) { $return_url = $_SESSION['return_url']; @@ -188,9 +188,9 @@ class Login extends BaseModule ] ); if (DBA::isResult($user)) { - if ($data->hash != cookie_hash($user)) { + if ($data->hash != Authentication::cookie_hash($user)) { logger("Hash for user " . $data->uid . " doesn't fit."); - nuke_session(); + Authentication::nuke_session(); goaway(self::getApp()->getBaseURL()); } @@ -198,11 +198,11 @@ class Login extends BaseModule // Expires after 7 days by default, // can be set via system.auth_cookie_lifetime $authcookiedays = Config::get('system', 'auth_cookie_lifetime', 7); - new_cookie($authcookiedays * 24 * 60 * 60, $user); + Authentication::new_cookie($authcookiedays * 24 * 60 * 60, $user); // Do the authentification if not done by now if (!isset($_SESSION) || !isset($_SESSION['authenticated'])) { - authenticate_success($user); + Authentication::authenticate_success($user); if (Config::get('system', 'paranoia')) { $_SESSION['addr'] = $data->ip; @@ -227,7 +227,7 @@ class Login extends BaseModule if ($check && ($_SESSION['addr'] != $_SERVER['REMOTE_ADDR'])) { logger('Session address changed. Paranoid setting in effect, blocking session. ' . $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']); - nuke_session(); + Authentication::nuke_session(); goaway(self::getApp()->getBaseURL()); } @@ -241,7 +241,7 @@ class Login extends BaseModule ] ); if (!DBA::isResult($user)) { - nuke_session(); + Authentication::nuke_session(); goaway(self::getApp()->getBaseURL()); } @@ -255,7 +255,7 @@ class Login extends BaseModule $_SESSION['last_login_date'] = DateTimeFormat::utcNow(); $login_refresh = true; } - authenticate_success($user, false, false, $login_refresh); + Authentication::authenticate_success($user, false, false, $login_refresh); } } } diff --git a/src/Module/Logout.php b/src/Module/Logout.php index cbfd245f30..74586dc69e 100644 --- a/src/Module/Logout.php +++ b/src/Module/Logout.php @@ -6,6 +6,7 @@ namespace Friendica\Module; use Friendica\BaseModule; use Friendica\Core\Addon; +use Friendica\Core\Authentication; use Friendica\Core\L10n; require_once 'boot.php'; @@ -24,7 +25,7 @@ class Logout extends BaseModule public static function init() { Addon::callHooks("logging_out"); - nuke_session(); + Authentication::nuke_session(); info(L10n::t('Logged out.') . EOL); goaway(self::getApp()->getBaseURL()); } diff --git a/src/Object/Thread.php b/src/Object/Thread.php index cd055ee5eb..89ccc566ef 100644 --- a/src/Object/Thread.php +++ b/src/Object/Thread.php @@ -7,6 +7,7 @@ namespace Friendica\Object; use Friendica\BaseObject; use Friendica\Core\Protocol; use Friendica\Object\Post; +use Friendica\Util\Security; require_once 'boot.php'; require_once 'include/text.php'; @@ -61,11 +62,11 @@ class Thread extends BaseObject break; case 'profile': $this->profile_owner = $a->profile['profile_uid']; - $this->writable = can_write_wall($this->profile_owner); + $this->writable = Security::can_write_wall($this->profile_owner); break; case 'display': $this->profile_owner = $a->profile['uid']; - $this->writable = can_write_wall($this->profile_owner) || $writable; + $this->writable = Security::can_write_wall($this->profile_owner) || $writable; break; case 'community': $this->profile_owner = 0; diff --git a/src/Util/Security.php b/src/Util/Security.php new file mode 100644 index 0000000000..1eb0c3f490 --- /dev/null +++ b/src/Util/Security.php @@ -0,0 +1,273 @@ + $remote_user, 'uid' => $owner_id, 'blocked' => false])) { + $remote_verified = true; + $groups = Group::getIdsByContactId($remote_user); + } + } + + if ($remote_verified) { + $gs = '<<>>'; // should be impossible to match + + if (is_array($groups)) { + foreach ($groups as $g) { + $gs .= '|<' . intval($g) . '>'; + } + } + + $sql = sprintf( + " AND ( NOT (deny_cid REGEXP '<%d>' OR deny_gid REGEXP '%s') + AND ( allow_cid REGEXP '<%d>' OR allow_gid REGEXP '%s' OR ( allow_cid = '' AND allow_gid = '') ) + ) + ", + intval($remote_user), + DBA::escape($gs), + intval($remote_user), + DBA::escape($gs) + ); + } + } + return $sql; + } + + public static function item_permissions_sql($owner_id, $remote_verified = false, $groups = null) + { + $local_user = local_user(); + $remote_user = remote_user(); + + /* + * Construct permissions + * + * default permissions - anonymous user + */ + $sql = " AND NOT `item`.`private`"; + + // Profile owner - everything is visible + if ($local_user && ($local_user == $owner_id)) { + $sql = ''; + } elseif ($remote_user) { + /* + * Authenticated visitor. Unless pre-verified, + * check that the contact belongs to this $owner_id + * and load the groups the visitor belongs to. + * If pre-verified, the caller is expected to have already + * done this and passed the groups into this function. + */ + $set = PermissionSet::get($owner_id, $remote_user, $groups); + + if (!empty($set)) { + $sql_set = " OR (`item`.`private` IN (1,2) AND `item`.`wall` AND `item`.`psid` IN (" . implode(',', $set) . "))"; + } else { + $sql_set = ''; + } + + $sql = " AND (NOT `item`.`private`" . $sql_set . ")"; + } + + return $sql; + } + + /* + * Functions used to protect against Cross-Site Request Forgery + * The security token has to base on at least one value that an attacker can't know - here it's the session ID and the private key. + * In this implementation, a security token is reusable (if the user submits a form, goes back and resubmits the form, maybe with small changes; + * or if the security token is used for ajax-calls that happen several times), but only valid for a certain amout of time (3hours). + * The "typename" seperates the security tokens of different types of forms. This could be relevant in the following case: + * A security token is used to protekt a link from CSRF (e.g. the "delete this profile"-link). + * If the new page contains by any chance external elements, then the used security token is exposed by the referrer. + * Actually, important actions should not be triggered by Links / GET-Requests at all, but somethimes they still are, + * so this mechanism brings in some damage control (the attacker would be able to forge a request to a form of this type, but not to forms of other types). + */ + public static function get_form_security_token($typename = '') + { + $a = get_app(); + + $timestamp = time(); + $sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $timestamp . $typename); + + return $timestamp . '.' . $sec_hash; + } + + public static function check_form_security_token($typename = '', $formname = 'form_security_token') + { + $hash = null; + + if (!empty($_REQUEST[$formname])) { + /// @TODO Careful, not secured! + $hash = $_REQUEST[$formname]; + } + + if (!empty($_SERVER['HTTP_X_CSRF_TOKEN'])) { + /// @TODO Careful, not secured! + $hash = $_SERVER['HTTP_X_CSRF_TOKEN']; + } + + if (empty($hash)) { + return false; + } + + $max_livetime = 10800; // 3 hours + + $a = get_app(); + + $x = explode('.', $hash); + if (time() > (IntVal($x[0]) + $max_livetime)) { + return false; + } + + $sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $x[0] . $typename); + + return ($sec_hash == $x[1]); + } + + private static function check_form_security_std_err_msg() + { + return L10n::t("The form security token was not correct. This probably happened because the form has been opened for too long \x28>3 hours\x29 before submitting it.") . EOL; + } + + public static function check_form_security_token_redirectOnErr($err_redirect, $typename = '', $formname = 'form_security_token') + { + if (!check_form_security_token($typename, $formname)) { + $a = get_app(); + logger('check_form_security_token failed: user ' . $a->user['guid'] . ' - form element ' . $typename); + logger('check_form_security_token failed: _REQUEST data: ' . print_r($_REQUEST, true), LOGGER_DATA); + notice(check_form_security_std_err_msg()); + goaway(System::baseUrl() . $err_redirect); + } + } + + public static function check_form_security_token_ForbiddenOnErr($typename = '', $formname = 'form_security_token') + { + if (!check_form_security_token($typename, $formname)) { + $a = get_app(); + logger('check_form_security_token failed: user ' . $a->user['guid'] . ' - form element ' . $typename); + logger('check_form_security_token failed: _REQUEST data: ' . print_r($_REQUEST, true), LOGGER_DATA); + header('HTTP/1.1 403 Forbidden'); + killme(); + } + } +} + +?> \ No newline at end of file From 45e5a7f59ff9ee5f088d4b3eef6f989c9876d083 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Wed, 17 Oct 2018 18:39:27 +0200 Subject: [PATCH 03/19] remove unsed require_onces of security.php --- mod/community.php | 1 - mod/filer.php | 1 - mod/item.php | 4 ---- mod/like.php | 1 - mod/notes.php | 1 - mod/poke.php | 1 - mod/search.php | 1 - mod/tagger.php | 1 - mod/videos.php | 1 - src/Module/Logout.php | 1 - src/Module/Proxy.php | 2 -- src/Util/Proxy.php | 2 -- 12 files changed, 17 deletions(-) diff --git a/mod/community.php b/mod/community.php index d1432b7bbb..01cf3ec70b 100644 --- a/mod/community.php +++ b/mod/community.php @@ -90,7 +90,6 @@ function community_content(App $a, $update = 0) } } - require_once 'include/security.php'; require_once 'include/conversation.php'; if (!$update) { diff --git a/mod/filer.php b/mod/filer.php index 9b0017322c..d8c89f8554 100644 --- a/mod/filer.php +++ b/mod/filer.php @@ -6,7 +6,6 @@ use Friendica\App; use Friendica\Core\L10n; use Friendica\Core\PConfig; -require_once 'include/security.php'; require_once 'include/items.php'; function filer_content(App $a) diff --git a/mod/item.php b/mod/item.php index 5a665fc7c8..98ab1cbd81 100644 --- a/mod/item.php +++ b/mod/item.php @@ -43,8 +43,6 @@ function item_post(App $a) { return 0; } - require_once 'include/security.php'; - $uid = local_user(); if (!empty($_REQUEST['dropitems'])) { @@ -872,8 +870,6 @@ function item_content(App $a) return; } - require_once 'include/security.php'; - $o = ''; if (($a->argc == 3) && ($a->argv[1] === 'drop') && intval($a->argv[2])) { diff --git a/mod/like.php b/mod/like.php index 957fe5fc42..08e3febbbc 100644 --- a/mod/like.php +++ b/mod/like.php @@ -4,7 +4,6 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Model\Item; -require_once 'include/security.php'; require_once 'include/items.php'; function like_content(App $a) { diff --git a/mod/notes.php b/mod/notes.php index da8352966e..55a92f8e64 100644 --- a/mod/notes.php +++ b/mod/notes.php @@ -33,7 +33,6 @@ function notes_content(App $a, $update = false) return; } - require_once 'include/security.php'; require_once 'include/conversation.php'; $o = Profile::getTabs($a, true); diff --git a/mod/poke.php b/mod/poke.php index 6ebb8632c1..80d476005c 100644 --- a/mod/poke.php +++ b/mod/poke.php @@ -21,7 +21,6 @@ use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\Model\Item; -require_once 'include/security.php'; require_once 'include/items.php'; function poke_init(App $a) diff --git a/mod/search.php b/mod/search.php index 64336e3487..b6e1a7e7f2 100644 --- a/mod/search.php +++ b/mod/search.php @@ -13,7 +13,6 @@ use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Model\Item; -require_once 'include/security.php'; require_once 'include/conversation.php'; require_once 'mod/dirfind.php'; diff --git a/mod/tagger.php b/mod/tagger.php index fd79d54150..f661968f35 100644 --- a/mod/tagger.php +++ b/mod/tagger.php @@ -10,7 +10,6 @@ use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\Model\Item; -require_once 'include/security.php'; require_once 'include/items.php'; function tagger_content(App $a) { diff --git a/mod/videos.php b/mod/videos.php index 0d217ef9c4..50ce361d81 100644 --- a/mod/videos.php +++ b/mod/videos.php @@ -193,7 +193,6 @@ function videos_content(App $a) return; } - require_once 'include/security.php'; require_once 'include/conversation.php'; if (empty($a->data['user'])) { diff --git a/src/Module/Logout.php b/src/Module/Logout.php index 74586dc69e..b2c03bf91f 100644 --- a/src/Module/Logout.php +++ b/src/Module/Logout.php @@ -10,7 +10,6 @@ use Friendica\Core\Authentication; use Friendica\Core\L10n; require_once 'boot.php'; -require_once 'include/security.php'; /** * Logout module diff --git a/src/Module/Proxy.php b/src/Module/Proxy.php index 776dcccb35..8c3493b2ad 100644 --- a/src/Module/Proxy.php +++ b/src/Module/Proxy.php @@ -17,8 +17,6 @@ use Friendica\Util\DateTimeFormat; use Friendica\Util\Network; use Friendica\Util\Proxy as ProxyUtils; -require_once 'include/security.php'; - /** * @brief Module Proxy */ diff --git a/src/Util/Proxy.php b/src/Util/Proxy.php index 0bb7537f78..8478ce868a 100644 --- a/src/Util/Proxy.php +++ b/src/Util/Proxy.php @@ -7,8 +7,6 @@ use Friendica\BaseObject; use Friendica\Core\Config; use Friendica\Core\System; -require_once 'include/security.php'; - /** * @brief Proxy utilities class */ From ce2b1f571573df4d1a9bb26518ab6981d77021b7 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Wed, 17 Oct 2018 18:45:32 +0200 Subject: [PATCH 04/19] Rename function Authentication::authenticate_success to Authentication::success --- include/api.php | 2 +- mod/manage.php | 2 +- mod/openid.php | 2 +- src/Core/Authentication.php | 2 +- src/Module/Login.php | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/api.php b/include/api.php index 51caa9019b..f853798912 100644 --- a/include/api.php +++ b/include/api.php @@ -242,7 +242,7 @@ function api_login(App $a) throw new UnauthorizedException("This API requires login"); } - Authentication::authenticate_success($record); + Authentication::success($record); $_SESSION["allow_api"] = true; diff --git a/mod/manage.php b/mod/manage.php index d54b92a3a7..9e724c1e9b 100644 --- a/mod/manage.php +++ b/mod/manage.php @@ -110,7 +110,7 @@ function manage_post(App $a) { unset($_SESSION['sysmsg_info']); } - Authentication::authenticate_success($r[0], true, true); + Authentication::success($r[0], true, true); if ($limited_id) { $_SESSION['submanage'] = $original_id; diff --git a/mod/openid.php b/mod/openid.php index a9930d0448..ca1129fd50 100644 --- a/mod/openid.php +++ b/mod/openid.php @@ -51,7 +51,7 @@ function openid_content(App $a) { unset($_SESSION['openid']); - Authentication::authenticate_success($r[0],true,true); + Authentication::success($r[0],true,true); // just in case there was no return url set // and we fell through diff --git a/src/Core/Authentication.php b/src/Core/Authentication.php index 3e53a5ae9a..2fbadcc920 100644 --- a/src/Core/Authentication.php +++ b/src/Core/Authentication.php @@ -65,7 +65,7 @@ class Authentication extends BaseObject * @param type $interactive * @param type $login_refresh */ - public static function authenticate_success($user_record, $login_initial = false, $interactive = false, $login_refresh = false) + public static function success($user_record, $login_initial = false, $interactive = false, $login_refresh = false) { $a = self::getApp(); diff --git a/src/Module/Login.php b/src/Module/Login.php index 3c123b198c..fc3b3fb49a 100644 --- a/src/Module/Login.php +++ b/src/Module/Login.php @@ -154,7 +154,7 @@ class Login extends BaseModule // if we haven't failed up this point, log them in. $_SESSION['remember'] = $remember; $_SESSION['last_login_date'] = DateTimeFormat::utcNow(); - Authentication::authenticate_success($record, true, true); + Authentication::success($record, true, true); if (x($_SESSION, 'return_url')) { $return_url = $_SESSION['return_url']; @@ -202,7 +202,7 @@ class Login extends BaseModule // Do the authentification if not done by now if (!isset($_SESSION) || !isset($_SESSION['authenticated'])) { - Authentication::authenticate_success($user); + Authentication::success($user); if (Config::get('system', 'paranoia')) { $_SESSION['addr'] = $data->ip; @@ -255,7 +255,7 @@ class Login extends BaseModule $_SESSION['last_login_date'] = DateTimeFormat::utcNow(); $login_refresh = true; } - Authentication::authenticate_success($user, false, false, $login_refresh); + Authentication::success($user, false, false, $login_refresh); } } } From f3fc1f36caf9139f8d72611b85849a2b7e6759c3 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Wed, 17 Oct 2018 21:30:41 +0200 Subject: [PATCH 05/19] Renaming functions + moving functions from security to Model/Item and BaseModule + fix multiline comments --- include/api.php | 2 +- mod/admin.php | 53 ++++++------- mod/attach.php | 2 +- mod/cal.php | 3 +- mod/delegate.php | 5 +- mod/display.php | 2 +- mod/group.php | 17 +++-- mod/invite.php | 5 +- mod/item.php | 2 +- mod/manage.php | 2 +- mod/openid.php | 2 +- mod/photo.php | 2 +- mod/photos.php | 10 +-- mod/profile.php | 4 +- mod/profile_photo.php | 7 +- mod/register.php | 5 +- mod/settings.php | 33 ++++---- mod/subthread.php | 2 +- mod/videos.php | 2 +- src/BaseModule.php | 83 +++++++++++++++++++++ src/Content/Widget/TagCloud.php | 3 +- src/Core/Authentication.php | 15 ++-- src/Model/Group.php | 3 +- src/Model/Item.php | 37 +++++++++ src/Model/Photo.php | 2 +- src/Module/Login.php | 18 ++--- src/Module/Logout.php | 2 +- src/Object/Thread.php | 4 +- src/Util/Security.php | 128 ++------------------------------ 29 files changed, 233 insertions(+), 222 deletions(-) diff --git a/include/api.php b/include/api.php index f853798912..5e108632c9 100644 --- a/include/api.php +++ b/include/api.php @@ -242,7 +242,7 @@ function api_login(App $a) throw new UnauthorizedException("This API requires login"); } - Authentication::success($record); + Authentication::setAuthenticatedSessionForUser($record); $_SESSION["allow_api"] = true; diff --git a/mod/admin.php b/mod/admin.php index ccadfa525c..094206eb96 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -6,6 +6,7 @@ */ use Friendica\App; +use Friendica\BaseModule; use Friendica\Content\Feature; use Friendica\Content\Text\Markdown; use Friendica\Core\Addon; @@ -314,7 +315,7 @@ function admin_page_tos(App $a) '$preview' => L10n::t('Privacy Statement Preview'), '$privtext' => $tos->privacy_complete, '$tostext' => ['tostext', L10n::t('The Terms of Service'), Config::get('system', 'tostext'), L10n::t('Enter the Terms of Service for your node here. You can use BBCode. Headers of sections should be [h2] and below.')], - '$form_security_token' => Security::get_form_security_token("admin_tos"), + '$form_security_token' => BaseModule::getFormSecurityToken("admin_tos"), '$submit' => L10n::t('Save Settings'), ]); } @@ -325,7 +326,7 @@ function admin_page_tos(App $a) */ function admin_page_tos_post(App $a) { - Security::check_form_security_token_redirectOnErr('/admin/tos', 'admin_tos'); + BaseModule::checkFormSecurityTokenRedirectOnError('/admin/tos', 'admin_tos'); if (!x($_POST, "page_tos")) { return; @@ -385,7 +386,7 @@ function admin_page_blocklist(App $a) '$entries' => $blocklistform, '$baseurl' => System::baseUrl(true), '$confirm_delete' => L10n::t('Delete entry from blocklist?'), - '$form_security_token' => Security::get_form_security_token("admin_blocklist") + '$form_security_token' => BaseModule::getFormSecurityToken("admin_blocklist") ]); } @@ -400,7 +401,7 @@ function admin_page_blocklist_post(App $a) return; } - Security::check_form_security_token_redirectOnErr('/admin/blocklist', 'admin_blocklist'); + BaseModule::checkFormSecurityTokenRedirectOnError('/admin/blocklist', 'admin_blocklist'); if (x($_POST['page_blocklist_save'])) { // Add new item to blocklist @@ -443,7 +444,7 @@ function admin_page_contactblock_post(App $a) $contact_url = x($_POST, 'contact_url') ? $_POST['contact_url'] : ''; $contacts = x($_POST, 'contacts') ? $_POST['contacts'] : []; - Security::check_form_security_token_redirectOnErr('/admin/contactblock', 'admin_contactblock'); + BaseModule::checkFormSecurityTokenRedirectOnError('/admin/contactblock', 'admin_contactblock'); if (x($_POST, 'page_contactblock_block')) { $contact_id = Contact::getIdForURL($contact_url); @@ -500,7 +501,7 @@ function admin_page_contactblock(App $a) '$h_newblock' => L10n::t('Block New Remote Contact'), '$th_contacts' => [L10n::t('Photo'), L10n::t('Name'), L10n::t('Address'), L10n::t('Profile URL')], - '$form_security_token' => Security::get_form_security_token("admin_contactblock"), + '$form_security_token' => BaseModule::getFormSecurityToken("admin_contactblock"), // values // '$baseurl' => System::baseUrl(true), @@ -535,7 +536,7 @@ function admin_page_deleteitem(App $a) '$intro2' => L10n::t('You need to know the GUID of the item. You can find it e.g. by looking at the display URL. The last part of http://example.com/display/123456 is the GUID, here 123456.'), '$deleteitemguid' => ['deleteitemguid', L10n::t("GUID"), '', L10n::t("The GUID of the item you want to delete."), 'required', 'autofocus'], '$baseurl' => System::baseUrl(), - '$form_security_token' => Security::get_form_security_token("admin_deleteitem") + '$form_security_token' => BaseModule::getFormSecurityToken("admin_deleteitem") ]); } @@ -553,7 +554,7 @@ function admin_page_deleteitem_post(App $a) return; } - Security::check_form_security_token_redirectOnErr('/admin/deleteitem/', 'admin_deleteitem'); + BaseModule::checkFormSecurityTokenRedirectOnError('/admin/deleteitem/', 'admin_deleteitem'); if (x($_POST['page_deleteitem_submit'])) { $guid = trim(notags($_POST['deleteitemguid'])); @@ -946,7 +947,7 @@ function admin_page_summary(App $a) */ function admin_page_site_post(App $a) { - Security::check_form_security_token_redirectOnErr('/admin/site', 'admin_site'); + BaseModule::checkFormSecurityTokenRedirectOnError('/admin/site', 'admin_site'); if (!empty($_POST['republish_directory'])) { Worker::add(PRIORITY_LOW, 'Directory'); @@ -1542,7 +1543,7 @@ function admin_page_site(App $a) '$relay_server_tags' => ['relay_server_tags', L10n::t("Server tags"), Config::get('system','relay_server_tags'), L10n::t("Comma separated list of tags for the 'tags' subscription.")], '$relay_user_tags' => ['relay_user_tags', L10n::t("Allow user tags"), Config::get('system', 'relay_user_tags', true), L10n::t("If enabled, the tags from the saved searches will used for the 'tags' subscription in addition to the 'relay_server_tags'.")], - '$form_security_token' => Security::get_form_security_token("admin_site"), + '$form_security_token' => BaseModule::getFormSecurityToken("admin_site"), '$relocate_button' => L10n::t('Start Relocation'), ]); } @@ -1657,7 +1658,7 @@ function admin_page_users_post(App $a) $nu_email = defaults($_POST, 'new_user_email' , ''); $nu_language = Config::get('system', 'language'); - Security::check_form_security_token_redirectOnErr('/admin/users', 'admin_users'); + BaseModule::checkFormSecurityTokenRedirectOnError('/admin/users', 'admin_users'); if (!($nu_name === "") && !($nu_email === "") && !($nu_nickname === "")) { try { @@ -1773,14 +1774,14 @@ function admin_page_users(App $a) } switch ($a->argv[2]) { case "delete": - Security::check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't'); + BaseModule::checkFormSecurityTokenRedirectOnError('/admin/users', 'admin_users', 't'); // delete user User::remove($uid); notice(L10n::t("User '%s' deleted", $user['username']) . EOL); break; case "block": - Security::check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't'); + BaseModule::checkFormSecurityTokenRedirectOnError('/admin/users', 'admin_users', 't'); q("UPDATE `user` SET `blocked` = %d WHERE `uid` = %s", intval(1 - $user['blocked']), intval($uid) @@ -1931,7 +1932,7 @@ function admin_page_users(App $a) '$confirm_delete_multi' => L10n::t('Selected users will be deleted!\n\nEverything these users had posted on this site will be permanently deleted!\n\nAre you sure?'), '$confirm_delete' => L10n::t('The user {0} will be deleted!\n\nEverything this user has posted on this site will be permanently deleted!\n\nAre you sure?'), - '$form_security_token' => Security::get_form_security_token("admin_users"), + '$form_security_token' => BaseModule::getFormSecurityToken("admin_users"), // values // '$baseurl' => System::baseUrl(true), @@ -1976,7 +1977,7 @@ function admin_page_addons(App $a) } if (x($_GET, "a") && $_GET['a'] == "t") { - Security::check_form_security_token_redirectOnErr('/admin/addons', 'admin_themes', 't'); + BaseModule::checkFormSecurityTokenRedirectOnError('/admin/addons', 'admin_themes', 't'); // Toggle addon status $idx = array_search($addon, $a->addons); @@ -2038,7 +2039,7 @@ function admin_page_addons(App $a) '$screenshot' => '', '$readme' => $readme, - '$form_security_token' => Security::get_form_security_token("admin_themes"), + '$form_security_token' => BaseModule::getFormSecurityToken("admin_themes"), ]); } @@ -2046,7 +2047,7 @@ function admin_page_addons(App $a) * List addons */ if (x($_GET, "a") && $_GET['a'] == "r") { - Security::check_form_security_token_redirectOnErr(System::baseUrl() . '/admin/addons', 'admin_themes', 't'); + BaseModule::checkFormSecurityTokenRedirectOnError(System::baseUrl() . '/admin/addons', 'admin_themes', 't'); Addon::reload(); info("Addons reloaded"); goaway(System::baseUrl() . '/admin/addons'); @@ -2089,7 +2090,7 @@ function admin_page_addons(App $a) '$addons' => $addons, '$pcount' => count($addons), '$noplugshint' => L10n::t('There are currently no addons available on your node. You can find the official addon repository at %1$s and might find other interesting addons in the open addon registry at %2$s', 'https://github.com/friendica/friendica-addons', 'http://addons.friendi.ca'), - '$form_security_token' => Security::get_form_security_token("admin_themes"), + '$form_security_token' => BaseModule::getFormSecurityToken("admin_themes"), ]); } @@ -2224,7 +2225,7 @@ function admin_page_themes(App $a) } if (x($_GET, "a") && $_GET['a'] == "t") { - Security::check_form_security_token_redirectOnErr('/admin/themes', 'admin_themes', 't'); + BaseModule::checkFormSecurityTokenRedirectOnError('/admin/themes', 'admin_themes', 't'); // Toggle theme status @@ -2306,13 +2307,13 @@ function admin_page_themes(App $a) '$screenshot' => $screenshot, '$readme' => $readme, - '$form_security_token' => Security::get_form_security_token("admin_themes"), + '$form_security_token' => BaseModule::getFormSecurityToken("admin_themes"), ]); } // reload active themes if (x($_GET, "a") && $_GET['a'] == "r") { - Security::check_form_security_token_redirectOnErr(System::baseUrl() . '/admin/themes', 'admin_themes', 't'); + BaseModule::checkFormSecurityTokenRedirectOnError(System::baseUrl() . '/admin/themes', 'admin_themes', 't'); foreach ($themes as $th) { if ($th['allowed']) { Theme::uninstall($th['name']); @@ -2345,7 +2346,7 @@ function admin_page_themes(App $a) '$noplugshint' => L10n::t('No themes found on the system. They should be placed in %1$s', '/view/themes'), '$experimental' => L10n::t('[Experimental]'), '$unsupported' => L10n::t('[Unsupported]'), - '$form_security_token' => Security::get_form_security_token("admin_themes"), + '$form_security_token' => BaseModule::getFormSecurityToken("admin_themes"), ]); } @@ -2357,7 +2358,7 @@ function admin_page_themes(App $a) function admin_page_logs_post(App $a) { if (x($_POST, "page_logs")) { - Security::check_form_security_token_redirectOnErr('/admin/logs', 'admin_logs'); + BaseModule::checkFormSecurityTokenRedirectOnError('/admin/logs', 'admin_logs'); $logfile = ((x($_POST,'logfile')) ? notags(trim($_POST['logfile'])) : ''); $debugging = ((x($_POST,'debugging')) ? true : false); @@ -2419,7 +2420,7 @@ function admin_page_logs(App $a) '$debugging' => ['debugging', L10n::t("Enable Debugging"), Config::get('system', 'debugging'), ""], '$logfile' => ['logfile', L10n::t("Log file"), Config::get('system', 'logfile'), L10n::t("Must be writable by web server. Relative to your Friendica top-level directory.")], '$loglevel' => ['loglevel', L10n::t("Log level"), Config::get('system', 'loglevel'), "", $log_choices], - '$form_security_token' => Security::get_form_security_token("admin_logs"), + '$form_security_token' => BaseModule::getFormSecurityToken("admin_logs"), '$phpheader' => L10n::t("PHP logging"), '$phphint' => L10n::t("To temporarily enable logging of PHP errors and warnings you can prepend the following to the index.php file of your installation. The filename set in the 'error_log' line is relative to the friendica top-level directory and must be writeable by the web server. The option '1' for 'log_errors' and 'display_errors' is to enable these options, set to '0' to disable them."), '$phplogcode' => "error_reporting(E_ERROR | E_WARNING | E_PARSE);\nini_set('error_log','php.out');\nini_set('log_errors','1');\nini_set('display_errors', '1');", @@ -2490,7 +2491,7 @@ function admin_page_viewlogs(App $a) */ function admin_page_features_post(App $a) { - Security::check_form_security_token_redirectOnErr('/admin/features', 'admin_manage_features'); + BaseModule::checkFormSecurityTokenRedirectOnError('/admin/features', 'admin_manage_features'); logger('postvars: ' . print_r($_POST, true), LOGGER_DATA); @@ -2555,7 +2556,7 @@ function admin_page_features(App $a) $tpl = get_markup_template('admin/settings_features.tpl'); $o = replace_macros($tpl, [ - '$form_security_token' => Security::get_form_security_token("admin_manage_features"), + '$form_security_token' => BaseModule::getFormSecurityToken("admin_manage_features"), '$title' => L10n::t('Manage Additional Features'), '$features' => $arr, '$submit' => L10n::t('Save Settings'), diff --git a/mod/attach.php b/mod/attach.php index 97eb10997e..9ca701ba35 100644 --- a/mod/attach.php +++ b/mod/attach.php @@ -27,7 +27,7 @@ function attach_init(App $a) return; } - $sql_extra = Security::permissions_sql($r['uid']); + $sql_extra = Security::getPermissionsSQLByUserId($r['uid']); // Now we'll see if we can access the attachment diff --git a/mod/cal.php b/mod/cal.php index cc6973d472..b55e078d83 100644 --- a/mod/cal.php +++ b/mod/cal.php @@ -17,6 +17,7 @@ use Friendica\Database\DBA; use Friendica\Model\Contact; use Friendica\Model\Event; use Friendica\Model\Group; +use Friendica\Model\Item; use Friendica\Model\Profile; use Friendica\Protocol\DFRN; use Friendica\Util\DateTimeFormat; @@ -142,7 +143,7 @@ function cal_content(App $a) } // get the permissions - $sql_perms = Security::item_permissions_sql($owner_uid, $remote_contact, $groups); + $sql_perms = Item::getPermissionsSQLByUserId($owner_uid, $remote_contact, $groups); // we only want to have the events of the profile owner $sql_extra = " AND `event`.`cid` = 0 " . $sql_perms; diff --git a/mod/delegate.php b/mod/delegate.php index f711f593fa..2b29632dda 100644 --- a/mod/delegate.php +++ b/mod/delegate.php @@ -4,6 +4,7 @@ */ use Friendica\App; +use Friendica\BaseModule; use Friendica\Core\L10n; use Friendica\Core\Protocol; use Friendica\Core\System; @@ -29,7 +30,7 @@ function delegate_post(App $a) return; } - Security::check_form_security_token_redirectOnErr('/delegate', 'delegate'); + BaseModule::checkFormSecurityTokenRedirectOnError('/delegate', 'delegate'); $parent_uid = defaults($_POST, 'parent_user', 0); $parent_password = defaults($_POST, 'parent_password', ''); @@ -163,7 +164,7 @@ function delegate_content(App $a) } $o = replace_macros(get_markup_template('delegate.tpl'), [ - '$form_security_token' => Security::get_form_security_token('delegate'), + '$form_security_token' => BaseModule::getFormSecurityToken('delegate'), '$parent_header' => L10n::t('Parent User'), '$parent_user' => $parent_user, '$parent_password' => $parent_password, diff --git a/mod/display.php b/mod/display.php index 0c1cc90375..081c3ce6cf 100644 --- a/mod/display.php +++ b/mod/display.php @@ -325,7 +325,7 @@ function display_content(App $a, $update = false, $update_uid = 0) $o .= status_editor($a, $x, 0, true); } - $sql_extra = Security::item_permissions_sql($a->profile['uid'], $is_remote_contact, $groups); + $sql_extra = Item::getPermissionsSQLByUserId($a->profile['uid'], $is_remote_contact, $groups); if (local_user() && (local_user() == $a->profile['uid'])) { $condition = ['parent-uri' => $item_parent_uri, 'uid' => local_user(), 'unseen' => true]; diff --git a/mod/group.php b/mod/group.php index 09fe676c17..129cf18c2a 100644 --- a/mod/group.php +++ b/mod/group.php @@ -6,6 +6,7 @@ */ use Friendica\App; +use Friendica\BaseModule; use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Core\PConfig; @@ -29,7 +30,7 @@ function group_post(App $a) { } if (($a->argc == 2) && ($a->argv[1] === 'new')) { - Security::check_form_security_token_redirectOnErr('/group/new', 'group_edit'); + BaseModule::checkFormSecurityTokenRedirectOnError('/group/new', 'group_edit'); $name = notags(trim($_POST['groupname'])); $r = Model\Group::create(local_user(), $name); @@ -47,7 +48,7 @@ function group_post(App $a) { } if (($a->argc == 2) && intval($a->argv[1])) { - Security::check_form_security_token_redirectOnErr('/group', 'group_edit'); + BaseModule::checkFormSecurityTokenRedirectOnError('/group', 'group_edit'); $r = q("SELECT * FROM `group` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($a->argv[1]), @@ -108,7 +109,7 @@ function group_content(App $a) { '$title' => L10n::t('Create a group of contacts/friends.'), '$gname' => ['groupname', L10n::t('Group Name: '), '', ''], '$gid' => 'new', - '$form_security_token' => Security::get_form_security_token("group_edit"), + '$form_security_token' => BaseModule::getFormSecurityToken("group_edit"), ]); @@ -138,7 +139,7 @@ function group_content(App $a) { if (($a->argc == 3) && ($a->argv[1] === 'drop')) { - Security::check_form_security_token_redirectOnErr('/group', 'group_drop', 't'); + BaseModule::checkFormSecurityTokenRedirectOnError('/group', 'group_drop', 't'); if (intval($a->argv[2])) { $r = q("SELECT `name` FROM `group` WHERE `id` = %d AND `uid` = %d LIMIT 1", @@ -163,7 +164,7 @@ function group_content(App $a) { } if (($a->argc > 2) && intval($a->argv[1]) && intval($a->argv[2])) { - Security::check_form_security_token_ForbiddenOnErr('group_member_change', 't'); + BaseModule::checkFormSecurityTokenForbiddenOnError('group_member_change', 't'); $r = q("SELECT `id` FROM `contact` WHERE `id` = %d AND `uid` = %d and `self` = 0 and `blocked` = 0 AND `pending` = 0 LIMIT 1", intval($a->argv[2]), @@ -217,7 +218,7 @@ function group_content(App $a) { $drop_txt = replace_macros($drop_tpl, [ '$id' => $group['id'], '$delete' => L10n::t('Delete Group'), - '$form_security_token' => Security::get_form_security_token("group_drop"), + '$form_security_token' => BaseModule::getFormSecurityToken("group_drop"), ]); @@ -226,7 +227,7 @@ function group_content(App $a) { '$gname' => ['groupname', L10n::t('Group Name: '), $group['name'], ''], '$gid' => $group['id'], '$drop' => $drop_txt, - '$form_security_token' => Security::get_form_security_token('group_edit'), + '$form_security_token' => BaseModule::getFormSecurityToken('group_edit'), '$edit_name' => L10n::t('Edit Group Name'), '$editable' => 1, ]; @@ -245,7 +246,7 @@ function group_content(App $a) { 'contacts' => [], ]; - $sec_token = addslashes(Security::get_form_security_token('group_member_change')); + $sec_token = addslashes(BaseModule::getFormSecurityToken('group_member_change')); // Format the data of the group members foreach ($members as $member) { diff --git a/mod/invite.php b/mod/invite.php index cd9de6cc0a..e73ef01edb 100644 --- a/mod/invite.php +++ b/mod/invite.php @@ -7,6 +7,7 @@ */ use Friendica\App; +use Friendica\BaseModule; use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Core\PConfig; @@ -23,7 +24,7 @@ function invite_post(App $a) return; } - Security::check_form_security_token_redirectOnErr('/', 'send_invite'); + BaseModule::checkFormSecurityTokenRedirectOnError('/', 'send_invite'); $max_invites = intval(Config::get('system', 'max_invites')); if (! $max_invites) { @@ -145,7 +146,7 @@ function invite_content(App $a) { } $o = replace_macros($tpl, [ - '$form_security_token' => Security::get_form_security_token("send_invite"), + '$form_security_token' => BaseModule::getFormSecurityToken("send_invite"), '$title' => L10n::t('Send invitations'), '$recipients' => ['recipients', L10n::t('Enter email addresses, one per line:')], '$message' => ['message', L10n::t('Your message:'),L10n::t('You are cordially invited to join me and other close friends on Friendica - and help us to create a better social web.') . "\r\n" . "\r\n" diff --git a/mod/item.php b/mod/item.php index 98ab1cbd81..dc93a9f798 100644 --- a/mod/item.php +++ b/mod/item.php @@ -161,7 +161,7 @@ function item_post(App $a) { $allow_comment = local_user() && ($profile_uid == 0) && $parent && in_array($parent_item['network'], [Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN]); // Now check that valid personal details have been provided - if (!Security::can_write_wall($profile_uid) && !$allow_comment) { + if (!Security::canWriteToUserWall($profile_uid) && !$allow_comment) { notice(L10n::t('Permission denied.') . EOL) ; if (!empty($_REQUEST['return'])) { diff --git a/mod/manage.php b/mod/manage.php index 9e724c1e9b..d38d90ce60 100644 --- a/mod/manage.php +++ b/mod/manage.php @@ -110,7 +110,7 @@ function manage_post(App $a) { unset($_SESSION['sysmsg_info']); } - Authentication::success($r[0], true, true); + Authentication::setAuthenticatedSessionForUser($r[0], true, true); if ($limited_id) { $_SESSION['submanage'] = $original_id; diff --git a/mod/openid.php b/mod/openid.php index ca1129fd50..41aabe7a97 100644 --- a/mod/openid.php +++ b/mod/openid.php @@ -51,7 +51,7 @@ function openid_content(App $a) { unset($_SESSION['openid']); - Authentication::success($r[0],true,true); + Authentication::setAuthenticatedSessionForUser($r[0],true,true); // just in case there was no return url set // and we fell through diff --git a/mod/photo.php b/mod/photo.php index 3a0a199d8c..083b7cfc99 100644 --- a/mod/photo.php +++ b/mod/photo.php @@ -110,7 +110,7 @@ function photo_init(App $a) intval($resolution) ); if (DBA::isResult($r)) { - $sql_extra = Security::permissions_sql($r[0]['uid']); + $sql_extra = Security::getPermissionsSQLByUserId($r[0]['uid']); // Now we'll see if we can access the photo $r = q("SELECT * FROM `photo` WHERE `resource-id` = '%s' AND `scale` <= %d $sql_extra ORDER BY scale DESC LIMIT 1", diff --git a/mod/photos.php b/mod/photos.php index 4208e22754..55c8881e4c 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -1052,7 +1052,7 @@ function photos_content(App $a) return; } - $sql_extra = Security::permissions_sql($owner_uid, $remote_contact, $groups); + $sql_extra = Security::getPermissionsSQLByUserId($owner_uid, $remote_contact, $groups); $o = ""; @@ -1472,7 +1472,7 @@ function photos_content(App $a) $tpl = get_markup_template('photo_item.tpl'); $return_url = $a->cmd; - if ($can_post || Security::can_write_wall($owner_uid)) { + if ($can_post || Security::canWriteToUserWall($owner_uid)) { $like_tpl = get_markup_template('like_noshare.tpl'); $likebuttons = replace_macros($like_tpl, [ '$id' => $link_item['id'], @@ -1484,7 +1484,7 @@ function photos_content(App $a) } if (!DBA::isResult($items)) { - if (($can_post || Security::can_write_wall($owner_uid))) { + if (($can_post || Security::canWriteToUserWall($owner_uid))) { $comments .= replace_macros($cmnt_tpl, [ '$return_path' => '', '$jsreload' => $return_url, @@ -1523,7 +1523,7 @@ function photos_content(App $a) $dislike = format_like($conv_responses['dislike'][$link_item['uri']], $conv_responses['dislike'][$link_item['uri'] . '-l'], 'dislike', $link_item['id']); } - if (($can_post || Security::can_write_wall($owner_uid))) { + if (($can_post || Security::canWriteToUserWall($owner_uid))) { $comments .= replace_macros($cmnt_tpl,[ '$return_path' => '', '$jsreload' => $return_url, @@ -1583,7 +1583,7 @@ function photos_content(App $a) '$comment' => $comment ]); - if (($can_post || Security::can_write_wall($owner_uid))) { + if (($can_post || Security::canWriteToUserWall($owner_uid))) { $comments .= replace_macros($cmnt_tpl, [ '$return_path' => '', '$jsreload' => $return_url, diff --git a/mod/profile.php b/mod/profile.php index 5484beb265..8d5ae87585 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -210,7 +210,7 @@ function profile_content(App $a, $update = 0) $a->page['aside'] .= Widget::categories(System::baseUrl(true) . '/profile/' . $a->profile['nickname'], (!empty($category) ? xmlify($category) : '')); $a->page['aside'] .= Widget::tagCloud(); - if (Security::can_write_wall($a->profile['profile_uid'])) { + if (Security::canWriteToUserWall($a->profile['profile_uid'])) { $x = [ 'is_owner' => $is_owner, 'allow_location' => ($is_owner || $commvisitor) && $a->profile['allow_location'], @@ -234,7 +234,7 @@ function profile_content(App $a, $update = 0) // Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups - $sql_extra = Security::item_permissions_sql($a->profile['profile_uid'], $remote_contact, $groups); + $sql_extra = Item::getPermissionsSQLByUserId($a->profile['profile_uid'], $remote_contact, $groups); $sql_extra2 = ''; if ($update) { diff --git a/mod/profile_photo.php b/mod/profile_photo.php index 492be7e4ae..1e0687c654 100644 --- a/mod/profile_photo.php +++ b/mod/profile_photo.php @@ -4,6 +4,7 @@ */ use Friendica\App; +use Friendica\BaseModule; use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Core\System; @@ -31,7 +32,7 @@ function profile_photo_post(App $a) return; } - Security::check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo'); + BaseModule::checkFormSecurityTokenRedirectOnError('/profile_photo', 'profile_photo'); if (!empty($_POST['cropfinal']) && $_POST['cropfinal'] == 1) { @@ -247,7 +248,7 @@ function profile_photo_content(App $a) '$title' => L10n::t('Upload Profile Photo'), '$submit' => L10n::t('Upload'), '$profiles' => $profiles, - '$form_security_token' => Security::get_form_security_token("profile_photo"), + '$form_security_token' => BaseModule::getFormSecurityToken("profile_photo"), '$select' => sprintf('%s %s', L10n::t('or'), ($newuser) ? '' . L10n::t('skip this step') . '' : '' . L10n::t('select a photo from your photo albums') . '') ]); @@ -264,7 +265,7 @@ function profile_photo_content(App $a) '$image_url' => System::baseUrl() . '/photo/' . $filename, '$title' => L10n::t('Crop Image'), '$desc' => L10n::t('Please adjust the image cropping for optimum viewing.'), - '$form_security_token' => Security::get_form_security_token("profile_photo"), + '$form_security_token' => BaseModule::getFormSecurityToken("profile_photo"), '$done' => L10n::t('Done Editing') ]); return $o; diff --git a/mod/register.php b/mod/register.php index 9a2ad0f482..7b53e907ec 100644 --- a/mod/register.php +++ b/mod/register.php @@ -4,6 +4,7 @@ */ use Friendica\App; +use Friendica\BaseModule; use Friendica\Content\Text\BBCode; use Friendica\Core\Addon; use Friendica\Core\Config; @@ -21,7 +22,7 @@ require_once 'include/enotify.php'; function register_post(App $a) { - Security::check_form_security_token_redirectOnErr('/register', 'register'); + BaseModule::checkFormSecurityTokenRedirectOnError('/register', 'register'); $verified = 0; $blocked = 1; @@ -292,7 +293,7 @@ function register_content(App $a) '$showprivstatement' => Config::get('system', 'tosprivstatement'), '$privstatement' => $tos->privacy_complete, '$baseurl' => System::baseurl(), - '$form_security_token' => Security::get_form_security_token("register"), + '$form_security_token' => BaseModule::getFormSecurityToken("register"), '$explicit_content' => Config::get('system', 'explicit_content', false), '$explicit_content_note' => L10n::t('Note: This node explicitly contains adult content') ]); diff --git a/mod/settings.php b/mod/settings.php index 3737aeadac..cb88823997 100644 --- a/mod/settings.php +++ b/mod/settings.php @@ -4,6 +4,7 @@ */ use Friendica\App; +use Friendica\BaseModule; use Friendica\Content\Feature; use Friendica\Content\Nav; use Friendica\Core\ACL; @@ -155,7 +156,7 @@ function settings_post(App $a) $old_page_flags = $a->user['page-flags']; if (($a->argc > 1) && ($a->argv[1] === 'oauth') && x($_POST, 'remove')) { - Security::check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth'); + BaseModule::checkFormSecurityTokenRedirectOnError('/settings/oauth', 'settings_oauth'); $key = $_POST['remove']; DBA::delete('tokens', ['id' => $key, 'uid' => local_user()]); @@ -164,7 +165,7 @@ function settings_post(App $a) } if (($a->argc > 2) && ($a->argv[1] === 'oauth') && ($a->argv[2] === 'edit'||($a->argv[2] === 'add')) && x($_POST, 'submit')) { - Security::check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth'); + BaseModule::checkFormSecurityTokenRedirectOnError('/settings/oauth', 'settings_oauth'); $name = defaults($_POST, 'name' , ''); $key = defaults($_POST, 'key' , ''); @@ -210,14 +211,14 @@ function settings_post(App $a) } if (($a->argc > 1) && ($a->argv[1] == 'addon')) { - Security::check_form_security_token_redirectOnErr('/settings/addon', 'settings_addon'); + BaseModule::checkFormSecurityTokenRedirectOnError('/settings/addon', 'settings_addon'); Addon::callHooks('addon_settings_post', $_POST); return; } if (($a->argc > 1) && ($a->argv[1] == 'connectors')) { - Security::check_form_security_token_redirectOnErr('/settings/connectors', 'settings_connectors'); + BaseModule::checkFormSecurityTokenRedirectOnError('/settings/connectors', 'settings_connectors'); if (x($_POST, 'general-submit')) { PConfig::set(local_user(), 'system', 'disable_cw', intval($_POST['disable_cw'])); @@ -299,7 +300,7 @@ function settings_post(App $a) } if (($a->argc > 1) && ($a->argv[1] === 'features')) { - Security::check_form_security_token_redirectOnErr('/settings/features', 'settings_features'); + BaseModule::checkFormSecurityTokenRedirectOnError('/settings/features', 'settings_features'); foreach ($_POST as $k => $v) { if (strpos($k, 'feature_') === 0) { PConfig::set(local_user(), 'feature', substr($k, 8), ((intval($v)) ? 1 : 0)); @@ -310,7 +311,7 @@ function settings_post(App $a) } if (($a->argc > 1) && ($a->argv[1] === 'display')) { - Security::check_form_security_token_redirectOnErr('/settings/display', 'settings_display'); + BaseModule::checkFormSecurityTokenRedirectOnError('/settings/display', 'settings_display'); $theme = x($_POST, 'theme') ? notags(trim($_POST['theme'])) : $a->user['theme']; $mobile_theme = x($_POST, 'mobile_theme') ? notags(trim($_POST['mobile_theme'])) : ''; @@ -374,7 +375,7 @@ function settings_post(App $a) return; // NOTREACHED } - Security::check_form_security_token_redirectOnErr('/settings', 'settings'); + BaseModule::checkFormSecurityTokenRedirectOnError('/settings', 'settings'); if (x($_POST,'resend_relocate')) { Worker::add(PRIORITY_HIGH, 'Notifier', 'relocate', local_user()); @@ -672,7 +673,7 @@ function settings_content(App $a) if (($a->argc > 2) && ($a->argv[2] === 'add')) { $tpl = get_markup_template('settings/oauth_edit.tpl'); $o .= replace_macros($tpl, [ - '$form_security_token' => Security::get_form_security_token("settings_oauth"), + '$form_security_token' => BaseModule::getFormSecurityToken("settings_oauth"), '$title' => L10n::t('Add application'), '$submit' => L10n::t('Save Settings'), '$cancel' => L10n::t('Cancel'), @@ -698,7 +699,7 @@ function settings_content(App $a) $tpl = get_markup_template('settings/oauth_edit.tpl'); $o .= replace_macros($tpl, [ - '$form_security_token' => Security::get_form_security_token("settings_oauth"), + '$form_security_token' => BaseModule::getFormSecurityToken("settings_oauth"), '$title' => L10n::t('Add application'), '$submit' => L10n::t('Update'), '$cancel' => L10n::t('Cancel'), @@ -712,7 +713,7 @@ function settings_content(App $a) } if (($a->argc > 3) && ($a->argv[2] === 'delete')) { - Security::check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth', 't'); + BaseModule::checkFormSecurityTokenRedirectOnError('/settings/oauth', 'settings_oauth', 't'); DBA::delete('clients', ['client_id' => $a->argv[3], 'uid' => local_user()]); goaway(System::baseUrl(true)."/settings/oauth/"); @@ -730,7 +731,7 @@ function settings_content(App $a) $tpl = get_markup_template('settings/oauth.tpl'); $o .= replace_macros($tpl, [ - '$form_security_token' => Security::get_form_security_token("settings_oauth"), + '$form_security_token' => BaseModule::getFormSecurityToken("settings_oauth"), '$baseurl' => System::baseUrl(true), '$title' => L10n::t('Connected Apps'), '$add' => L10n::t('Add application'), @@ -757,7 +758,7 @@ function settings_content(App $a) $tpl = get_markup_template('settings/addons.tpl'); $o .= replace_macros($tpl, [ - '$form_security_token' => Security::get_form_security_token("settings_addon"), + '$form_security_token' => BaseModule::getFormSecurityToken("settings_addon"), '$title' => L10n::t('Addon Settings'), '$settings_addons' => $settings_addons ]); @@ -778,7 +779,7 @@ function settings_content(App $a) $tpl = get_markup_template('settings/features.tpl'); $o .= replace_macros($tpl, [ - '$form_security_token' => Security::get_form_security_token("settings_features"), + '$form_security_token' => BaseModule::getFormSecurityToken("settings_features"), '$title' => L10n::t('Additional Features'), '$features' => $arr, '$submit' => L10n::t('Save Settings'), @@ -837,7 +838,7 @@ function settings_content(App $a) $mail_disabled_message = (($mail_disabled) ? L10n::t('Email access is disabled on this site.') : ''); $o .= replace_macros($tpl, [ - '$form_security_token' => Security::get_form_security_token("settings_connectors"), + '$form_security_token' => BaseModule::getFormSecurityToken("settings_connectors"), '$title' => L10n::t('Social Networks'), @@ -957,7 +958,7 @@ function settings_content(App $a) $tpl = get_markup_template('settings/display.tpl'); $o = replace_macros($tpl, [ '$ptitle' => L10n::t('Display Settings'), - '$form_security_token' => Security::get_form_security_token("settings_display"), + '$form_security_token' => BaseModule::getFormSecurityToken("settings_display"), '$submit' => L10n::t('Save Settings'), '$baseurl' => System::baseUrl(true), '$uid' => local_user(), @@ -1186,7 +1187,7 @@ function settings_content(App $a) '$submit' => L10n::t('Save Settings'), '$baseurl' => System::baseUrl(true), '$uid' => local_user(), - '$form_security_token' => Security::get_form_security_token("settings"), + '$form_security_token' => BaseModule::getFormSecurityToken("settings"), '$nickname_block' => $prof_addr, '$h_pass' => L10n::t('Password Settings'), diff --git a/mod/subthread.php b/mod/subthread.php index 8bd60e8fef..0082021df5 100644 --- a/mod/subthread.php +++ b/mod/subthread.php @@ -32,7 +32,7 @@ function subthread_content(App $a) { $owner_uid = $item['uid']; - if (!Security::can_write_wall($owner_uid)) { + if (!Security::canWriteToUserWall($owner_uid)) { return; } diff --git a/mod/videos.php b/mod/videos.php index 50ce361d81..54451a74b4 100644 --- a/mod/videos.php +++ b/mod/videos.php @@ -301,7 +301,7 @@ function videos_content(App $a) return; } - $sql_extra = Security::permissions_sql($owner_uid, $remote_contact, $groups); + $sql_extra = Security::getPermissionsSQLByUserId($owner_uid, $remote_contact, $groups); $o = ""; diff --git a/src/BaseModule.php b/src/BaseModule.php index 1da9397a78..0f6fbd785b 100644 --- a/src/BaseModule.php +++ b/src/BaseModule.php @@ -2,6 +2,9 @@ namespace Friendica; +use Friendica\Core\L10n; +use Friendica\Core\System; + /** * All modules in Friendica should extend BaseModule, although not all modules * need to extend all the methods described here @@ -69,4 +72,84 @@ abstract class BaseModule extends BaseObject { } + + /* + * Functions used to protect against Cross-Site Request Forgery + * The security token has to base on at least one value that an attacker can't know - here it's the session ID and the private key. + * In this implementation, a security token is reusable (if the user submits a form, goes back and resubmits the form, maybe with small changes; + * or if the security token is used for ajax-calls that happen several times), but only valid for a certain amout of time (3hours). + * The "typename" seperates the security tokens of different types of forms. This could be relevant in the following case: + * A security token is used to protekt a link from CSRF (e.g. the "delete this profile"-link). + * If the new page contains by any chance external elements, then the used security token is exposed by the referrer. + * Actually, important actions should not be triggered by Links / GET-Requests at all, but somethimes they still are, + * so this mechanism brings in some damage control (the attacker would be able to forge a request to a form of this type, but not to forms of other types). + */ + public static function getFormSecurityToken($typename = '') + { + $a = get_app(); + + $timestamp = time(); + $sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $timestamp . $typename); + + return $timestamp . '.' . $sec_hash; + } + + public static function checkFormSecurityToken($typename = '', $formname = 'form_security_token') + { + $hash = null; + + if (!empty($_REQUEST[$formname])) { + /// @TODO Careful, not secured! + $hash = $_REQUEST[$formname]; + } + + if (!empty($_SERVER['HTTP_X_CSRF_TOKEN'])) { + /// @TODO Careful, not secured! + $hash = $_SERVER['HTTP_X_CSRF_TOKEN']; + } + + if (empty($hash)) { + return false; + } + + $max_livetime = 10800; // 3 hours + + $a = get_app(); + + $x = explode('.', $hash); + if (time() > (IntVal($x[0]) + $max_livetime)) { + return false; + } + + $sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $x[0] . $typename); + + return ($sec_hash == $x[1]); + } + + public static function getFormSecurityStandardErrorMessage() + { + return L10n::t("The form security token was not correct. This probably happened because the form has been opened for too long \x28>3 hours\x29 before submitting it.") . EOL; + } + + public static function checkFormSecurityTokenRedirectOnError($err_redirect, $typename = '', $formname = 'form_security_token') + { + if (!self::checkFormSecurityToken($typename, $formname)) { + $a = get_app(); + logger('check_form_security_token failed: user ' . $a->user['guid'] . ' - form element ' . $typename); + logger('check_form_security_token failed: _REQUEST data: ' . print_r($_REQUEST, true), LOGGER_DATA); + notice(check_form_security_std_err_msg()); + goaway(System::baseUrl() . $err_redirect); + } + } + + public static function checkFormSecurityTokenForbiddenOnError($typename = '', $formname = 'form_security_token') + { + if (!self::checkFormSecurityToken($typename, $formname)) { + $a = get_app(); + logger('check_form_security_token failed: user ' . $a->user['guid'] . ' - form element ' . $typename); + logger('check_form_security_token failed: _REQUEST data: ' . print_r($_REQUEST, true), LOGGER_DATA); + header('HTTP/1.1 403 Forbidden'); + killme(); + } + } } diff --git a/src/Content/Widget/TagCloud.php b/src/Content/Widget/TagCloud.php index 3a2b01123a..309f9a5bdb 100644 --- a/src/Content/Widget/TagCloud.php +++ b/src/Content/Widget/TagCloud.php @@ -9,6 +9,7 @@ namespace Friendica\Content\Widget; use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Database\DBA; +use Friendica\Model\Item; use Friendica\Util\Security; require_once 'include/dba.php'; @@ -73,7 +74,7 @@ class TagCloud */ private static function tagadelic($uid, $count = 0, $owner_id = 0, $flags = '', $type = TERM_HASHTAG) { - $sql_options = Security::item_permissions_sql($uid); + $sql_options = Item::getPermissionsSQLByUserId($uid); $limit = $count ? sprintf('LIMIT %d', intval($count)) : ''; if ($flags) { diff --git a/src/Core/Authentication.php b/src/Core/Authentication.php index 2fbadcc920..3a4471d2a4 100644 --- a/src/Core/Authentication.php +++ b/src/Core/Authentication.php @@ -25,7 +25,7 @@ class Authentication extends BaseObject * * @return string Hashed data */ - public static function cookie_hash($user) + public static function getCookieHashForUser($user) { return(hash("sha256", Config::get("system", "site_prvkey") . $user["prvkey"] . @@ -38,7 +38,7 @@ class Authentication extends BaseObject * @param int $time * @param array $user Record from "user" table */ - public static function new_cookie($time, $user = []) + public static function setCookie($time, $user = []) { if ($time != 0) { $time = $time + time(); @@ -46,7 +46,7 @@ class Authentication extends BaseObject if ($user) { $value = json_encode(["uid" => $user["uid"], - "hash" => self::cookie_hash($user), + "hash" => self::getCookieHashForUser($user), "ip" => defaults($_SERVER, 'REMOTE_ADDR', '0.0.0.0')]); } else { $value = ""; @@ -65,7 +65,7 @@ class Authentication extends BaseObject * @param type $interactive * @param type $login_refresh */ - public static function success($user_record, $login_initial = false, $interactive = false, $login_refresh = false) + public static function setAuthenticatedSessionForUser($user_record, $login_initial = false, $interactive = false, $login_refresh = false) { $a = self::getApp(); @@ -185,7 +185,7 @@ class Authentication extends BaseObject */ if (!empty($_SESSION['remember'])) { logger('Injecting cookie for remembered user ' . $a->user['nickname']); - self::new_cookie(604800, $user_record); + self::setCookie(604800, $user_record); unset($_SESSION['remember']); } } @@ -202,12 +202,11 @@ class Authentication extends BaseObject /** * @brief Kills the "Friendica" cookie and all session data */ - public static function nuke_session() + public static function deleteSession() { - self::new_cookie(-3600); // make sure cookie is deleted on browser close, as a security measure + self::setCookie(-3600); // make sure cookie is deleted on browser close, as a security measure session_unset(); session_destroy(); } } -?> diff --git a/src/Model/Group.php b/src/Model/Group.php index 4f6f97c49d..4d0bd87e6a 100644 --- a/src/Model/Group.php +++ b/src/Model/Group.php @@ -4,6 +4,7 @@ */ namespace Friendica\Model; +use Friendica\BaseModule; use Friendica\BaseObject; use Friendica\Core\L10n; use Friendica\Database\DBA; @@ -410,7 +411,7 @@ class Group extends BaseObject '$createtext' => L10n::t('Create a new group'), '$creategroup' => L10n::t('Group Name: '), '$editgroupstext' => L10n::t('Edit groups'), - '$form_security_token' => Security::get_form_security_token('group_edit'), + '$form_security_token' => BaseModule::getFormSecurityToken('group_edit'), ]); diff --git a/src/Model/Item.php b/src/Model/Item.php index 9513f4787a..bc31f3d819 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -3246,4 +3246,41 @@ class Item extends BaseObject } } } + + public static function getPermissionsSQLByUserId($owner_id, $remote_verified = false, $groups = null) + { + $local_user = local_user(); + $remote_user = remote_user(); + + /* + * Construct permissions + * + * default permissions - anonymous user + */ + $sql = " AND NOT `item`.`private`"; + + // Profile owner - everything is visible + if ($local_user && ($local_user == $owner_id)) { + $sql = ''; + } elseif ($remote_user) { + /* + * Authenticated visitor. Unless pre-verified, + * check that the contact belongs to this $owner_id + * and load the groups the visitor belongs to. + * If pre-verified, the caller is expected to have already + * done this and passed the groups into this function. + */ + $set = PermissionSet::get($owner_id, $remote_user, $groups); + + if (!empty($set)) { + $sql_set = " OR (`item`.`private` IN (1,2) AND `item`.`wall` AND `item`.`psid` IN (" . implode(',', $set) . "))"; + } else { + $sql_set = ''; + } + + $sql = " AND (NOT `item`.`private`" . $sql_set . ")"; + } + + return $sql; + } } diff --git a/src/Model/Photo.php b/src/Model/Photo.php index 9abd73e762..372e875ea7 100644 --- a/src/Model/Photo.php +++ b/src/Model/Photo.php @@ -227,7 +227,7 @@ class Photo */ public static function getAlbums($uid, $update = false) { - $sql_extra = Security::permissions_sql($uid); + $sql_extra = Security::getPermissionsSQLByUserId($uid); $key = "photo_albums:".$uid.":".local_user().":".remote_user(); $albums = Cache::get($key); diff --git a/src/Module/Login.php b/src/Module/Login.php index fc3b3fb49a..deb6afcfbc 100644 --- a/src/Module/Login.php +++ b/src/Module/Login.php @@ -148,13 +148,13 @@ class Login extends BaseModule } if (!$remember) { - Authentication::new_cookie(0); // 0 means delete on browser exit + Authentication::setCookie(0); // 0 means delete on browser exit } // if we haven't failed up this point, log them in. $_SESSION['remember'] = $remember; $_SESSION['last_login_date'] = DateTimeFormat::utcNow(); - Authentication::success($record, true, true); + Authentication::setAuthenticatedSessionForUser($record, true, true); if (x($_SESSION, 'return_url')) { $return_url = $_SESSION['return_url']; @@ -188,9 +188,9 @@ class Login extends BaseModule ] ); if (DBA::isResult($user)) { - if ($data->hash != Authentication::cookie_hash($user)) { + if ($data->hash != Authentication::getCookieHashForUser($user)) { logger("Hash for user " . $data->uid . " doesn't fit."); - Authentication::nuke_session(); + Authentication::deleteSession(); goaway(self::getApp()->getBaseURL()); } @@ -198,11 +198,11 @@ class Login extends BaseModule // Expires after 7 days by default, // can be set via system.auth_cookie_lifetime $authcookiedays = Config::get('system', 'auth_cookie_lifetime', 7); - Authentication::new_cookie($authcookiedays * 24 * 60 * 60, $user); + Authentication::setCookie($authcookiedays * 24 * 60 * 60, $user); // Do the authentification if not done by now if (!isset($_SESSION) || !isset($_SESSION['authenticated'])) { - Authentication::success($user); + Authentication::setAuthenticatedSessionForUser($user); if (Config::get('system', 'paranoia')) { $_SESSION['addr'] = $data->ip; @@ -227,7 +227,7 @@ class Login extends BaseModule if ($check && ($_SESSION['addr'] != $_SERVER['REMOTE_ADDR'])) { logger('Session address changed. Paranoid setting in effect, blocking session. ' . $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']); - Authentication::nuke_session(); + Authentication::deleteSession(); goaway(self::getApp()->getBaseURL()); } @@ -241,7 +241,7 @@ class Login extends BaseModule ] ); if (!DBA::isResult($user)) { - Authentication::nuke_session(); + Authentication::deleteSession(); goaway(self::getApp()->getBaseURL()); } @@ -255,7 +255,7 @@ class Login extends BaseModule $_SESSION['last_login_date'] = DateTimeFormat::utcNow(); $login_refresh = true; } - Authentication::success($user, false, false, $login_refresh); + Authentication::setAuthenticatedSessionForUser($user, false, false, $login_refresh); } } } diff --git a/src/Module/Logout.php b/src/Module/Logout.php index b2c03bf91f..b12ba10287 100644 --- a/src/Module/Logout.php +++ b/src/Module/Logout.php @@ -24,7 +24,7 @@ class Logout extends BaseModule public static function init() { Addon::callHooks("logging_out"); - Authentication::nuke_session(); + Authentication::deleteSession(); info(L10n::t('Logged out.') . EOL); goaway(self::getApp()->getBaseURL()); } diff --git a/src/Object/Thread.php b/src/Object/Thread.php index 89ccc566ef..08c04f546f 100644 --- a/src/Object/Thread.php +++ b/src/Object/Thread.php @@ -62,11 +62,11 @@ class Thread extends BaseObject break; case 'profile': $this->profile_owner = $a->profile['profile_uid']; - $this->writable = Security::can_write_wall($this->profile_owner); + $this->writable = Security::canWriteToUserWall($this->profile_owner); break; case 'display': $this->profile_owner = $a->profile['uid']; - $this->writable = Security::can_write_wall($this->profile_owner) || $writable; + $this->writable = Security::canWriteToUserWall($this->profile_owner) || $writable; break; case 'community': $this->profile_owner = 0; diff --git a/src/Util/Security.php b/src/Util/Security.php index 1eb0c3f490..11059c0bcf 100644 --- a/src/Util/Security.php +++ b/src/Util/Security.php @@ -18,7 +18,7 @@ use Friendica\Core\System; */ class Security extends BaseObject { - public static function can_write_wall($owner) + public static function canWriteToUserWall($owner) { static $verified = 0; @@ -84,12 +84,12 @@ class Security extends BaseObject } /// @TODO $groups should be array - public static function permissions_sql($owner_id, $remote_verified = false, $groups = null) + public static function getPermissionsSQLByUserId($owner_id, $remote_verified = false, $groups = null) { $local_user = local_user(); $remote_user = remote_user(); - /** + /* * Construct permissions * * default permissions - anonymous user @@ -100,12 +100,12 @@ class Security extends BaseObject AND deny_gid = '' "; - /** + /* * Profile owner - everything is visible */ if ($local_user && $local_user == $owner_id) { $sql = ''; - /** + /* * Authenticated visitor. Unless pre-verified, * check that the contact belongs to this $owner_id * and load the groups the visitor belongs to. @@ -152,122 +152,4 @@ class Security extends BaseObject return $sql; } - public static function item_permissions_sql($owner_id, $remote_verified = false, $groups = null) - { - $local_user = local_user(); - $remote_user = remote_user(); - - /* - * Construct permissions - * - * default permissions - anonymous user - */ - $sql = " AND NOT `item`.`private`"; - - // Profile owner - everything is visible - if ($local_user && ($local_user == $owner_id)) { - $sql = ''; - } elseif ($remote_user) { - /* - * Authenticated visitor. Unless pre-verified, - * check that the contact belongs to this $owner_id - * and load the groups the visitor belongs to. - * If pre-verified, the caller is expected to have already - * done this and passed the groups into this function. - */ - $set = PermissionSet::get($owner_id, $remote_user, $groups); - - if (!empty($set)) { - $sql_set = " OR (`item`.`private` IN (1,2) AND `item`.`wall` AND `item`.`psid` IN (" . implode(',', $set) . "))"; - } else { - $sql_set = ''; - } - - $sql = " AND (NOT `item`.`private`" . $sql_set . ")"; - } - - return $sql; - } - - /* - * Functions used to protect against Cross-Site Request Forgery - * The security token has to base on at least one value that an attacker can't know - here it's the session ID and the private key. - * In this implementation, a security token is reusable (if the user submits a form, goes back and resubmits the form, maybe with small changes; - * or if the security token is used for ajax-calls that happen several times), but only valid for a certain amout of time (3hours). - * The "typename" seperates the security tokens of different types of forms. This could be relevant in the following case: - * A security token is used to protekt a link from CSRF (e.g. the "delete this profile"-link). - * If the new page contains by any chance external elements, then the used security token is exposed by the referrer. - * Actually, important actions should not be triggered by Links / GET-Requests at all, but somethimes they still are, - * so this mechanism brings in some damage control (the attacker would be able to forge a request to a form of this type, but not to forms of other types). - */ - public static function get_form_security_token($typename = '') - { - $a = get_app(); - - $timestamp = time(); - $sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $timestamp . $typename); - - return $timestamp . '.' . $sec_hash; - } - - public static function check_form_security_token($typename = '', $formname = 'form_security_token') - { - $hash = null; - - if (!empty($_REQUEST[$formname])) { - /// @TODO Careful, not secured! - $hash = $_REQUEST[$formname]; - } - - if (!empty($_SERVER['HTTP_X_CSRF_TOKEN'])) { - /// @TODO Careful, not secured! - $hash = $_SERVER['HTTP_X_CSRF_TOKEN']; - } - - if (empty($hash)) { - return false; - } - - $max_livetime = 10800; // 3 hours - - $a = get_app(); - - $x = explode('.', $hash); - if (time() > (IntVal($x[0]) + $max_livetime)) { - return false; - } - - $sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $x[0] . $typename); - - return ($sec_hash == $x[1]); - } - - private static function check_form_security_std_err_msg() - { - return L10n::t("The form security token was not correct. This probably happened because the form has been opened for too long \x28>3 hours\x29 before submitting it.") . EOL; - } - - public static function check_form_security_token_redirectOnErr($err_redirect, $typename = '', $formname = 'form_security_token') - { - if (!check_form_security_token($typename, $formname)) { - $a = get_app(); - logger('check_form_security_token failed: user ' . $a->user['guid'] . ' - form element ' . $typename); - logger('check_form_security_token failed: _REQUEST data: ' . print_r($_REQUEST, true), LOGGER_DATA); - notice(check_form_security_std_err_msg()); - goaway(System::baseUrl() . $err_redirect); - } - } - - public static function check_form_security_token_ForbiddenOnErr($typename = '', $formname = 'form_security_token') - { - if (!check_form_security_token($typename, $formname)) { - $a = get_app(); - logger('check_form_security_token failed: user ' . $a->user['guid'] . ' - form element ' . $typename); - logger('check_form_security_token failed: _REQUEST data: ' . print_r($_REQUEST, true), LOGGER_DATA); - header('HTTP/1.1 403 Forbidden'); - killme(); - } - } } - -?> \ No newline at end of file From 0c0e17b7a7c8b4e5f827bfa6c583ab424dde8305 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Wed, 17 Oct 2018 21:52:08 +0200 Subject: [PATCH 06/19] Remove unneeded Util/Security includings + Resolve including merge conflict with develop --- mod/admin.php | 1 - mod/register.php | 1 - 2 files changed, 2 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index 094206eb96..a60af3b120 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -26,7 +26,6 @@ use Friendica\Util\Arrays; use Friendica\Util\DateTimeFormat; use Friendica\Util\Temporal; use Friendica\Util\Network; -use Friendica\Util\Security; require_once 'include/enotify.php'; require_once 'include/text.php'; diff --git a/mod/register.php b/mod/register.php index 7b53e907ec..1720e0ff3a 100644 --- a/mod/register.php +++ b/mod/register.php @@ -16,7 +16,6 @@ use Friendica\Database\DBA; use Friendica\Model\User; use Friendica\Module\Tos; use Friendica\Util\DateTimeFormat; -use Friendica\Util\Security; require_once 'include/enotify.php'; From a937cf06a3bf352c062f6aaaed3bd8c6fdb6eb0d Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Wed, 17 Oct 2018 22:35:49 +0200 Subject: [PATCH 07/19] add remaning/moving to files not touch by refactoring because of typo --- mod/profiles.php | 20 ++++++++++---------- src/Model/Item.php | 3 ++- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/mod/profiles.php b/mod/profiles.php index 37277f3f24..22f192b4ce 100644 --- a/mod/profiles.php +++ b/mod/profiles.php @@ -4,6 +4,7 @@ */ use Friendica\App; +use Friendica\BaseModule; use Friendica\Content\ContactSelector; use Friendica\Content\Feature; use Friendica\Content\Nav; @@ -20,7 +21,6 @@ use Friendica\Model\Profile; use Friendica\Network\Probe; use Friendica\Util\DateTimeFormat; use Friendica\Util\Temporal; -use Friendica\Utill\Security; use Friendica\Module\Login; function profiles_init(App $a) { @@ -42,7 +42,7 @@ function profiles_init(App $a) { return; // NOTREACHED } - Security::check_form_security_token_redirectOnErr('/profiles', 'profile_drop', 't'); + BaseModule::checkFormSecurityTokenRedirectOnError('/profiles', 'profile_drop', 't'); // move every contact using this profile as their default to the user default @@ -65,7 +65,7 @@ function profiles_init(App $a) { if (($a->argc > 1) && ($a->argv[1] === 'new')) { - Security::check_form_security_token_redirectOnErr('/profiles', 'profile_new', 't'); + BaseModule::checkFormSecurityTokenRedirectOnError('/profiles', 'profile_new', 't'); $r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d", intval(local_user())); @@ -101,7 +101,7 @@ function profiles_init(App $a) { if (($a->argc > 2) && ($a->argv[1] === 'clone')) { - Security::check_form_security_token_redirectOnErr('/profiles', 'profile_clone', 't'); + BaseModule::checkFormSecurityTokenRedirectOnError('/profiles', 'profile_clone', 't'); $r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d", intval(local_user())); @@ -196,7 +196,7 @@ function profiles_post(App $a) { return; } - Security::check_form_security_token_redirectOnErr('/profiles', 'profile_edit'); + BaseModule::checkFormSecurityTokenRedirectOnError('/profiles', 'profile_edit'); $is_default = (($orig[0]['is-default']) ? 1 : 0); @@ -566,10 +566,10 @@ function profiles_content(App $a) { ], '$multi_profiles' => Feature::isEnabled(local_user(), 'multi_profiles'), - '$form_security_token' => Security::get_form_security_token("profile_edit"), - '$form_security_token_photo' => Security::get_form_security_token("profile_photo"), - '$profile_clone_link' => ((Feature::isEnabled(local_user(), 'multi_profiles')) ? 'profiles/clone/' . $r[0]['id'] . '?t=' . Security::get_form_security_token("profile_clone") : ""), - '$profile_drop_link' => 'profiles/drop/' . $r[0]['id'] . '?t=' . Security::get_form_security_token("profile_drop"), + '$form_security_token' => BaseModule::getFormSecurityToken("profile_edit"), + '$form_security_token_photo' => BaseModule::getFormSecurityToken("profile_photo"), + '$profile_clone_link' => ((Feature::isEnabled(local_user(), 'multi_profiles')) ? 'profiles/clone/' . $r[0]['id'] . '?t=' . BaseModule::getFormSecurityToken("profile_clone") : ""), + '$profile_drop_link' => 'profiles/drop/' . $r[0]['id'] . '?t=' . BaseModule::getFormSecurityToken("profile_drop"), '$profile_action' => L10n::t('Profile Actions'), '$banner' => L10n::t('Edit Profile Details'), @@ -682,7 +682,7 @@ function profiles_content(App $a) { '$header' => L10n::t('Edit/Manage Profiles'), '$chg_photo' => L10n::t('Change profile photo'), '$cr_new' => L10n::t('Create New Profile'), - '$cr_new_link' => 'profiles/new?t=' . Security::get_form_security_token("profile_new"), + '$cr_new_link' => 'profiles/new?t=' . BaseModule::getFormSecurityToken("profile_new"), '$profiles' => $profiles ]); } diff --git a/src/Model/Item.php b/src/Model/Item.php index bc31f3d819..dd513d0008 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -24,6 +24,7 @@ use Friendica\Protocol\Diaspora; use Friendica\Protocol\OStatus; use Friendica\Util\DateTimeFormat; use Friendica\Util\XML; +use Friendica\Util\Security; use Text_LanguageDetect; require_once 'boot.php'; @@ -3060,7 +3061,7 @@ class Item extends BaseObject $uid = local_user(); } - if (!Security::can_write_wall($uid)) { + if (!Security::canWriteToUserWall($uid)) { logger('like: unable to write on wall ' . $uid); return false; } From 0628b44f8e2bad78fb25cab8506331a6c95abac4 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 18 Oct 2018 21:35:48 +0000 Subject: [PATCH 08/19] The handling with item-content and item-activity had been simplified --- src/Model/Item.php | 75 +++++++--------------------------------------- 1 file changed, 11 insertions(+), 64 deletions(-) diff --git a/src/Model/Item.php b/src/Model/Item.php index 097baa658f..5cda415c52 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -80,7 +80,7 @@ class Item extends BaseObject // All fields in the item table const ITEM_FIELDLIST = ['id', 'uid', 'parent', 'uri', 'parent-uri', 'thr-parent', 'guid', 'contact-id', 'type', 'wall', 'gravity', 'extid', 'icid', 'iaid', 'psid', - 'uri-hash', 'created', 'edited', 'commented', 'received', 'changed', 'verb', + 'created', 'edited', 'commented', 'received', 'changed', 'verb', 'postopts', 'plink', 'resource-id', 'event-id', 'tag', 'attach', 'inform', 'file', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'post-type', 'private', 'pubmail', 'moderated', 'visible', 'starred', 'bookmark', @@ -529,7 +529,7 @@ class Item extends BaseObject $fields['item'] = ['id', 'uid', 'parent', 'uri', 'parent-uri', 'thr-parent', 'guid', 'contact-id', 'owner-id', 'author-id', 'type', 'wall', 'gravity', 'extid', - 'created', 'edited', 'commented', 'received', 'changed', 'psid', 'uri-hash', + 'created', 'edited', 'commented', 'received', 'changed', 'psid', 'resource-id', 'event-id', 'tag', 'attach', 'post-type', 'file', 'private', 'pubmail', 'moderated', 'visible', 'starred', 'bookmark', 'unseen', 'deleted', 'origin', 'forum_mode', 'mention', 'global', @@ -765,19 +765,6 @@ class Item extends BaseObject return $query; } - /** - * @brief Generate a server unique item hash for linking between the item tables - * - * @param string $uri Item URI - * @param date $created Item creation date - * - * @return string the item hash - */ - private static function itemHash($uri, $created) - { - return round(strtotime($created) / 100) . hash('ripemd128', $uri); - } - /** * @brief Update existing item entries * @@ -803,7 +790,7 @@ class Item extends BaseObject // We cannot simply expand the condition to check for origin entries // The condition needn't to be a simple array but could be a complex condition. // And we have to execute this query before the update to ensure to fetch the same data. - $items = DBA::select('item', ['id', 'origin', 'uri', 'created', 'uri-hash', 'iaid', 'icid', 'tag', 'file'], $condition); + $items = DBA::select('item', ['id', 'origin', 'uri', 'uri-id', 'iaid', 'icid', 'tag', 'file'], $condition); $content_fields = []; foreach (array_merge(self::CONTENT_FIELDLIST, self::MIXED_CONTENT_FIELDLIST) as $field) { @@ -858,34 +845,11 @@ class Item extends BaseObject $rows = DBA::affectedRows(); while ($item = DBA::fetch($items)) { - - // This part here can safely be removed when the legacy fields in the item had been removed - if (empty($item['uri-hash']) && !empty($item['uri']) && !empty($item['created'])) { - - // Fetch the uri-hash from an existing item entry if there is one - $item_condition = ["`uri` = ? AND `uri-hash` != ''", $item['uri']]; - $existing = DBA::selectfirst('item', ['uri-hash'], $item_condition); - if (DBA::isResult($existing)) { - $item['uri-hash'] = $existing['uri-hash']; - } else { - $item['uri-hash'] = self::itemHash($item['uri'], $item['created']); - } - - DBA::update('item', ['uri-hash' => $item['uri-hash']], ['id' => $item['id']]); - DBA::update('item-activity', ['uri-hash' => $item['uri-hash']], ["`uri` = ? AND `uri-hash` = ''", $item['uri']]); - DBA::update('item-content', ['uri-plink-hash' => $item['uri-hash']], ["`uri` = ? AND `uri-plink-hash` = ''", $item['uri']]); - } - if (!empty($item['iaid']) || (!empty($content_fields['verb']) && (self::activityToIndex($content_fields['verb']) >= 0))) { - if (!empty($item['iaid'])) { - $update_condition = ['id' => $item['iaid']]; - } else { - $update_condition = ['uri-hash' => $item['uri-hash']]; - } - self::updateActivity($content_fields, $update_condition); + self::updateActivity($content_fields, ['uri-id' => $item['uri-id']]); if (empty($item['iaid'])) { - $item_activity = DBA::selectFirst('item-activity', ['id'], ['uri-hash' => $item['uri-hash']]); + $item_activity = DBA::selectFirst('item-activity', ['id'], ['uri-id' => $item['uri-id']]); if (DBA::isResult($item_activity)) { $item_fields = ['iaid' => $item_activity['id'], 'icid' => null]; foreach (self::MIXED_CONTENT_FIELDLIST as $field) { @@ -909,15 +873,10 @@ class Item extends BaseObject } } } else { - if (!empty($item['icid'])) { - $update_condition = ['id' => $item['icid']]; - } else { - $update_condition = ['uri-plink-hash' => $item['uri-hash']]; - } - self::updateContent($content_fields, $update_condition); + self::updateContent($content_fields, ['uri-id' => $item['uri-id']]); if (empty($item['icid'])) { - $item_content = DBA::selectFirst('item-content', [], ['uri-plink-hash' => $item['uri-hash']]); + $item_content = DBA::selectFirst('item-content', [], ['uri-id' => $item['uri-id']]); if (DBA::isResult($item_content)) { $item_fields = ['icid' => $item_content['id']]; // Clear all fields in the item table that have a content in the item-content table @@ -1380,13 +1339,6 @@ class Item extends BaseObject } } - // Ensure to always have the same creation date. - $existing = self::selectfirst(['created', 'uri-hash'], ['uri' => $item['uri']]); - if (DBA::isResult($existing)) { - $item['created'] = $existing['created']; - $item['uri-hash'] = $existing['uri-hash']; - } - $item['wall'] = intval(defaults($item, 'wall', 0)); $item['extid'] = trim(defaults($item, 'extid', '')); $item['author-name'] = trim(defaults($item, 'author-name', '')); @@ -1429,9 +1381,6 @@ class Item extends BaseObject $item['inform'] = trim(defaults($item, 'inform', '')); $item['file'] = trim(defaults($item, 'file', '')); - // Unique identifier to be linked against item-activities and item-content - $item['uri-hash'] = defaults($item, 'uri-hash', self::itemHash($item['uri'], $item['created'])); - // When there is no content then we don't post it if ($item['body'].$item['title'] == '') { logger('No body, no title.'); @@ -1927,8 +1876,7 @@ class Item extends BaseObject return false; } - $fields = ['uri' => $item['uri'], 'activity' => $activity_index, - 'uri-hash' => $item['uri-hash'], 'uri-id' => $item['uri-id']]; + $fields = ['activity' => $activity_index, 'uri-hash' => (string)$item['uri-id'], 'uri-id' => $item['uri-id']]; // We just remove everything that is content foreach (array_merge(self::CONTENT_FIELDLIST, self::MIXED_CONTENT_FIELDLIST) as $field) { @@ -1942,7 +1890,7 @@ class Item extends BaseObject } // Do we already have this content? - $item_activity = DBA::selectFirst('item-activity', ['id'], ['uri-hash' => $item['uri-hash']]); + $item_activity = DBA::selectFirst('item-activity', ['id'], ['uri-id' => $item['uri-id']]); if (DBA::isResult($item_activity)) { $item['iaid'] = $item_activity['id']; logger('Fetched activity for URI ' . $item['uri'] . ' (' . $item['iaid'] . ')'); @@ -1968,8 +1916,7 @@ class Item extends BaseObject */ private static function insertContent(&$item) { - $fields = ['uri' => $item['uri'], 'uri-plink-hash' => $item['uri-hash'], - 'uri-id' => $item['uri-id']]; + $fields = ['uri-plink-hash' => (string)$item['uri-id'], 'uri-id' => $item['uri-id']]; foreach (array_merge(self::CONTENT_FIELDLIST, self::MIXED_CONTENT_FIELDLIST) as $field) { if (isset($item[$field])) { @@ -1985,7 +1932,7 @@ class Item extends BaseObject } // Do we already have this content? - $item_content = DBA::selectFirst('item-content', ['id'], ['uri-plink-hash' => $item['uri-hash']]); + $item_content = DBA::selectFirst('item-content', ['id'], ['uri-id' => $item['uri-id']]); if (DBA::isResult($item_content)) { $item['icid'] = $item_content['id']; logger('Fetched content for URI ' . $item['uri'] . ' (' . $item['icid'] . ')'); From 18763e32af30d5627033f867e2a468c4b6db0815 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 18 Oct 2018 18:22:48 -0400 Subject: [PATCH 09/19] Remove superfluous L10n::t() parameter in Model\user --- src/Model/User.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Model/User.php b/src/Model/User.php index eb042eb8b4..17c9831ca9 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -684,7 +684,7 @@ class User Login Name: %4$s Password: %5$s ', - $body, $user['username'], $sitename, $siteurl, $user['nickname'], $password + $user['username'], $sitename, $siteurl, $user['nickname'], $password )); return notification([ @@ -742,7 +742,7 @@ class User If you ever want to delete your account, you can do so at %3$s/removeme Thank you and welcome to %2$s.', - $body, $user['email'], $sitename, $siteurl, $user['username'], $password + $user['email'], $sitename, $siteurl, $user['username'], $password )); return notification([ From eb714f0487a78ab64104fe1d2ab6b117c480116d Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 18 Oct 2018 22:39:06 -0400 Subject: [PATCH 10/19] Diaspora: Widen the magic link regular expression --- src/Content/Text/BBCode.php | 2 +- src/Protocol/Diaspora.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 8d5da11cda..be2054067b 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -1319,7 +1319,7 @@ class BBCode extends BaseObject // Handle Diaspora posts $text = preg_replace_callback( - "&\[url=/posts/([^\[\]]*)\](.*)\[\/url\]&Usi", + "&\[url=/?posts/([^\[\]]*)\](.*)\[\/url\]&Usi", function ($match) { return "[url=" . System::baseUrl() . "/display/" . $match[1] . "]" . $match[2] . "[/url]"; }, $text diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index 0c3a52b2d3..5792d56b6e 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -1200,7 +1200,7 @@ class Diaspora ); preg_replace_callback( - "&\[url=/posts/([^\[\]]*)\](.*)\[\/url\]&Usi", + "&\[url=/?posts/([^\[\]]*)\](.*)\[\/url\]&Usi", function ($match) use ($item) { self::fetchGuidSub($match, $item); }, From d0681075bf7b6d1bf998da8ac2c43ce2134f4804 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 18 Oct 2018 22:49:25 -0400 Subject: [PATCH 11/19] Add itemsource module --- src/Model/Conversation.php | 5 ++++ src/Module/Itemsource.php | 39 +++++++++++++++++++++++++++++ view/templates/debug/itemsource.tpl | 28 +++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 src/Module/Itemsource.php create mode 100644 view/templates/debug/itemsource.tpl diff --git a/src/Model/Conversation.php b/src/Model/Conversation.php index be1eaf2295..25075dcfbe 100644 --- a/src/Model/Conversation.php +++ b/src/Model/Conversation.php @@ -26,6 +26,11 @@ class Conversation const PARCEL_TWITTER = 67; const PARCEL_UNKNOWN = 255; + public static function getByItemUri($item_uri) + { + return DBA::selectFirst('conversation', [], ['item-uri' => $item_uri]); + } + /** * @brief Store the conversation data * diff --git a/src/Module/Itemsource.php b/src/Module/Itemsource.php new file mode 100644 index 0000000000..bcbd557182 --- /dev/null +++ b/src/Module/Itemsource.php @@ -0,0 +1,39 @@ + + */ +class Itemsource extends \Friendica\BaseModule +{ + public static function content() + { + if (!is_site_admin()) { + return; + } + + $source = ''; + $item_uri = ''; + if (!empty($_REQUEST['guid'])) { + $item = Model\Item::selectFirst([], ['guid' => $_REQUEST['guid']]); + + $conversation = Model\Conversation::getByItemUri($item['uri']); + + $item_uri = $item['uri']; + $source = htmlspecialchars($conversation['source']); + } + + $tpl = get_markup_template('debug/itemsource.tpl'); + $o = replace_macros($tpl, [ + '$guid' => ['guid', L10n::t('Item Guid'), htmlentities(defaults($_REQUEST, 'guid', '')), ''], + '$source' => $source, + '$item_uri' => $item_uri + ]); + + return $o; + } +} diff --git a/view/templates/debug/itemsource.tpl b/view/templates/debug/itemsource.tpl new file mode 100644 index 0000000000..377409ebf3 --- /dev/null +++ b/view/templates/debug/itemsource.tpl @@ -0,0 +1,28 @@ +

Item Source

+
+
+
+ {{include file="field_input.tpl" field=$guid}} +
+

+
+
+ +{{if $source}} +
+
+
+

Item URI

+
+
+ {{$item_uri}} +
+
+
+
+

Source

+
+
{{$source}}
+
+
+{{/if}} From cdeb4682ef6fc0ed6d5f6264564ffd29c1ac735c Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 19 Oct 2018 05:27:54 +0000 Subject: [PATCH 12/19] Use nickname based mentions for AP --- src/Protocol/ActivityPub/Transmitter.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 7f22e8386b..2a930fcc6f 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -743,6 +743,26 @@ class Transmitter return $attachments; } + /** + * @brief Callback function to replace a Friendica style mention in a mention that is used on AP + * + * @param array $match Matching values for the callback + * @return string Replaced mention + */ + private static function MentionCallback($match) + { + if (empty($match[1])) { + return; + } + + $data = Contact::getDetailsByURL($match[1]); + if (empty($data) || empty($data['nick'])) { + return; + } + + return '@[url=' . $data['url'] . ']' . $data['nick'] . '[/url]'; + } + /** * Remove image elements and replaces them with links to the image * @@ -851,6 +871,9 @@ class Transmitter $body = self::removePictures($body); } + $regexp = "/[@!]\[url\=([^\[\]]*)\].*?\[\/url\]/ism"; + $body = preg_replace_callback($regexp, ['self', 'MentionCallback'], $body); + $data['content'] = BBCode::convert($body, false, 7); $data['source'] = ['content' => $item['body'], 'mediaType' => "text/bbcode"]; From cafd5ca7819d90d38d06e84fcf0cbb2951956223 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Fri, 19 Oct 2018 10:03:52 +0200 Subject: [PATCH 13/19] update function names in logger and comments --- mod/profile_photo.php | 2 +- mod/videos.php | 2 +- src/BaseModule.php | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mod/profile_photo.php b/mod/profile_photo.php index 1e0687c654..5fdff41e8c 100644 --- a/mod/profile_photo.php +++ b/mod/profile_photo.php @@ -188,7 +188,7 @@ function profile_photo_content(App $a) $imagecrop = []; if (isset($a->argv[1]) && $a->argv[1] == 'use' && $a->argc >= 3) { - // check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo'); + // BaseModule::checkFormSecurityTokenRedirectOnError('/profile_photo', 'profile_photo'); $resource_id = $a->argv[2]; //die(":".local_user()); diff --git a/mod/videos.php b/mod/videos.php index 54451a74b4..b66a7cbcda 100644 --- a/mod/videos.php +++ b/mod/videos.php @@ -60,7 +60,7 @@ function videos_init(App $a) ]); /// @TODO Old-lost code? - /*$sql_extra = permissions_sql($a->data['user']['uid']); + /*$sql_extra = Security::getPermissionsSQLByUserId($a->data['user']['uid']); $albums = q("SELECT distinct(`album`) AS `album` FROM `photo` WHERE `uid` = %d $sql_extra order by created desc", intval($a->data['user']['uid']) diff --git a/src/BaseModule.php b/src/BaseModule.php index 0f6fbd785b..e77b1a1491 100644 --- a/src/BaseModule.php +++ b/src/BaseModule.php @@ -135,9 +135,9 @@ abstract class BaseModule extends BaseObject { if (!self::checkFormSecurityToken($typename, $formname)) { $a = get_app(); - logger('check_form_security_token failed: user ' . $a->user['guid'] . ' - form element ' . $typename); - logger('check_form_security_token failed: _REQUEST data: ' . print_r($_REQUEST, true), LOGGER_DATA); - notice(check_form_security_std_err_msg()); + logger('checkFormSecurityToken failed: user ' . $a->user['guid'] . ' - form element ' . $typename); + logger('checkFormSecurityToken failed: _REQUEST data: ' . print_r($_REQUEST, true), LOGGER_DATA); + notice(self::getFormSecurityStandardErrorMessage()); goaway(System::baseUrl() . $err_redirect); } } @@ -146,8 +146,8 @@ abstract class BaseModule extends BaseObject { if (!self::checkFormSecurityToken($typename, $formname)) { $a = get_app(); - logger('check_form_security_token failed: user ' . $a->user['guid'] . ' - form element ' . $typename); - logger('check_form_security_token failed: _REQUEST data: ' . print_r($_REQUEST, true), LOGGER_DATA); + logger('checkFormSecurityToken failed: user ' . $a->user['guid'] . ' - form element ' . $typename); + logger('checkFormSecurityToken failed: _REQUEST data: ' . print_r($_REQUEST, true), LOGGER_DATA); header('HTTP/1.1 403 Forbidden'); killme(); } From bedab33e0b3a1636332c8f07c157a357bf3fd459 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 19 Oct 2018 13:08:46 +0000 Subject: [PATCH 14/19] Fix function naming --- src/Protocol/ActivityPub/Transmitter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 2a930fcc6f..98422f3ad0 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -749,7 +749,7 @@ class Transmitter * @param array $match Matching values for the callback * @return string Replaced mention */ - private static function MentionCallback($match) + private static function mentionCallback($match) { if (empty($match[1])) { return; @@ -872,7 +872,7 @@ class Transmitter } $regexp = "/[@!]\[url\=([^\[\]]*)\].*?\[\/url\]/ism"; - $body = preg_replace_callback($regexp, ['self', 'MentionCallback'], $body); + $body = preg_replace_callback($regexp, ['self', 'mentionCallback'], $body); $data['content'] = BBCode::convert($body, false, 7); $data['source'] = ['content' => $item['body'], 'mediaType' => "text/bbcode"]; From afeb6df22528f2b8500e8b7e2cea9d32703f5fc4 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 19 Oct 2018 10:46:09 -0400 Subject: [PATCH 15/19] [frio] Enable click through image caption in file browser --- view/theme/frio/css/style.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index c563dd121a..5fa84abdfe 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -1489,6 +1489,9 @@ section #jotOpen { .fbrowser.image .photo-album-image-wrapper { box-shadow: 2px 2px 5px 0px rgba(0, 0, 0, 0.2); } +.fbrowser.image .photo-album-image-wrapper .caption { + pointer-events: none; +} .fbrowser .profile-rotator-wrapper { min-height: 200px; } From d9209b9c7a280eedce8f4b926366878656ab6f5b Mon Sep 17 00:00:00 2001 From: Benjamin Lorteau Date: Fri, 19 Oct 2018 11:26:48 -0400 Subject: [PATCH 16/19] Use local temporary directory for PasswordExposedChecker cache --- src/Model/User.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Model/User.php b/src/Model/User.php index 17c9831ca9..63aaa1e3de 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -5,7 +5,7 @@ */ namespace Friendica\Model; -use DivineOmega\PasswordExposed\PasswordStatus; +use DivineOmega\PasswordExposed; use Exception; use Friendica\Core\Addon; use Friendica\Core\Config; @@ -20,7 +20,6 @@ use Friendica\Util\Crypto; use Friendica\Util\DateTimeFormat; use Friendica\Util\Network; use LightOpenID; -use function password_exposed; require_once 'boot.php'; require_once 'include/dba.php'; @@ -280,7 +279,14 @@ class User */ public static function isPasswordExposed($password) { - return password_exposed($password) === PasswordStatus::EXPOSED; + $cache = new \DivineOmega\DOFileCachePSR6\CacheItemPool(); + $cache->changeConfig([ + 'cacheDirectory' => get_temppath() . '/password-exposed-cache/', + ]); + + $PasswordExposedCHecker = new PasswordExposed\PasswordExposedChecker(null, $cache); + + return $PasswordExposedCHecker->passwordExposed($password) === PasswordExposed\PasswordStatus::EXPOSED; } /** From 7795643134a7cb5ea5522469d6c130925ebc5b99 Mon Sep 17 00:00:00 2001 From: Benjamin Lorteau Date: Fri, 19 Oct 2018 11:27:11 -0400 Subject: [PATCH 17/19] Add system.temppath description to config/settings.ini.php --- config/settings.ini.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config/settings.ini.php b/config/settings.ini.php index 353b1fa1f4..02482c8af8 100644 --- a/config/settings.ini.php +++ b/config/settings.ini.php @@ -92,6 +92,10 @@ optimize_max_tablesize = -1 ; Set to 0 to disable, 2 to enable, 1 is deprecated but wont need mcrypt. rino_encrypt = 2 +; temppath (String) +; Custom temporary file directory +temppath = + ; theme (String) ; System theme name. theme = vier From a2666b0d021ce8c560ecba211a710606fd3d8ed4 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 19 Oct 2018 15:11:51 -0400 Subject: [PATCH 18/19] Remove reference to deleted include/security.php --- src/Protocol/DFRN.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index f92d1401df..21a0f43944 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -216,7 +216,6 @@ class DFRN } $contact = $r[0]; - include_once 'include/security.php'; $set = PermissionSet::get($owner_id, $contact['id']); From ed52b5d0a93325fb94c12ba61054fc88ea199e6a Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 19 Oct 2018 15:12:53 -0400 Subject: [PATCH 19/19] Remove reference to deleted include/security in mod/pubsub --- mod/pubsub.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mod/pubsub.php b/mod/pubsub.php index bc284a4eb2..f4c7e311ca 100644 --- a/mod/pubsub.php +++ b/mod/pubsub.php @@ -6,8 +6,7 @@ use Friendica\Database\DBA; use Friendica\Model\Contact; use Friendica\Protocol\OStatus; -require_once('include/security.php'); -require_once('include/items.php'); +require_once 'include/items.php'; function hub_return($valid, $body) {