2010-07-01 19:48:07 -04:00
< ? php
2018-01-21 13:33:59 -05:00
/**
* @ file include / security . php
*/
2018-01-24 21:08:45 -05:00
2018-01-17 13:42:40 -05:00
use Friendica\Core\Addon ;
2017-11-06 21:22:52 -05:00
use Friendica\Core\Config ;
2018-01-21 13:33:59 -05:00
use Friendica\Core\L10n ;
2017-11-06 21:22:52 -05:00
use Friendica\Core\PConfig ;
2017-08-26 02:04:21 -04:00
use Friendica\Core\System ;
2018-07-20 08:19:26 -04:00
use Friendica\Database\DBA ;
2017-12-16 19:21:56 -05:00
use Friendica\Model\Group ;
2018-01-26 21:38:34 -05:00
use Friendica\Util\DateTimeFormat ;
2017-04-30 00:07:00 -04:00
2017-03-11 19:11:35 -05:00
/**
* @ brief Calculate the hash that is needed for the " Friendica " cookie
*
* @ param array $user Record from " user " table
*
* @ return string Hashed data
*/
2017-12-16 19:19:51 -05:00
function cookie_hash ( $user )
{
return ( hash ( " sha256 " , Config :: get ( " system " , " site_prvkey " ) .
$user [ " prvkey " ] .
$user [ " password " ]));
2017-03-11 19:11:35 -05:00
}
/**
* @ brief Set the " Friendica " cookie
*
* @ param int $time
* @ param array $user Record from " user " table
*/
2018-01-15 08:05:12 -05:00
function new_cookie ( $time , $user = [])
2017-12-16 19:19:51 -05:00
{
2017-03-13 18:09:09 -04:00
if ( $time != 0 ) {
2017-03-11 19:11:35 -05:00
$time = $time + time ();
2017-03-13 18:09:09 -04:00
}
2017-03-11 19:11:35 -05:00
2017-03-13 18:09:09 -04:00
if ( $user ) {
2018-01-15 08:05:12 -05:00
$value = json_encode ([ " uid " => $user [ " uid " ],
2017-12-16 19:19:51 -05:00
" hash " => cookie_hash ( $user ),
2018-07-01 00:15:11 -04:00
" ip " => defaults ( $_SERVER , 'REMOTE_ADDR' , '0.0.0.0' )]);
2017-12-16 19:19:51 -05:00
} else {
2017-03-11 19:11:35 -05:00
$value = " " ;
2017-03-13 18:09:09 -04:00
}
2017-03-11 19:11:35 -05:00
2017-12-16 19:19:51 -05:00
setcookie ( " Friendica " , $value , $time , " / " , " " , ( Config :: get ( 'system' , 'ssl_policy' ) == SSL_POLICY_FULL ), true );
2017-03-11 19:11:35 -05:00
}
2017-12-16 19:19:51 -05:00
/**
* @ 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 )
{
2012-01-12 18:46:39 -05:00
$a = get_app ();
$_SESSION [ 'uid' ] = $user_record [ 'uid' ];
$_SESSION [ 'theme' ] = $user_record [ 'theme' ];
2017-11-06 21:22:52 -05:00
$_SESSION [ 'mobile-theme' ] = PConfig :: get ( $user_record [ 'uid' ], 'system' , 'mobile_theme' );
2012-01-12 18:46:39 -05:00
$_SESSION [ 'authenticated' ] = 1 ;
$_SESSION [ 'page_flags' ] = $user_record [ 'page-flags' ];
2017-08-26 03:32:10 -04:00
$_SESSION [ 'my_url' ] = System :: baseUrl () . '/profile/' . $user_record [ 'nickname' ];
2017-12-16 19:19:51 -05:00
$_SESSION [ 'my_address' ] = $user_record [ 'nickname' ] . '@' . substr ( System :: baseUrl (), strpos ( System :: baseUrl (), '://' ) + 3 );
2018-07-01 00:15:11 -04:00
$_SESSION [ 'addr' ] = defaults ( $_SERVER , 'REMOTE_ADDR' , '0.0.0.0' );
2012-01-12 18:46:39 -05:00
$a -> user = $user_record ;
2017-04-04 13:48:25 -04:00
if ( $interactive ) {
2017-03-18 08:13:43 -04:00
if ( $a -> user [ 'login_date' ] <= NULL_DATE ) {
2012-01-12 18:46:39 -05:00
$_SESSION [ 'return_url' ] = 'profile_photo/new' ;
$a -> module = 'profile_photo' ;
2018-01-22 15:21:43 -05:00
info ( L10n :: t ( " Welcome " ) . $a -> user [ 'username' ] . EOL );
info ( L10n :: t ( 'Please upload a profile photo.' ) . EOL );
2017-04-04 13:48:25 -04:00
} else {
2018-01-22 15:21:43 -05:00
info ( L10n :: t ( " Welcome back " ) . $a -> user [ 'username' ] . EOL );
2017-04-04 13:48:25 -04:00
}
2012-01-12 18:46:39 -05:00
}
$member_since = strtotime ( $a -> user [ 'register_date' ]);
2017-04-04 13:48:25 -04:00
if ( time () < ( $member_since + ( 60 * 60 * 24 * 14 ))) {
2012-01-12 18:46:39 -05:00
$_SESSION [ 'new_member' ] = true ;
2017-04-04 13:48:25 -04:00
} else {
2012-01-12 18:46:39 -05:00
$_SESSION [ 'new_member' ] = false ;
2017-04-04 13:48:25 -04:00
}
if ( strlen ( $a -> user [ 'timezone' ])) {
2012-01-12 18:46:39 -05:00
date_default_timezone_set ( $a -> user [ 'timezone' ]);
$a -> timezone = $a -> user [ 'timezone' ];
}
2014-03-11 18:52:32 -04:00
$master_record = $a -> user ;
2012-01-27 15:56:36 -05:00
2017-12-16 19:19:51 -05:00
if (( x ( $_SESSION , 'submanage' )) && intval ( $_SESSION [ 'submanage' ])) {
2018-07-20 08:19:26 -04:00
$user = DBA :: selectFirst ( 'user' , [], [ 'uid' => $_SESSION [ 'submanage' ]]);
2018-07-21 08:46:04 -04:00
if ( DBA :: isResult ( $user )) {
2018-06-19 17:33:07 -04:00
$master_record = $user ;
2017-04-04 13:48:25 -04:00
}
2012-01-26 19:52:12 -05:00
}
2018-02-08 17:18:34 -05:00
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
2018-07-20 08:19:26 -04:00
$r = DBA :: select ( 'user' , [ 'uid' , 'username' , 'nickname' ],
2018-02-08 17:18:34 -05:00
[ 'parent-uid' => $master_record [ 'uid' ], 'account_removed' => false ]);
2018-07-21 08:46:04 -04:00
if ( DBA :: isResult ( $r )) {
2018-07-20 22:03:40 -04:00
$a -> identities = array_merge ( $a -> identities , DBA :: toArray ( $r ));
2018-02-08 17:18:34 -05:00
}
2017-04-04 13:48:25 -04:00
} else {
2018-02-08 17:18:34 -05:00
// Just ensure that the array is always defined
2018-01-15 08:05:12 -05:00
$a -> identities = [];
2018-02-08 17:18:34 -05:00
// First entry is our parent
2018-07-20 08:19:26 -04:00
$r = DBA :: select ( 'user' , [ 'uid' , 'username' , 'nickname' ],
2018-02-08 17:18:34 -05:00
[ 'uid' => $master_record [ 'parent-uid' ], 'account_removed' => false ]);
2018-07-21 08:46:04 -04:00
if ( DBA :: isResult ( $r )) {
2018-07-20 22:03:40 -04:00
$a -> identities = DBA :: toArray ( $r );
2018-02-08 17:18:34 -05:00
}
// Then add all siblings
2018-07-20 08:19:26 -04:00
$r = DBA :: select ( 'user' , [ 'uid' , 'username' , 'nickname' ],
2018-02-08 17:18:34 -05:00
[ 'parent-uid' => $master_record [ 'parent-uid' ], 'account_removed' => false ]);
2018-07-21 08:46:04 -04:00
if ( DBA :: isResult ( $r )) {
2018-07-20 22:03:40 -04:00
$a -> identities = array_merge ( $a -> identities , DBA :: toArray ( $r ));
2018-02-08 17:18:34 -05:00
}
2017-04-04 13:48:25 -04:00
}
2012-01-12 18:46:39 -05:00
2018-07-20 08:19:26 -04:00
$r = DBA :: p ( " SELECT `user`.`uid`, `user`.`username`, `user`.`nickname`
2017-04-04 13:48:25 -04:00
FROM `manage`
INNER JOIN `user` ON `manage` . `mid` = `user` . `uid`
2017-08-11 04:04:01 -04:00
WHERE `user` . `account_removed` = 0 AND `manage` . `uid` = ? " ,
$master_record [ 'uid' ]
2012-01-26 19:52:12 -05:00
);
2018-07-21 08:46:04 -04:00
if ( DBA :: isResult ( $r )) {
2018-07-20 22:03:40 -04:00
$a -> identities = array_merge ( $a -> identities , DBA :: toArray ( $r ));
2017-04-04 13:48:25 -04:00
}
2012-01-12 18:46:39 -05:00
2017-04-04 13:48:25 -04:00
if ( $login_initial ) {
2017-12-16 19:19:51 -05:00
logger ( 'auth_identities: ' . print_r ( $a -> identities , true ), LOGGER_DEBUG );
2017-04-04 13:48:25 -04:00
}
if ( $login_refresh ) {
2017-12-16 19:19:51 -05:00
logger ( 'auth_identities refresh: ' . print_r ( $a -> identities , true ), LOGGER_DEBUG );
2017-04-04 13:48:25 -04:00
}
2012-01-27 15:56:36 -05:00
2018-07-20 08:19:26 -04:00
$contact = DBA :: selectFirst ( 'contact' , [], [ 'uid' => $_SESSION [ 'uid' ], 'self' => true ]);
2018-07-21 08:46:04 -04:00
if ( DBA :: isResult ( $contact )) {
2018-06-19 17:33:07 -04:00
$a -> contact = $contact ;
$a -> cid = $contact [ 'id' ];
2012-01-12 18:46:39 -05:00
$_SESSION [ 'cid' ] = $a -> cid ;
}
2017-12-16 19:19:51 -05:00
header ( 'X-Account-Management-Status: active; name="' . $a -> user [ 'username' ] . '"; id="' . $a -> user [ 'nickname' ] . '"' );
2012-01-12 18:46:39 -05:00
2017-04-04 13:48:25 -04:00
if ( $login_initial || $login_refresh ) {
2018-07-20 08:19:26 -04:00
DBA :: update ( 'user' , [ 'login_date' => DateTimeFormat :: utcNow ()], [ 'uid' => $_SESSION [ 'uid' ]]);
2015-05-09 17:47:45 -04:00
// Set the login date for all identities of the user
2018-07-20 08:19:26 -04:00
DBA :: update ( 'user' , [ 'login_date' => DateTimeFormat :: utcNow ()],
2018-02-08 17:18:34 -05:00
[ 'parent-uid' => $master_record [ 'uid' ], 'account_removed' => false ]);
2012-11-08 19:00:37 -05:00
}
2017-03-11 19:11:35 -05:00
if ( $login_initial ) {
2018-07-19 07:11:03 -04:00
/*
* 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 .
*/
2017-03-11 19:11:35 -05:00
if ( $_SESSION [ 'remember' ]) {
2018-07-19 07:11:03 -04:00
logger ( 'Injecting cookie for remembered user ' . $a -> user [ 'nickname' ]);
2017-03-11 19:11:35 -05:00
new_cookie ( 604800 , $user_record );
unset ( $_SESSION [ 'remember' ]);
}
}
2016-12-20 11:43:46 -05:00
if ( $login_initial ) {
2018-01-17 13:42:40 -05:00
Addon :: callHooks ( 'logged_in' , $a -> user );
2012-01-12 18:46:39 -05:00
2016-12-20 11:43:46 -05:00
if (( $a -> module !== 'home' ) && isset ( $_SESSION [ 'return_url' ])) {
2017-08-26 03:32:10 -04:00
goaway ( System :: baseUrl () . '/' . $_SESSION [ 'return_url' ]);
2016-12-20 11:43:46 -05:00
}
2012-01-12 18:46:39 -05:00
}
}
2018-01-03 21:05:55 -05:00
function can_write_wall ( $owner )
2017-12-16 19:19:51 -05:00
{
2010-12-03 00:09:55 -05:00
static $verified = 0 ;
2010-10-17 23:24:58 -04:00
2017-12-16 19:19:51 -05:00
if ( ! local_user () && ! remote_user ()) {
2010-12-03 00:09:55 -05:00
return false ;
2016-12-20 11:43:46 -05:00
}
2010-12-03 00:09:55 -05:00
$uid = local_user ();
2018-01-03 21:05:55 -05:00
if ( $uid == $owner ) {
2010-12-03 00:09:55 -05:00
return true ;
}
2018-07-16 00:00:57 -04:00
if ( local_user () && ( $owner == 0 )) {
return true ;
}
2016-12-20 11:43:46 -05:00
if ( remote_user ()) {
2012-03-05 18:04:43 -05:00
// use remembered decision and avoid a DB lookup for each and every display item
2010-12-03 00:09:55 -05:00
// DO NOT use this function if there are going to be multiple owners
2012-03-05 18:04:43 -05:00
// 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
2016-12-20 11:43:46 -05:00
if ( $verified === 2 ) {
2010-12-03 00:09:55 -05:00
return true ;
2016-12-20 11:43:46 -05:00
} elseif ( $verified === 1 ) {
2010-12-03 00:09:55 -05:00
return false ;
2016-12-20 11:43:46 -05:00
} else {
2012-09-05 01:50:28 -04:00
$cid = 0 ;
2016-12-20 11:43:46 -05:00
if ( is_array ( $_SESSION [ 'remote' ])) {
foreach ( $_SESSION [ 'remote' ] as $visitor ) {
if ( $visitor [ 'uid' ] == $owner ) {
2012-09-05 01:50:28 -04:00
$cid = $visitor [ 'cid' ];
break ;
}
}
}
2017-12-16 19:19:51 -05:00
if ( ! $cid ) {
2012-09-05 01:50:28 -04:00
return false ;
2016-12-20 11:43:46 -05:00
}
2012-03-05 18:04:43 -05:00
2017-01-09 07:09:01 -05:00
$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
2011-03-20 20:54:50 -04:00
AND `user` . `blockwall` = 0 AND `readonly` = 0 AND ( `contact` . `rel` IN ( % d , % d ) OR `user` . `page-flags` = % d ) LIMIT 1 " ,
2010-11-08 23:43:58 -05:00
intval ( $owner ),
2012-09-05 01:50:28 -04:00
intval ( $cid ),
2011-08-18 19:47:45 -04:00
intval ( CONTACT_IS_SHARING ),
2011-08-07 19:15:54 -04:00
intval ( CONTACT_IS_FRIEND ),
2010-11-08 23:43:58 -05:00
intval ( PAGE_COMMUNITY )
);
2012-03-05 18:04:43 -05:00
2018-07-21 08:46:04 -04:00
if ( DBA :: isResult ( $r )) {
2010-12-03 00:09:55 -05:00
$verified = 2 ;
return true ;
2017-12-16 19:19:51 -05:00
} else {
2010-12-03 00:09:55 -05:00
$verified = 1 ;
}
2010-11-08 23:43:58 -05:00
}
2010-12-03 00:09:55 -05:00
}
2010-07-01 19:48:07 -04:00
2010-12-03 00:09:55 -05:00
return false ;
2010-07-01 19:48:07 -04:00
}
2011-06-30 20:35:35 -04:00
2018-05-14 16:25:39 -04:00
/// @TODO $groups should be array
2017-12-16 19:19:51 -05:00
function permissions_sql ( $owner_id , $remote_verified = false , $groups = null )
{
2011-06-30 20:35:35 -04:00
$local_user = local_user ();
$remote_user = remote_user ();
2012-03-06 20:52:00 -05:00
/**
* Construct permissions
*
* default permissions - anonymous user
*/
2017-01-09 07:09:01 -05:00
$sql = " AND allow_cid = ''
AND allow_gid = ''
AND deny_cid = ''
AND deny_gid = ''
2012-03-06 20:52:00 -05:00
" ;
/**
* Profile owner - everything is visible
*/
2017-12-16 19:19:51 -05:00
if ( $local_user && $local_user == $owner_id ) {
2017-01-09 07:09:01 -05:00
$sql = '' ;
2017-07-16 14:35:42 -04:00
/**
* 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 .
*/
2017-06-18 16:10:03 -04:00
} 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 .
*/
2012-03-06 20:52:00 -05:00
2017-12-16 19:19:51 -05:00
if ( ! $remote_verified ) {
2012-03-06 20:52:00 -05:00
$r = q ( " SELECT id FROM contact WHERE id = %d AND uid = %d AND blocked = 0 LIMIT 1 " ,
intval ( $remote_user ),
intval ( $owner_id )
);
2018-07-21 08:46:04 -04:00
if ( DBA :: isResult ( $r )) {
2012-03-06 20:52:00 -05:00
$remote_verified = true ;
2017-12-16 19:21:56 -05:00
$groups = Group :: getIdsByContactId ( $remote_user );
2012-03-06 20:52:00 -05:00
}
}
2014-03-11 18:52:32 -04:00
2017-12-16 19:19:51 -05:00
if ( $remote_verified ) {
2012-03-06 20:52:00 -05:00
$gs = '<<>>' ; // should be impossible to match
2018-05-14 16:25:39 -04:00
if ( is_array ( $groups )) {
2017-01-26 10:01:56 -05:00
foreach ( $groups as $g ) {
2012-03-06 20:52:00 -05:00
$gs .= '|<' . intval ( $g ) . '>' ;
2017-01-26 10:01:56 -05:00
}
2017-01-09 07:09:01 -05:00
}
2012-03-06 20:52:00 -05:00
2012-09-29 19:54:37 -04:00
$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 ),
dbesc ( $gs ),
intval ( $remote_user ),
dbesc ( $gs )
2012-03-06 20:52:00 -05:00
);
}
}
return $sql ;
}
2017-12-16 19:19:51 -05:00
function item_permissions_sql ( $owner_id , $remote_verified = false , $groups = null )
{
2012-03-06 20:52:00 -05:00
$local_user = local_user ();
$remote_user = remote_user ();
2017-12-16 19:19:51 -05:00
/*
2011-06-30 20:35:35 -04:00
* Construct permissions
*
* default permissions - anonymous user
*/
2014-03-09 04:19:14 -04:00
$sql = " AND `item`.allow_cid = ''
AND `item` . allow_gid = ''
AND `item` . deny_cid = ''
AND `item` . deny_gid = ''
2018-07-16 00:00:57 -04:00
AND `item` . private != 1
2011-06-30 20:35:35 -04:00
" ;
2017-12-16 19:19:51 -05:00
// Profile owner - everything is visible
2017-04-04 13:48:25 -04:00
if ( $local_user && ( $local_user == $owner_id )) {
2013-01-28 00:42:36 -05:00
$sql = '' ;
2017-06-18 16:10:03 -04:00
} 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 .
*/
2017-12-16 19:19:51 -05:00
if ( ! $remote_verified ) {
2011-06-30 20:35:35 -04:00
$r = q ( " SELECT id FROM contact WHERE id = %d AND uid = %d AND blocked = 0 LIMIT 1 " ,
intval ( $remote_user ),
intval ( $owner_id )
);
2018-07-21 08:46:04 -04:00
if ( DBA :: isResult ( $r )) {
2011-06-30 20:35:35 -04:00
$remote_verified = true ;
2017-12-16 19:21:56 -05:00
$groups = Group :: getIdsByContactId ( $remote_user );
2011-06-30 20:35:35 -04:00
}
}
2017-04-04 13:48:25 -04:00
if ( $remote_verified ) {
2014-03-09 04:19:14 -04:00
2011-06-30 20:35:35 -04:00
$gs = '<<>>' ; // should be impossible to match
2017-04-04 13:48:25 -04:00
if ( is_array ( $groups ) && count ( $groups )) {
2017-06-18 16:10:03 -04:00
foreach ( $groups as $g ) {
2011-06-30 20:35:35 -04:00
$gs .= '|<' . intval ( $g ) . '>' ;
2017-06-18 16:10:03 -04:00
}
2017-01-09 07:09:01 -05:00
}
2011-06-30 20:35:35 -04:00
$sql = sprintf (
2014-03-16 17:42:47 -04:00
" AND ( `item`.private = 0 OR ( `item`.private in (1,2) AND `item`.`wall` = 1
2014-03-09 04:19:14 -04:00
AND ( NOT ( `item` . deny_cid REGEXP '<%d>' OR `item` . deny_gid REGEXP '%s' )
2014-03-16 17:42:47 -04:00
AND ( `item` . allow_cid REGEXP '<%d>' OR `item` . allow_gid REGEXP '%s' OR ( `item` . allow_cid = '' AND `item` . allow_gid = '' )))))
2013-02-04 22:27:30 -05:00
" ,
intval ( $remote_user ),
dbesc ( $gs ),
intval ( $remote_user ),
dbesc ( $gs )
2011-06-30 20:35:35 -04:00
);
}
}
2012-03-09 03:31:17 -05:00
2011-06-30 20:35:35 -04:00
return $sql ;
2012-03-06 20:52:00 -05:00
}
2012-03-12 16:17:37 -04:00
/*
* 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 ( 3 hours ) .
* 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 ) .
2017-01-09 07:09:01 -05:00
*/
2017-12-16 19:19:51 -05:00
function get_form_security_token ( $typename = '' )
{
2012-03-12 16:17:37 -04:00
$a = get_app ();
2017-01-09 07:09:01 -05:00
2012-03-12 16:17:37 -04:00
$timestamp = time ();
2012-03-19 03:37:09 -04:00
$sec_hash = hash ( 'whirlpool' , $a -> user [ 'guid' ] . $a -> user [ 'prvkey' ] . session_id () . $timestamp . $typename );
2017-01-09 07:09:01 -05:00
2012-03-19 03:37:09 -04:00
return $timestamp . '.' . $sec_hash ;
2012-03-12 16:17:37 -04:00
}
2017-12-16 19:19:51 -05:00
function check_form_security_token ( $typename = '' , $formname = 'form_security_token' )
{
2018-04-11 23:28:51 -04:00
$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' ];
2017-06-18 16:10:03 -04:00
}
2018-04-11 23:28:51 -04:00
if ( empty ( $hash )) {
return false ;
}
2017-01-09 07:09:01 -05:00
2012-03-12 16:17:37 -04:00
$max_livetime = 10800 ; // 3 hours
2017-01-09 07:09:01 -05:00
2012-03-12 16:17:37 -04:00
$a = get_app ();
2017-01-09 07:09:01 -05:00
2012-03-19 03:37:09 -04:00
$x = explode ( '.' , $hash );
2017-06-18 16:10:03 -04:00
if ( time () > ( IntVal ( $x [ 0 ]) + $max_livetime )) {
return false ;
}
2017-01-09 07:09:01 -05:00
2012-03-19 03:37:09 -04:00
$sec_hash = hash ( 'whirlpool' , $a -> user [ 'guid' ] . $a -> user [ 'prvkey' ] . session_id () . $x [ 0 ] . $typename );
2017-01-09 07:09:01 -05:00
2012-03-12 16:17:37 -04:00
return ( $sec_hash == $x [ 1 ]);
}
2017-12-16 19:19:51 -05:00
function check_form_security_std_err_msg ()
{
2018-01-24 16:51:32 -05:00
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 ;
2012-03-12 16:17:37 -04:00
}
2017-12-16 19:19:51 -05:00
function check_form_security_token_redirectOnErr ( $err_redirect , $typename = '' , $formname = 'form_security_token' )
{
2012-03-12 16:17:37 -04:00
if ( ! check_form_security_token ( $typename , $formname )) {
$a = get_app ();
2012-03-19 03:37:09 -04:00
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 );
2017-12-16 19:19:51 -05:00
notice ( check_form_security_std_err_msg ());
goaway ( System :: baseUrl () . $err_redirect );
2012-03-12 16:17:37 -04:00
}
}
2017-12-16 19:19:51 -05:00
function check_form_security_token_ForbiddenOnErr ( $typename = '' , $formname = 'form_security_token' )
{
2012-03-18 11:44:33 -04:00
if ( ! check_form_security_token ( $typename , $formname )) {
2017-06-18 16:10:03 -04:00
$a = get_app ();
2012-03-19 03:37:09 -04:00
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 );
2012-03-18 11:44:33 -04:00
header ( 'HTTP/1.1 403 Forbidden' );
killme ();
}
2012-04-14 16:24:35 -04:00
}
2017-12-17 11:40:59 -05:00
/**
* @ 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 ();
}