mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Improved SASL
This commit is contained in:
parent
e96ced3bde
commit
fcc219cc07
5 changed files with 71 additions and 51 deletions
|
|
@ -180,56 +180,40 @@ class ImapClient extends \MailSo\Net\NetClient
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if ('CRAM-MD5' === $type)
|
if (0 === \strpos($type, 'SCRAM-SHA-'))
|
||||||
{
|
{
|
||||||
$oContinuationResponse = $this->SendRequestGetResponse('AUTHENTICATE', array($type))->getLast();
|
$sAuthzid = $this->getResponseValue($this->SendRequestGetResponse('AUTHENTICATE', array($type)), Enumerations\ResponseType::CONTINUATION);
|
||||||
if ($oContinuationResponse && Enumerations\ResponseType::CONTINUATION === $oContinuationResponse->ResponseType)
|
$this->sendRaw($SASL->authenticate($sLogin, $sPassword/*, $sAuthzid*/));
|
||||||
{
|
$sChallenge = $SASL->challenge($this->getResponseValue($this->getResponse(), Enumerations\ResponseType::CONTINUATION));
|
||||||
$sTicket = $oContinuationResponse->ResponseList[1] ?? null;
|
if ($this->oLogger) {
|
||||||
if ($sTicket)
|
$this->oLogger->AddSecret($sChallenge);
|
||||||
{
|
|
||||||
$sToken = $SASL->authenticate($sLogin, $sPassword, $sTicket);
|
|
||||||
|
|
||||||
$this->oLogger->Write('ticket: '.\base64_decode($sTicket));
|
|
||||||
|
|
||||||
if ($this->oLogger)
|
|
||||||
{
|
|
||||||
$this->oLogger->AddSecret($sToken);
|
|
||||||
}
|
}
|
||||||
|
$this->sendRaw($sChallenge, true, '*******');
|
||||||
$this->sendRaw($sToken, 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();
|
$this->getResponse();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
$this->writeLogException(
|
|
||||||
new Exceptions\LoginException,
|
|
||||||
\MailSo\Log\Enumerations\Type::NOTICE, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$this->writeLogException(
|
|
||||||
new Exceptions\LoginException,
|
|
||||||
\MailSo\Log\Enumerations\Type::NOTICE, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ('PLAIN' === $type)
|
else if ('PLAIN' === $type)
|
||||||
{
|
{
|
||||||
$sToken = $SASL->authenticate($sLogin, $sPassword);
|
$sAuth = $SASL->authenticate($sLogin, $sPassword);
|
||||||
if ($this->oLogger)
|
if ($this->oLogger) {
|
||||||
{
|
$this->oLogger->AddSecret($sAuth);
|
||||||
$this->oLogger->AddSecret($sToken);
|
|
||||||
}
|
}
|
||||||
|
if ($this->IsSupported('SASL-IR')) {
|
||||||
if ($this->IsSupported('SASL-IR'))
|
$this->SendRequestGetResponse('AUTHENTICATE', array('PLAIN', $sAuth));
|
||||||
{
|
} else {
|
||||||
$this->SendRequestGetResponse('AUTHENTICATE', array('PLAIN', $sToken));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$this->SendRequestGetResponse('AUTHENTICATE', array('PLAIN'));
|
$this->SendRequestGetResponse('AUTHENTICATE', array('PLAIN'));
|
||||||
$this->sendRaw($sToken, true, '*******');
|
$this->sendRaw($sAuth, true, '*******');
|
||||||
$this->getResponse();
|
$this->getResponse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1025,6 +1009,23 @@ class ImapClient extends \MailSo\Net\NetClient
|
||||||
return $this->getResponse();
|
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
|
public function GetLastResponse() : ResponseCollection
|
||||||
{
|
{
|
||||||
return $this->oLastResponse;
|
return $this->oLastResponse;
|
||||||
|
|
|
||||||
|
|
@ -120,12 +120,31 @@ class ManageSieveClient extends \MailSo\Net\NetClient
|
||||||
|
|
||||||
if ($this->IsSupported('SASL'))
|
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;
|
$bAuth = false;
|
||||||
try
|
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)
|
if ($this->__USE_INITIAL_AUTH_PLAIN_COMMAND)
|
||||||
{
|
{
|
||||||
|
|
@ -142,10 +161,10 @@ class ManageSieveClient extends \MailSo\Net\NetClient
|
||||||
$this->parseStartupResponse($aResponse);
|
$this->parseStartupResponse($aResponse);
|
||||||
$bAuth = true;
|
$bAuth = true;
|
||||||
}
|
}
|
||||||
else if ($this->IsAuthSupported('LOGIN'))
|
else if ('LOGIN' === $type)
|
||||||
{
|
{
|
||||||
$sLogin = \base64_encode($sLogin);
|
$sLogin = $SASL->authenticate($sLogin, $sPassword);
|
||||||
$sPassword = \base64_encode($sPassword);
|
$sPassword = $SASL->challenge('');
|
||||||
|
|
||||||
$this->sendRequest('AUTHENTICATE "LOGIN"');
|
$this->sendRequest('AUTHENTICATE "LOGIN"');
|
||||||
$this->sendRequest('{'.\strlen($sLogin).'+}');
|
$this->sendRequest('{'.\strlen($sLogin).'+}');
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ abstract class SASL
|
||||||
public
|
public
|
||||||
$base64 = false;
|
$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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ class Login extends \SnappyMail\SASL
|
||||||
return $this->encode($username);
|
return $this->encode($username);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function challenge(string $challenge) : string
|
public function challenge(string $challenge) : ?string
|
||||||
{
|
{
|
||||||
if ($challenge && 'Password:' !== $this->decode($challenge)) {
|
if ($challenge && 'Password:' !== $this->decode($challenge)) {
|
||||||
throw new \Exception("invalid response: {$challenge}");
|
throw new \Exception("invalid response: {$challenge}");
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ class Scram extends \SnappyMail\SASL
|
||||||
return $this->encode($this->gs2_header . $this->auth_message);
|
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);
|
$challenge = $this->decode($challenge);
|
||||||
$values = static::parseMessage($challenge);
|
$values = static::parseMessage($challenge);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue