N°4289 Security hardening

This commit is contained in:
Pierre Goiffon
2021-10-21 11:55:21 +02:00
parent a353317746
commit 7757f1f2d2
3 changed files with 111 additions and 34 deletions

View File

@@ -193,10 +193,32 @@ class privUITransactionSession
*/
class privUITransactionFile
{
/**
* @return int
* @throws \SecurityException if no connected user
*
* @since 2.6.5 2.7.6 3.0.0 N°4289 method creation
*/
private static function GetCurrentUserId() {
$iCurrentUserId = UserRights::GetConnectedUserId();
if ('' === $iCurrentUserId) {
throw new SecurityException('Cannot creation transaction_id when no user logged');
}
return $iCurrentUserId;
}
/**
* Create a new transaction id, store it in the session and return its id
*
* @param void
*
* @return int The identifier of the new transaction
*
* @throws \SecurityException
* @throws \Exception
*
* @since 2.6.5 2.7.6 3.0.0 security hardening + throws SecurityException if no user logged
*/
public static function GetNewTransactionId()
{
@@ -212,24 +234,36 @@ class privUITransactionFile
throw new Exception('Failed to create the directory "'.APPROOT.'data/transactions". Ajust the rights on the parent directory or let an administrator create the transactions directory and give the web sever enough rights to write into it.');
}
}
if (!is_writable(APPROOT.'data/transactions'))
{
throw new Exception('The directory "'.APPROOT.'data/transactions" must be writable to the application.');
}
self::CleanupOldTransactions();
$id = basename(tempnam(APPROOT.'data/transactions', static::GetUserPrefix()));
self::Info('GetNewTransactionId: Created transaction: '.$id);
return (string)$id;
$iCurrentUserId = static::GetCurrentUserId();
self::CleanupOldTransactions();
$sTransactionIdFullPath = tempnam(APPROOT.'data/transactions', static::GetUserPrefix());
file_put_contents($sTransactionIdFullPath, $iCurrentUserId, LOCK_EX);
$sTransactionIdFileName = basename($sTransactionIdFullPath);
self::Info('GetNewTransactionId: Created transaction: '.$sTransactionIdFileName);
return $sTransactionIdFileName;
}
/**
* Check whether a transaction is valid or not and (optionally) remove the valid transaction from
* the session so that another call to IsTransactionValid for the same transaction id
* will return false
*
* @param int $id Identifier of the transaction, as returned by GetNewTransactionId
* @param bool $bRemoveTransaction True if the transaction must be removed
*
* @return bool True if the transaction is valid, false otherwise
*
* @since 2.6.5 2.7.6 3.0.0 N°4289 security hardening
*/
public static function IsTransactionValid($id, $bRemoveTransaction = true)
{
@@ -243,25 +277,32 @@ class privUITransactionFile
clearstatcache(true, $sFilepath);
$bResult = file_exists($sFilepath);
if ($bResult)
if (false === $bResult) {
self::Info("IsTransactionValid: Transaction '$id' not found. Pending transactions:\n".implode("\n", self::GetPendingTransactions()));
return false;
}
$iCurrentUserId = static::GetCurrentUserId();
$sTransactionIdUserId = file_get_contents($sFilepath);
if ($iCurrentUserId != $sTransactionIdUserId) {
self::Info("IsTransactionValid: Transaction '$id' not existing for current user. Pending transactions:\n".implode("\n", self::GetPendingTransactions()));
return false;
}
if ($bRemoveTransaction)
{
if ($bRemoveTransaction)
$bResult = @unlink($sFilepath);
if (!$bResult)
{
$bResult = @unlink($sFilepath);
if (!$bResult)
{
self::Error('IsTransactionValid: FAILED to remove transaction '.$id);
}
else
{
self::Info('IsTransactionValid: OK. Removed transaction: '.$id);
}
self::Error('IsTransactionValid: FAILED to remove transaction '.$id);
}
else
{
self::Info('IsTransactionValid: OK. Removed transaction: '.$id);
}
}
else
{
self::Info("IsTransactionValid: Transaction '$id' not found. Pending transactions for this user:\n".implode("\n", self::GetPendingTransactions()));
}
return $bResult;
}
@@ -269,26 +310,20 @@ class privUITransactionFile
* Removes the transaction specified by its id
* @param int $id The Identifier (as returned by GetNewTransactionId) of the transaction to be removed.
* @return bool true if the token can be removed
*
* @since 2.6.5 2.7.6 3.0.0 N°4289 security hardening
*/
public static function RemoveTransaction($id)
{
$sFilepath = APPROOT.'data/transactions/'.$id;
clearstatcache(true, $sFilepath);
if (!file_exists($sFilepath)) {
$bSuccess = false;
self::Error("RemoveTransaction: Transaction '$id' not found. Pending transactions for this user:\n"
/** @noinspection PhpRedundantOptionalArgumentInspection */
$bResult = static::IsTransactionValid($id, true);
if (false === $bResult) {
self::Error("RemoveTransaction: Transaction '$id' is invalid. Pending transactions:\n"
.implode("\n", self::GetPendingTransactions()));
} else {
$bSuccess = @unlink($sFilepath);
return false;
}
if (!$bSuccess) {
self::Error('RemoveTransaction: FAILED to remove transaction '.$id);
} else {
self::Info('RemoveTransaction: OK '.$id);
}
return $bSuccess;
return true;
}
/**