Added support for initial response in SASL authentication.
This commit is contained in:
parent
c655495025
commit
c860c273d3
@ -355,7 +355,26 @@ void IMAPConnection::authenticateSASL()
|
||||
|
||||
saslSession->init();
|
||||
|
||||
send(true, "AUTHENTICATE " + mech->getName(), true);
|
||||
std::ostringstream cmd;
|
||||
cmd << "AUTHENTICATE " << mech->getName();
|
||||
|
||||
if (saslSession->getMechanism()->hasInitialResponse())
|
||||
{
|
||||
byte_t* initialResp = 0;
|
||||
size_t initialRespLen = 0;
|
||||
|
||||
saslSession->evaluateChallenge(NULL, 0, &initialResp, &initialRespLen);
|
||||
|
||||
string encodedInitialResp(saslContext->encodeB64(initialResp, initialRespLen));
|
||||
delete [] initialResp;
|
||||
|
||||
if (encodedInitialResp.empty())
|
||||
cmd << " =";
|
||||
else
|
||||
cmd << " " << encodedInitialResp;
|
||||
}
|
||||
|
||||
send(true, cmd.str(), true);
|
||||
|
||||
for (bool cont = true ; cont ; )
|
||||
{
|
||||
|
@ -73,6 +73,17 @@ shared_ptr <POP3Command> POP3Command::AUTH(const string& mechName)
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
shared_ptr <POP3Command> POP3Command::AUTH(const string& mechName, const string& initialResponse)
|
||||
{
|
||||
std::ostringstream cmd;
|
||||
cmd.imbue(std::locale::classic());
|
||||
cmd << "AUTH " << mechName << " " << initialResponse;
|
||||
|
||||
return createCommand(cmd.str());
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
shared_ptr <POP3Command> POP3Command::STLS()
|
||||
{
|
||||
|
@ -57,6 +57,7 @@ public:
|
||||
static shared_ptr <POP3Command> CAPA();
|
||||
static shared_ptr <POP3Command> NOOP();
|
||||
static shared_ptr <POP3Command> AUTH(const string& mechName);
|
||||
static shared_ptr <POP3Command> AUTH(const string& mechName, const string& initialResponse);
|
||||
static shared_ptr <POP3Command> STLS();
|
||||
static shared_ptr <POP3Command> APOP(const string& username, const string& digest);
|
||||
static shared_ptr <POP3Command> USER(const string& username);
|
||||
|
@ -446,7 +446,29 @@ void POP3Connection::authenticateSASL()
|
||||
|
||||
saslSession->init();
|
||||
|
||||
POP3Command::AUTH(mech->getName())->send(dynamicCast <POP3Connection>(shared_from_this()));
|
||||
shared_ptr <POP3Command> authCmd;
|
||||
|
||||
if (saslSession->getMechanism()->hasInitialResponse())
|
||||
{
|
||||
byte_t* initialResp = 0;
|
||||
size_t initialRespLen = 0;
|
||||
|
||||
saslSession->evaluateChallenge(NULL, 0, &initialResp, &initialRespLen);
|
||||
|
||||
string encodedInitialResp(saslContext->encodeB64(initialResp, initialRespLen));
|
||||
delete [] initialResp;
|
||||
|
||||
if (encodedInitialResp.empty())
|
||||
authCmd = POP3Command::AUTH(mech->getName(), "=");
|
||||
else
|
||||
authCmd = POP3Command::AUTH(mech->getName(), encodedInitialResp);
|
||||
}
|
||||
else
|
||||
{
|
||||
authCmd = POP3Command::AUTH(mech->getName());
|
||||
}
|
||||
|
||||
authCmd->send(dynamicCast <POP3Connection>(shared_from_this()));
|
||||
|
||||
for (bool cont = true ; cont ; )
|
||||
{
|
||||
|
@ -79,6 +79,17 @@ shared_ptr <SMTPCommand> SMTPCommand::AUTH(const string& mechName)
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
shared_ptr <SMTPCommand> SMTPCommand::AUTH(const string& mechName, const std::string& initialResponse)
|
||||
{
|
||||
std::ostringstream cmd;
|
||||
cmd.imbue(std::locale::classic());
|
||||
cmd << "AUTH " << mechName << " " << initialResponse;
|
||||
|
||||
return createCommand(cmd.str());
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
shared_ptr <SMTPCommand> SMTPCommand::STARTTLS()
|
||||
{
|
||||
|
@ -60,6 +60,7 @@ public:
|
||||
static shared_ptr <SMTPCommand> HELO(const string& hostname);
|
||||
static shared_ptr <SMTPCommand> EHLO(const string& hostname);
|
||||
static shared_ptr <SMTPCommand> AUTH(const string& mechName);
|
||||
static shared_ptr <SMTPCommand> AUTH(const string& mechName, const std::string& initialResponse);
|
||||
static shared_ptr <SMTPCommand> STARTTLS();
|
||||
static shared_ptr <SMTPCommand> MAIL(const mailbox& mbox, const bool utf8);
|
||||
static shared_ptr <SMTPCommand> MAIL(const mailbox& mbox, const bool utf8, const size_t size);
|
||||
|
@ -367,7 +367,25 @@ void SMTPConnection::authenticateSASL()
|
||||
|
||||
saslSession->init();
|
||||
|
||||
sendRequest(SMTPCommand::AUTH(mech->getName()));
|
||||
if (saslSession->getMechanism()->hasInitialResponse())
|
||||
{
|
||||
byte_t* initialResp = 0;
|
||||
size_t initialRespLen = 0;
|
||||
|
||||
saslSession->evaluateChallenge(NULL, 0, &initialResp, &initialRespLen);
|
||||
|
||||
string encodedInitialResp(saslContext->encodeB64(initialResp, initialRespLen));
|
||||
delete [] initialResp;
|
||||
|
||||
if (encodedInitialResp.empty())
|
||||
sendRequest(SMTPCommand::AUTH(mech->getName(), "="));
|
||||
else
|
||||
sendRequest(SMTPCommand::AUTH(mech->getName(), encodedInitialResp));
|
||||
}
|
||||
else
|
||||
{
|
||||
sendRequest(SMTPCommand::AUTH(mech->getName()));
|
||||
}
|
||||
|
||||
for (bool cont = true ; cont ; )
|
||||
{
|
||||
|
@ -58,6 +58,9 @@ public:
|
||||
* server (challenge), process it and return data to be returned
|
||||
* in response to the server.
|
||||
*
|
||||
* If the challenge is empty (challengeLen == 0), the initial
|
||||
* response is returned, if this mechanism has one.
|
||||
*
|
||||
* @param sess SASL session
|
||||
* @param challenge challenge sent from the server
|
||||
* @param challengeLen length of challenge
|
||||
@ -84,6 +87,15 @@ public:
|
||||
*/
|
||||
virtual bool isComplete() const = 0;
|
||||
|
||||
/** Determine if this mechanism has an optional initial response.
|
||||
* If true, caller should call step() with an empty challenge to
|
||||
* get the initial response.
|
||||
*
|
||||
* @return true if this mechanism has an initial response, or
|
||||
* false otherwise
|
||||
*/
|
||||
virtual bool hasInitialResponse() const = 0;
|
||||
|
||||
/** Encode data according to negotiated SASL mechanism. This
|
||||
* might mean that data is integrity or privacy protected.
|
||||
*
|
||||
|
@ -96,6 +96,9 @@ public:
|
||||
* server (challenge), process it and return data to be returned
|
||||
* in response to the server.
|
||||
*
|
||||
* If the challenge is empty (challengeLen == 0), the initial
|
||||
* response is returned, if the mechanism has one.
|
||||
*
|
||||
* @param challenge challenge sent from the server
|
||||
* @param challengeLen length of challenge
|
||||
* @param response response to send to the server (allocated by
|
||||
|
@ -120,6 +120,13 @@ bool builtinSASLMechanism::isComplete() const
|
||||
}
|
||||
|
||||
|
||||
bool builtinSASLMechanism::hasInitialResponse() const
|
||||
{
|
||||
// It seems GNU SASL does not support initial response
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void builtinSASLMechanism::encode
|
||||
(shared_ptr <SASLSession> sess, const byte_t* input, const size_t inputLen,
|
||||
byte_t** output, size_t* outputLen)
|
||||
|
@ -61,6 +61,8 @@ public:
|
||||
|
||||
bool isComplete() const;
|
||||
|
||||
bool hasInitialResponse() const;
|
||||
|
||||
void encode(shared_ptr <SASLSession> sess,
|
||||
const byte_t* input, const size_t inputLen,
|
||||
byte_t** output, size_t* outputLen);
|
||||
|
@ -39,6 +39,7 @@ VMIME_TEST_SUITE_BEGIN(POP3CommandTest)
|
||||
VMIME_TEST(testCAPA)
|
||||
VMIME_TEST(testNOOP)
|
||||
VMIME_TEST(testAUTH)
|
||||
VMIME_TEST(testAUTH_InitialResponse)
|
||||
VMIME_TEST(testSTLS)
|
||||
VMIME_TEST(testAPOP)
|
||||
VMIME_TEST(testUSER)
|
||||
@ -97,6 +98,14 @@ VMIME_TEST_SUITE_BEGIN(POP3CommandTest)
|
||||
VASSERT_EQ("Text", "AUTH saslmechanism", cmd->getText());
|
||||
}
|
||||
|
||||
void testAUTH_InitialResponse()
|
||||
{
|
||||
vmime::shared_ptr <POP3Command> cmd = POP3Command::AUTH("saslmechanism", "initial-response");
|
||||
|
||||
VASSERT_NOT_NULL("Not null", cmd);
|
||||
VASSERT_EQ("Text", "AUTH saslmechanism initial-response", cmd->getText());
|
||||
}
|
||||
|
||||
void testSTLS()
|
||||
{
|
||||
vmime::shared_ptr <POP3Command> cmd = POP3Command::STLS();
|
||||
|
@ -37,6 +37,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandTest)
|
||||
VMIME_TEST(testHELO)
|
||||
VMIME_TEST(testEHLO)
|
||||
VMIME_TEST(testAUTH)
|
||||
VMIME_TEST(testAUTH_InitialResponse)
|
||||
VMIME_TEST(testSTARTTLS)
|
||||
VMIME_TEST(testMAIL)
|
||||
VMIME_TEST(testMAIL_Encoded)
|
||||
@ -95,6 +96,14 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandTest)
|
||||
VASSERT_EQ("Text", "AUTH saslmechanism", cmd->getText());
|
||||
}
|
||||
|
||||
void testAUTH_InitialResponse()
|
||||
{
|
||||
vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::AUTH("saslmechanism", "initial-response");
|
||||
|
||||
VASSERT_NOT_NULL("Not null", cmd);
|
||||
VASSERT_EQ("Text", "AUTH saslmechanism initial-response", cmd->getText());
|
||||
}
|
||||
|
||||
void testSTARTTLS()
|
||||
{
|
||||
vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::STARTTLS();
|
||||
|
Loading…
Reference in New Issue
Block a user