From d9af71e691e50d7c9f3f16cd259298d3b8f0cd14 Mon Sep 17 00:00:00 2001 From: Michael Goulish Date: Fri, 14 May 2010 08:56:45 +0000 Subject: Cluster + Security ----------------------------------- * initial observation of a problem was a 2% failure rate in perftests of 20,000 messages against a cluster with security enabled. Problem was occasional receit of encrypted frames before the security codec had been enabled. This is fixed with locking in cluster code (no new locks in broker code) and a callback that is fired by broker::ConnectionHandler::Handler to tell the cluster code when the opening handshake has finished. This was never a problem in the non-clustered broker before because everything happened in a single thread. * the brokers that "shadow" the connection must not have null authenticators rather than real ones, so that they go through all the motions but don't do anythig. Only the directly-connected broker can perform the security handshake. * once the directly-connected broker receives the real user ID from its callback, it mcasts that ID to all other brokers. Otherwise the shadowing brokers will al think that the user ID is "anonymous". Check this by doing a substantial perftest, and using qpid-stat -c localhost:PORT to confirm that the brokers all have the same userID for the same connection. * the user ID, negotiated during the Sasl security startup, is communicated from the directly connected broker to all other cluster brokers. * If security is *not* being used, then this code should *not* tell the brokers anything about the userID -- or it will step on the value that is being set by other code pathways. * test program at cpp/src/tests/cluster_authentication_soak is not yet fully automated -- run it with something like "sudo ./cluster_authentication_soak 500" git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@944158 13f79535-47bb-0310-9956-ffa450edef68 --- cpp/src/qpid/broker/SaslAuthenticator.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'cpp/src/qpid/broker/SaslAuthenticator.cpp') diff --git a/cpp/src/qpid/broker/SaslAuthenticator.cpp b/cpp/src/qpid/broker/SaslAuthenticator.cpp index 0f72f9643d..c55f3edb38 100644 --- a/cpp/src/qpid/broker/SaslAuthenticator.cpp +++ b/cpp/src/qpid/broker/SaslAuthenticator.cpp @@ -41,10 +41,12 @@ using qpid::sys::SecuritySettings; using boost::format; using boost::str; + namespace qpid { namespace broker { + class NullAuthenticator : public SaslAuthenticator { Connection& connection; @@ -62,6 +64,8 @@ public: #if HAVE_SASL + + class CyrusAuthenticator : public SaslAuthenticator { sasl_conn_t *sasl_conn; @@ -84,8 +88,7 @@ public: std::auto_ptr getSecurityLayer(uint16_t maxFrameSize); }; -bool SaslAuthenticator::available(void) -{ +bool SaslAuthenticator::available(void) { return true; } @@ -109,8 +112,7 @@ void SaslAuthenticator::fini(void) typedef NullAuthenticator CyrusAuthenticator; -bool SaslAuthenticator::available(void) -{ +bool SaslAuthenticator::available(void) { return false; } @@ -126,18 +128,20 @@ void SaslAuthenticator::fini(void) #endif -std::auto_ptr SaslAuthenticator::createAuthenticator(Connection& c) +std::auto_ptr SaslAuthenticator::createAuthenticator(Connection& c, bool isShadow ) { - static bool needWarning = true; if (c.getBroker().getOptions().auth) { - return std::auto_ptr(new CyrusAuthenticator(c, c.getBroker().getOptions().requireEncrypted)); + if ( isShadow ) + return std::auto_ptr(new NullAuthenticator(c, c.getBroker().getOptions().requireEncrypted)); + else + return std::auto_ptr(new CyrusAuthenticator(c, c.getBroker().getOptions().requireEncrypted)); } else { QPID_LOG(debug, "SASL: No Authentication Performed"); - needWarning = false; return std::auto_ptr(new NullAuthenticator(c, c.getBroker().getOptions().requireEncrypted)); } } + NullAuthenticator::NullAuthenticator(Connection& c, bool e) : connection(c), client(c.getOutput()), realm(c.getBroker().getOptions().realm), encrypt(e) {} NullAuthenticator::~NullAuthenticator() {} @@ -200,7 +204,6 @@ std::auto_ptr NullAuthenticator::getSecurityLayer(uint16_t) #if HAVE_SASL - CyrusAuthenticator::CyrusAuthenticator(Connection& c, bool _encrypt) : sasl_conn(0), connection(c), client(c.getOutput()), encrypt(_encrypt) { @@ -386,7 +389,7 @@ void CyrusAuthenticator::processAuthenticationStep(int code, const char *challen // authentication failure, when one is available throw ConnectionForcedException("Authenticated username unavailable"); } - QPID_LOG(info, "SASL: Authentication succeeded for: " << uid); + QPID_LOG(info, connection.getMgmtId() << " SASL: Authentication succeeded for: " << uid); connection.setUserId(uid); @@ -432,7 +435,6 @@ std::auto_ptr CyrusAuthenticator::getSecurityLayer(uint16_t maxFr uint ssf = *(reinterpret_cast(value)); std::auto_ptr securityLayer; if (ssf) { - QPID_LOG(info, "Installing security layer, SSF: "<< ssf); securityLayer = std::auto_ptr(new CyrusSecurityLayer(sasl_conn, maxFrameSize)); } return securityLayer; -- cgit v1.2.1