]> git.mxchange.org Git - friendica.git/commitdiff
Move include/security tp /src/Core/Authentication and /src/Util/Security
authorJonny Tischbein <jonny_tischbein@systemli.org>
Wed, 17 Oct 2018 12:19:58 +0000 (14:19 +0200)
committerJonny Tischbein <jonny_tischbein@systemli.org>
Wed, 17 Oct 2018 12:19:58 +0000 (14:19 +0200)
30 files changed:
include/api.php
include/security.php [deleted file]
mod/admin.php
mod/attach.php
mod/cal.php
mod/delegate.php
mod/display.php
mod/group.php
mod/invite.php
mod/item.php
mod/manage.php
mod/openid.php
mod/photo.php
mod/photos.php
mod/profile.php
mod/profile_photo.php
mod/profiles.php
mod/register.php
mod/settings.php
mod/subthread.php
mod/videos.php
src/Content/Widget/TagCloud.php
src/Core/Authentication.php [new file with mode: 0644]
src/Model/Group.php
src/Model/Item.php
src/Model/Photo.php
src/Module/Login.php
src/Module/Logout.php
src/Object/Thread.php
src/Util/Security.php [new file with mode: 0644]

index ff763e98855c36bb0199fbc86ab7ce67b992a0c0..51caa9019b1bb1737cd31cb26581a2f2371d7fc8 100644 (file)
@@ -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 (file)
index 2063bdd..0000000
+++ /dev/null
@@ -1,457 +0,0 @@
-<?php
-/**
- * @file include/security.php
- */
-
-use Friendica\Core\Addon;
-use Friendica\Core\Config;
-use Friendica\Core\L10n;
-use Friendica\Core\PConfig;
-use Friendica\Core\System;
-use Friendica\Database\DBA;
-use Friendica\Model\Contact;
-use Friendica\Model\Group;
-use Friendica\Util\DateTimeFormat;
-use Friendica\Model\PermissionSet;
-
-/**
- * @brief Calculate the hash that is needed for the "Friendica" cookie
- *
- * @param array $user Record from "user" table
- *
- * @return string Hashed data
- */
-function cookie_hash($user)
-{
-       return(hash("sha256", Config::get("system", "site_prvkey") .
-                       $user["prvkey"] .
-                       $user["password"]));
-}
-
-/**
- * @brief Set the "Friendica" cookie
- *
- * @param int $time
- * @param array $user Record from "user" table
- */
-function new_cookie($time, $user = [])
-{
-       if ($time != 0) {
-               $time = $time + time();
-       }
-
-       if ($user) {
-               $value = json_encode(["uid" => $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();
-}
index b02db73bdd9bdf76468881ae6164c3fc8b185279..ccadfa525c1e808c10b80ee3a562b7bbae06e8f7 100644 (file)
@@ -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', '<code>/view/themes</code>'),
                '$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'),
index 99f0fc46000bdb54c6ef74678a53779bb3a64a1c..97eb10997e6bbe5cf2d364cc12c9385495c2ed70 100644 (file)
@@ -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
 
index ae1060c47ad5d36a1a76e774857ffd6c4f25e939..cc6973d472cc8802a88c93152bccbb73600a8614 100644 (file)
@@ -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;
 
index ed4f854377109c6c4466487ec6ab9f34eedb0eff..f711f593fabbbf1690c43c253372f4b16e7865be 100644 (file)
@@ -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,
index a03b918372efd61636961fbbf488f486aec18ddc..0c1cc9037502ee770205b03a19f860140d4aaa56 100644 (file)
@@ -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];
index f8fefc78f9e96cf91ac481f713ea956b8568df77..09fe676c17ccee667c1b0fc6f903fd5ec6368fcf 100644 (file)
@@ -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) {
index 2a98d19ffcffaf5d3e3c660252e7f304d8d9572b..cd9de6cc0a0ed6e915d3b0ef459766013ee386ac 100644 (file)
@@ -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"
index 053a00c977ba77f45482aebe52dda7c86154c102..5a665fc7c8bc3f9beb927b4e94e68863a53df50c 100644 (file)
@@ -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'])) {
index f81afb09a6e30e18ca2ba0bcecd23151adb2a7da..d54b92a3a77a4c62d62b4c59ad5c427e0959dd8d 100644 (file)
@@ -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;
index 63b29684b3c5eded4a1fa651470a76ee192dc8b5..a9930d0448c94ebee9aaa3955d815cd47c84b170 100644 (file)
@@ -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
index b1dd9a5c3a3c60863c5fb71b5c7fc2f194016581..3a0a199d8c5b4448ade17ce8c9be550bf5a60561 100644 (file)
@@ -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",
index 259209ed4041ede16cf179b0c688030eaf10d4a8..4208e227545fde549762dd866b4475cdc7e67f35 100644 (file)
@@ -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,
index aa284d1669a0184a1e6fdf05c84074d76e02ce46..5484beb26599f7a9a7e7332919005409a9f072ec 100644 (file)
@@ -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) {
index 984ebfed6f39fc27bfa6bc157d903e5be905953a..492be7e4ae68b7db3eac2618188c04f60c29a252 100644 (file)
@@ -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) ? '<a href="' . System::baseUrl() . '">' . L10n::t('skip this step') . '</a>' : '<a href="' . System::baseUrl() . '/photos/' . $a->user['nickname'] . '">' . L10n::t('select a photo from your photo albums') . '</a>')
                ]);
@@ -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;
index 3e6bd1cb0d0ff29bacf720540dcf125cd2132e1c..37277f3f24e44e2f1665892d889a8300cc7978a9 100644 (file)
@@ -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
                        ]);
                }
index 454062d89b6c90c874f7511a1acd8d0ca003fc93..9a2ad0f4824030a7531d80117b8a394288ed0dd6 100644 (file)
@@ -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')
        ]);
index 5632193e3bddcf4255713060a28ac05e2d98bbd8..3737aeadac02ed348d34221b0c9cd40a3104d49a 100644 (file)
@@ -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'),
index 105cf60feb7f1e3d3a3ba458c3b37625a149f29c..8bd60e8fef0fe46fe01083aa1139a61047396876 100644 (file)
@@ -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;
        }
 
index e52c78cab11f794a0b5f2e4fdd7ab30dfd35c2a0..0d217ef9c4bfd33662d961c377c865dbb9a0d0d0 100644 (file)
@@ -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 = "";
 
index 71872830cbb6c52cf12f746e134dfb113916e5c9..3a2b01123a975a1d58700641ad603fadae4dbdaa 100644 (file)
@@ -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 (file)
index 0000000..3e53a5a
--- /dev/null
@@ -0,0 +1,213 @@
+<?php
+/**
+ * @file /src/Core/Authentication.php
+ */
+
+namespace Friendica\Core;
+
+use Friendica\Core\Addon;
+use Friendica\BaseObject;
+use Friendica\Core\Config;
+use Friendica\Util\DateTimeFormat;
+use Friendica\Database\DBA;
+use Friendica\Core\L10n;
+use Friendica\Core\PConfig;
+
+/**
+* Handle Authentification, Session and Cookies
+*/    
+class Authentication extends BaseObject
+{
+       /**
+        * @brief Calculate the hash that is needed for the "Friendica" cookie
+        *
+        * @param array $user Record from "user" table
+        *
+        * @return string Hashed data
+        */
+       public static function cookie_hash($user)
+       {
+               return(hash("sha256", Config::get("system", "site_prvkey") .
+                               $user["prvkey"] .
+                               $user["password"]));
+       }
+
+       /**
+        * @brief Set the "Friendica" cookie
+        *
+        * @param int $time
+        * @param array $user Record from "user" table
+        */
+       public static  function new_cookie($time, $user = [])
+       {
+               if ($time != 0) {
+                       $time = $time + time();
+               }
+
+               if ($user) {
+                       $value = json_encode(["uid" => $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();
+       }
+}
+
+?>
index e313842e4143677afceb1f143dddb18eff3a0c31..4f6f97c49d645dca869305f628e586b9934112b4 100644 (file)
@@ -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'),
                ]);
 
 
index 824e240cc36e54edcf7377889a80878ecfbb35d8..9513f4787ada6a0a5d78c45aa08985a3f25d7413 100644 (file)
@@ -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;
                }
index e64158e175ced54a67d79fecf190be2965c561b5..9abd73e762ba27933fb0ebb45592c98b97768a7d 100644 (file)
@@ -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);
index 15505a38be61295c8118d9b449a4da51b2daed7b..3c123b198c00337bd8ad11ea13fc8cf0b59ae08d 100644 (file)
@@ -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);
                        }
                }
        }
index cbfd245f302f47f276cff27f8ee1ab1e192d0459..74586dc69ef1b771c1154a54a9af761ce392a448 100644 (file)
@@ -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());
        }
index cd055ee5ebfa4e17eb4cf963219afaca2bfabdd2..89ccc566ef49e86a96c2e2bc4d539a0ac5d2008f 100644 (file)
@@ -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 (file)
index 0000000..1eb0c3f
--- /dev/null
@@ -0,0 +1,273 @@
+<?php
+/**
+ * @file /src/Util/Security.php
+ */
+
+namespace Friendica\Util;
+
+use Friendica\BaseObject;
+use Friendica\Database\DBA;
+use Friendica\Model\Contact;
+use Friendica\Model\Group;
+use Friendica\Core\L10n;
+use Friendica\Model\PermissionSet;
+use Friendica\Core\System;
+
+/**
+ * Secures that User is allow to do requests
+ */
+class Security extends BaseObject
+{
+       public static 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
+       public static 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;
+       }
+
+       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