diff --git a/apps/files_external/js/public_key.js b/apps/files_external/js/public_key.js index 669f109573..6856c7d021 100644 --- a/apps/files_external/js/public_key.js +++ b/apps/files_external/js/public_key.js @@ -1,7 +1,7 @@ $(document).ready(function() { OCA.External.Settings.mountConfig.whenSelectAuthMechanism(function($tr, authMechanism, scheme, onCompletion) { - if (scheme === 'publickey') { + if (scheme === 'publickey' && authMechanism === 'publickey::rsa') { var config = $tr.find('.configuration'); if ($(config).find('[name="public_key_generate"]').length === 0) { setupTableRow($tr, config); diff --git a/apps/files_external/lib/AppInfo/Application.php b/apps/files_external/lib/AppInfo/Application.php index f312e06511..e372a906ba 100644 --- a/apps/files_external/lib/AppInfo/Application.php +++ b/apps/files_external/lib/AppInfo/Application.php @@ -29,6 +29,7 @@ namespace OCA\Files_External\AppInfo; +use OCA\Files_External\Lib\Auth\PublicKey\RSAPrivateKey; use \OCP\AppFramework\App; use OCP\AppFramework\IAppContainer; use \OCA\Files_External\Service\BackendService; @@ -138,6 +139,7 @@ class Application extends App implements IBackendProvider, IAuthMechanismProvide // AuthMechanism::SCHEME_PUBLICKEY mechanisms $container->query(RSA::class), + $container->query(RSAPrivateKey::class), // AuthMechanism::SCHEME_OPENSTACK mechanisms $container->query(OpenStackV2::class), diff --git a/apps/files_external/lib/Lib/Auth/PublicKey/RSAPrivateKey.php b/apps/files_external/lib/Lib/Auth/PublicKey/RSAPrivateKey.php new file mode 100644 index 0000000000..fecdbae9e4 --- /dev/null +++ b/apps/files_external/lib/Lib/Auth/PublicKey/RSAPrivateKey.php @@ -0,0 +1,65 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Files_External\Lib\Auth\PublicKey; + +use \OCP\IL10N; +use \OCA\Files_External\Lib\DefinitionParameter; +use \OCA\Files_External\Lib\Auth\AuthMechanism; +use \OCA\Files_External\Lib\StorageConfig; +use \OCP\IConfig; +use OCP\IUser; +use \phpseclib\Crypt\RSA as RSACrypt; + +/** + * RSA public key authentication + */ +class RSAPrivateKey extends AuthMechanism { + + /** @var IConfig */ + private $config; + + public function __construct(IL10N $l, IConfig $config) { + $this->config = $config; + + $this + ->setIdentifier('publickey::rsa_private') + ->setScheme(self::SCHEME_PUBLICKEY) + ->setText($l->t('RSA private key')) + ->addParameters([ + new DefinitionParameter('user', $l->t('Username')), + (new DefinitionParameter('password', $l->t('Password'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL) + ->setType(DefinitionParameter::VALUE_PASSWORD), + new DefinitionParameter('private_key', $l->t('Private key')), + ]); + } + + public function manipulateStorageConfig(StorageConfig &$storage, IUser $user = null) { + $auth = new RSACrypt(); + $auth->setPassword($this->config->getSystemValue('secret', '')); + if (!$auth->loadKey($storage->getBackendOption('private_key'))) { + throw new \RuntimeException('unable to load private key'); + } + $storage->setBackendOption('public_key_auth', $auth); + } +} diff --git a/apps/files_external/lib/Lib/Storage/SFTP.php b/apps/files_external/lib/Lib/Storage/SFTP.php index 6bd77dd249..9340b08fef 100644 --- a/apps/files_external/lib/Lib/Storage/SFTP.php +++ b/apps/files_external/lib/Lib/Storage/SFTP.php @@ -47,7 +47,7 @@ class SFTP extends \OC\Files\Storage\Common { private $root; private $port = 22; - private $auth; + private $auth = []; /** * @var \phpseclib\Net\SFTP @@ -93,10 +93,13 @@ class SFTP extends \OC\Files\Storage\Common { $this->user = $params['user']; if (isset($params['public_key_auth'])) { - $this->auth = $params['public_key_auth']; - } elseif (isset($params['password'])) { - $this->auth = $params['password']; - } else { + $this->auth[] = $params['public_key_auth']; + } + if (isset($params['password']) && $params['password'] !== '') { + $this->auth[] = $params['password']; + } + + if ($this->auth === []) { throw new \UnexpectedValueException('no authentication parameters specified'); } @@ -132,7 +135,15 @@ class SFTP extends \OC\Files\Storage\Common { $this->writeHostKeys($hostKeys); } - if (!$this->client->login($this->user, $this->auth)) { + $login = false; + foreach ($this->auth as $auth) { + $login = $this->client->login($this->user, $auth); + if ($login === true) { + break; + } + } + + if ($login === false) { throw new \Exception('Login failed'); } return $this->client;