summaryrefslogtreecommitdiff
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
commitee678a32e10a7ac437e2a0c655ad9c7d03c0a2ee (patch)
tree9315acb7ef9bfa155c5398627d68c716c921f828
parentac04e936aed7ecf6ecb2349f26f591bf777c7e05 (diff)
downloadqpid-python-ee678a32e10a7ac437e2a0c655ad9c7d03c0a2ee.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@1024541 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--qpid/cpp/src/CMakeLists.txt2
-rw-r--r--qpid/cpp/src/Makefile.am6
-rw-r--r--qpid/cpp/src/qpid/Sasl.h (renamed from qpid/cpp/src/qpid/client/Sasl.h)12
-rw-r--r--qpid/cpp/src/qpid/SaslFactory.cpp (renamed from qpid/cpp/src/qpid/client/SaslFactory.cpp)62
-rw-r--r--qpid/cpp/src/qpid/SaslFactory.h (renamed from qpid/cpp/src/qpid/client/SaslFactory.h)13
-rw-r--r--qpid/cpp/src/qpid/broker/Connection.cpp32
-rw-r--r--qpid/cpp/src/qpid/broker/Connection.h4
-rw-r--r--qpid/cpp/src/qpid/broker/ConnectionHandler.cpp104
-rw-r--r--qpid/cpp/src/qpid/broker/ConnectionHandler.h15
-rw-r--r--qpid/cpp/src/qpid/broker/LinkRegistry.cpp36
-rw-r--r--qpid/cpp/src/qpid/broker/LinkRegistry.h4
-rw-r--r--qpid/cpp/src/qpid/broker/SecureConnection.cpp5
-rw-r--r--qpid/cpp/src/qpid/broker/SecureConnection.h2
-rw-r--r--qpid/cpp/src/qpid/client/ConnectionHandler.cpp10
-rw-r--r--qpid/cpp/src/qpid/client/ConnectionHandler.h2
-rw-r--r--qpid/cpp/src/tests/sasl.mk1
-rwxr-xr-xqpid/cpp/src/tests/sasl_fed152
-rwxr-xr-xqpid/tools/src/py/qpid-route21
18 files changed, 424 insertions, 59 deletions
diff --git a/qpid/cpp/src/CMakeLists.txt b/qpid/cpp/src/CMakeLists.txt
index e52ccb6777..ba2a866cfb 100644
--- a/qpid/cpp/src/CMakeLists.txt
+++ b/qpid/cpp/src/CMakeLists.txt
@@ -712,7 +712,6 @@ else (CMAKE_SYSTEM_NAME STREQUAL Windows)
)
set (qpidclient_platform_SOURCES
- qpid/client/SaslFactory.cpp
)
set (qpidd_platform_SOURCES
@@ -732,6 +731,7 @@ set (qpidcommon_SOURCES
qpid/Options.cpp
qpid/Plugin.cpp
qpid/RefCountedBuffer.cpp
+ qpid/SaslFactory.cpp
qpid/SessionState.cpp
qpid/SessionId.cpp
qpid/StringUtils.cpp
diff --git a/qpid/cpp/src/Makefile.am b/qpid/cpp/src/Makefile.am
index 0ce1480825..9a6f7f3949 100644
--- a/qpid/cpp/src/Makefile.am
+++ b/qpid/cpp/src/Makefile.am
@@ -331,6 +331,9 @@ libqpidcommon_la_SOURCES += \
qpid/RefCounted.h \
qpid/RefCountedBuffer.cpp \
qpid/RefCountedBuffer.h \
+ qpid/Sasl.h \
+ qpid/SaslFactory.cpp \
+ qpid/SaslFactory.h \
qpid/Serializer.h \
qpid/SessionId.cpp \
qpid/SessionState.cpp \
@@ -692,9 +695,6 @@ libqpidclient_la_SOURCES = \
qpid/client/QueueOptions.cpp \
qpid/client/Results.cpp \
qpid/client/Results.h \
- qpid/client/Sasl.h \
- qpid/client/SaslFactory.cpp \
- qpid/client/SaslFactory.h \
qpid/client/SessionBase_0_10.cpp \
qpid/client/SessionBase_0_10Access.h \
qpid/client/SessionImpl.cpp \
diff --git a/qpid/cpp/src/qpid/client/Sasl.h b/qpid/cpp/src/qpid/Sasl.h
index 56735a5fc3..9a9d61b037 100644
--- a/qpid/cpp/src/qpid/client/Sasl.h
+++ b/qpid/cpp/src/qpid/Sasl.h
@@ -1,5 +1,5 @@
-#ifndef QPID_CLIENT_SASL_H
-#define QPID_CLIENT_SASL_H
+#ifndef QPID_SASL_H
+#define QPID_SASL_H
/*
*
@@ -33,10 +33,6 @@ class SecurityLayer;
struct SecuritySettings;
}
-namespace client {
-
-struct ConnectionSettings;
-
/**
* Interface to SASL support. This class is implemented by platform-specific
* SASL providers.
@@ -59,6 +55,6 @@ class Sasl
virtual std::auto_ptr<qpid::sys::SecurityLayer> getSecurityLayer(uint16_t maxFrameSize) = 0;
virtual ~Sasl() {}
};
-}} // namespace qpid::client
+} // namespace qpid
-#endif /*!QPID_CLIENT_SASL_H*/
+#endif /*!QPID_SASL_H*/
diff --git a/qpid/cpp/src/qpid/client/SaslFactory.cpp b/qpid/cpp/src/qpid/SaslFactory.cpp
index 79acf3cd7c..28c27f7529 100644
--- a/qpid/cpp/src/qpid/client/SaslFactory.cpp
+++ b/qpid/cpp/src/qpid/SaslFactory.cpp
@@ -18,8 +18,7 @@
* under the License.
*
*/
-#include "qpid/client/SaslFactory.h"
-#include "qpid/client/ConnectionSettings.h"
+#include "qpid//SaslFactory.h"
#include <map>
#include <string.h>
@@ -30,7 +29,6 @@
#ifndef HAVE_SASL
namespace qpid {
-namespace client {
//Null implementation
@@ -47,7 +45,7 @@ SaslFactory& SaslFactory::getInstance()
return *instance;
}
-std::auto_ptr<Sasl> SaslFactory::create(const ConnectionSettings&)
+std::auto_ptr<Sasl> SaslFactory::create( const std::string &, const std::string &, const std::string &, const std::string &, int, int )
{
return std::auto_ptr<Sasl>();
}
@@ -55,7 +53,7 @@ std::auto_ptr<Sasl> SaslFactory::create(const ConnectionSettings&)
qpid::sys::Mutex SaslFactory::lock;
std::auto_ptr<SaslFactory> SaslFactory::instance;
-}} // namespace qpid::client
+} // namespace qpid
#else
@@ -69,7 +67,6 @@ std::auto_ptr<SaslFactory> SaslFactory::instance;
#include <strings.h>
namespace qpid {
-namespace client {
using qpid::sys::SecurityLayer;
using qpid::sys::SecuritySettings;
@@ -78,10 +75,42 @@ using qpid::framing::InternalErrorException;
const size_t MAX_LOGIN_LENGTH = 50;
+struct CyrusSaslSettings
+{
+ CyrusSaslSettings ( ) :
+ username ( std::string(0) ),
+ password ( std::string(0) ),
+ service ( std::string(0) ),
+ host ( std::string(0) ),
+ minSsf ( 0 ),
+ maxSsf ( 0 )
+ {
+ }
+
+ CyrusSaslSettings ( const std::string & user, const std::string & password, const std::string & service, const std::string & host, int minSsf, int maxSsf ) :
+ username(user),
+ password(password),
+ service(service),
+ host(host),
+ minSsf(minSsf),
+ maxSsf(maxSsf)
+ {
+ }
+
+ std::string username,
+ password,
+ service,
+ host;
+
+ int minSsf,
+ maxSsf;
+};
+
+
class CyrusSasl : public Sasl
{
public:
- CyrusSasl(const ConnectionSettings&);
+ CyrusSasl(const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf);
~CyrusSasl();
std::string start(const std::string& mechanisms, const SecuritySettings* externalSettings);
std::string step(const std::string& challenge);
@@ -91,7 +120,7 @@ class CyrusSasl : public Sasl
private:
sasl_conn_t* conn;
sasl_callback_t callbacks[5];//realm, user, authname, password, end-of-list
- ConnectionSettings settings;
+ CyrusSaslSettings settings;
std::string input;
std::string mechanism;
char login[MAX_LOGIN_LENGTH];
@@ -130,13 +159,14 @@ SaslFactory& SaslFactory::getInstance()
return *instance;
}
-std::auto_ptr<Sasl> SaslFactory::create(const ConnectionSettings& settings)
+std::auto_ptr<Sasl> SaslFactory::create(const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf)
{
- std::auto_ptr<Sasl> sasl(new CyrusSasl(settings));
+ std::auto_ptr<Sasl> sasl(new CyrusSasl(username, password, serviceName, hostName, minSsf, maxSsf));
return sasl;
}
-CyrusSasl::CyrusSasl(const ConnectionSettings& s) : conn(0), settings(s)
+CyrusSasl::CyrusSasl(const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf)
+ : conn(0), settings(username, password, serviceName, hostName, minSsf, maxSsf)
{
size_t i = 0;
@@ -336,7 +366,7 @@ std::auto_ptr<SecurityLayer> CyrusSasl::getSecurityLayer(uint16_t maxFrameSize)
int getUserFromSettings(void* context, int /*id*/, const char** result, unsigned* /*len*/)
{
if (context) {
- *result = ((ConnectionSettings*) context)->username.c_str();
+ *result = ((CyrusSaslSettings*) context)->username.c_str();
QPID_LOG(debug, "getUserFromSettings(): " << (*result));
return SASL_OK;
} else {
@@ -345,7 +375,7 @@ int getUserFromSettings(void* context, int /*id*/, const char** result, unsigned
}
namespace {
-// Global map of secrest allocated for SASL connections via callback
+// Global map of secrets allocated for SASL connections via callback
// to getPasswordFromSettings. Ensures secrets are freed.
class SecretsMap {
typedef std::map<sasl_conn_t*, void*> Map;
@@ -368,11 +398,11 @@ SecretsMap getPasswordFromSettingsSecrets;
int getPasswordFromSettings(sasl_conn_t* conn, void* context, int /*id*/, sasl_secret_t** psecret)
{
if (context) {
- size_t length = ((ConnectionSettings*) context)->password.size();
+ size_t length = ((CyrusSaslSettings*) context)->password.size();
sasl_secret_t* secret = (sasl_secret_t*) malloc(sizeof(sasl_secret_t) + length);
getPasswordFromSettingsSecrets.keep(conn, secret);
secret->len = length;
- memcpy(secret->data, ((ConnectionSettings*) context)->password.data(), length);
+ memcpy(secret->data, ((CyrusSaslSettings*) context)->password.data(), length);
*psecret = secret;
return SASL_OK;
} else {
@@ -380,6 +410,6 @@ int getPasswordFromSettings(sasl_conn_t* conn, void* context, int /*id*/, sasl_s
}
}
-}} // namespace qpid::client
+} // namespace qpid
#endif
diff --git a/qpid/cpp/src/qpid/client/SaslFactory.h b/qpid/cpp/src/qpid/SaslFactory.h
index d012af06f7..d9d83c494d 100644
--- a/qpid/cpp/src/qpid/client/SaslFactory.h
+++ b/qpid/cpp/src/qpid/SaslFactory.h
@@ -1,5 +1,5 @@
-#ifndef QPID_CLIENT_SASLFACTORY_H
-#define QPID_CLIENT_SASLFACTORY_H
+#ifndef QPID_SASLFACTORY_H
+#define QPID_SASLFACTORY_H
/*
*
@@ -21,12 +21,11 @@
* under the License.
*
*/
-#include "qpid/client/Sasl.h"
+#include "qpid/Sasl.h"
#include "qpid/sys/Mutex.h"
#include <memory>
namespace qpid {
-namespace client {
/**
* Factory for instances of the Sasl interface through which Sasl
@@ -35,7 +34,7 @@ namespace client {
class SaslFactory
{
public:
- std::auto_ptr<Sasl> create(const ConnectionSettings&);
+ std::auto_ptr<Sasl> create(const std::string & userName, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf );
static SaslFactory& getInstance();
~SaslFactory();
private:
@@ -43,6 +42,6 @@ class SaslFactory
static qpid::sys::Mutex lock;
static std::auto_ptr<SaslFactory> instance;
};
-}} // namespace qpid::client
+} // namespace qpid
-#endif /*!QPID_CLIENT_SASLFACTORY_H*/
+#endif /*!QPID_SASLFACTORY_H*/
diff --git a/qpid/cpp/src/qpid/broker/Connection.cpp b/qpid/cpp/src/qpid/broker/Connection.cpp
index d50f0c946a..98743cdae6 100644
--- a/qpid/cpp/src/qpid/broker/Connection.cpp
+++ b/qpid/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/qpid/cpp/src/qpid/broker/Connection.h b/qpid/cpp/src/qpid/broker/Connection.h
index c1b2b5a8fc..d978187e0c 100644
--- a/qpid/cpp/src/qpid/broker/Connection.h
+++ b/qpid/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/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp b/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp
index c349bc7ac7..c812374d38 100644
--- a/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp
+++ b/qpid/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/qpid/cpp/src/qpid/broker/ConnectionHandler.h b/qpid/cpp/src/qpid/broker/ConnectionHandler.h
index 6d55cab647..70882a24e9 100644
--- a/qpid/cpp/src/qpid/broker/ConnectionHandler.h
+++ b/qpid/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/qpid/cpp/src/qpid/broker/LinkRegistry.cpp b/qpid/cpp/src/qpid/broker/LinkRegistry.cpp
index 9d429a2dcc..ea14552cc1 100644
--- a/qpid/cpp/src/qpid/broker/LinkRegistry.cpp
+++ b/qpid/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/qpid/cpp/src/qpid/broker/LinkRegistry.h b/qpid/cpp/src/qpid/broker/LinkRegistry.h
index 52ab700cfc..a1931920d7 100644
--- a/qpid/cpp/src/qpid/broker/LinkRegistry.h
+++ b/qpid/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/qpid/cpp/src/qpid/broker/SecureConnection.cpp b/qpid/cpp/src/qpid/broker/SecureConnection.cpp
index 74aec239ca..5c1ebf3e8b 100644
--- a/qpid/cpp/src/qpid/broker/SecureConnection.cpp
+++ b/qpid/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/qpid/cpp/src/qpid/broker/SecureConnection.h b/qpid/cpp/src/qpid/broker/SecureConnection.h
index 4a0cc50e34..1547faae1e 100644
--- a/qpid/cpp/src/qpid/broker/SecureConnection.h
+++ b/qpid/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;
diff --git a/qpid/cpp/src/qpid/client/ConnectionHandler.cpp b/qpid/cpp/src/qpid/client/ConnectionHandler.cpp
index e615878703..8dc1e8338a 100644
--- a/qpid/cpp/src/qpid/client/ConnectionHandler.cpp
+++ b/qpid/cpp/src/qpid/client/ConnectionHandler.cpp
@@ -21,7 +21,7 @@
#include "qpid/client/ConnectionHandler.h"
-#include "qpid/client/SaslFactory.h"
+#include "qpid/SaslFactory.h"
#include "qpid/client/Bounds.h"
#include "qpid/framing/amqp_framing.h"
#include "qpid/framing/all_method_bodies.h"
@@ -208,7 +208,13 @@ void ConnectionHandler::start(const FieldTable& /*serverProps*/, const Array& me
{
checkState(NOT_STARTED, INVALID_STATE_START);
setState(NEGOTIATING);
- sasl = SaslFactory::getInstance().create(*this);
+ sasl = SaslFactory::getInstance().create( username,
+ password,
+ service,
+ host,
+ minSsf,
+ maxSsf
+ );
std::string mechlist;
bool chosenMechanismSupported = mechanism.empty();
diff --git a/qpid/cpp/src/qpid/client/ConnectionHandler.h b/qpid/cpp/src/qpid/client/ConnectionHandler.h
index 61709db174..6af2e987fb 100644
--- a/qpid/cpp/src/qpid/client/ConnectionHandler.h
+++ b/qpid/cpp/src/qpid/client/ConnectionHandler.h
@@ -23,7 +23,7 @@
#include "qpid/client/ChainableFrameHandler.h"
#include "qpid/client/ConnectionSettings.h"
-#include "qpid/client/Sasl.h"
+#include "qpid/Sasl.h"
#include "qpid/client/StateManager.h"
#include "qpid/framing/AMQMethodBody.h"
#include "qpid/framing/AMQP_HighestVersion.h"
diff --git a/qpid/cpp/src/tests/sasl.mk b/qpid/cpp/src/tests/sasl.mk
index 52cebe63f6..ae1666e891 100644
--- a/qpid/cpp/src/tests/sasl.mk
+++ b/qpid/cpp/src/tests/sasl.mk
@@ -26,6 +26,7 @@ cluster_authentication_soak_SOURCES=cluster_authentication_soak.cpp ForkedBroke
cluster_authentication_soak_LDADD=$(lib_client) $(lib_broker)
TESTS += run_cluster_authentication_test
+TESTS += sasl_fed
LONG_TESTS += run_cluster_authentication_soak
endif # HAVE_SASL
diff --git a/qpid/cpp/src/tests/sasl_fed b/qpid/cpp/src/tests/sasl_fed
new file mode 100755
index 0000000000..550b5a1626
--- /dev/null
+++ b/qpid/cpp/src/tests/sasl_fed
@@ -0,0 +1,152 @@
+#! /bin/bash
+
+source test_env.sh
+
+minimum_sasl_version="2.1.22"
+if [ ! `pkg-config --atleast-version $minimum_sasl_version cyrus-sasl`]; then
+ echo "sasl_fed requires at least $minimum_sasl_version"
+ exit 0
+fi
+
+let minimum_sasl_version=$((2 * 65536 + 1 * 256 + 22))
+sasl_version_numbers=(`rpm -q cyrus-sasl-devel | head -1 | tr '-' ' ' | awk '{print $4}' | tr '.' ' '`)
+let sasl_version=$((${sasl_version_numbers[0]} * 65536 + ${sasl_version_numbers[1]} * 256 + ${sasl_version_numbers[2]}))
+
+if [ "$sasl_version" -lt "$minimum_sasl_version" ]; then
+ echo "sasl_fed requires version 2.1.22 or later"
+ exit 0
+fi
+
+exit
+
+QPID_SRC=$top_srcdir/src
+QPIDD=$QPID_SRC/.libs/qpidd
+PY_TOOLS=$QPID_TOOLS/src/py
+
+sasl_config_file=$QPID_SRC/tests/sasl_config
+
+my_random_number=$RANDOM
+tmp_root=/tmp/sasl_fed/$my_random_number
+mkdir -p $tmp_root
+
+
+#--------------------------------------------------
+#echo " Starting broker 1"
+#--------------------------------------------------
+$QPIDD \
+ -p 0 \
+ --data-dir $tmp_root/data_1 \
+ --auth=yes \
+ --mgmt-enable=yes \
+ --log-enable info+ \
+ --log-source yes \
+ --log-to-file $tmp_root/qpidd_1.log \
+ --sasl-config=$sasl_config_file \
+ -d > $tmp_root/broker_1_port
+
+broker_1_port=`cat $tmp_root/broker_1_port`
+
+
+#--------------------------------------------------
+#echo " Starting broker 2"
+#--------------------------------------------------
+$QPIDD \
+ -p 0 \
+ --data-dir $tmp_root/data_2 \
+ --auth=yes \
+ --mgmt-enable=yes \
+ --log-enable info+ \
+ --log-source yes \
+ --log-to-file $tmp_root/qpidd_2.log \
+ --sasl-config=$sasl_config_file \
+ -d > $tmp_root/broker_2_port
+
+broker_2_port=`cat $tmp_root/broker_2_port`
+
+
+# Now find the PIDs so I can kill them later.
+#pids=`ps -aef | grep -v grep | grep sasl_fed | grep $my_random_number | awk '{print $2}'`
+
+
+# I am not randomizing these names, because the test creates its own brokers.
+QUEUE_NAME=sasl_fed_queue
+ROUTING_KEY=sasl_fed_queue
+EXCHANGE_NAME=sasl_fedex
+
+#--------------------------------------------------
+#echo " add exchanges"
+#--------------------------------------------------
+$PY_TOOLS/qpid-config -a localhost:$broker_1_port add exchange direct $EXCHANGE_NAME
+$PY_TOOLS/qpid-config -a localhost:$broker_2_port add exchange direct $EXCHANGE_NAME
+
+
+#--------------------------------------------------
+#echo " add queues"
+#--------------------------------------------------
+$PY_TOOLS/qpid-config -a localhost:$broker_1_port add queue $QUEUE_NAME
+$PY_TOOLS/qpid-config -a localhost:$broker_2_port add queue $QUEUE_NAME
+
+sleep 5
+
+#--------------------------------------------------
+#echo " create bindings"
+#--------------------------------------------------
+$PY_TOOLS/qpid-config -a localhost:$broker_1_port bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY
+$PY_TOOLS/qpid-config -a localhost:$broker_2_port bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY
+
+sleep 5
+
+
+#--------------------------------------------------
+#echo " qpid-route route add"
+#--------------------------------------------------
+$PY_TOOLS/qpid-route route add zag/zag@localhost:$broker_2_port zag/zag@localhost:$broker_1_port $EXCHANGE_NAME $ROUTING_KEY "" "" DIGEST-MD5
+
+sleep 5
+
+
+n_messages=100
+#--------------------------------------------------
+#echo " Sending 100 messages to $broker_1_port "
+#--------------------------------------------------
+$QPID_SRC/tests/datagen --count $n_messages | $QPID_SRC/tests/sender --username zag --password zag --exchange $EXCHANGE_NAME --routing-key $ROUTING_KEY --port $broker_1_port
+
+sleep 5
+
+#--------------------------------------------------
+#echo " Examine Broker $broker_1_port"
+#--------------------------------------------------
+broker_1_message_count=`$PY_TOOLS/qpid-stat -q localhost:$broker_1_port | grep sasl_fed_queue | awk '{print $2}'`
+#echo " "
+
+#--------------------------------------------------
+#echo " Examine Broker $broker_2_port"
+#--------------------------------------------------
+broker_2_message_count=`$PY_TOOLS/qpid-stat -q localhost:$broker_2_port | grep sasl_fed_queue | awk '{print $2}'`
+#echo " "
+
+#--------------------------------------------------
+#echo " Asking brokers to quit."
+#--------------------------------------------------
+$QPIDD --port $broker_1_port --quit
+$QPIDD --port $broker_2_port --quit
+
+
+#--------------------------------------------------
+#echo "Removing temporary directory $tmp_root"
+#--------------------------------------------------
+rm -rf $tmp_root
+
+if [ "$broker_2_message_count" = "$n_messages" ]; then
+ echo "good: $broker_2_message_count"
+ exit 0
+else
+ echo "not ideal: $broker_1_message_count != $n_messages"
+ exit 1
+fi
+
+
+
+
+
+
diff --git a/qpid/tools/src/py/qpid-route b/qpid/tools/src/py/qpid-route
index be6bdf958c..0b5069a277 100755
--- a/qpid/tools/src/py/qpid-route
+++ b/qpid/tools/src/py/qpid-route
@@ -30,7 +30,7 @@ def Usage(short=False):
print "Usage: qpid-route [OPTIONS] dynamic add <dest-broker> <src-broker> <exchange> [tag] [exclude-list]"
print " qpid-route [OPTIONS] dynamic del <dest-broker> <src-broker> <exchange>"
print
- print " qpid-route [OPTIONS] route add <dest-broker> <src-broker> <exchange> <routing-key> [tag] [exclude-list]"
+ print " qpid-route [OPTIONS] route add <dest-broker> <src-broker> <exchange> <routing-key> [tag] [exclude-list] [mechanism]"
print " qpid-route [OPTIONS] route del <dest-broker> <src-broker> <exchange> <routing-key>"
print " qpid-route [OPTIONS] queue add <dest-broker> <src-broker> <exchange> <queue>"
print " qpid-route [OPTIONS] queue del <dest-broker> <src-broker> <exchange> <queue>"
@@ -98,7 +98,7 @@ class RouteManager:
return link
return None
- def addLink(self, remoteBroker):
+ def addLink(self, remoteBroker, mech="PLAIN"):
self.remote = BrokerURL(remoteBroker)
if self.local.match(self.remote.host, self.remote.port):
raise Exception("Linking broker to itself is not permitted")
@@ -107,10 +107,6 @@ class RouteManager:
broker = brokers[0]
link = self.getLink()
if link == None:
- if not self.remote.authName or self.remote.authName == "anonymous":
- mech = "ANONYMOUS"
- else:
- mech = "PLAIN"
res = broker.connect(self.remote.host, self.remote.port, _durable,
mech, self.remote.authName or "", self.remote.authPass or "",
_transport)
@@ -231,11 +227,11 @@ class RouteManager:
if b[0] != self.local.name():
self.qmf.delBroker(b[1])
- def addRoute(self, remoteBroker, exchange, routingKey, tag, excludes, dynamic=False):
+ def addRoute(self, remoteBroker, exchange, routingKey, tag, excludes, mech="PLAIN", dynamic=False):
if dynamic and _srclocal:
raise Exception("--src-local is not permitted on dynamic routes")
- self.addLink(remoteBroker)
+ self.addLink(remoteBroker, mech)
link = self.getLink()
if link == None:
raise Exception("Link failed to create")
@@ -494,9 +490,10 @@ try:
tag = ""
excludes = ""
+ mech = "PLAIN"
if nargs > 5: tag = cargs[5]
if nargs > 6: excludes = cargs[6]
- rm.addRoute(remoteBroker, cargs[4], "", tag, excludes, dynamic=True)
+ rm.addRoute(remoteBroker, cargs[4], "", tag, excludes, mech, dynamic=True)
elif cmd == "del":
if nargs != 5:
Usage()
@@ -505,14 +502,16 @@ try:
elif group == "route":
if cmd == "add":
- if nargs < 6 or nargs > 8:
+ if nargs < 6 or nargs > 9:
Usage()
tag = ""
excludes = ""
+ mech = "PLAIN"
if nargs > 6: tag = cargs[6]
if nargs > 7: excludes = cargs[7]
- rm.addRoute(remoteBroker, cargs[4], cargs[5], tag, excludes, dynamic=False)
+ if nargs > 8: mech = cargs[8]
+ rm.addRoute(remoteBroker, cargs[4], cargs[5], tag, excludes, mech, dynamic=False)
elif cmd == "del":
if nargs != 6:
Usage()