diff options
author | Stephen D. Huston <shuston@apache.org> | 2008-10-16 22:32:31 +0000 |
---|---|---|
committer | Stephen D. Huston <shuston@apache.org> | 2008-10-16 22:32:31 +0000 |
commit | 1832f8b41b85cabdf42dc2af36c3e1b15f574325 (patch) | |
tree | 05ebb13271037dd5ef29acadfc313fb0d70571da /qpid/cpp/src | |
parent | 4aafb6bfb9b51265b58dae045cf5b4b460199275 (diff) | |
download | qpid-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.am | 4 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/broker/Broker.cpp | 33 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/broker/Broker.h | 4 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp | 40 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/broker/SaslAuthenticator.h | 6 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/broker/posix/BrokerDefaults.cpp | 30 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/broker/windows/BrokerDefaults.cpp | 30 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp | 175 |
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!!!"); +} + +}} |