summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGordon Sim <gsim@apache.org>2014-07-07 19:44:42 +0000
committerGordon Sim <gsim@apache.org>2014-07-07 19:44:42 +0000
commit2f97912d86184ebe0db8aced67174d6be2c46f9d (patch)
treeef59f2af158e0b34f5ca97748ad21e9825d9bde6
parent9c9362101ab9373e0398372d49479194675f5f37 (diff)
downloadqpid-python-2f97912d86184ebe0db8aced67174d6be2c46f9d.tar.gz
QPID-5882: fix authentication failure on 1.0 codepath
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1608578 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--cpp/include/qpid/messaging/exceptions.h5
-rw-r--r--cpp/src/qpid/messaging/amqp/ConnectionContext.cpp47
-rw-r--r--cpp/src/qpid/messaging/amqp/Sasl.cpp49
-rw-r--r--cpp/src/qpid/messaging/amqp/Sasl.h2
-rw-r--r--cpp/src/qpid/messaging/exceptions.cpp1
5 files changed, 74 insertions, 30 deletions
diff --git a/cpp/include/qpid/messaging/exceptions.h b/cpp/include/qpid/messaging/exceptions.h
index f1d79b2535..d5527cdd63 100644
--- a/cpp/include/qpid/messaging/exceptions.h
+++ b/cpp/include/qpid/messaging/exceptions.h
@@ -208,6 +208,11 @@ struct QPID_MESSAGING_CLASS_EXTERN ConnectionError : public MessagingException
QPID_MESSAGING_EXTERN ConnectionError(const std::string&);
};
+struct QPID_MESSAGING_CLASS_EXTERN AuthenticationFailure : public ConnectionError
+{
+ QPID_MESSAGING_EXTERN AuthenticationFailure(const std::string&);
+};
+
/**
* Thrown to indicate loss of underlying connection. When
* auto-reconnect is used this will be caught by the library and used
diff --git a/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp b/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp
index 9ed3713920..5aba00fc50 100644
--- a/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp
+++ b/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp
@@ -851,13 +851,17 @@ std::size_t ConnectionContext::decode(const char* buffer, std::size_t size)
{
qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
size_t decoded = 0;
- if (sasl.get() && !sasl->authenticated()) {
- decoded = sasl->decode(buffer, size);
- if (!sasl->authenticated()) return decoded;
- }
- if (decoded < size) {
- if (sasl.get() && sasl->getSecurityLayer()) decoded += sasl->getSecurityLayer()->decode(buffer+decoded, size-decoded);
- else decoded += decodePlain(buffer+decoded, size-decoded);
+ try {
+ if (sasl.get() && !sasl->authenticated()) {
+ decoded = sasl->decode(buffer, size);
+ if (!sasl->authenticated()) return decoded;
+ }
+ if (decoded < size) {
+ if (sasl.get() && sasl->getSecurityLayer()) decoded += sasl->getSecurityLayer()->decode(buffer+decoded, size-decoded);
+ else decoded += decodePlain(buffer+decoded, size-decoded);
+ }
+ } catch (const AuthenticationFailure&) {
+ transport->close();
}
return decoded;
}
@@ -865,13 +869,17 @@ std::size_t ConnectionContext::encode(char* buffer, std::size_t size)
{
qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
size_t encoded = 0;
- if (sasl.get() && sasl->canEncode()) {
- encoded += sasl->encode(buffer, size);
- if (!sasl->authenticated()) return encoded;
- }
- if (encoded < size) {
- if (sasl.get() && sasl->getSecurityLayer()) encoded += sasl->getSecurityLayer()->encode(buffer+encoded, size-encoded);
- else encoded += encodePlain(buffer+encoded, size-encoded);
+ try {
+ if (sasl.get() && sasl->canEncode()) {
+ encoded += sasl->encode(buffer, size);
+ if (!sasl->authenticated()) return encoded;
+ }
+ if (encoded < size) {
+ if (sasl.get() && sasl->getSecurityLayer()) encoded += sasl->getSecurityLayer()->encode(buffer+encoded, size-encoded);
+ else encoded += encodePlain(buffer+encoded, size-encoded);
+ }
+ } catch (const AuthenticationFailure&) {
+ transport->close();
}
return encoded;
}
@@ -879,9 +887,14 @@ bool ConnectionContext::canEncode()
{
qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
if (sasl.get()) {
- if (sasl->canEncode()) return true;
- else if (!sasl->authenticated()) return false;
- else if (sasl->getSecurityLayer()) return sasl->getSecurityLayer()->canEncode();
+ try {
+ if (sasl->canEncode()) return true;
+ else if (!sasl->authenticated()) return false;
+ else if (sasl->getSecurityLayer()) return sasl->getSecurityLayer()->canEncode();
+ } catch (const AuthenticationFailure&) {
+ transport->close();
+ return false;
+ }
}
return canEncodePlain();
}
diff --git a/cpp/src/qpid/messaging/amqp/Sasl.cpp b/cpp/src/qpid/messaging/amqp/Sasl.cpp
index 9c198f81af..e1c15c2c22 100644
--- a/cpp/src/qpid/messaging/amqp/Sasl.cpp
+++ b/cpp/src/qpid/messaging/amqp/Sasl.cpp
@@ -93,21 +93,29 @@ void Sasl::mechanisms(const std::string& offered)
mechanisms = offered;
}
- if (sasl->start(mechanisms, response, context.getTransportSecuritySettings())) {
- init(sasl->getMechanism(), &response, hostname.size() ? &hostname : 0);
- } else {
- init(sasl->getMechanism(), 0, hostname.size() ? &hostname : 0);
+ try {
+ if (sasl->start(mechanisms, response, context.getTransportSecuritySettings())) {
+ init(sasl->getMechanism(), &response, hostname.size() ? &hostname : 0);
+ } else {
+ init(sasl->getMechanism(), 0, hostname.size() ? &hostname : 0);
+ }
+ haveOutput = true;
+ context.activateOutput();
+ } catch (const std::exception& e) {
+ failed(e.what());
}
- haveOutput = true;
- context.activateOutput();
}
void Sasl::challenge(const std::string& challenge)
{
QPID_LOG_CAT(debug, protocol, id << " Received SASL-CHALLENGE(" << challenge.size() << " bytes)");
- std::string r = sasl->step(challenge);
- response(&r);
- haveOutput = true;
- context.activateOutput();
+ try {
+ std::string r = sasl->step(challenge);
+ response(&r);
+ haveOutput = true;
+ context.activateOutput();
+ } catch (const std::exception& e) {
+ failed(e.what());
+ }
}
namespace {
const std::string EMPTY;
@@ -115,8 +123,12 @@ const std::string EMPTY;
void Sasl::challenge()
{
QPID_LOG_CAT(debug, protocol, id << " Received SASL-CHALLENGE(null)");
- std::string r = sasl->step(EMPTY);
- response(&r);
+ try {
+ std::string r = sasl->step(EMPTY);
+ response(&r);
+ } catch (const std::exception& e) {
+ failed(e.what());
+ }
}
void Sasl::outcome(uint8_t result, const std::string& extra)
{
@@ -146,15 +158,26 @@ qpid::sys::Codec* Sasl::getSecurityLayer()
return securityLayer.get();
}
+namespace {
+const std::string DEFAULT_ERROR("Authentication failed");
+}
+
bool Sasl::authenticated()
{
switch (state) {
case SUCCEEDED: return true;
- case FAILED: throw qpid::messaging::UnauthorizedAccess("Failed to authenticate");
+ case FAILED: throw qpid::messaging::AuthenticationFailure(error.size() ? error : DEFAULT_ERROR);
case NONE: default: return false;
}
}
+void Sasl::failed(const std::string& text)
+{
+ QPID_LOG_CAT(info, client, id << " Failure during authentication: " << text);
+ error = text;
+ state = FAILED;
+}
+
std::string Sasl::getAuthenticatedUsername()
{
return sasl->getUserId();
diff --git a/cpp/src/qpid/messaging/amqp/Sasl.h b/cpp/src/qpid/messaging/amqp/Sasl.h
index 6de36bd7f2..a836e2e465 100644
--- a/cpp/src/qpid/messaging/amqp/Sasl.h
+++ b/cpp/src/qpid/messaging/amqp/Sasl.h
@@ -61,12 +61,14 @@ class Sasl : public qpid::sys::Codec, qpid::amqp::SaslClient
NONE, FAILED, SUCCEEDED
} state;
std::auto_ptr<qpid::sys::SecurityLayer> securityLayer;
+ std::string error;
void mechanisms(const std::string&);
void challenge(const std::string&);
void challenge(); //null != empty string
void outcome(uint8_t result, const std::string&);
void outcome(uint8_t result);
+ void failed(const std::string&);
protected:
bool stopReading();
};
diff --git a/cpp/src/qpid/messaging/exceptions.cpp b/cpp/src/qpid/messaging/exceptions.cpp
index 11b0eb33f7..d21477b494 100644
--- a/cpp/src/qpid/messaging/exceptions.cpp
+++ b/cpp/src/qpid/messaging/exceptions.cpp
@@ -56,6 +56,7 @@ TransactionAborted::TransactionAborted(const std::string& msg) : TransactionErro
UnauthorizedAccess::UnauthorizedAccess(const std::string& msg) : SessionError(msg) {}
ConnectionError::ConnectionError(const std::string& msg) : MessagingException(msg) {}
+AuthenticationFailure::AuthenticationFailure(const std::string& msg) : ConnectionError(msg) {}
TransportFailure::TransportFailure(const std::string& msg) : MessagingException(msg) {}