diff --git a/.eslintrc.js b/.eslintrc.js index f51c13b..ad2e02f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,7 +1,7 @@ module.exports = { - // extends: [ - // '@nextcloud', - // ], + extends: [ + '@nextcloud', + ], // some unused toolgit files ignorePatterns: [ 'src/toolkit/util/file-download.js', @@ -38,13 +38,25 @@ module.exports = { }, overrides: [ { + // Vue files with TypeScript need the TypeScript parser files: ['*.vue'], + parser: 'vue-eslint-parser', + parserOptions: { + parser: '@typescript-eslint/parser', + sourceType: 'module', + ecmaVersion: 2022, + }, rules: { semi: ['error', 'never'], + // False positive with TypeScript generics like defineEmits<{...}>() + 'func-call-spacing': 'off', + '@typescript-eslint/func-call-spacing': 'off', + // Webpack ?raw query not recognized by eslint resolver + 'import/no-unresolved': ['error', { ignore: ['\\?raw$'] }], }, }, { - files: ['*.ts', '*.cts', '*.mts', '*.tsx', '*.vue'], + files: ['*.ts', '*.cts', '*.mts', '*.tsx'], rules: { '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], }, diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index ec1570c..1fff2ed 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -60,6 +60,10 @@ class SettingsController extends Controller Config::FORCE_SSO => [ 'rw' => true, 'default' => Config::FORCE_SSO_DEFAULT, ], Config::SHOW_TOP_LINE => [ 'rw' => true, 'default' => Config::SHOW_TOP_LINE_DEFAULT, ], Config::ENABLE_SSL_VERIFY => [ 'rw' => true, 'default' => Config::ENABLE_SSL_VERIFY_DEFAULT, ], + Config::ENABLE_TLS_CLIENT_CERTIFICATES => [ 'rw' => true, 'default' => Config::ENABLE_TLS_CLIENT_CERTIFICATES_DEFAULT, ], + Config::CLIENT_TLS_KEY_FILE => [ 'rw' => true, 'default' => Config::CLIENT_TLS_KEY_FILE_DEFAULT, ], + Config::CLIENT_TLS_CERTIFICATE_FILE => [ 'rw' => true, 'default' => Config::CLIENT_TLS_CERTIFICATE_FILE_DEFAULT, ], + Config::CLIENT_TLS_KEY_PASSWORD => [ 'rw' => true, 'default' => Config::CLIENT_TLS_KEY_PASSWORD_DEFAULT, ], Config::PERSONAL_ENCRYPTION => [ 'rw' => true, 'default' => Config::PERSONAL_ENCRYPTION_DEFAULT, ], Config::CARDDAV_PROVISIONG_TAG => [ 'rw' => true, 'default' => Config::CARDDAV_PROVISIONG_TAG_DEFAULT, ], ]; @@ -151,6 +155,9 @@ public function setAdmin(string $setting, mixed $value, bool $force = false):Dat case Config::EMAIL_ADDRESS_CHOICE: case Config::FIXED_SINGLE_EMAIL_ADDRESS: case Config::CARDDAV_PROVISIONG_TAG: + case Config::CLIENT_TLS_KEY_FILE: + case Config::CLIENT_TLS_CERTIFICATE_FILE: + case Config::CLIENT_TLS_KEY_PASSWORD: $newValue = $value; break; case Config::FIXED_SINGLE_EMAIL_PASSWORD: @@ -162,6 +169,7 @@ public function setAdmin(string $setting, mixed $value, bool $force = false):Dat case Config::SHOW_TOP_LINE: case Config::ENABLE_SSL_VERIFY: case Config::PERSONAL_ENCRYPTION: + case Config::ENABLE_TLS_CLIENT_CERTIFICATES: $newValue = filter_var($value, FILTER_VALIDATE_BOOLEAN, ['flags' => FILTER_NULL_ON_FAILURE]); if ($newValue === null) { return self::grumble($this->l->t( @@ -240,6 +248,9 @@ public function getAdmin(?string $setting = null):DataResponse case Config::EMAIL_ADDRESS_CHOICE: case Config::FIXED_SINGLE_EMAIL_ADDRESS: case Config::CARDDAV_PROVISIONG_TAG: + case Config::CLIENT_TLS_KEY_FILE: + case Config::CLIENT_TLS_CERTIFICATE_FILE: + case Config::CLIENT_TLS_KEY_PASSWORD: break; case Config::FIXED_SINGLE_EMAIL_PASSWORD: $humanValue = '●●●●●●●●'; @@ -249,6 +260,7 @@ public function getAdmin(?string $setting = null):DataResponse case Config::SHOW_TOP_LINE: case Config::ENABLE_SSL_VERIFY: case Config::PERSONAL_ENCRYPTION: + case Config::ENABLE_TLS_CLIENT_CERTIFICATES: if ($humanValue !== null) { $humanValue = $humanValue ? $this->l->t('true') : $this->l->t('false'); } diff --git a/lib/Service/AuthRoundCube.php b/lib/Service/AuthRoundCube.php index be6555b..f65ac7d 100644 --- a/lib/Service/AuthRoundCube.php +++ b/lib/Service/AuthRoundCube.php @@ -55,9 +55,13 @@ class AuthRoundCube /** @var string */ private $appName; + private $clientTLSKeyFile; + private $clientTLSCertificateFile; + private $clientTLSKeyPassword; /** @var bool */ private $enableSSLVerify; + private $enableClientTLSCertificates; private $proto; private $host; @@ -80,6 +84,10 @@ public function __construct( protected ILogger $logger, ) { $this->enableSSLVerify = $this->config->getAppValue(Config::ENABLE_SSL_VERIFY); + $this->enableClientTLSCertificates = $this->config->getAppValue(Config::ENABLE_TLS_CLIENT_CERTIFICATES); + $this->clientTLSKeyFile = $this->config->getAppValue(Config::CLIENT_TLS_KEY_FILE); + $this->clientTLSCertificateFile = $this->config->getAppValue(Config::CLIENT_TLS_CERTIFICATE_FILE); + $this->clientTLSKeyPassword = $this->config->getAppValue(Config::CLIENT_TLS_KEY_PASSWORD); $location = $this->config->getAppValue(Config::EXTERNAL_LOCATION); if ($location[0] == '/') { @@ -458,6 +466,12 @@ private function sendRequest(string $rcQuery = '', string $method = 'POST', ?arr $curlOpts[CURLOPT_SSL_VERIFYPEER] = false; $curlOpts[CURLOPT_SSL_VERIFYHOST] = 0; } + if ($this->enableClientTLSCertificates) { + $curlOpts[CURLOPT_SSLKEY] = $this->clientTLSKeyFile; + $curlOpts[CURLOPT_SSLCERT] = $this->clientTLSCertificateFile; + $curlOpts[CURLOPT_SSLKEYPASSWD] = $this->clientTLSKeyPassword; + } + curl_setopt_array($curl, $curlOpts); $rawResponse = curl_exec($curl); diff --git a/lib/Service/Config.php b/lib/Service/Config.php index 115dea5..5be4410 100644 --- a/lib/Service/Config.php +++ b/lib/Service/Config.php @@ -66,6 +66,14 @@ class Config public const SHOW_TOP_LINE_DEFAULT = false; public const ENABLE_SSL_VERIFY = 'enableSSLVerify'; public const ENABLE_SSL_VERIFY_DEFAULT = true; + public const ENABLE_TLS_CLIENT_CERTIFICATES = 'enableTLSClientCertificates'; + public const ENABLE_TLS_CLIENT_CERTIFICATES_DEFAULT = false; + public const CLIENT_TLS_KEY_FILE = 'clientTLSKeyFile'; + public const CLIENT_TLS_KEY_FILE_DEFAULT = ''; + public const CLIENT_TLS_CERTIFICATE_FILE = 'clientTLSCertificateFile'; + public const CLIENT_TLS_CERTIFICATE_FILE_DEFAULT = ''; + public const CLIENT_TLS_KEY_PASSWORD = 'clientTLSKeyPassword'; + public const CLIENT_TLS_KEY_PASSWORD_DEFAULT = ''; public const PERSONAL_ENCRYPTION = 'personalEncryption'; public const PERSONAL_ENCRYPTION_DEFAULT = false; public const CARDDAV_PROVISIONG_TAG = 'cardDavProvisioningTag'; @@ -78,6 +86,10 @@ class Config self::FORCE_SSO => self::FORCE_SSO_DEFAULT, self::SHOW_TOP_LINE => self::SHOW_TOP_LINE_DEFAULT, self::ENABLE_SSL_VERIFY => self::ENABLE_SSL_VERIFY_DEFAULT, + self::ENABLE_TLS_CLIENT_CERTIFICATES => self::ENABLE_TLS_CLIENT_CERTIFICATES_DEFAULT, + self::CLIENT_TLS_KEY_FILE => self::CLIENT_TLS_KEY_FILE_DEFAULT, + self::CLIENT_TLS_CERTIFICATE_FILE => self::CLIENT_TLS_CERTIFICATE_FILE_DEFAULT, + self::CLIENT_TLS_KEY_PASSWORD => self::CLIENT_TLS_KEY_PASSWORD_DEFAULT, self::PERSONAL_ENCRYPTION => self::PERSONAL_ENCRYPTION_DEFAULT, self::CARDDAV_PROVISIONG_TAG => self::CARDDAV_PROVISIONG_TAG_DEFAULT, ]; diff --git a/src/AdminSettings.vue b/src/AdminSettings.vue index c8e36e0..62fe560 100644 --- a/src/AdminSettings.vue +++ b/src/AdminSettings.vue @@ -170,6 +170,41 @@ > {{ t(appName, 'Enable SSL verification.') }} + + + + +