Version 4.5.0
This commit is contained in:
1 parent
1a0c7fd3c2
commit
f79dcf067a
3791 files changed
+248032
-76372
No files matched your search
+117
-22
@@ -26,11 +26,11 @@ if ( file_exists( "../../constants.php" ) )
|
||||
{
|
||||
require "../../constants.php";
|
||||
}
|
||||
foreach ( array( 'FOLDER_PERMISSION_NO_WRITE' => 0755, 'FILE_PERMISSION_NO_WRITE' => 0644, 'TEMP_DIRECTORY' => sys_get_temp_dir() ) as $k => $v )
|
||||
foreach ( array( 'FOLDER_PERMISSION_NO_WRITE' => 0755, 'FILE_PERMISSION_NO_WRITE' => 0644, 'IPS_FILE_PERMISSION' => 0666, 'TEMP_DIRECTORY' => sys_get_temp_dir() ) as $k => $v )
|
||||
{
|
||||
if ( !defined( $k ) )
|
||||
if ( !\defined( $k ) )
|
||||
{
|
||||
define( $k, $v );
|
||||
\define( $k, $v );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ class Extractor
|
||||
{
|
||||
if ( !$file or !$container )
|
||||
{
|
||||
throw new Exception;
|
||||
throw new Exception( "Zip file or directory to extract to was not supplied" );
|
||||
}
|
||||
|
||||
$this->file = $file;
|
||||
@@ -108,7 +108,28 @@ class Extractor
|
||||
public function securityCheck( $key )
|
||||
{
|
||||
require "../../conf_global.php";
|
||||
return $key === md5( $INFO['board_start'] . $_GET['file'] . $INFO['sql_pass'] );
|
||||
|
||||
$db = new mysqli( $INFO['sql_host'], $INFO['sql_user'], $INFO['sql_pass'], $INFO['sql_database'], !empty( $INFO['sql_port'] ) ? $INFO['sql_port'] : null, !empty( $INFO['sql_socket'] ) ? $INFO['sql_socket'] : null );
|
||||
|
||||
/* If the connection failed, do not continue */
|
||||
if( $error = mysqli_connect_error() )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check that there is an upgrade in progress */
|
||||
$query = $db->query( "SELECT conf_value FROM {$INFO['sql_tbl_prefix']}core_sys_conf_settings WHERE conf_key='setup_in_progress'" );
|
||||
if( !$query )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( (bool) $query->fetch_assoc()['conf_value'] === FALSE )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return $this->_compareHashes( md5( $INFO['board_start'] . $_GET['file'] . $INFO['sql_pass'] ), $key );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,21 +145,21 @@ class Extractor
|
||||
$this->ssh = ssh2_connect( $value['server'], $value['port'] );
|
||||
if ( $this->ssh === FALSE )
|
||||
{
|
||||
throw new Exception;
|
||||
throw new Exception( "Could not connect to SCP" );
|
||||
}
|
||||
if ( !@ssh2_auth_password( $this->ssh, $value['un'], $value['pw'] ) )
|
||||
{
|
||||
throw new Exception;
|
||||
throw new Exception( "Could not login to SCP" );
|
||||
}
|
||||
$this->sftp = @ssh2_sftp( $this->ssh );
|
||||
if ( $this->sftp === FALSE )
|
||||
{
|
||||
throw new Exception;
|
||||
throw new Exception( "Could not initiate SFTP connection" );
|
||||
}
|
||||
|
||||
if ( $value['path'] and !@ssh2_sftp_stat( $this->sftp, $value['path'] ) )
|
||||
{
|
||||
throw new Exception;
|
||||
throw new Exception( "Could not locate path via SFTP" );
|
||||
}
|
||||
|
||||
$this->sftpDir = ssh2_sftp_realpath( $this->sftp, $value['path'] ) . '/';
|
||||
@@ -155,11 +176,11 @@ class Extractor
|
||||
}
|
||||
if ( $this->ftp === FALSE )
|
||||
{
|
||||
throw new Exception;
|
||||
throw new Exception( "Could not connect to FTP" );
|
||||
}
|
||||
if ( !@ftp_login( $this->ftp, $value['un'], $value['pw'] ) )
|
||||
{
|
||||
throw new Exception;
|
||||
throw new Exception( "Could not login to FTP" );
|
||||
}
|
||||
if( ftp_nlist( $this->ftp, '.' ) === FALSE )
|
||||
{
|
||||
@@ -168,7 +189,7 @@ class Extractor
|
||||
|
||||
if ( !@ftp_chdir( $this->ftp, $value['path'] ) )
|
||||
{
|
||||
throw new Exception;
|
||||
throw new Exception( "Could not change directory to {$value['path']}" );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -196,7 +217,7 @@ class Extractor
|
||||
$this->contents = $this->zip->listContent();
|
||||
if ( !$this->contents )
|
||||
{
|
||||
throw new Exception;
|
||||
throw new Exception( "Could not list the files in the zip" );
|
||||
}
|
||||
|
||||
$done = 0;
|
||||
@@ -234,11 +255,11 @@ class Extractor
|
||||
}
|
||||
|
||||
/* Create a directory if needed */
|
||||
$dir = dirname( $path );
|
||||
$dir = \dirname( $path );
|
||||
$directories = array( $dir );
|
||||
while ( $dir != '.' )
|
||||
{
|
||||
$dir = dirname( $dir );
|
||||
$dir = \dirname( $dir );
|
||||
if ( $dir != '.' )
|
||||
{
|
||||
$directories[] = $dir;
|
||||
@@ -273,16 +294,16 @@ class Extractor
|
||||
|
||||
if ( $this->sftp )
|
||||
{
|
||||
if ( @ssh2_scp_send( $this->ssh, $tmpFile, $this->sftpDir . $path ) === FALSE )
|
||||
if ( @ssh2_scp_send( $this->ssh, $tmpFile, $this->sftpDir . $path, FILE_PERMISSION_NO_WRITE ) === FALSE )
|
||||
{
|
||||
throw new \Exception;
|
||||
throw new \Exception( "Could not transfer file to server via SFTP" );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( @ftp_put( $this->ftp, $path, $tmpFile, FTP_BINARY ) === FALSE )
|
||||
{
|
||||
throw new \Exception;
|
||||
throw new \Exception( "Could not transfer file to server via FTP" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,7 +330,7 @@ class Extractor
|
||||
/* If the file existed before we started, we should clear it from opcache if opcache is enabled */
|
||||
if( $fileExists )
|
||||
{
|
||||
if ( function_exists( 'opcache_invalidate' ) )
|
||||
if ( \function_exists( 'opcache_invalidate' ) )
|
||||
{
|
||||
@opcache_invalidate( "../../{$path}" );
|
||||
}
|
||||
@@ -323,6 +344,78 @@ class Extractor
|
||||
@\fclose( $fh );
|
||||
}
|
||||
}
|
||||
|
||||
/* !Misc Utility Methods */
|
||||
|
||||
/**
|
||||
* Compare hashes in fixed length, time constant manner.
|
||||
* This is replicated from \IPS\Login::compareHashes(), however we don't want to include framework code here.
|
||||
*
|
||||
* @param string $expected The expected hash
|
||||
* @param string $provided The provided input
|
||||
* @return boolean
|
||||
*/
|
||||
private function _compareHashes( $expected, $provided )
|
||||
{
|
||||
if ( !\is_string( $expected ) || !\is_string( $provided ) || $expected === '*0' || $expected === '*1' || $provided === '*0' || $provided === '*1' ) // *0 and *1 are failures from crypt() - if we have ended up with an invalid hash anywhere, we will reject it to prevent a possible vulnerability from deliberately generating invalid hashes
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$len = \strlen( $expected );
|
||||
if ( $len !== \strlen( $provided ) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$status = 0;
|
||||
for ( $i = 0; $i < $len; $i++ )
|
||||
{
|
||||
$status |= \ord( $expected[ $i ] ) ^ \ord( $provided[ $i ] );
|
||||
}
|
||||
|
||||
return $status === 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to write a log file to disk
|
||||
*
|
||||
* @param mixed $message Exception or message to log
|
||||
* @return void
|
||||
*/
|
||||
function writeLogFile( $message )
|
||||
{
|
||||
/* What are we writing? */
|
||||
$date = date('r');
|
||||
if ( $message instanceof \Exception )
|
||||
{
|
||||
$messageToLog = $date . "\n" . \get_class( $message ) . '::' . $message->getCode() . "\n" . $message->getMessage() . "\n" . $message->getTraceAsString();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( \is_array( $message ) )
|
||||
{
|
||||
$message = var_export( $message, TRUE );
|
||||
}
|
||||
$messageToLog = $date . "\n" . $message . "\n" . ( new \Exception )->getTraceAsString();
|
||||
}
|
||||
|
||||
/* Where are we writing it? */
|
||||
$dir = rtrim( __DIR__, '/' ) . '/../../uploads/logs';
|
||||
|
||||
/* Write it */
|
||||
$header = "<?php exit; ?>\n\n";
|
||||
$file = $dir . '/' . date( 'Y' ) . '_' . date( 'm' ) . '_' . date('d') . '_' . ( 'extractfailure' ) . '.php';
|
||||
if ( file_exists( $file ) )
|
||||
{
|
||||
@\file_put_contents( $file, "\n\n-------------\n\n" . $messageToLog, FILE_APPEND );
|
||||
}
|
||||
else
|
||||
{
|
||||
@\file_put_contents( $file, $header . $messageToLog );
|
||||
}
|
||||
@chmod( $file, IPS_FILE_PERMISSION );
|
||||
}
|
||||
|
||||
/* ! Controller */
|
||||
@@ -333,7 +426,7 @@ try
|
||||
/* Check this request came from the ACP */
|
||||
if ( !$extractor->securityCheck( $_GET['key'] ) )
|
||||
{
|
||||
throw new Exception;
|
||||
throw new Exception( "Security check failed" );
|
||||
}
|
||||
|
||||
/* Establish an FTP connection if necessary */
|
||||
@@ -351,7 +444,7 @@ try
|
||||
{
|
||||
@unlink( $_GET['file'] );
|
||||
|
||||
if ( function_exists( 'opcache_reset' ) )
|
||||
if ( \function_exists( 'opcache_reset' ) )
|
||||
{
|
||||
@opcache_reset();
|
||||
}
|
||||
@@ -387,8 +480,10 @@ HTML;
|
||||
HTML;
|
||||
}
|
||||
}
|
||||
catch ( Exception $e )
|
||||
catch ( Throwable $e )
|
||||
{
|
||||
writeLogFile( $e );
|
||||
|
||||
echo "<script type='text/javascript'>parent.location = parent.location + '&fail=1';</script><noscript>An error occurred. Please visit the <a href='https://remoteservices.invisionpower.com/docs/client_area' target='_blank' rel='noopener'>client area</a> to manually download the latest version. After uploading the files, <a href='index.php' target='_parent'>continue to the upgrader</a>.</noscript>";
|
||||
exit;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user