diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php index 246b89694..1d15db1c8 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php @@ -180,56 +180,40 @@ class ImapClient extends \MailSo\Net\NetClient try { - if ('CRAM-MD5' === $type) + if (0 === \strpos($type, 'SCRAM-SHA-')) { - $oContinuationResponse = $this->SendRequestGetResponse('AUTHENTICATE', array($type))->getLast(); - if ($oContinuationResponse && Enumerations\ResponseType::CONTINUATION === $oContinuationResponse->ResponseType) - { - $sTicket = $oContinuationResponse->ResponseList[1] ?? null; - if ($sTicket) - { - $sToken = $SASL->authenticate($sLogin, $sPassword, $sTicket); - - $this->oLogger->Write('ticket: '.\base64_decode($sTicket)); - - if ($this->oLogger) - { - $this->oLogger->AddSecret($sToken); - } - - $this->sendRaw($sToken, true, '*******'); - $this->getResponse(); - } - else - { - $this->writeLogException( - new Exceptions\LoginException, - \MailSo\Log\Enumerations\Type::NOTICE, true); - } + $sAuthzid = $this->getResponseValue($this->SendRequestGetResponse('AUTHENTICATE', array($type)), Enumerations\ResponseType::CONTINUATION); + $this->sendRaw($SASL->authenticate($sLogin, $sPassword/*, $sAuthzid*/)); + $sChallenge = $SASL->challenge($this->getResponseValue($this->getResponse(), Enumerations\ResponseType::CONTINUATION)); + if ($this->oLogger) { + $this->oLogger->AddSecret($sChallenge); } - else - { - $this->writeLogException( - new Exceptions\LoginException, - \MailSo\Log\Enumerations\Type::NOTICE, true); + $this->sendRaw($sChallenge, true, '*******'); + $sSignature = $this->getResponseValue($this->getResponse()); + $SASL->verify($sSignature); + } + else if ('CRAM-MD5' === $type) + { + $sChallenge = $this->getResponseValue($this->SendRequestGetResponse('AUTHENTICATE', array($type)), Enumerations\ResponseType::CONTINUATION); + $this->oLogger->Write('challenge: '.\base64_decode($sChallenge)); + $sAuth = $SASL->authenticate($sLogin, $sPassword, $sChallenge); + if ($this->oLogger) { + $this->oLogger->AddSecret($sAuth); } + $this->sendRaw($sAuth, true, '*******'); + $this->getResponse(); } else if ('PLAIN' === $type) { - $sToken = $SASL->authenticate($sLogin, $sPassword); - if ($this->oLogger) - { - $this->oLogger->AddSecret($sToken); + $sAuth = $SASL->authenticate($sLogin, $sPassword); + if ($this->oLogger) { + $this->oLogger->AddSecret($sAuth); } - - if ($this->IsSupported('SASL-IR')) - { - $this->SendRequestGetResponse('AUTHENTICATE', array('PLAIN', $sToken)); - } - else - { + if ($this->IsSupported('SASL-IR')) { + $this->SendRequestGetResponse('AUTHENTICATE', array('PLAIN', $sAuth)); + } else { $this->SendRequestGetResponse('AUTHENTICATE', array('PLAIN')); - $this->sendRaw($sToken, true, '*******'); + $this->sendRaw($sAuth, true, '*******'); $this->getResponse(); } } @@ -1025,6 +1009,23 @@ class ImapClient extends \MailSo\Net\NetClient return $this->getResponse(); } + private function getResponseValue(ResponseCollection $oResponseCollection, int $type = 0) : string + { + $oResponse = $oResponseCollection->getLast(); + if ($oResponse && (!$type || $type === $oResponse->ResponseType)) { + $sResult = $oResponse->ResponseList[1] ?? null; + if ($sResult) { + return $sResult; + } + $this->writeLogException( + new Exceptions\LoginException, + \MailSo\Log\Enumerations\Type::NOTICE, true); + } + $this->writeLogException( + new Exceptions\LoginException, + \MailSo\Log\Enumerations\Type::NOTICE, true); + } + public function GetLastResponse() : ResponseCollection { return $this->oLastResponse; diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Sieve/ManageSieveClient.php b/snappymail/v/0.0.0/app/libraries/MailSo/Sieve/ManageSieveClient.php index 69752b485..aefaededa 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Sieve/ManageSieveClient.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Sieve/ManageSieveClient.php @@ -120,12 +120,31 @@ class ManageSieveClient extends \MailSo\Net\NetClient if ($this->IsSupported('SASL')) { +// $encrypted = !empty(\stream_get_meta_data($this->rConnect)['crypto']); + $type = ''; + $types = [ +// 'SCRAM-SHA-256' => 1, // !$encrypted +// 'SCRAM-SHA-1' => 1, // !$encrypted +// 'CRAM-MD5' => 1, // $encrypted + 'PLAIN' => 1, // $encrypted + 'LOGIN' => 1 // $encrypted + ]; + foreach ($types as $sasl_type => $active) { + if ($active && $this->IsAuthSupported($sasl_type) && \SnappyMail\SASL::isSupported($sasl_type)) { + $type = $sasl_type; + break; + } + } + + $SASL = \SnappyMail\SASL::factory($type); + $SASL->base64 = true; + $bAuth = false; try { - if ($this->IsAuthSupported('PLAIN')) + if ('PLAIN' === $type) { - $sAuth = \base64_encode($sLoginAuthKey."\0".$sLogin."\0".$sPassword); + $sAuth = $SASL->authenticate($sLogin, $sPassword, $sLoginAuthKey); if ($this->__USE_INITIAL_AUTH_PLAIN_COMMAND) { @@ -142,10 +161,10 @@ class ManageSieveClient extends \MailSo\Net\NetClient $this->parseStartupResponse($aResponse); $bAuth = true; } - else if ($this->IsAuthSupported('LOGIN')) + else if ('LOGIN' === $type) { - $sLogin = \base64_encode($sLogin); - $sPassword = \base64_encode($sPassword); + $sLogin = $SASL->authenticate($sLogin, $sPassword); + $sPassword = $SASL->challenge(''); $this->sendRequest('AUTHENTICATE "LOGIN"'); $this->sendRequest('{'.\strlen($sLogin).'+}'); diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/sasl.php b/snappymail/v/0.0.0/app/libraries/snappymail/sasl.php index bc5b6020f..9d0dfdbcf 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/sasl.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/sasl.php @@ -7,9 +7,9 @@ abstract class SASL public $base64 = false; - abstract public function authenticate(string $authcid, string $passphrase, ?string $authzid = null); + abstract public function authenticate(string $authcid, string $passphrase, ?string $authzid = null) : string; - public function challenge(string $challenge) : string + public function challenge(string $challenge) : ?string { return null; } diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/sasl/login.php b/snappymail/v/0.0.0/app/libraries/snappymail/sasl/login.php index 743a62f6f..4a84b4835 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/sasl/login.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/sasl/login.php @@ -16,7 +16,7 @@ class Login extends \SnappyMail\SASL return $this->encode($username); } - public function challenge(string $challenge) : string + public function challenge(string $challenge) : ?string { if ($challenge && 'Password:' !== $this->decode($challenge)) { throw new \Exception("invalid response: {$challenge}"); diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/sasl/scram.php b/snappymail/v/0.0.0/app/libraries/snappymail/sasl/scram.php index f1b630917..f4ea724d4 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/sasl/scram.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/sasl/scram.php @@ -42,7 +42,7 @@ class Scram extends \SnappyMail\SASL return $this->encode($this->gs2_header . $this->auth_message); } - public function challenge(string $challenge) : string + public function challenge(string $challenge) : ?string { $challenge = $this->decode($challenge); $values = static::parseMessage($challenge);