aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files_external/lib/Lib/Backend/SMB.php
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_external/lib/Lib/Backend/SMB.php')
-rw-r--r--apps/files_external/lib/Lib/Backend/SMB.php158
1 files changed, 114 insertions, 44 deletions
diff --git a/apps/files_external/lib/Lib/Backend/SMB.php b/apps/files_external/lib/Lib/Backend/SMB.php
index c4aadbd13f6..e86ad98880c 100644
--- a/apps/files_external/lib/Lib/Backend/SMB.php
+++ b/apps/files_external/lib/Lib/Backend/SMB.php
@@ -1,70 +1,140 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_External\Lib\Backend;
-use \OCP\IL10N;
-use \OCA\Files_External\Lib\Backend\Backend;
-use \OCA\Files_External\Lib\DefinitionParameter;
-use \OCA\Files_External\Lib\Auth\AuthMechanism;
-use \OCA\Files_External\Service\BackendService;
-use \OCA\Files_External\Lib\StorageConfig;
-use \OCA\Files_External\Lib\LegacyDependencyCheckPolyfill;
-
-use \OCA\Files_External\Lib\Auth\Password\Password;
+use Icewind\SMB\BasicAuth;
+use Icewind\SMB\KerberosAuth;
+use Icewind\SMB\KerberosTicket;
+use Icewind\SMB\Native\NativeServer;
+use Icewind\SMB\Wrapped\Server;
+use OCA\Files_External\Lib\Auth\AuthMechanism;
+use OCA\Files_External\Lib\Auth\Password\Password;
+use OCA\Files_External\Lib\Auth\SMB\KerberosApacheAuth as KerberosApacheAuthMechanism;
+use OCA\Files_External\Lib\DefinitionParameter;
+use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException;
+use OCA\Files_External\Lib\MissingDependency;
+use OCA\Files_External\Lib\Storage\SystemBridge;
+use OCA\Files_External\Lib\StorageConfig;
+use OCP\IL10N;
use OCP\IUser;
class SMB extends Backend {
-
- use LegacyDependencyCheckPolyfill;
-
public function __construct(IL10N $l, Password $legacyAuth) {
$this
->setIdentifier('smb')
- ->addIdentifierAlias('\OC\Files\Storage\SMB') // legacy compat
+ ->addIdentifierAlias('\OC\Files\Storage\SMB')// legacy compat
->setStorageClass('\OCA\Files_External\Lib\Storage\SMB')
- ->setText($l->t('SMB / CIFS'))
+ ->setText($l->t('SMB/CIFS'))
->addParameters([
- (new DefinitionParameter('host', $l->t('Host'))),
- (new DefinitionParameter('share', $l->t('Share'))),
+ new DefinitionParameter('host', $l->t('Host')),
+ new DefinitionParameter('share', $l->t('Share')),
(new DefinitionParameter('root', $l->t('Remote subfolder')))
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
(new DefinitionParameter('domain', $l->t('Domain')))
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
+ (new DefinitionParameter('show_hidden', $l->t('Show hidden files')))
+ ->setType(DefinitionParameter::VALUE_BOOLEAN)
+ ->setFlag(DefinitionParameter::FLAG_OPTIONAL),
+ (new DefinitionParameter('case_sensitive', $l->t('Case sensitive file system')))
+ ->setType(DefinitionParameter::VALUE_BOOLEAN)
+ ->setFlag(DefinitionParameter::FLAG_OPTIONAL)
+ ->setDefaultValue(true)
+ ->setTooltip($l->t('Disabling it will allow to use a case insensitive file system, but comes with a performance penalty')),
+ (new DefinitionParameter('check_acl', $l->t('Verify ACL access when listing files')))
+ ->setType(DefinitionParameter::VALUE_BOOLEAN)
+ ->setFlag(DefinitionParameter::FLAG_OPTIONAL)
+ ->setTooltip($l->t("Check the ACL's of each file or folder inside a directory to filter out items where the account has no read permissions, comes with a performance penalty")),
+ (new DefinitionParameter('timeout', $l->t('Timeout')))
+ ->setType(DefinitionParameter::VALUE_TEXT)
+ ->setFlag(DefinitionParameter::FLAG_OPTIONAL)
+ ->setFlag(DefinitionParameter::FLAG_HIDDEN),
])
->addAuthScheme(AuthMechanism::SCHEME_PASSWORD)
- ->setLegacyAuthMechanism($legacyAuth)
- ;
+ ->addAuthScheme(AuthMechanism::SCHEME_SMB)
+ ->setLegacyAuthMechanism($legacyAuth);
}
- /**
- * @param StorageConfig $storage
- * @param IUser $user
- */
- public function manipulateStorageConfig(StorageConfig &$storage, IUser $user = null) {
- $user = $storage->getBackendOption('user');
- if ($domain = $storage->getBackendOption('domain')) {
- $storage->setBackendOption('user', $domain.'\\'.$user);
+ public function manipulateStorageConfig(StorageConfig &$storage, ?IUser $user = null): void {
+ $auth = $storage->getAuthMechanism();
+ if ($auth->getScheme() === AuthMechanism::SCHEME_PASSWORD) {
+ if (!is_string($storage->getBackendOption('user')) || !is_string($storage->getBackendOption('password'))) {
+ throw new \InvalidArgumentException('user or password is not set');
+ }
+
+ $smbAuth = new BasicAuth(
+ $storage->getBackendOption('user'),
+ $storage->getBackendOption('domain'),
+ $storage->getBackendOption('password')
+ );
+ } else {
+ switch ($auth->getIdentifier()) {
+ case 'smb::kerberos':
+ $smbAuth = new KerberosAuth();
+ break;
+ case 'smb::kerberosapache':
+ if (!$auth instanceof KerberosApacheAuthMechanism) {
+ throw new \InvalidArgumentException('invalid authentication backend');
+ }
+ $credentialsStore = $auth->getCredentialsStore();
+ $kerbAuth = new KerberosAuth();
+ $kerbAuth->setTicket(KerberosTicket::fromEnv());
+ // check if a kerberos ticket is available, else fallback to session credentials
+ if ($kerbAuth->getTicket()?->isValid()) {
+ $smbAuth = $kerbAuth;
+ } else {
+ try {
+ $credentials = $credentialsStore->getLoginCredentials();
+ $loginName = $credentials->getLoginName();
+ $pass = $credentials->getPassword();
+ preg_match('/(.*)@(.*)/', $loginName, $matches);
+ $realm = $storage->getBackendOption('default_realm');
+ if (empty($realm)) {
+ $realm = 'WORKGROUP';
+ }
+ if (count($matches) === 0) {
+ $username = $loginName;
+ $workgroup = $realm;
+ } else {
+ [, $username, $workgroup] = $matches;
+ }
+ $smbAuth = new BasicAuth(
+ $username,
+ $workgroup,
+ $pass
+ );
+ } catch (\Exception) {
+ throw new InsufficientDataForMeaningfulAnswerException('No session credentials saved');
+ }
+ }
+
+ break;
+ default:
+ throw new \InvalidArgumentException('unknown authentication backend');
+ }
}
+
+ $storage->setBackendOption('auth', $smbAuth);
}
+ public function checkDependencies(): array {
+ $system = \OCP\Server::get(SystemBridge::class);
+ if (NativeServer::available($system)) {
+ return [];
+ } elseif (Server::available($system)) {
+ $missing = new MissingDependency('php-smbclient');
+ $missing->setOptional(true);
+ $missing->setMessage('The php-smbclient library provides improved compatibility and performance for SMB storages.');
+ return [$missing];
+ } else {
+ $missing = new MissingDependency('php-smbclient');
+ $missing->setMessage('Either the php-smbclient library (preferred) or the smbclient binary is required for SMB storages.');
+ return [$missing, new MissingDependency('smbclient')];
+ }
+ }
}