Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(deps): Upgrade phpseclib to v3 #48183

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion 3rdparty
Submodule 3rdparty updated 358 files
4 changes: 1 addition & 3 deletions apps/encryption/lib/Crypto/Crypt.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
use OCP\IConfig;
use OCP\IL10N;
use OCP\IUserSession;
use phpseclib\Crypt\RC4;
use phpseclib3\Crypt\RC4;
use Psr\Log\LoggerInterface;

/**
Expand Down Expand Up @@ -724,7 +724,6 @@ public function useLegacyBase64Encoding(): bool {
*/
private function rc4Decrypt(string $data, string $secret): string {
$rc4 = new RC4();
/** @psalm-suppress InternalMethod */
$rc4->setKey($secret);

return $rc4->decrypt($data);
Expand All @@ -735,7 +734,6 @@ private function rc4Decrypt(string $data, string $secret): string {
*/
private function rc4Encrypt(string $data, string $secret): string {
$rc4 = new RC4();
/** @psalm-suppress InternalMethod */
$rc4->setKey($secret);

return $rc4->encrypt($data);
Expand Down
18 changes: 10 additions & 8 deletions apps/files_external/lib/Controller/AjaxController.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,15 @@ public function __construct(
*/
private function generateSshKeys($keyLength) {
$key = $this->rsaMechanism->createKey($keyLength);
// Replace the placeholder label with a more meaningful one
$key['publickey'] = str_replace('phpseclib-generated-key', gethostname(), $key['publickey']);

return $key;
return [
'private_key' => $key->toString('PKCS1'),
// Replace the placeholder label with a more meaningful one
'public_key' => str_replace(
'phpseclib-generated-key',
gethostname(),
$key->getPublicKey()->toString('OpenSSH'),
),
];
}

/**
Expand All @@ -57,10 +62,7 @@ private function generateSshKeys($keyLength) {
public function getSshKeys($keyLength = 1024) {
$key = $this->generateSshKeys($keyLength);
return new JSONResponse(
['data' => [
'private_key' => $key['privatekey'],
'public_key' => $key['publickey']
],
['data' => $key,
'status' => 'success'
]);
}
Expand Down
28 changes: 14 additions & 14 deletions apps/files_external/lib/Lib/Auth/PublicKey/RSA.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
use OCP\IConfig;
use OCP\IL10N;
use OCP\IUser;
use phpseclib\Crypt\RSA as RSACrypt;
use phpseclib3\Crypt\RSA as RSACrypt;

/**
* RSA public key authentication
Expand Down Expand Up @@ -41,33 +41,33 @@
* @return void
*/
public function manipulateStorageConfig(StorageConfig &$storage, ?IUser $user = null) {
$auth = new RSACrypt();
$auth->setPassword($this->config->getSystemValue('secret', ''));
if (!$auth->loadKey($storage->getBackendOption('private_key'))) {
try {
$auth = RSACrypt::loadPrivateKey(
$storage->getBackendOption('private_key'),
$this->config->getSystemValue('secret', '')
);
} catch (\Throwable) {
// Add fallback routine for a time where secret was not enforced to be exists
$auth->setPassword('');
if (!$auth->loadKey($storage->getBackendOption('private_key'))) {
throw new \RuntimeException('unable to load private key');
}
$auth = RSACrypt::loadPrivateKey($storage->getBackendOption('private_key'));
}

$storage->setBackendOption('public_key_auth', $auth);
}

/**
* Generate a keypair
*
* @param int $keyLenth
* @return array ['privatekey' => $privateKey, 'publickey' => $publicKey]
*/
public function createKey($keyLength) {
public function createKey($keyLength): RSACrypt\PrivateKey {
$rsa = new RSACrypt();

Check failure on line 63 in apps/files_external/lib/Lib/Auth/PublicKey/RSA.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

AbstractInstantiation

apps/files_external/lib/Lib/Auth/PublicKey/RSA.php:63:10: AbstractInstantiation: Unable to instantiate a abstract class phpseclib3\Crypt\RSA (see https://psalm.dev/072)
$rsa->setPublicKeyFormat(RSACrypt::PUBLIC_FORMAT_OPENSSH);
$rsa->setPassword($this->config->getSystemValue('secret', ''));


if ($keyLength !== 1024 && $keyLength !== 2048 && $keyLength !== 4096) {
$keyLength = 1024;
}

return $rsa->createKey($keyLength);
$secret = $this->config->getSystemValue('secret', '');
return $rsa->createKey($keyLength)
->withPassword($secret);
}
}
12 changes: 6 additions & 6 deletions apps/files_external/lib/Lib/Auth/PublicKey/RSAPrivateKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use OCP\IConfig;
use OCP\IL10N;
use OCP\IUser;
use phpseclib\Crypt\RSA as RSACrypt;
use phpseclib3\Crypt\RSA;

/**
* RSA public key authentication
Expand Down Expand Up @@ -39,12 +39,12 @@
* @return void
*/
public function manipulateStorageConfig(StorageConfig &$storage, ?IUser $user = null) {
$auth = new RSACrypt();
$auth->setPassword($this->config->getSystemValue('secret', ''));
if (!$auth->loadKey($storage->getBackendOption('private_key'))) {
$auth = new RSA\PrivateKey();

Check failure on line 42 in apps/files_external/lib/Lib/Auth/PublicKey/RSAPrivateKey.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

InaccessibleMethod

apps/files_external/lib/Lib/Auth/PublicKey/RSAPrivateKey.php:42:11: InaccessibleMethod: Cannot access protected method phpseclib3\Crypt\RSA\PrivateKey::__construct from context OCA\Files_External\Lib\Auth\PublicKey\RSAPrivateKey (see https://psalm.dev/003)
$auth->withPassword($this->config->getSystemValue('secret', ''));
if (!$auth->loadPrivateKey($storage->getBackendOption('private_key'))) {
// Add fallback routine for a time where secret was not enforced to be exists
$auth->setPassword('');
if (!$auth->loadKey($storage->getBackendOption('private_key'))) {
$auth->withPassword('');
if (!$auth->loadPrivateKey($storage->getBackendOption('private_key'))) {
throw new \RuntimeException('unable to load private key');
}
}
Expand Down
12 changes: 6 additions & 6 deletions apps/files_external/lib/Lib/Storage/SFTP.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use OCP\Constants;
use OCP\Files\FileInfo;
use OCP\Files\IMimeTypeDetector;
use phpseclib\Net\SFTP\Stream;
use phpseclib3\Net\SFTP\Stream;

/**
* Uses phpseclib's Net\SFTP class and the Net\SFTP\Stream stream wrapper to
Expand All @@ -29,7 +29,7 @@
private $auth = [];

/**
* @var \phpseclib\Net\SFTP
* @var \phpseclib3\Net\SFTP
*/
protected $client;
private IMimeTypeDetector $mimeTypeDetector;
Expand Down Expand Up @@ -93,16 +93,16 @@
/**
* Returns the connection.
*
* @return \phpseclib\Net\SFTP connected client instance
* @return \phpseclib3\Net\SFTP connected client instance
* @throws \Exception when the connection failed
*/
public function getConnection(): \phpseclib\Net\SFTP {
public function getConnection(): \phpseclib3\Net\SFTP {
if (!is_null($this->client)) {
return $this->client;
}

$hostKeys = $this->readHostKeys();
$this->client = new \phpseclib\Net\SFTP($this->host, $this->port);
$this->client = new \phpseclib3\Net\SFTP($this->host, $this->port);

// The SSH Host Key MUST be verified before login().
$currentHostKey = $this->client->getServerPublicHostKey();
Expand Down Expand Up @@ -315,7 +315,7 @@
case 'wb':
SFTPWriteStream::register();
// the SFTPWriteStream doesn't go through the "normal" methods so it doesn't clear the stat cache.
$connection->_remove_from_stat_cache($absPath);

Check failure on line 318 in apps/files_external/lib/Lib/Storage/SFTP.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

UndefinedMethod

apps/files_external/lib/Lib/Storage/SFTP.php:318:19: UndefinedMethod: Method phpseclib3\Net\SFTP::_remove_from_stat_cache does not exist (see https://psalm.dev/022)
$context = stream_context_create(['sftp' => ['session' => $connection]]);
return fopen('sftpwrite://' . trim($absPath, '/'), 'w', false, $context);
case 'a':
Expand Down Expand Up @@ -442,7 +442,7 @@
$absTarget = $this->absPath($target);

$connection = $this->getConnection();
$size = $connection->size($absSource);

Check failure on line 445 in apps/files_external/lib/Lib/Storage/SFTP.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

UndefinedMethod

apps/files_external/lib/Lib/Storage/SFTP.php:445:25: UndefinedMethod: Method phpseclib3\Net\SFTP::size does not exist (see https://psalm.dev/022)
if ($size === false) {
return false;
}
Expand All @@ -453,7 +453,7 @@
return false;
}
/** @psalm-suppress InternalMethod */
if (!$connection->put($absTarget, $chunk, \phpseclib\Net\SFTP::SOURCE_STRING, $i)) {
if (!$connection->put($absTarget, $chunk, \phpseclib3\Net\SFTP::SOURCE_STRING, $i)) {
return false;
}
}
Expand Down
6 changes: 3 additions & 3 deletions apps/files_external/lib/Lib/Storage/SFTPReadStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
namespace OCA\Files_External\Lib\Storage;

use Icewind\Streams\File;
use phpseclib\Net\SSH2;
use phpseclib3\Net\SSH2;

class SFTPReadStream implements File {
/** @var resource */
public $context;

/** @var \phpseclib\Net\SFTP */
/** @var \phpseclib3\Net\SFTP */
private $sftp;

/** @var string */
Expand Down Expand Up @@ -53,7 +53,7 @@
} else {
throw new \BadMethodCallException('Invalid context, "' . $name . '" options not set');
}
if (isset($context['session']) and $context['session'] instanceof \phpseclib\Net\SFTP) {
if (isset($context['session']) and $context['session'] instanceof \phpseclib3\Net\SFTP) {
$this->sftp = $context['session'];
} else {
throw new \BadMethodCallException('Invalid context, session not set');
Expand All @@ -71,27 +71,27 @@

$this->loadContext('sftp');

if (!($this->sftp->bitmap & SSH2::MASK_LOGIN)) {

Check failure on line 74 in apps/files_external/lib/Lib/Storage/SFTPReadStream.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

InaccessibleProperty

apps/files_external/lib/Lib/Storage/SFTPReadStream.php:74:9: InaccessibleProperty: Cannot access protected property phpseclib3\Net\SFTP::$bitmap from context OCA\Files_External\Lib\Storage\SFTPReadStream (see https://psalm.dev/054)
return false;
}

$remote_file = $this->sftp->_realpath($path);

Check failure on line 78 in apps/files_external/lib/Lib/Storage/SFTPReadStream.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

UndefinedMethod

apps/files_external/lib/Lib/Storage/SFTPReadStream.php:78:31: UndefinedMethod: Method phpseclib3\Net\SFTP::_realpath does not exist (see https://psalm.dev/022)
if ($remote_file === false) {
return false;
}

$packet = pack('Na*N2', strlen($remote_file), $remote_file, NET_SFTP_OPEN_READ, 0);
if (!$this->sftp->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {

Check failure on line 84 in apps/files_external/lib/Lib/Storage/SFTPReadStream.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

UndefinedMethod

apps/files_external/lib/Lib/Storage/SFTPReadStream.php:84:21: UndefinedMethod: Method phpseclib3\Net\SFTP::_send_sftp_packet does not exist (see https://psalm.dev/022)
return false;
}

$response = $this->sftp->_get_sftp_packet();

Check failure on line 88 in apps/files_external/lib/Lib/Storage/SFTPReadStream.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

UndefinedMethod

apps/files_external/lib/Lib/Storage/SFTPReadStream.php:88:28: UndefinedMethod: Method phpseclib3\Net\SFTP::_get_sftp_packet does not exist (see https://psalm.dev/022)
switch ($this->sftp->packet_type) {

Check failure on line 89 in apps/files_external/lib/Lib/Storage/SFTPReadStream.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

InaccessibleProperty

apps/files_external/lib/Lib/Storage/SFTPReadStream.php:89:11: InaccessibleProperty: Cannot access private property phpseclib3\Net\SFTP::$packet_type from context OCA\Files_External\Lib\Storage\SFTPReadStream (see https://psalm.dev/054)
case NET_SFTP_HANDLE:
$this->handle = substr($response, 4);
break;
case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
$this->sftp->_logError($response);

Check failure on line 94 in apps/files_external/lib/Lib/Storage/SFTPReadStream.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

UndefinedMethod

apps/files_external/lib/Lib/Storage/SFTPReadStream.php:94:18: UndefinedMethod: Method phpseclib3\Net\SFTP::_logError does not exist (see https://psalm.dev/022)
return false;
default:
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
Expand Down
6 changes: 3 additions & 3 deletions apps/files_external/lib/Lib/Storage/SFTPWriteStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
namespace OCA\Files_External\Lib\Storage;

use Icewind\Streams\File;
use phpseclib\Net\SSH2;
use phpseclib3\Net\SSH2;

class SFTPWriteStream implements File {
/** @var resource */
public $context;

/** @var \phpseclib\Net\SFTP */
/** @var \phpseclib3\Net\SFTP */
private $sftp;

/** @var string */
Expand Down Expand Up @@ -51,7 +51,7 @@ protected function loadContext(string $name) {
} else {
throw new \BadMethodCallException('Invalid context, "' . $name . '" options not set');
}
if (isset($context['session']) and $context['session'] instanceof \phpseclib\Net\SFTP) {
if (isset($context['session']) and $context['session'] instanceof \phpseclib3\Net\SFTP) {
$this->sftp = $context['session'];
} else {
throw new \BadMethodCallException('Invalid context, session not set');
Expand Down
2 changes: 1 addition & 1 deletion apps/files_external/lib/MountConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
use OCP\Files\StorageNotAvailableException;
use OCP\IL10N;
use OCP\Util;
use phpseclib\Crypt\AES;
use phpseclib3\Crypt\AES;
use Psr\Log\LoggerInterface;

/**
Expand Down
48 changes: 32 additions & 16 deletions apps/files_external/tests/Controller/AjaxControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,27 @@
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserSession;
use phpseclib3\Crypt\RSA as CryptRSA;
use phpseclib3\Crypt\RSA\PrivateKey;
use phpseclib3\Crypt\RSA\PublicKey;
use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;

class AjaxControllerTest extends TestCase {
/** @var IRequest */
private $request;
/** @var RSA */
private $rsa;
/** @var GlobalAuth */
private $globalAuth;
/** @var IUserSession */
private $userSession;
/** @var IGroupManager */
private $groupManager;
/** @var AjaxController */
private $ajaxController;
private IRequest&MockObject $request;
private RSA&MockObject $rsa;
private GlobalAuth&MockObject $globalAuth;
private IUserSession&MockObject $userSession;
private IGroupManager&MockObject $groupManager;

private AjaxController $ajaxController;

protected function setUp(): void {
$this->request = $this->createMock(IRequest::class);
$this->rsa = $this->getMockBuilder('\\OCA\\Files_External\\Lib\\Auth\\PublicKey\\RSA')
$this->rsa = $this->getMockBuilder(RSA::class)
->disableOriginalConstructor()
->getMock();
$this->globalAuth = $this->getMockBuilder('\\OCA\\Files_External\\Lib\\Auth\\Password\GlobalAuth')
$this->globalAuth = $this->getMockBuilder(GlobalAuth::class)
->disableOriginalConstructor()
->getMock();
$this->userSession = $this->createMock(IUserSession::class);
Expand All @@ -53,12 +52,29 @@ protected function setUp(): void {
}

public function testGetSshKeys(): void {
$keyImpl = $this->createMock(CryptRSA::class);
$keyImpl->expects(self::once())
->method('toString')
->with('OpenSSH')
->willReturn('MyPublicKey');

$publicKey = $this->createMock(PublicKey::class);
$publicKey->expects(self::once())
->method('getPublicKey')
->willReturn($keyImpl);

$privateKey = $this->createMock(PrivateKey::class);
$privateKey->expects(self::once())
->method('toString')
->with('PKCS1')
->willReturn('MyPrivatekey');

$this->rsa
->expects($this->once())
->method('createKey')
->willReturn([
'privatekey' => 'MyPrivateKey',
'publickey' => 'MyPublicKey',
'privatekey' => $privateKey,
'publickey' => $publicKey,
]);

$expected = new JSONResponse(
Expand Down
7 changes: 3 additions & 4 deletions core/Command/Integrity/SignApp.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
use OC\IntegrityCheck\Checker;
use OC\IntegrityCheck\Helpers\FileAccessHelper;
use OCP\IURLGenerator;
use phpseclib\Crypt\RSA;
use phpseclib\File\X509;
use phpseclib3\Crypt\RSA;
use phpseclib3\File\X509;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
Expand Down Expand Up @@ -68,8 +68,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
return 1;
}

$rsa = new RSA();
$rsa->loadKey($privateKey);
$rsa = RSA::loadPrivateKey($privateKey);
$x509 = new X509();
$x509->loadX509($keyBundle);
$x509->setPrivateKey($rsa);
Expand Down
7 changes: 3 additions & 4 deletions core/Command/Integrity/SignCore.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

use OC\IntegrityCheck\Checker;
use OC\IntegrityCheck\Helpers\FileAccessHelper;
use phpseclib\Crypt\RSA;
use phpseclib\File\X509;
use phpseclib3\Crypt\RSA;
use phpseclib3\File\X509;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
Expand Down Expand Up @@ -63,8 +63,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
return 1;
}

$rsa = new RSA();
$rsa->loadKey($privateKey);
$rsa = RSA::loadPrivateKey($privateKey);
$x509 = new X509();
$x509->loadX509($keyBundle);
$x509->setPrivateKey($rsa);
Expand Down
2 changes: 1 addition & 1 deletion lib/private/Installer.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
use OCP\IConfig;
use OCP\ITempManager;
use OCP\Migration\IOutput;
use phpseclib\File\X509;
use phpseclib3\File\X509;
use Psr\Log\LoggerInterface;

/**
Expand Down
Loading
Loading