summaryrefslogtreecommitdiff
path: root/cpp/src/qpid/broker
diff options
context:
space:
mode:
authorMichael Goulish <mgoulish@apache.org>2010-10-20 08:03:36 +0000
committerMichael Goulish <mgoulish@apache.org>2010-10-20 08:03:36 +0000
commitbcb149706cdace4a333a811969e473451d9ab331 (patch)
tree6ad1e5797a8696968b91bdcf511eeac4bf4cb54f /cpp/src/qpid/broker
parent346e5a55b9152ab603bf8b15bd7718beb9d6ff76 (diff)
downloadqpid-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.cpp32
-rw-r--r--cpp/src/qpid/broker/Connection.h4
-rw-r--r--cpp/src/qpid/broker/ConnectionHandler.cpp104
-rw-r--r--cpp/src/qpid/broker/ConnectionHandler.h15
-rw-r--r--cpp/src/qpid/broker/LinkRegistry.cpp36
-rw-r--r--cpp/src/qpid/broker/LinkRegistry.h4
-rw-r--r--cpp/src/qpid/broker/SecureConnection.cpp5
-rw-r--r--cpp/src/qpid/broker/SecureConnection.h2
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;