OCA\SnappyMail\Settings\AdminSettings
@@ -85,4 +86,7 @@ There, click on the link to go to the SnappyMail admin panel.
OCA\SnappyMail\Migration\InstallStep
+
+ OCA\SnappyMail\Command\Settings
+
diff --git a/integrations/nextcloud/snappymail/l10n/eu.json b/integrations/nextcloud/snappymail/l10n/eu.json
index d981fe513..d9ef0f7e4 100644
--- a/integrations/nextcloud/snappymail/l10n/eu.json
+++ b/integrations/nextcloud/snappymail/l10n/eu.json
@@ -1,5 +1,5 @@
{ "translations": {
- "Email" : "Helbide elektronikoa",
+ "Email" : "Posta",
"Error" : "Errorea",
"Invalid argument(s)" : "Argumentu baliogabea(k)",
"Saved successfully" : "Ondo gorde da",
@@ -16,4 +16,4 @@
"Enter an email and password to auto-login to SnappyMail." : "Saioa automatikoki hasteko sartu helbide elektronikoa eta pasahitza SnappyMail-en.",
"Password" : "Pasahitza"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
-}
\ No newline at end of file
+}
diff --git a/integrations/nextcloud/snappymail/lib/AppInfo/Application.php b/integrations/nextcloud/snappymail/lib/AppInfo/Application.php
index 0b040139c..df40033cf 100644
--- a/integrations/nextcloud/snappymail/lib/AppInfo/Application.php
+++ b/integrations/nextcloud/snappymail/lib/AppInfo/Application.php
@@ -75,20 +75,24 @@ class Application extends App implements IBootstrap
$dispatcher = $context->getAppContainer()->query('OCP\EventDispatcher\IEventDispatcher');
$dispatcher->addListener(PostLoginEvent::class, function (PostLoginEvent $Event) {
+/*
$config = \OC::$server->getConfig();
// Only store the user's password in the current session if they have
// enabled auto-login using Nextcloud username or email address.
if ($config->getAppValue('snappymail', 'snappymail-autologin', false)
|| $config->getAppValue('snappymail', 'snappymail-autologin-with-email', false)) {
+*/
$sUID = $Event->getUser()->getUID();
\OC::$server->getSession()['snappymail-nc-uid'] = $sUID;
- \OC::$server->getSession()['snappymail-password'] = SnappyMailHelper::encodePassword($Event->getPassword(), $sUID);
+ \OC::$server->getSession()['snappymail-passphrase'] = SnappyMailHelper::encodePassword($Event->getPassword(), $sUID);
+/*
}
+*/
});
$dispatcher->addListener(BeforeUserLoggedOutEvent::class, function (BeforeUserLoggedOutEvent $Event) {
// https://github.com/nextcloud/server/issues/36083#issuecomment-1387370634
-// \OC::$server->getSession()['snappymail-password'] = '';
+// \OC::$server->getSession()['snappymail-passphrase'] = '';
SnappyMailHelper::loadApp();
// \RainLoop\Api::Actions()->Logout(true);
\RainLoop\Api::Actions()->DoLogout();
@@ -99,12 +103,12 @@ class Application extends App implements IBootstrap
$class = 'OCA\Impersonate\Events\BeginImpersonateEvent';
if (\class_exists($class)) {
$dispatcher->addListener($class, function ($Event) {
- \OC::$server->getSession()['snappymail-password'] = '';
+ \OC::$server->getSession()['snappymail-passphrase'] = '';
SnappyMailHelper::loadApp();
\RainLoop\Api::Actions()->Logout(true);
});
$dispatcher->addListener('OCA\Impersonate\Events\EndImpersonateEvent', function ($Event) {
- \OC::$server->getSession()['snappymail-password'] = '';
+ \OC::$server->getSession()['snappymail-passphrase'] = '';
SnappyMailHelper::loadApp();
\RainLoop\Api::Actions()->Logout(true);
});
diff --git a/integrations/nextcloud/snappymail/lib/Command/Settings.php b/integrations/nextcloud/snappymail/lib/Command/Settings.php
new file mode 100644
index 000000000..1e6cae25d
--- /dev/null
+++ b/integrations/nextcloud/snappymail/lib/Command/Settings.php
@@ -0,0 +1,70 @@
+userManager = $userManager;
+ $this->config = $config;
+ }
+
+ protected function configure() {
+ $this
+ ->setName('snappymail:settings')
+ ->setDescription('modifies configuration')
+ ->addArgument(
+ 'uid',
+ InputArgument::REQUIRED,
+ 'User ID used to login'
+ )
+ ->addArgument(
+ 'user',
+ InputArgument::REQUIRED,
+ 'The login username'
+ )
+ ->addArgument(
+ 'pass',
+ InputArgument::OPTIONAL,
+ 'The login passphrase'
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int {
+ $uid = $input->getArgument('uid');
+ if (!$this->userManager->userExists($uid)) {
+ $output->writeln('The user "' . $uid . '" does not exist.');
+ return 1;
+ }
+
+ $sEmail = $input->getArgument('user');
+ $this->config->setUserValue($uid, 'snappymail', 'snappymail-email', $sEmail);
+
+ $sPass = $input->getArgument('pass');
+ if (empty($sPass)) {
+ // Prompt on command line for value
+ if (\is_callable('readline')) {
+ $sPass = \readline("password: ");
+ } else {
+ echo "password: ";
+ $sPass = \stream_get_line(STDIN, 1024, PHP_EOL);
+ }
+ }
+ $sPass = ($sEmail && $sPass) ? SnappyMailHelper::encodePassword($sPass, \md5($sEmail)) : '';
+ $this->config->setUserValue($uid, 'snappymail', 'passphrase', $sPass);
+ return 0;
+ }
+}
diff --git a/integrations/nextcloud/snappymail/lib/Controller/FetchController.php b/integrations/nextcloud/snappymail/lib/Controller/FetchController.php
index 134c2462b..ee8122357 100644
--- a/integrations/nextcloud/snappymail/lib/Controller/FetchController.php
+++ b/integrations/nextcloud/snappymail/lib/Controller/FetchController.php
@@ -53,6 +53,7 @@ class FetchController extends Controller {
$this->config->setAppValue('snappymail', 'snappymail-autologin-with-email',
isset($_POST['snappymail-autologin']) ? '2' === $_POST['snappymail-autologin'] : false);
$this->config->setAppValue('snappymail', 'snappymail-no-embed', isset($_POST['snappymail-no-embed']));
+ $this->config->setAppValue('snappymail', 'snappymail-autologin-oidc', isset($_POST['snappymail-autologin-oidc']));
} else {
return new JSONResponse([
'status' => 'error',
@@ -101,7 +102,7 @@ class FetchController extends Controller {
$sPass = $_POST['snappymail-password'];
if ('******' !== $sPass) {
- $this->config->setUserValue($sUser, 'snappymail', 'snappymail-password',
+ $this->config->setUserValue($sUser, 'snappymail', 'passphrase',
$sPass ? SnappyMailHelper::encodePassword($sPass, \md5($sEmail)) : '');
}
} else {
diff --git a/integrations/nextcloud/snappymail/lib/Migration/InstallStep.php b/integrations/nextcloud/snappymail/lib/Migration/InstallStep.php
index 6e805af6a..cca015aa9 100644
--- a/integrations/nextcloud/snappymail/lib/Migration/InstallStep.php
+++ b/integrations/nextcloud/snappymail/lib/Migration/InstallStep.php
@@ -72,7 +72,7 @@ class InstallStep implements IRepairStep
if ('12345' == $sPassword || !$sPassword) {
$output->info('Generate admin password');
$sPassword = \substr(\base64_encode(\random_bytes(16)), 0, 12);
- $oConfig->SetPassword($sPassword);
+ $oConfig->SetPassword(new \SnappyMail\SensitiveString($sPassword));
\RainLoop\Utils::saveFile(APP_PRIVATE_DATA . 'admin_password.txt', $sPassword . "\n");
$bSave = true;
}
@@ -85,11 +85,15 @@ class InstallStep implements IRepairStep
// $oDomain = \RainLoop\Model\Domain::fromIniArray('nextcloud', []);
$oDomain = new \RainLoop\Model\Domain('nextcloud');
$iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::NONE;
- $oDomain->SetConfig(
- 'localhost', 143, $iSecurityType, true,
- true, 'localhost', 4190, $iSecurityType,
- 'localhost', 25, $iSecurityType, true, true, false, false,
- '');
+ $oDomain->ImapSettings()->host = 'localhost';
+ $oDomain->ImapSettings()->type = $iSecurityType;
+ $oDomain->ImapSettings()->shortLogin = true;
+ $oDomain->SieveSettings()->enabled = true;
+ $oDomain->SieveSettings()->host = 'localhost';
+ $oDomain->SieveSettings()->type = $iSecurityType;
+ $oDomain->SmtpSettings()->host = 'localhost';
+ $oDomain->SmtpSettings()->type = $iSecurityType;
+ $oDomain->SmtpSettings()->shortLogin = true;
$oProvider->Save($oDomain);
if (!$oConfig->Get('login', 'default_domain', '')) {
$oConfig->Set('login', 'default_domain', 'nextcloud');
diff --git a/integrations/nextcloud/snappymail/lib/Settings/AdminSettings.php b/integrations/nextcloud/snappymail/lib/Settings/AdminSettings.php
index 81c1deafc..052d5e877 100644
--- a/integrations/nextcloud/snappymail/lib/Settings/AdminSettings.php
+++ b/integrations/nextcloud/snappymail/lib/Settings/AdminSettings.php
@@ -22,7 +22,8 @@ class AdminSettings implements ISettings
$keys = [
'snappymail-autologin',
'snappymail-autologin-with-email',
- 'snappymail-no-embed'
+ 'snappymail-no-embed',
+ 'snappymail-autologin-oidc'
];
$parameters = [];
foreach ($keys as $k) {
diff --git a/integrations/nextcloud/snappymail/lib/Settings/PersonalSettings.php b/integrations/nextcloud/snappymail/lib/Settings/PersonalSettings.php
index 22211e659..801bf09aa 100644
--- a/integrations/nextcloud/snappymail/lib/Settings/PersonalSettings.php
+++ b/integrations/nextcloud/snappymail/lib/Settings/PersonalSettings.php
@@ -18,21 +18,13 @@ class PersonalSettings implements ISettings
{
$uid = \OC::$server->getUserSession()->getUser()->getUID();
$sEmail = $this->config->getUserValue($uid, 'snappymail', 'snappymail-email');
- if (!$sEmail) {
- $aRainLoop = \OCA\SnappyMail\Util\RainLoop::getLoginCredentials($uid, $this->config);
- if ($aRainLoop) {
- $sEmail = $aRainLoop[0];
- $this->config->setUserValue($uid, 'snappymail', 'snappymail-email', $sEmail);
- if ($aRainLoop[1]) {
- $this->config->setUserValue($uid, 'snappymail', 'snappymail-password',
- \OCA\SnappyMail\Util\SnappyMailHelper::encodePassword($aRainLoop[1], \md5($sEmail))
- );
- }
- }
+ if ($sPass = $this->config->getUserValue($uid, 'snappymail', 'snappymail-password')) {
+ $this->config->deleteUserValue($uid, 'snappymail', 'snappymail-password');
+ $this->config->setUserValue($uid, 'snappymail', 'passphrase', $sPass);
}
$parameters = [
'snappymail-email' => $sEmail,
- 'snappymail-password' => $this->config->getUserValue($uid, 'snappymail', 'snappymail-password') ? '******' : ''
+ 'snappymail-password' => $this->config->getUserValue($uid, 'snappymail', 'passphrase') ? '******' : ''
];
\OCP\Util::addScript('snappymail', 'snappymail');
return new TemplateResponse('snappymail', 'personal_settings', $parameters, '');
diff --git a/integrations/nextcloud/snappymail/lib/Util/RainLoop.php b/integrations/nextcloud/snappymail/lib/Util/RainLoop.php
index e49e9dc1c..7f8073aa2 100644
--- a/integrations/nextcloud/snappymail/lib/Util/RainLoop.php
+++ b/integrations/nextcloud/snappymail/lib/Util/RainLoop.php
@@ -4,20 +4,6 @@ namespace OCA\SnappyMail\Util;
class RainLoop
{
-
- public static function getLoginCredentials($sUID, $config) : ?array
- {
- $sEmail = \trim($config->getUserValue($sUID, 'rainloop', 'rainloop-email'));
- if ($sEmail) {
- $sPassword = $config->getUserValue($sUID, 'rainloop', 'rainloop-password', '');
- return [
- $sEmail,
- $sPassword ? static::decodePassword($sPassword, \md5($sEmail)) : ''
- ];
- }
- return null;
- }
-
/**
* Imports data from RainLoop
* skips: /data/rainloop-storage/_data_/_default_/configs/application.ini
@@ -82,47 +68,4 @@ class RainLoop
return $result;
}
-
- /**
- * @param string $sPassword
- * @param string $sSalt
- *
- * @return string
- */
- public static function decodePassword($sPassword, $sSalt)
- {
- $sPassword = \base64_decode(\trim($sPassword));
-
- $method = 'AES-256-CBC';
- if (\function_exists('openssl_encrypt')
- && \function_exists('openssl_decrypt')
- && \function_exists('openssl_random_pseudo_bytes')
- && \function_exists('openssl_cipher_iv_length')
- && \function_exists('openssl_get_cipher_methods')
- && \defined('OPENSSL_RAW_DATA')
- && \defined('OPENSSL_ZERO_PADDING')
- && \in_array($method, \openssl_get_cipher_methods())
- ) {
- $aParts = \explode('|', $sPassword, 2);
- if (\is_array($aParts) && !empty($aParts[0]) && !empty($aParts[1])) {
- $sData = \base64_decode($aParts[0]);
- $iv = \base64_decode($aParts[1]);
- return \base64_decode(\trim(
- \openssl_decrypt($sData, $method, \md5($sSalt), OPENSSL_RAW_DATA, $iv)
- ));
- }
- }
-
- if (\function_exists('mcrypt_encrypt')
- && \function_exists('mcrypt_decrypt')
- && \defined('MCRYPT_RIJNDAEL_256')
- && \defined('MCRYPT_MODE_ECB')
- ) {
- return \base64_decode(\trim(
- \mcrypt_decrypt(MCRYPT_RIJNDAEL_256, \md5($sSalt), $sPassword, MCRYPT_MODE_ECB)
- ));
- }
-
- return $sPassword;
- }
}
diff --git a/integrations/nextcloud/snappymail/lib/Util/SnappyMailHelper.php b/integrations/nextcloud/snappymail/lib/Util/SnappyMailHelper.php
index 409de91b3..5cf37e6e1 100644
--- a/integrations/nextcloud/snappymail/lib/Util/SnappyMailHelper.php
+++ b/integrations/nextcloud/snappymail/lib/Util/SnappyMailHelper.php
@@ -4,15 +4,15 @@ namespace OCA\SnappyMail\Util;
class SnappyMailResponse extends \OCP\AppFramework\Http\Response
{
- public function render(): string
- {
+ public function render(): string
+ {
$data = '';
$i = \ob_get_level();
while ($i--) {
$data .= \ob_get_clean();
}
return $data;
- }
+ }
}
class SnappyMailHelper
@@ -91,23 +91,25 @@ class SnappyMailHelper
*/
if ($doLogin && $aCredentials[1] && $aCredentials[2]) {
try {
- $oActions->Logger()->AddSecret($aCredentials[2]);
- $oAccount = $oActions->LoginProcess($aCredentials[1], $aCredentials[2]);
- if ($oAccount) {
- // Must be here due to bug #1241
- $oActions->SetMainAuthAccount($oAccount);
- $oActions->Plugins()->RunHook('login.success', array($oAccount));
-
- $oActions->SetAuthToken($oAccount);
- if ($oConfig->Get('login', 'sign_me_auto', \RainLoop\Enumerations\SignMeType::DEFAULT_OFF) === \RainLoop\Enumerations\SignMeType::DEFAULT_ON) {
+ $ocSession = \OC::$server->getSession();
+ if ($ocSession->get('is_oidc')) {
+ $pwd = new \SnappyMail\SensitiveString($aCredentials[1]);
+ $oAccount = $oActions->LoginProcess($aCredentials[1], $pwd);
+ if ($oAccount) {
$oActions->SetSignMeToken($oAccount);
}
+ } else {
+ $oAccount = $oActions->LoginProcess($aCredentials[1], $aCredentials[2]);
+ if ($oAccount && $oConfig->Get('login', 'sign_me_auto', \RainLoop\Enumerations\SignMeType::DefaultOff) === \RainLoop\Enumerations\SignMeType::DefaultOn) {
+ $oActions->SetSignMeToken($oAccount);
+ }
}
} catch (\Throwable $e) {
// Login failure, reset password to prevent more attempts
$sUID = \OC::$server->getUserSession()->getUser()->getUID();
- \OC::$server->getSession()['snappymail-password'] = '';
- \OC::$server->getConfig()->setUserValue($sUID, 'snappymail', 'snappymail-password', '');
+ \OC::$server->getSession()['snappymail-passphrase'] = '';
+ \OC::$server->getConfig()->setUserValue($sUID, 'snappymail', 'passphrase', '');
+ \SnappyMail\Log::error('Nextcloud', $e->getMessage());
}
}
}
@@ -124,45 +126,66 @@ class SnappyMailHelper
}
}
- public static function getLoginCredentials() : array
+ private static function getLoginCredentials() : array
{
- $sEmail = '';
- $sPassword = '';
- $config = \OC::$server->getConfig();
$sUID = \OC::$server->getUserSession()->getUser()->getUID();
+ $config = \OC::$server->getConfig();
$ocSession = \OC::$server->getSession();
- // Only use the user's password in the current session if they have
- // enabled auto-login using Nextcloud username or email address.
- if ($ocSession['snappymail-nc-uid'] == $sUID) {
- if ($config->getAppValue('snappymail', 'snappymail-autologin', false)) {
- $sEmail = $sUID;
- $sPassword = $ocSession['snappymail-password'];
- } else if ($config->getAppValue('snappymail', 'snappymail-autologin-with-email', false)) {
- $sEmail = $config->getUserValue($sUID, 'settings', 'email');
- $sPassword = $ocSession['snappymail-password'];
- }
+
+ // If the user has set credentials for SnappyMail in their personal settings,
+ // this has the first priority.
+ $sEmail = $config->getUserValue($sUID, 'snappymail', 'snappymail-email');
+ $sPassword = $config->getUserValue($sUID, 'snappymail', 'passphrase')
+ ?: $config->getUserValue($sUID, 'snappymail', 'snappymail-password');
+ if ($sEmail && $sPassword) {
+ $sPassword = static::decodePassword($sPassword, \md5($sEmail));
if ($sPassword) {
- $sPassword = static::decodePassword($sPassword, $sUID);
+ return [$sUID, $sEmail, $sPassword];
+ } else {
+ \SnappyMail\Log::debug('Nextcloud', 'decodePassword failed for getUserValue');
}
}
- // If the user has set credentials for SnappyMail in their personal
- // settings, override everything before and use those instead.
- $sCustomEmail = $config->getUserValue($sUID, 'snappymail', 'snappymail-email');
- if ($sCustomEmail) {
- $sEmail = $sCustomEmail;
- $sPassword = $config->getUserValue($sUID, 'snappymail', 'snappymail-password');
+ // If the current user ID is identical to login ID (not valid when using account switching),
+ // this has the second priority.
+ if ($ocSession['snappymail-nc-uid'] == $sUID) {
+
+ // If OpenID Connect (OIDC) is enabled and used for login, use this.
+ // https://apps.nextcloud.com/apps/oidc_login
+ if ($config->getAppValue('snappymail', 'snappymail-autologin-oidc', false)) {
+ if ($ocSession->get('is_oidc')) {
+ // IToken->getPassword() ???
+ if ($sAccessToken = $ocSession->get('oidc_access_token')) {
+ $sEmail = $config->getUserValue($sUID, 'settings', 'email');
+ return [$sUID, $sEmail, $sAccessToken];
+ }
+ \SnappyMail\Log::debug('Nextcloud', 'OIDC access_token missing');
+ } else {
+ \SnappyMail\Log::debug('Nextcloud', 'No OIDC login');
+ }
+ }
+
+ // Only use the user's password in the current session if they have
+ // enabled auto-login using Nextcloud username or email address.
+ $sEmail = '';
+ $sPassword = '';
+ if ($config->getAppValue('snappymail', 'snappymail-autologin', false)) {
+ $sEmail = $sUID;
+ $sPassword = $ocSession['snappymail-passphrase'];
+ } else if ($config->getAppValue('snappymail', 'snappymail-autologin-with-email', false)) {
+ $sEmail = $config->getUserValue($sUID, 'settings', 'email');
+ $sPassword = $ocSession['snappymail-passphrase'];
+ } else {
+ \SnappyMail\Log::debug('Nextcloud', 'snappymail-autologin is off');
+ }
if ($sPassword) {
- $sPassword = static::decodePassword($sPassword, \md5($sEmail));
- }
- } else if ($aRainLoop = RainLoop::getLoginCredentials($sUID, $config)) {
- $sEmail = $aRainLoop[0];
- $config->setUserValue($sUID, 'snappymail', 'snappymail-email', $sEmail);
- if ($aRainLoop[1]) {
- $config->setUserValue($sUID, 'snappymail', 'snappymail-password', static::encodePassword($aRainLoop[1], \md5($sEmail)));
+ return [$sUID, $sEmail, static::decodePassword($sPassword, $sUID)];
}
+ } else {
+ \SnappyMail\Log::debug('Nextcloud', "snappymail-nc-uid mismatch '{$ocSession['snappymail-nc-uid']}' != '{$sUID}'");
}
- return [$sUID, $sEmail, $sPassword ?: ''];
+
+ return [$sUID, '', ''];
}
public static function getAppUrl() : string
@@ -186,9 +209,10 @@ class SnappyMailHelper
return \SnappyMail\Crypt::EncryptUrlSafe($sPassword, $sSalt);
}
- public static function decodePassword(string $sPassword, string $sSalt)/* : mixed */
+ public static function decodePassword(string $sPassword, string $sSalt) : ?\SnappyMail\SensitiveString
{
static::loadApp();
- return \SnappyMail\Crypt::DecryptUrlSafe($sPassword, $sSalt);
+ $result = \SnappyMail\Crypt::DecryptUrlSafe($sPassword, $sSalt);
+ return $result ? new \SnappyMail\SensitiveString($result) : null;
}
}
diff --git a/integrations/nextcloud/snappymail/templates/admin-local.php b/integrations/nextcloud/snappymail/templates/admin-local.php
index 446e8a4bd..8fd72a4ac 100644
--- a/integrations/nextcloud/snappymail/templates/admin-local.php
+++ b/integrations/nextcloud/snappymail/templates/admin-local.php
@@ -38,6 +38,15 @@
+
+
+ >
+
+
+
+
>