diff options
| author | Michael Goulish <mgoulish@apache.org> | 2010-10-20 08:03:36 +0000 |
|---|---|---|
| committer | Michael Goulish <mgoulish@apache.org> | 2010-10-20 08:03:36 +0000 |
| commit | bcb149706cdace4a333a811969e473451d9ab331 (patch) | |
| tree | 6ad1e5797a8696968b91bdcf511eeac4bf4cb54f /cpp/src/qpid/broker | |
| parent | 346e5a55b9152ab603bf8b15bd7718beb9d6ff76 (diff) | |
| download | qpid-python-bcb149706cdace4a333a811969e473451d9ab331.tar.gz | |
SASLizing Interbroker Links
-------------------------------------------------------------
1. Brokers already knew how to handle the server side of SASLized
links, but not the client side. So we promoted the client-side
SASL code from the client library to the common library so that
the broker could also use it. This affected SaslFactory.{h,cpp}
and Sasl.h
TODO -- can the server-side and client-side code be unified here?
2. Some of the SASL verbs in broker/ConnectionHandler.cpp are
expanded: start, secure, tune.
3. broker/SecureConnection is altered to get the client-broker and
the server-broker to agree on when the security layer should be
inserted.
4. the python tool qpid-route is modified so that, in the "route add"
command, you can specify the security mechanism for SASL to use.
TODO -- should we also pass in {min,max}SSF ?
5. Changes in broker/LinkRegistry to allow the information input by
qpid-route to be passed up to where it is needed.
6. A bash script test run by "make check" that creates a SASLized
federation link and sends some messages down it.
TODO - write a python unit test instead of a bash script. I
think I uncovered a bug in the python code when I tried.
7. NOTE - testing for this feature does not work with versions of
SASL earlier than 2.1.22, becuase I can't tell SASL to use a
SASL database file in a nonstandard location. The test is
disabled for earlier versions.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1024541 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid/broker')
| -rw-r--r-- | cpp/src/qpid/broker/Connection.cpp | 32 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/Connection.h | 4 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/ConnectionHandler.cpp | 104 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/ConnectionHandler.h | 15 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/LinkRegistry.cpp | 36 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/LinkRegistry.h | 4 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/SecureConnection.cpp | 5 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/SecureConnection.h | 2 |
8 files changed, 192 insertions, 10 deletions
diff --git a/cpp/src/qpid/broker/Connection.cpp b/cpp/src/qpid/broker/Connection.cpp index d50f0c946a..98743cdae6 100644 --- a/cpp/src/qpid/broker/Connection.cpp +++ b/cpp/src/qpid/broker/Connection.cpp @@ -192,6 +192,38 @@ string Connection::getAuthMechanism() return links.getAuthMechanism(mgmtId); } +string Connection::getUsername ( ) +{ + if (!isLink) + return string("anonymous"); + + return links.getUsername(mgmtId); +} + +string Connection::getPassword ( ) +{ + if (!isLink) + return string(""); + + return links.getPassword(mgmtId); +} + +string Connection::getHost ( ) +{ + if (!isLink) + return string(""); + + return links.getHost(mgmtId); +} + +uint16_t Connection::getPort ( ) +{ + if (!isLink) + return 0; + + return links.getPort(mgmtId); +} + string Connection::getAuthCredentials() { if (!isLink) diff --git a/cpp/src/qpid/broker/Connection.h b/cpp/src/qpid/broker/Connection.h index c1b2b5a8fc..d978187e0c 100644 --- a/cpp/src/qpid/broker/Connection.h +++ b/cpp/src/qpid/broker/Connection.h @@ -115,6 +115,10 @@ class Connection : public sys::ConnectionInputHandler, void recordFromClient (framing::AMQFrame& frame); std::string getAuthMechanism(); std::string getAuthCredentials(); + std::string getUsername(); + std::string getPassword(); + std::string getHost(); + uint16_t getPort(); void notifyConnectionForced(const std::string& text); void setUserId(const std::string& uid); void raiseConnectEvent(); diff --git a/cpp/src/qpid/broker/ConnectionHandler.cpp b/cpp/src/qpid/broker/ConnectionHandler.cpp index c349bc7ac7..c812374d38 100644 --- a/cpp/src/qpid/broker/ConnectionHandler.cpp +++ b/cpp/src/qpid/broker/ConnectionHandler.cpp @@ -20,6 +20,7 @@ * */ +#include "qpid/SaslFactory.h" #include "qpid/broker/ConnectionHandler.h" #include "qpid/broker/Connection.h" #include "qpid/broker/SecureConnection.h" @@ -49,6 +50,7 @@ const std::string CLIENT_PROCESS_NAME("qpid.client_process"); const std::string CLIENT_PID("qpid.client_pid"); const std::string CLIENT_PPID("qpid.client_ppid"); const int SESSION_FLOW_CONTROL_VER = 1; +const std::string SPACE(" "); } void ConnectionHandler::close(connection::CloseCode code, const string& text) @@ -106,7 +108,10 @@ ConnectionHandler::Handler::Handler(Connection& c, bool isClient, bool isShadow) boost::shared_ptr<FieldValue> l(new Str16Value(en_US)); locales.add(l); proxy.start(properties, mechanisms, locales); + } + + maxFrameSize = (64 * 1024) - 1; } @@ -230,33 +235,105 @@ void ConnectionHandler::Handler::heartbeat(){ } void ConnectionHandler::Handler::start(const FieldTable& serverProperties, - const framing::Array& /*mechanisms*/, + const framing::Array& supportedMechanisms, const framing::Array& /*locales*/) { - string mechanism = connection.getAuthMechanism(); + string requestedMechanism = connection.getAuthMechanism(); string response = connection.getAuthCredentials(); + std::string username = connection.getUsername(); + std::string password = connection.getPassword(); + std::string host = connection.getHost(); + std::string service("qpidd"); + + sasl = SaslFactory::getInstance().create( username, + password, + service, + host, + 0, // TODO -- mgoulish Fri Sep 24 06:41:26 EDT 2010 + 256 /* TODO -- mgoulish*/ ); + std::string supportedMechanismsList; + bool requestedMechanismIsSupported = false; + Array::const_iterator i; + + /* + If no specific mechanism has been requested, just make + a list of all of them, and assert that the one the caller + requested is there. ( If *any* are supported! ) + */ + if ( requestedMechanism.empty() ) { + for ( i = supportedMechanisms.begin(); i != supportedMechanisms.end(); ++i) { + if (i != supportedMechanisms.begin()) + supportedMechanismsList += SPACE; + supportedMechanismsList += (*i)->get<std::string>(); + requestedMechanismIsSupported = true; + } + } + else { + requestedMechanismIsSupported = false; + /* + The caller has requested a mechanism. If it's available, + make sure it ends up at the head of the list. + */ + for ( i = supportedMechanisms.begin(); i != supportedMechanisms.end(); ++i) { + string currentMechanism = (*i)->get<std::string>(); + + if ( requestedMechanism == currentMechanism ) { + requestedMechanismIsSupported = true; + supportedMechanismsList = currentMechanism + SPACE + supportedMechanismsList; + } else { + if (i != supportedMechanisms.begin()) + supportedMechanismsList += SPACE; + supportedMechanismsList += currentMechanism; + } + } + } + connection.setFederationPeerTag(serverProperties.getAsString(QPID_FED_TAG)); FieldTable ft; ft.setInt(QPID_FED_LINK,1); ft.setString(QPID_FED_TAG, connection.getBroker().getFederationTag()); - proxy.startOk(ft, mechanism, response, en_US); + + if (sasl.get()) { + string response = + sasl->start ( requestedMechanism.empty() + ? supportedMechanismsList + : requestedMechanism, + getSecuritySettings + ? getSecuritySettings() + : 0 + ); + proxy.startOk ( ft, sasl->getMechanism(), response, en_US ); + } + else { + string response = ((char)0) + username + ((char)0) + password; + proxy.startOk ( ft, requestedMechanism, response, en_US ); + } + } -void ConnectionHandler::Handler::secure(const string& /*challenge*/) +void ConnectionHandler::Handler::secure(const string& challenge ) { - proxy.secureOk(""); + if (sasl.get()) { + string response = sasl->step(challenge); + proxy.secureOk(response); + } + else { + proxy.secureOk(""); + } } void ConnectionHandler::Handler::tune(uint16_t channelMax, - uint16_t frameMax, + uint16_t maxFrameSizeProposed, uint16_t /*heartbeatMin*/, uint16_t heartbeatMax) { - connection.setFrameMax(frameMax); + maxFrameSize = std::min(maxFrameSize, maxFrameSizeProposed); + connection.setFrameMax(maxFrameSize); + connection.setHeartbeat(heartbeatMax); - proxy.tuneOk(channelMax, frameMax, heartbeatMax); + proxy.tuneOk(channelMax, maxFrameSize, heartbeatMax); proxy.open("/", Array(), true); } @@ -266,6 +343,17 @@ void ConnectionHandler::Handler::openOk(const framing::Array& knownHosts) Url url((*i)->get<std::string>()); connection.getKnownHosts().push_back(url); } + + if (sasl.get()) { + std::auto_ptr<qpid::sys::SecurityLayer> securityLayer = sasl->getSecurityLayer(maxFrameSize); + + if ( securityLayer.get() ) { + secured->activateSecurityLayer(securityLayer, true); + } + + saslUserId = sasl->getUserId(); + } + isOpen = true; } diff --git a/cpp/src/qpid/broker/ConnectionHandler.h b/cpp/src/qpid/broker/ConnectionHandler.h index 6d55cab647..70882a24e9 100644 --- a/cpp/src/qpid/broker/ConnectionHandler.h +++ b/cpp/src/qpid/broker/ConnectionHandler.h @@ -22,6 +22,7 @@ #define _ConnectionAdapter_ #include <memory> +#include "qpid/Sasl.h" #include "qpid/broker/SaslAuthenticator.h" #include "qpid/framing/amqp_types.h" #include "qpid/framing/AMQFrame.h" @@ -33,8 +34,16 @@ #include "qpid/framing/ProtocolVersion.h" #include "qpid/Exception.h" #include "qpid/broker/AclModule.h" +#include "qpid/sys/SecurityLayer.h" + namespace qpid { + +namespace sys { +struct SecuritySettings; +} + + namespace broker { class Connection; @@ -79,6 +88,12 @@ class ConnectionHandler : public framing::FrameHandler void openOk(const framing::Array& knownHosts); void redirect(const std::string& host, const framing::Array& knownHosts); + + std::auto_ptr<Sasl> sasl; + typedef boost::function<const qpid::sys::SecuritySettings*()> GetSecuritySettings; + GetSecuritySettings getSecuritySettings; /* query the transport for its security details */ + std::string saslUserId; + uint16_t maxFrameSize; }; std::auto_ptr<Handler> handler; diff --git a/cpp/src/qpid/broker/LinkRegistry.cpp b/cpp/src/qpid/broker/LinkRegistry.cpp index 9d429a2dcc..ea14552cc1 100644 --- a/cpp/src/qpid/broker/LinkRegistry.cpp +++ b/cpp/src/qpid/broker/LinkRegistry.cpp @@ -312,6 +312,42 @@ std::string LinkRegistry::getAuthCredentials(const std::string& key) return result; } +std::string LinkRegistry::getUsername(const std::string& key) +{ + Link::shared_ptr link = findLink(key); + if (!link) + return string(); + + return link->getUsername(); +} + +std::string LinkRegistry::getHost(const std::string& key) +{ + Link::shared_ptr link = findLink(key); + if (!link) + return string(); + + return link->getHost(); +} + +uint16_t LinkRegistry::getPort(const std::string& key) +{ + Link::shared_ptr link = findLink(key); + if (!link) + return 0; + + return link->getPort(); +} + +std::string LinkRegistry::getPassword(const std::string& key) +{ + Link::shared_ptr link = findLink(key); + if (!link) + return string(); + + return link->getPassword(); +} + std::string LinkRegistry::getAuthIdentity(const std::string& key) { Link::shared_ptr link = findLink(key); diff --git a/cpp/src/qpid/broker/LinkRegistry.h b/cpp/src/qpid/broker/LinkRegistry.h index 52ab700cfc..a1931920d7 100644 --- a/cpp/src/qpid/broker/LinkRegistry.h +++ b/cpp/src/qpid/broker/LinkRegistry.h @@ -132,6 +132,10 @@ namespace broker { std::string getAuthMechanism (const std::string& key); std::string getAuthCredentials (const std::string& key); std::string getAuthIdentity (const std::string& key); + std::string getUsername (const std::string& key); + std::string getPassword (const std::string& key); + std::string getHost (const std::string& key); + uint16_t getPort (const std::string& key); /** * Called by links failing over to new address diff --git a/cpp/src/qpid/broker/SecureConnection.cpp b/cpp/src/qpid/broker/SecureConnection.cpp index 74aec239ca..5c1ebf3e8b 100644 --- a/cpp/src/qpid/broker/SecureConnection.cpp +++ b/cpp/src/qpid/broker/SecureConnection.cpp @@ -78,10 +78,13 @@ void SecureConnection:: setCodec(std::auto_ptr<ConnectionCodec> c) codec = c; } -void SecureConnection::activateSecurityLayer(std::auto_ptr<SecurityLayer> sl) +void SecureConnection::activateSecurityLayer(std::auto_ptr<SecurityLayer> sl, bool secureImmediately) { securityLayer = sl; securityLayer->init(codec.get()); + + if ( secureImmediately ) + secured = true; } }} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SecureConnection.h b/cpp/src/qpid/broker/SecureConnection.h index 4a0cc50e34..1547faae1e 100644 --- a/cpp/src/qpid/broker/SecureConnection.h +++ b/cpp/src/qpid/broker/SecureConnection.h @@ -49,7 +49,7 @@ class SecureConnection : public qpid::sys::ConnectionCodec bool isClosed() const; framing::ProtocolVersion getVersion() const; void setCodec(std::auto_ptr<ConnectionCodec>); - void activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer>); + void activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer>, bool secureImmediately=false); private: std::auto_ptr<ConnectionCodec> codec; std::auto_ptr<qpid::sys::SecurityLayer> securityLayer; |
