Author: shuston
Date: Thu Oct 16 15:32:31 2008
New Revision: 705382

URL: http://svn.apache.org/viewvc?rev=705382&view=rev
Log:
Make SaslAuthenticator reimplementable for schemes other than Cyrus, such as 
Windows; resolves QPID-1365

Added:
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/posix/
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/posix/BrokerDefaults.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/windows/
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/windows/BrokerDefaults.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp
Modified:
    incubator/qpid/trunk/qpid/cpp/src/Makefile.am
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.h
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/SaslAuthenticator.h

Modified: incubator/qpid/trunk/qpid/cpp/src/Makefile.am
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/Makefile.am?rev=705382&r1=705381&r2=705382&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/Makefile.am (original)
+++ incubator/qpid/trunk/qpid/cpp/src/Makefile.am Thu Oct 16 15:32:31 2008
@@ -104,6 +104,9 @@
 platform_src = $(posix_plat_src) $(poller)
 platform_hdr = $(posix_plat_hdr)
 
+posix_broker_src = \
+  qpid/broker/posix/BrokerDefaults.cpp
+
 lib_LTLIBRARIES = libqpidcommon.la libqpidbroker.la libqpidclient.la
 
 # Definitions for client and daemon plugins
@@ -288,6 +291,7 @@
 
 libqpidbroker_la_SOURCES = \
   $(mgen_broker_cpp) \
+  $(posix_broker_src) \
   qpid/amqp_0_10/Connection.h \
   qpid/amqp_0_10/Connection.cpp \
   qpid/broker/Broker.cpp \

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp?rev=705382&r1=705381&r2=705382&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp Thu Oct 16 
15:32:31 2008
@@ -19,7 +19,6 @@
  *
  */
 
-#include "config.h"
 #include "Broker.h"
 #include "DirectExchange.h"
 #include "FanOutExchange.h"
@@ -27,6 +26,7 @@
 #include "MessageStoreModule.h"
 #include "NullMessageStore.h"
 #include "RecoveryManagerImpl.h"
+#include "SaslAuthenticator.h"
 #include "TopicExchange.h"
 #include "Link.h"
 
@@ -56,13 +56,6 @@
 #include <memory>
 #include <stdlib.h>
 
-#if HAVE_SASL
-#include <sasl/sasl.h>
-static const bool AUTH_DEFAULT=true;
-#else
-static const bool AUTH_DEFAULT=false;
-#endif
-
 using qpid::sys::ProtocolFactory;
 using qpid::sys::Poller;
 using qpid::sys::Dispatcher;
@@ -89,7 +82,7 @@
     enableMgmt(1),
     mgmtPubInterval(10),
     queueCleanInterval(60*10),//10 minutes
-    auth(AUTH_DEFAULT),
+    auth(SaslAuthenticator::available()),
     realm("QPID"),
     replayFlushLimit(0),
     replayHardLimit(0),
@@ -101,10 +94,10 @@
     char *home = ::getenv("HOME");
 
     if (home == 0)
-        dataDir += "/tmp";
+        dataDir += DEFAULT_DATA_DIR_LOCATION;
     else
         dataDir += home;
-    dataDir += "/.qpidd";
+    dataDir += DEFAULT_DATA_DIR_NAME;
 
     addOptions()
         ("data-dir", optValue(dataDir,"DIR"), "Directory to contain persistent 
data generated by the broker")
@@ -234,17 +227,8 @@
      * SASL setup, can fail and terminate startup
      */
     if (conf.auth) {
-#if HAVE_SASL
-        int code = sasl_server_init(NULL, BROKER_SASL_NAME);
-        if (code != SASL_OK) {
-                // TODO: Figure out who owns the char* returned by
-                // sasl_errstring, though it probably does not matter much
-            throw Exception(sasl_errstring(code, NULL, NULL));
-        }
+        SaslAuthenticator::init(qpid::saslName);
         QPID_LOG(info, "SASL enabled");
-#else
-        throw Exception("Requested authentication but SASL unavailable");
-#endif
     }
 
     // Initialize plugins
@@ -318,11 +302,8 @@
     shutdown();
     finalize();                 // Finalize any plugins.
     delete store;    
-    if (config.auth) {
-#if HAVE_SASL
-        sasl_done();
-#endif
-    }
+    if (config.auth)
+        SaslAuthenticator::fini();
     QPID_LOG(notice, "Shut down");
 }
 

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.h
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.h?rev=705382&r1=705381&r2=705382&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.h Thu Oct 16 15:32:31 
2008
@@ -50,6 +50,7 @@
 #include "AclModule.h"
 
 #include <boost/intrusive_ptr.hpp>
+#include <string>
 #include <vector>
 
 namespace qpid { 
@@ -80,6 +81,9 @@
   public:
 
     struct Options : public qpid::Options {
+        static const std::string DEFAULT_DATA_DIR_LOCATION;
+        static const std::string DEFAULT_DATA_DIR_NAME;
+
         Options(const std::string& name="Broker Options");
 
         bool noDataDir;

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp?rev=705382&r1=705381&r2=705382&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp 
(original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp Thu Oct 
16 15:32:31 2008
@@ -19,7 +19,9 @@
  *
  */
 
-#include "config.h"
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
 
 #include "Connection.h"
 #include "qpid/log/Statement.h"
@@ -66,10 +68,46 @@
     void step(const std::string& response);
 };
 
+bool SaslAuthenticator::available(void)
+{
+    return true;
+}
+
+// Initialize the SASL mechanism; throw if it fails.
+void SaslAuthenticator::init(const std::string& saslName)
+{
+    int code = sasl_server_init(NULL, saslName.c_str());
+    if (code != SASL_OK) {
+        // TODO: Figure out who owns the char* returned by
+        // sasl_errstring, though it probably does not matter much
+        throw Exception(sasl_errstring(code, NULL, NULL));
+    }
+}
+
+void SaslAuthenticator::fini(void)
+{
+    sasl_done();
+}
+
 #else
 
 typedef NullAuthenticator CyrusAuthenticator;
 
+bool SaslAuthenticator::available(void)
+{
+    return false;
+}
+
+void SaslAuthenticator::init(const std::string& /*saslName*/)
+{
+    throw Exception("Requested authentication but SASL unavailable");
+}
+
+void SaslAuthenticator::fini(void)
+{
+    return;
+}
+
 #endif
 
 std::auto_ptr<SaslAuthenticator> 
SaslAuthenticator::createAuthenticator(Connection& c)

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/SaslAuthenticator.h
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/SaslAuthenticator.h?rev=705382&r1=705381&r2=705382&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/SaslAuthenticator.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/SaslAuthenticator.h Thu Oct 
16 15:32:31 2008
@@ -39,6 +39,12 @@
     virtual void start(const std::string& mechanism, const std::string& 
response) = 0;
     virtual void step(const std::string& response) = 0;
 
+    static bool available(void);
+
+    // Initialize the SASL mechanism; throw if it fails.
+    static void init(const std::string& saslName);
+    static void fini(void);
+
     static std::auto_ptr<SaslAuthenticator> createAuthenticator(Connection& 
connection);
 };
 

Added: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/posix/BrokerDefaults.cpp
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/posix/BrokerDefaults.cpp?rev=705382&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/posix/BrokerDefaults.cpp 
(added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/posix/BrokerDefaults.cpp Thu 
Oct 16 15:32:31 2008
@@ -0,0 +1,30 @@
+/*
+ *
+ * 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/broker/Broker.h"
+
+namespace qpid {
+namespace broker {
+
+const std::string Broker::Options::DEFAULT_DATA_DIR_LOCATION("/tmp");
+const std::string Broker::Options::DEFAULT_DATA_DIR_NAME("/.qpidd");
+
+}}

Added: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/windows/BrokerDefaults.cpp
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/windows/BrokerDefaults.cpp?rev=705382&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/windows/BrokerDefaults.cpp 
(added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/windows/BrokerDefaults.cpp 
Thu Oct 16 15:32:31 2008
@@ -0,0 +1,30 @@
+/*
+ *
+ * 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/broker/Broker.h"
+
+namespace qpid {
+namespace broker {
+
+const std::string Broker::Options::DEFAULT_DATA_DIR_LOCATION("\\TEMP");
+const std::string Broker::Options::DEFAULT_DATA_DIR_NAME("\\QPIDD.DATA");
+
+}}

Added: 
incubator/qpid/trunk/qpid/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp?rev=705382&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp 
(added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp 
Thu Oct 16 15:32:31 2008
@@ -0,0 +1,175 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+// This source is only used on Windows; SSPI is the Windows mechanism for
+// accessing authentication mechanisms, analogous to Cyrus SASL.
+
+#include "Connection.h"
+#include "qpid/log/Statement.h"
+#include "qpid/framing/reply_exceptions.h"
+
+#include <windows.h>
+
+using namespace qpid::framing;
+
+namespace qpid {
+namespace broker {
+
+class NullAuthenticator : public SaslAuthenticator
+{
+    Connection& connection;
+    framing::AMQP_ClientProxy::Connection client;
+public:
+    NullAuthenticator(Connection& connection);
+    ~NullAuthenticator();
+    void getMechanisms(framing::Array& mechanisms);
+    void start(const std::string& mechanism, const std::string& response);
+    void step(const std::string&) {}
+};
+
+class SspiAuthenticator : public SaslAuthenticator
+{
+    HANDLE userToken;
+    Connection& connection;
+    framing::AMQP_ClientProxy::Connection client;
+
+public:
+    SspiAuthenticator(Connection& connection);
+    ~SspiAuthenticator();
+    void getMechanisms(framing::Array& mechanisms);
+    void start(const std::string& mechanism, const std::string& response);
+    void step(const std::string& response);
+};
+
+bool SaslAuthenticator::available(void)
+{
+    return true;
+}
+
+// Initialize the SASL mechanism; throw if it fails.
+void SaslAuthenticator::init(const std::string& /*saslName*/)
+{
+    return;
+}
+
+void SaslAuthenticator::fini(void)
+{
+    return;
+}
+
+std::auto_ptr<SaslAuthenticator> 
SaslAuthenticator::createAuthenticator(Connection& c)
+{
+    if (c.getBroker().getOptions().auth) {
+        return std::auto_ptr<SaslAuthenticator>(new SspiAuthenticator(c));
+    } else {
+        return std::auto_ptr<SaslAuthenticator>(new NullAuthenticator(c));
+    }
+}
+
+NullAuthenticator::NullAuthenticator(Connection& c) : connection(c), 
client(c.getOutput()) {}
+NullAuthenticator::~NullAuthenticator() {}
+
+void NullAuthenticator::getMechanisms(Array& mechanisms)
+{
+    mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value("ANONYMOUS")));
+}
+
+void NullAuthenticator::start(const string& mechanism, const string& response)
+{
+    QPID_LOG(warning, "SASL: No Authentication Performed");
+    if (mechanism == "PLAIN") { // Old behavior
+        if (response.size() > 0 && response[0] == (char) 0) {
+            string temp = response.substr(1);
+            string::size_type i = temp.find((char)0);
+            string uid = temp.substr(0, i);
+            string pwd = temp.substr(i + 1);
+            connection.setUserId(uid);
+        }
+    } else {
+        connection.setUserId("anonymous");
+    }   
+    client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0);
+}
+
+
+SspiAuthenticator::SspiAuthenticator(Connection& c) : 
userToken(INVALID_HANDLE_VALUE), connection(c), client(c.getOutput()) 
+{
+}
+
+SspiAuthenticator::~SspiAuthenticator()
+{
+    if (INVALID_HANDLE_VALUE != userToken) {
+        CloseHandle(userToken);
+        userToken = INVALID_HANDLE_VALUE;
+    }
+}
+
+void SspiAuthenticator::getMechanisms(Array& mechanisms)
+{
+    mechanisms.add(boost::shared_ptr<FieldValue>(new 
Str16Value(string("ANONYMOUS"))));
+    mechanisms.add(boost::shared_ptr<FieldValue>(new 
Str16Value(string("PLAIN"))));
+    QPID_LOG(info, "SASL: Mechanism list: ANONYMOUS PLAIN");
+}
+
+void SspiAuthenticator::start(const string& mechanism, const string& response)
+{
+    QPID_LOG(info, "SASL: Starting authentication with mechanism: " << 
mechanism);
+    if (mechanism == "ANONYMOUS") {
+        connection.setUserId("anonymous");
+        client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0);
+        return;
+    }
+    if (mechanism != "PLAIN")
+        throw ConnectionForcedException("Unsupported mechanism");
+
+    // PLAIN's response is composed of 3 strings separated by 0 bytes:
+    // authorization id, authentication id (user), clear-text password.
+    if (response.size() == 0)
+        throw ConnectionForcedException("Authentication failed");
+
+    string::size_type i = response.find((char)0);
+    string auth = response.substr(0, i);
+    string::size_type j = response.find((char)0, i+1);
+    string uid = response.substr(i+1, j-1);
+    string pwd = response.substr(j+1);
+    int error = 0;
+    if (!LogonUser(uid.c_str(), ".", pwd.c_str(),
+                   LOGON32_LOGON_NETWORK,
+                   LOGON32_PROVIDER_DEFAULT,
+                   &userToken))
+        error = GetLastError();
+    pwd.replace(0, string::npos, 1, (char)0);
+    if (error != 0) {
+      QPID_LOG(info,
+               "SASL: Auth failed [" << error << "]: " << 
qpid::sys::strError(error));
+        throw ConnectionForcedException("Authentication failed");
+    }
+
+    connection.setUserId(uid);
+    client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0);
+}
+        
+void SspiAuthenticator::step(const string& response)
+{
+  QPID_LOG(info, "SASL: Need another step!!!");
+}
+
+}}


Reply via email to