summaryrefslogtreecommitdiff
path: root/qpid/cpp/src
diff options
context:
space:
mode:
authorStephen D. Huston <shuston@apache.org>2008-10-16 22:32:31 +0000
committerStephen D. Huston <shuston@apache.org>2008-10-16 22:32:31 +0000
commit1832f8b41b85cabdf42dc2af36c3e1b15f574325 (patch)
tree05ebb13271037dd5ef29acadfc313fb0d70571da /qpid/cpp/src
parent4aafb6bfb9b51265b58dae045cf5b4b460199275 (diff)
downloadqpid-python-1832f8b41b85cabdf42dc2af36c3e1b15f574325.tar.gz
Make SaslAuthenticator reimplementable for schemes other than Cyrus, such as Windows; resolves QPID-1365
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk@705382 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/cpp/src')
-rw-r--r--qpid/cpp/src/Makefile.am4
-rw-r--r--qpid/cpp/src/qpid/broker/Broker.cpp33
-rw-r--r--qpid/cpp/src/qpid/broker/Broker.h4
-rw-r--r--qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp40
-rw-r--r--qpid/cpp/src/qpid/broker/SaslAuthenticator.h6
-rw-r--r--qpid/cpp/src/qpid/broker/posix/BrokerDefaults.cpp30
-rw-r--r--qpid/cpp/src/qpid/broker/windows/BrokerDefaults.cpp30
-rw-r--r--qpid/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp175
8 files changed, 295 insertions, 27 deletions
diff --git a/qpid/cpp/src/Makefile.am b/qpid/cpp/src/Makefile.am
index c63b98b18d..d0b882e97d 100644
--- a/qpid/cpp/src/Makefile.am
+++ b/qpid/cpp/src/Makefile.am
@@ -104,6 +104,9 @@ endif
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 @@ endif
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 \
diff --git a/qpid/cpp/src/qpid/broker/Broker.cpp b/qpid/cpp/src/qpid/broker/Broker.cpp
index 910c774958..6a308ab64d 100644
--- a/qpid/cpp/src/qpid/broker/Broker.cpp
+++ b/qpid/cpp/src/qpid/broker/Broker.cpp
@@ -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 @@ Broker::Options::Options(const std::string& name) :
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 @@ Broker::Options::Options(const std::string& name) :
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 @@ Broker::Broker(const Broker::Options& conf) :
* 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 @@ Broker::~Broker() {
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");
}
diff --git a/qpid/cpp/src/qpid/broker/Broker.h b/qpid/cpp/src/qpid/broker/Broker.h
index cdb4c4a034..089db69c6b 100644
--- a/qpid/cpp/src/qpid/broker/Broker.h
+++ b/qpid/cpp/src/qpid/broker/Broker.h
@@ -50,6 +50,7 @@
#include "AclModule.h"
#include <boost/intrusive_ptr.hpp>
+#include <string>
#include <vector>
namespace qpid {
@@ -80,6 +81,9 @@ class Broker : public sys::Runnable, public Plugin::Target,
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;
diff --git a/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp b/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp
index 136cf6f785..d0e0d5bead 100644
--- a/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp
+++ b/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp
@@ -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 @@ public:
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)
diff --git a/qpid/cpp/src/qpid/broker/SaslAuthenticator.h b/qpid/cpp/src/qpid/broker/SaslAuthenticator.h
index c2d4ecf7c0..3e277f0527 100644
--- a/qpid/cpp/src/qpid/broker/SaslAuthenticator.h
+++ b/qpid/cpp/src/qpid/broker/SaslAuthenticator.h
@@ -39,6 +39,12 @@ public:
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);
};
diff --git a/qpid/cpp/src/qpid/broker/posix/BrokerDefaults.cpp b/qpid/cpp/src/qpid/broker/posix/BrokerDefaults.cpp
new file mode 100644
index 0000000000..b3ef48fe58
--- /dev/null
+++ b/qpid/cpp/src/qpid/broker/posix/BrokerDefaults.cpp
@@ -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");
+
+}}
diff --git a/qpid/cpp/src/qpid/broker/windows/BrokerDefaults.cpp b/qpid/cpp/src/qpid/broker/windows/BrokerDefaults.cpp
new file mode 100644
index 0000000000..138995980a
--- /dev/null
+++ b/qpid/cpp/src/qpid/broker/windows/BrokerDefaults.cpp
@@ -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");
+
+}}
diff --git a/qpid/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp b/qpid/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp
new file mode 100644
index 0000000000..2cee7d8a99
--- /dev/null
+++ b/qpid/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp
@@ -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!!!");
+}
+
+}}