Author: mgoulish
Date: Wed Oct 20 08:03:36 2010
New Revision: 1024541

URL: http://svn.apache.org/viewvc?rev=1024541&view=rev
Log:
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.



Added:
    qpid/trunk/qpid/cpp/src/qpid/Sasl.h
    qpid/trunk/qpid/cpp/src/qpid/SaslFactory.cpp
    qpid/trunk/qpid/cpp/src/qpid/SaslFactory.h
    qpid/trunk/qpid/cpp/src/tests/sasl_fed   (with props)
Removed:
    qpid/trunk/qpid/cpp/src/qpid/client/Sasl.h
    qpid/trunk/qpid/cpp/src/qpid/client/SaslFactory.cpp
    qpid/trunk/qpid/cpp/src/qpid/client/SaslFactory.h
Modified:
    qpid/trunk/qpid/cpp/src/CMakeLists.txt
    qpid/trunk/qpid/cpp/src/Makefile.am
    qpid/trunk/qpid/cpp/src/qpid/broker/Connection.cpp
    qpid/trunk/qpid/cpp/src/qpid/broker/Connection.h
    qpid/trunk/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp
    qpid/trunk/qpid/cpp/src/qpid/broker/ConnectionHandler.h
    qpid/trunk/qpid/cpp/src/qpid/broker/LinkRegistry.cpp
    qpid/trunk/qpid/cpp/src/qpid/broker/LinkRegistry.h
    qpid/trunk/qpid/cpp/src/qpid/broker/SecureConnection.cpp
    qpid/trunk/qpid/cpp/src/qpid/broker/SecureConnection.h
    qpid/trunk/qpid/cpp/src/qpid/client/ConnectionHandler.cpp
    qpid/trunk/qpid/cpp/src/qpid/client/ConnectionHandler.h
    qpid/trunk/qpid/cpp/src/tests/sasl.mk
    qpid/trunk/qpid/tools/src/py/qpid-route

Modified: qpid/trunk/qpid/cpp/src/CMakeLists.txt
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/CMakeLists.txt?rev=1024541&r1=1024540&r2=1024541&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/CMakeLists.txt (original)
+++ qpid/trunk/qpid/cpp/src/CMakeLists.txt Wed Oct 20 08:03:36 2010
@@ -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

Modified: qpid/trunk/qpid/cpp/src/Makefile.am
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/Makefile.am?rev=1024541&r1=1024540&r2=1024541&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/Makefile.am (original)
+++ qpid/trunk/qpid/cpp/src/Makefile.am Wed Oct 20 08:03:36 2010
@@ -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                  \

Added: qpid/trunk/qpid/cpp/src/qpid/Sasl.h
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/Sasl.h?rev=1024541&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/Sasl.h (added)
+++ qpid/trunk/qpid/cpp/src/qpid/Sasl.h Wed Oct 20 08:03:36 2010
@@ -0,0 +1,60 @@
+#ifndef QPID_SASL_H
+#define QPID_SASL_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <memory>
+#include <string>
+#include "qpid/sys/IntegerTypes.h"
+
+namespace qpid {
+
+namespace sys {
+class SecurityLayer;
+struct SecuritySettings;
+}
+
+/**
+ * Interface to SASL support. This class is implemented by platform-specific
+ * SASL providers.
+ */
+class Sasl
+{
+  public:
+    /**
+     * Start SASL negotiation with the broker.
+     *
+     * @param mechanisms Comma-separated list of the SASL mechanism the
+     *             client supports.
+     * @param externalSecuritySettings security related details from the 
underlying transport
+     */
+    virtual std::string start(const std::string& mechanisms,
+                              const qpid::sys::SecuritySettings* 
externalSecuritySettings = 0) = 0;
+    virtual std::string step(const std::string& challenge) = 0;
+    virtual std::string getMechanism() = 0;
+    virtual std::string getUserId() = 0;
+    virtual std::auto_ptr<qpid::sys::SecurityLayer> getSecurityLayer(uint16_t 
maxFrameSize) = 0;    
+    virtual ~Sasl() {}
+};
+} // namespace qpid
+
+#endif  /*!QPID_SASL_H*/

Added: qpid/trunk/qpid/cpp/src/qpid/SaslFactory.cpp
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/SaslFactory.cpp?rev=1024541&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/SaslFactory.cpp (added)
+++ qpid/trunk/qpid/cpp/src/qpid/SaslFactory.cpp Wed Oct 20 08:03:36 2010
@@ -0,0 +1,415 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid//SaslFactory.h"
+#include <map>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#ifndef HAVE_SASL
+
+namespace qpid {
+
+//Null implementation
+
+SaslFactory::SaslFactory() {}
+
+SaslFactory::~SaslFactory() {}
+
+SaslFactory& SaslFactory::getInstance()
+{
+    qpid::sys::Mutex::ScopedLock l(lock);
+    if (!instance.get()) {
+        instance = std::auto_ptr<SaslFactory>(new SaslFactory());
+    }
+    return *instance;
+}
+
+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>();
+}
+
+qpid::sys::Mutex SaslFactory::lock;
+std::auto_ptr<SaslFactory> SaslFactory::instance;
+
+} // namespace qpid
+
+#else
+
+#include "qpid/Exception.h"
+#include "qpid/framing/reply_exceptions.h"
+#include "qpid/sys/SecurityLayer.h"
+#include "qpid/sys/SecuritySettings.h"
+#include "qpid/sys/cyrus/CyrusSecurityLayer.h"
+#include "qpid/log/Statement.h"
+#include <sasl/sasl.h>
+#include <strings.h>
+
+namespace qpid {
+
+using qpid::sys::SecurityLayer;
+using qpid::sys::SecuritySettings;
+using qpid::sys::cyrus::CyrusSecurityLayer;
+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 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);
+    std::string getMechanism();
+    std::string getUserId();
+    std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize);
+  private:
+    sasl_conn_t* conn;    
+    sasl_callback_t callbacks[5];//realm, user, authname, password, end-of-list
+    CyrusSaslSettings settings;
+    std::string input;
+    std::string mechanism;
+    char login[MAX_LOGIN_LENGTH];
+
+    void interact(sasl_interact_t* client_interact);
+};
+
+//sasl callback functions
+int getUserFromSettings(void *context, int id, const char **result, unsigned 
*len);
+int getPasswordFromSettings(sasl_conn_t *conn, void *context, int id, 
sasl_secret_t **psecret);
+typedef int CallbackProc();
+
+qpid::sys::Mutex SaslFactory::lock;
+std::auto_ptr<SaslFactory> SaslFactory::instance;
+
+SaslFactory::SaslFactory()
+{
+    sasl_callback_t* callbacks = 0;
+    int result = sasl_client_init(callbacks);
+    if (result != SASL_OK) {
+        throw InternalErrorException(QPID_MSG("Sasl error: " << 
sasl_errstring(result, 0, 0)));
+    }
+}
+
+SaslFactory::~SaslFactory()
+{
+    sasl_done();
+}
+
+SaslFactory& SaslFactory::getInstance()
+{
+    qpid::sys::Mutex::ScopedLock l(lock);
+    if (!instance.get()) {
+        instance = std::auto_ptr<SaslFactory>(new SaslFactory());
+    }
+    return *instance;
+}
+
+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(username, password, serviceName, 
hostName, minSsf, maxSsf));
+    return sasl;
+}
+
+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;
+
+    callbacks[i].id = SASL_CB_GETREALM;
+    callbacks[i].proc = 0;
+    callbacks[i++].context = 0;
+
+    if (!settings.username.empty()) {
+        callbacks[i].id = SASL_CB_AUTHNAME;
+        callbacks[i].proc = (CallbackProc*) &getUserFromSettings;
+        callbacks[i++].context = &settings;
+    }
+
+    callbacks[i].id = SASL_CB_PASS;
+    if (settings.password.empty()) {
+        callbacks[i].proc = 0;
+        callbacks[i++].context = 0;        
+    } else {
+        callbacks[i].proc = (CallbackProc*) &getPasswordFromSettings;
+        callbacks[i++].context = &settings;
+    }
+
+    callbacks[i].id = SASL_CB_LIST_END;
+    callbacks[i].proc = 0;
+    callbacks[i++].context = 0;
+}
+
+CyrusSasl::~CyrusSasl() 
+{
+    if (conn) {
+        sasl_dispose(&conn);
+    }
+}
+
+namespace {
+    const std::string SSL("ssl");
+}
+
+std::string CyrusSasl::start(const std::string& mechanisms, const 
SecuritySettings* externalSettings)
+{
+    QPID_LOG(debug, "CyrusSasl::start(" << mechanisms << ")");
+    int result = sasl_client_new(settings.service.c_str(),
+                                 settings.host.c_str(),
+                                 0, 0, /* Local and remote IP address strings 
*/
+                                 callbacks,
+                                 0,          /* security flags */
+                                 &conn);
+    
+    if (result != SASL_OK) throw InternalErrorException(QPID_MSG("Sasl error: 
" << sasl_errdetail(conn)));
+
+    sasl_security_properties_t secprops;
+
+    if (externalSettings) {
+        sasl_ssf_t external_ssf = (sasl_ssf_t) externalSettings->ssf;
+        if (external_ssf) {
+            int result = sasl_setprop(conn, SASL_SSF_EXTERNAL, &external_ssf);
+            if (result != SASL_OK) {
+                throw framing::InternalErrorException(QPID_MSG("SASL error: 
unable to set external SSF: " << result));
+            }
+            QPID_LOG(debug, "external SSF detected and set to " << 
external_ssf);
+        }
+        if (externalSettings->authid.size()) {
+            const char* external_authid = externalSettings->authid.c_str();
+            result = sasl_setprop(conn, SASL_AUTH_EXTERNAL, external_authid);
+            if (result != SASL_OK) {
+                throw framing::InternalErrorException(QPID_MSG("SASL error: 
unable to set external auth: " << result));
+            }
+            QPID_LOG(debug, "external auth detected and set to " << 
external_authid);
+        }
+    }
+
+    secprops.min_ssf = settings.minSsf;
+    secprops.max_ssf = settings.maxSsf;
+    secprops.maxbufsize = 65535;
+
+    QPID_LOG(debug, "min_ssf: " << secprops.min_ssf << ", max_ssf: " << 
secprops.max_ssf);
+    
+    secprops.property_names = 0;
+    secprops.property_values = 0;
+    secprops.security_flags = 0;//TODO: provide means for application to 
configure these
+    
+    result = sasl_setprop(conn, SASL_SEC_PROPS, &secprops);
+    if (result != SASL_OK) {
+        throw framing::InternalErrorException(QPID_MSG("SASL error: " << 
sasl_errdetail(conn)));
+    }
+
+    sasl_interact_t* client_interact = 0;
+    const char *out = 0;
+    unsigned outlen = 0;
+    const char *chosenMechanism = 0;
+
+    do {        
+        result = sasl_client_start(conn,
+                                   mechanisms.c_str(),
+                                   &client_interact,
+                                   &out,
+                                   &outlen,
+                                   &chosenMechanism);
+        
+        if (result == SASL_INTERACT) {
+            interact(client_interact);
+        }        
+    } while (result == SASL_INTERACT);
+
+    if (result != SASL_CONTINUE && result != SASL_OK) {
+        throw InternalErrorException(QPID_MSG("Sasl error: " << 
sasl_errdetail(conn)));
+    }
+
+    mechanism = std::string(chosenMechanism);
+    QPID_LOG(debug, "CyrusSasl::start(" << mechanisms << "): selected "
+             << mechanism << " response: '" << std::string(out, outlen) << 
"'");
+    return std::string(out, outlen);
+}
+
+std::string CyrusSasl::step(const std::string& challenge)
+{
+    sasl_interact_t* client_interact = 0;
+    const char *out = 0;
+    unsigned outlen = 0;
+    int result = 0;
+    do {
+        result = sasl_client_step(conn,  /* our context */
+                                  challenge.data(), /* the data from the 
server */
+                                  challenge.size(), /* it's length */
+                                  &client_interact,  /* this should be
+                                                        unallocated and NULL */
+                                  &out,     /* filled in on success */
+                                  &outlen); /* filled in on success */
+        
+        if (result == SASL_INTERACT) {
+            interact(client_interact);
+        }        
+    } while (result == SASL_INTERACT);
+
+    std::string response;
+    if (result == SASL_CONTINUE || result == SASL_OK) response = 
std::string(out, outlen);
+    else if (result != SASL_OK) {
+        throw InternalErrorException(QPID_MSG("Sasl error: " << 
sasl_errdetail(conn)));
+    }
+    QPID_LOG(debug, "CyrusSasl::step(" << challenge << "): " << response);
+    return response;
+}
+
+std::string CyrusSasl::getMechanism()
+{
+    return mechanism;
+}
+
+std::string CyrusSasl::getUserId()
+{
+    int propResult;
+    const void* operName;
+
+    propResult = sasl_getprop(conn, SASL_USERNAME, &operName);
+    if (propResult == SASL_OK)
+        return std::string((const char*) operName);
+
+    return std::string();
+}
+
+void CyrusSasl::interact(sasl_interact_t* client_interact)
+{
+
+    if (client_interact->id == SASL_CB_PASS) {
+        char* password = getpass(client_interact->prompt);
+        input = std::string(password);
+        client_interact->result = input.data();
+        client_interact->len = input.size();
+    } else {
+        std::cout << client_interact->prompt;
+        if (client_interact->defresult) std::cout << " (" << 
client_interact->defresult << ")";
+        std::cout << ": ";
+        if (std::cin >> input) {
+            client_interact->result = input.data();
+            client_interact->len = input.size();
+        }
+    }
+
+}
+
+std::auto_ptr<SecurityLayer> CyrusSasl::getSecurityLayer(uint16_t maxFrameSize)
+{
+    const void* value(0);
+    int result = sasl_getprop(conn, SASL_SSF, &value);
+    if (result != SASL_OK) {
+        throw framing::InternalErrorException(QPID_MSG("SASL error: " << 
sasl_errdetail(conn)));
+    }
+    uint ssf = *(reinterpret_cast<const unsigned*>(value));
+    std::auto_ptr<SecurityLayer> securityLayer;
+    if (ssf) {
+        QPID_LOG(info, "Installing security layer,  SSF: "<< ssf);
+        securityLayer = std::auto_ptr<SecurityLayer>(new 
CyrusSecurityLayer(conn, maxFrameSize));
+    }
+    return securityLayer;
+}
+
+int getUserFromSettings(void* context, int /*id*/, const char** result, 
unsigned* /*len*/)
+{
+    if (context) {
+        *result = ((CyrusSaslSettings*) context)->username.c_str();
+        QPID_LOG(debug, "getUserFromSettings(): " << (*result));
+        return SASL_OK;
+    } else {
+        return SASL_FAIL;
+    }
+}
+
+namespace {
+// 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;
+    Map map;
+  public:
+    void keep(sasl_conn_t* conn, void* secret) {
+        Map::iterator i = map.find(conn);
+        if (i != map.end()) free(i->second);
+        map[conn] = secret;
+    }
+
+    ~SecretsMap() {
+        for (Map::iterator i = map.begin(); i != map.end(); ++i)
+            free(i->second);
+    }
+};
+SecretsMap getPasswordFromSettingsSecrets;
+}
+
+int getPasswordFromSettings(sasl_conn_t* conn, void* context, int /*id*/, 
sasl_secret_t** psecret)
+{
+    if (context) {
+        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, ((CyrusSaslSettings*) context)->password.data(), 
length);
+        *psecret = secret;
+        return SASL_OK;
+    } else {
+        return SASL_FAIL;
+    }
+}
+
+} // namespace qpid
+
+#endif

Added: qpid/trunk/qpid/cpp/src/qpid/SaslFactory.h
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/SaslFactory.h?rev=1024541&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/SaslFactory.h (added)
+++ qpid/trunk/qpid/cpp/src/qpid/SaslFactory.h Wed Oct 20 08:03:36 2010
@@ -0,0 +1,47 @@
+#ifndef QPID_SASLFACTORY_H
+#define QPID_SASLFACTORY_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/Sasl.h"
+#include "qpid/sys/Mutex.h"
+#include <memory>
+
+namespace qpid {
+
+/**
+ * Factory for instances of the Sasl interface through which Sasl
+ * support is provided to a ConnectionHandler.
+ */
+class SaslFactory
+{
+  public:
+    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:
+    SaslFactory();
+    static qpid::sys::Mutex lock;
+    static std::auto_ptr<SaslFactory> instance;
+};
+} // namespace qpid
+
+#endif  /*!QPID_SASLFACTORY_H*/

Modified: qpid/trunk/qpid/cpp/src/qpid/broker/Connection.cpp
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/broker/Connection.cpp?rev=1024541&r1=1024540&r2=1024541&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/broker/Connection.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/broker/Connection.cpp Wed Oct 20 08:03:36 2010
@@ -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)

Modified: qpid/trunk/qpid/cpp/src/qpid/broker/Connection.h
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/broker/Connection.h?rev=1024541&r1=1024540&r2=1024541&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/broker/Connection.h (original)
+++ qpid/trunk/qpid/cpp/src/qpid/broker/Connection.h Wed Oct 20 08:03:36 2010
@@ -115,6 +115,10 @@ class Connection : public sys::Connectio
     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();

Modified: qpid/trunk/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp?rev=1024541&r1=1024540&r2=1024541&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp Wed Oct 20 
08:03:36 2010
@@ -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("q
 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(Conn
         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::heartbe
 }
 
 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(
         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;
 }
 

Modified: qpid/trunk/qpid/cpp/src/qpid/broker/ConnectionHandler.h
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/broker/ConnectionHandler.h?rev=1024541&r1=1024540&r2=1024541&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/broker/ConnectionHandler.h (original)
+++ qpid/trunk/qpid/cpp/src/qpid/broker/ConnectionHandler.h Wed Oct 20 08:03:36 
2010
@@ -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
         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;
 

Modified: qpid/trunk/qpid/cpp/src/qpid/broker/LinkRegistry.cpp
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/broker/LinkRegistry.cpp?rev=1024541&r1=1024540&r2=1024541&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/broker/LinkRegistry.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/broker/LinkRegistry.cpp Wed Oct 20 08:03:36 
2010
@@ -312,6 +312,42 @@ std::string LinkRegistry::getAuthCredent
     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);

Modified: qpid/trunk/qpid/cpp/src/qpid/broker/LinkRegistry.h
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/broker/LinkRegistry.h?rev=1024541&r1=1024540&r2=1024541&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/broker/LinkRegistry.h (original)
+++ qpid/trunk/qpid/cpp/src/qpid/broker/LinkRegistry.h Wed Oct 20 08:03:36 2010
@@ -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

Modified: qpid/trunk/qpid/cpp/src/qpid/broker/SecureConnection.cpp
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/broker/SecureConnection.cpp?rev=1024541&r1=1024540&r2=1024541&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/broker/SecureConnection.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/broker/SecureConnection.cpp Wed Oct 20 
08:03:36 2010
@@ -78,10 +78,13 @@ void SecureConnection:: setCodec(std::au
     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

Modified: qpid/trunk/qpid/cpp/src/qpid/broker/SecureConnection.h
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/broker/SecureConnection.h?rev=1024541&r1=1024540&r2=1024541&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/broker/SecureConnection.h (original)
+++ qpid/trunk/qpid/cpp/src/qpid/broker/SecureConnection.h Wed Oct 20 08:03:36 
2010
@@ -49,7 +49,7 @@ class SecureConnection : public qpid::sy
     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;

Modified: qpid/trunk/qpid/cpp/src/qpid/client/ConnectionHandler.cpp
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/client/ConnectionHandler.cpp?rev=1024541&r1=1024540&r2=1024541&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/client/ConnectionHandler.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/client/ConnectionHandler.cpp Wed Oct 20 
08:03:36 2010
@@ -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 Fiel
 {
     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();

Modified: qpid/trunk/qpid/cpp/src/qpid/client/ConnectionHandler.h
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/client/ConnectionHandler.h?rev=1024541&r1=1024540&r2=1024541&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/client/ConnectionHandler.h (original)
+++ qpid/trunk/qpid/cpp/src/qpid/client/ConnectionHandler.h Wed Oct 20 08:03:36 
2010
@@ -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"

Modified: qpid/trunk/qpid/cpp/src/tests/sasl.mk
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/sasl.mk?rev=1024541&r1=1024540&r2=1024541&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/sasl.mk (original)
+++ qpid/trunk/qpid/cpp/src/tests/sasl.mk Wed Oct 20 08:03:36 2010
@@ -26,6 +26,7 @@ cluster_authentication_soak_SOURCES=clus
 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

Added: qpid/trunk/qpid/cpp/src/tests/sasl_fed
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/sasl_fed?rev=1024541&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/sasl_fed (added)
+++ qpid/trunk/qpid/cpp/src/tests/sasl_fed Wed Oct 20 08:03:36 2010
@@ -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/z...@localhost:$broker_2_port 
zag/z...@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
+
+
+
+
+
+

Propchange: qpid/trunk/qpid/cpp/src/tests/sasl_fed
------------------------------------------------------------------------------
    svn:executable = *

Modified: qpid/trunk/qpid/tools/src/py/qpid-route
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/tools/src/py/qpid-route?rev=1024541&r1=1024540&r2=1024541&view=diff
==============================================================================
--- qpid/trunk/qpid/tools/src/py/qpid-route (original)
+++ qpid/trunk/qpid/tools/src/py/qpid-route Wed Oct 20 08:03:36 2010
@@ -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()



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:[email protected]

Reply via email to