aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vmime/net/imap/IMAPConnection.cpp21
-rw-r--r--src/vmime/net/pop3/POP3Command.cpp11
-rw-r--r--src/vmime/net/pop3/POP3Command.hpp1
-rw-r--r--src/vmime/net/pop3/POP3Connection.cpp24
-rw-r--r--src/vmime/net/smtp/SMTPCommand.cpp11
-rw-r--r--src/vmime/net/smtp/SMTPCommand.hpp1
-rw-r--r--src/vmime/net/smtp/SMTPConnection.cpp20
-rw-r--r--src/vmime/security/sasl/SASLMechanism.hpp12
-rw-r--r--src/vmime/security/sasl/SASLSession.hpp3
-rw-r--r--src/vmime/security/sasl/builtinSASLMechanism.cpp7
-rw-r--r--src/vmime/security/sasl/builtinSASLMechanism.hpp2
-rw-r--r--tests/net/pop3/POP3CommandTest.cpp9
-rw-r--r--tests/net/smtp/SMTPCommandTest.cpp9
13 files changed, 128 insertions, 3 deletions
diff --git a/src/vmime/net/imap/IMAPConnection.cpp b/src/vmime/net/imap/IMAPConnection.cpp
index 5e6f6f8f..04705f6c 100644
--- a/src/vmime/net/imap/IMAPConnection.cpp
+++ b/src/vmime/net/imap/IMAPConnection.cpp
@@ -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 ; )
{
diff --git a/src/vmime/net/pop3/POP3Command.cpp b/src/vmime/net/pop3/POP3Command.cpp
index 6fe301ce..3c544fc0 100644
--- a/src/vmime/net/pop3/POP3Command.cpp
+++ b/src/vmime/net/pop3/POP3Command.cpp
@@ -74,6 +74,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()
{
return createCommand("STLS");
diff --git a/src/vmime/net/pop3/POP3Command.hpp b/src/vmime/net/pop3/POP3Command.hpp
index cc3c4fd5..e34e4e2b 100644
--- a/src/vmime/net/pop3/POP3Command.hpp
+++ b/src/vmime/net/pop3/POP3Command.hpp
@@ -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);
diff --git a/src/vmime/net/pop3/POP3Connection.cpp b/src/vmime/net/pop3/POP3Connection.cpp
index f5a1a448..45c668f5 100644
--- a/src/vmime/net/pop3/POP3Connection.cpp
+++ b/src/vmime/net/pop3/POP3Connection.cpp
@@ -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 ; )
{
diff --git a/src/vmime/net/smtp/SMTPCommand.cpp b/src/vmime/net/smtp/SMTPCommand.cpp
index 949ab0c1..2120caf5 100644
--- a/src/vmime/net/smtp/SMTPCommand.cpp
+++ b/src/vmime/net/smtp/SMTPCommand.cpp
@@ -80,6 +80,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()
{
return createCommand("STARTTLS");
diff --git a/src/vmime/net/smtp/SMTPCommand.hpp b/src/vmime/net/smtp/SMTPCommand.hpp
index dbb0888b..a5b8cca5 100644
--- a/src/vmime/net/smtp/SMTPCommand.hpp
+++ b/src/vmime/net/smtp/SMTPCommand.hpp
@@ -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);
diff --git a/src/vmime/net/smtp/SMTPConnection.cpp b/src/vmime/net/smtp/SMTPConnection.cpp
index a45f9149..4985b563 100644
--- a/src/vmime/net/smtp/SMTPConnection.cpp
+++ b/src/vmime/net/smtp/SMTPConnection.cpp
@@ -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 ; )
{
diff --git a/src/vmime/security/sasl/SASLMechanism.hpp b/src/vmime/security/sasl/SASLMechanism.hpp
index 5492e48c..8756471f 100644
--- a/src/vmime/security/sasl/SASLMechanism.hpp
+++ b/src/vmime/security/sasl/SASLMechanism.hpp
@@ -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.
*
diff --git a/src/vmime/security/sasl/SASLSession.hpp b/src/vmime/security/sasl/SASLSession.hpp
index ccf181cb..21ccc420 100644
--- a/src/vmime/security/sasl/SASLSession.hpp
+++ b/src/vmime/security/sasl/SASLSession.hpp
@@ -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
diff --git a/src/vmime/security/sasl/builtinSASLMechanism.cpp b/src/vmime/security/sasl/builtinSASLMechanism.cpp
index e179e715..9e352334 100644
--- a/src/vmime/security/sasl/builtinSASLMechanism.cpp
+++ b/src/vmime/security/sasl/builtinSASLMechanism.cpp
@@ -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)
diff --git a/src/vmime/security/sasl/builtinSASLMechanism.hpp b/src/vmime/security/sasl/builtinSASLMechanism.hpp
index 09b46f00..6cecd1b9 100644
--- a/src/vmime/security/sasl/builtinSASLMechanism.hpp
+++ b/src/vmime/security/sasl/builtinSASLMechanism.hpp
@@ -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);
diff --git a/tests/net/pop3/POP3CommandTest.cpp b/tests/net/pop3/POP3CommandTest.cpp
index 4733c96b..139e948b 100644
--- a/tests/net/pop3/POP3CommandTest.cpp
+++ b/tests/net/pop3/POP3CommandTest.cpp
@@ -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();
diff --git a/tests/net/smtp/SMTPCommandTest.cpp b/tests/net/smtp/SMTPCommandTest.cpp
index 6d466865..9480948c 100644
--- a/tests/net/smtp/SMTPCommandTest.cpp
+++ b/tests/net/smtp/SMTPCommandTest.cpp
@@ -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();