diff options
author | Gordon Sim <gsim@apache.org> | 2008-04-14 09:54:16 +0000 |
---|---|---|
committer | Gordon Sim <gsim@apache.org> | 2008-04-14 09:54:16 +0000 |
commit | f58096364147d54676f520efc003c58fa7897d0f (patch) | |
tree | 2e1954201b139d6cca7beae9f703a46be2cda922 /cpp/src | |
parent | 1bf367821416484ebbb14480a5b68d1e6110b4c9 (diff) | |
download | qpid-python-f58096364147d54676f520efc003c58fa7897d0f.tar.gz |
QPID-648: Initial support for sasl authentication for c++ broker. From patch submitted by mfarrellee@redhat.com.
Authentication is optional at compile time (based on user selection or availability of cyrus sasl libs) and at
runtime (through broker config option). Note: At present the runtime default is to not authenticate; this is a
temporary measure to give some time for any automation scripts etc to be updated and will revert shortly to be
on by default.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@647716 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/qpid/broker/Broker.cpp | 37 | ||||
-rw-r--r-- | cpp/src/qpid/broker/Broker.h | 4 | ||||
-rw-r--r-- | cpp/src/qpid/broker/PreviewConnection.cpp | 19 | ||||
-rw-r--r-- | cpp/src/qpid/broker/PreviewConnection.h | 14 | ||||
-rw-r--r-- | cpp/src/qpid/broker/PreviewConnectionHandler.cpp | 57 | ||||
-rw-r--r-- | cpp/src/tests/BrokerFixture.h | 1 | ||||
-rwxr-xr-x | cpp/src/tests/run_federation_tests | 4 | ||||
-rwxr-xr-x | cpp/src/tests/start_broker | 2 |
8 files changed, 132 insertions, 6 deletions
diff --git a/cpp/src/qpid/broker/Broker.cpp b/cpp/src/qpid/broker/Broker.cpp index d834399180..b9268db9e5 100644 --- a/cpp/src/qpid/broker/Broker.cpp +++ b/cpp/src/qpid/broker/Broker.cpp @@ -48,6 +48,10 @@ #include <iostream> #include <memory> +#if HAVE_SASL +#include <sasl/sasl.h> +#endif + using qpid::sys::Acceptor; using qpid::framing::FrameHandler; using qpid::framing::ChannelId; @@ -71,6 +75,15 @@ Broker::Options::Options(const std::string& name) : stagingThreshold(5000000), enableMgmt(1), mgmtPubInterval(10), +#if HAVE_SASL + //Authentication disabled by default for now to allow any + //scripts etc that might fail authentication to be updated. + //Note that this is a temporary measure (GS 14-APR-2008). + auth(false), + //auth(true), +#else + auth(false), +#endif ack(0) { int c = sys::SystemInfo::concurrency(); @@ -94,6 +107,8 @@ Broker::Options::Options(const std::string& name) : "Enable Management") ("mgmt-pub-interval", optValue(mgmtPubInterval, "SECONDS"), "Management Publish Interval") + ("auth", optValue(auth, "yes|no"), + "Enable authentication, if disabled all incoming connections will be trusted") ("ack", optValue(ack, "N"), "Send session.ack/solicit-ack at least every N frames. 0 disables voluntary ack/solitict-ack"); } @@ -184,6 +199,23 @@ Broker::Broker(const Broker::Options& conf) : else QPID_LOG(info, "Management not enabled"); + /** + * 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)); + } + QPID_LOG(info, "SASL enabled"); +#else + throw Exception("Requested authentication but SASL unavailable"); +#endif + } + // Initialize plugins for (Plugin::Plugins::const_iterator i = plugins.begin(); i != plugins.end(); @@ -236,6 +268,11 @@ Broker::~Broker() { shutdown(); ManagementAgent::shutdown (); delete store; + if (config.auth) { +#if HAVE_SASL + sasl_done(); +#endif + } } uint16_t Broker::getPort() const { return getAcceptor().getPort(); } diff --git a/cpp/src/qpid/broker/Broker.h b/cpp/src/qpid/broker/Broker.h index 481191eb55..8d39c6005d 100644 --- a/cpp/src/qpid/broker/Broker.h +++ b/cpp/src/qpid/broker/Broker.h @@ -22,6 +22,8 @@ * */ +#include "config.h" + #include "ConnectionFactory.h" #include "ConnectionToken.h" #include "DirectExchange.h" @@ -76,6 +78,7 @@ class Broker : public sys::Runnable, public Plugin::Target, uint64_t stagingThreshold; bool enableMgmt; uint16_t mgmtPubInterval; + bool auth; uint32_t ack; }; @@ -109,6 +112,7 @@ class Broker : public sys::Runnable, public Plugin::Target, uint64_t getStagingThreshold() { return config.stagingThreshold; } DtxManager& getDtxManager() { return dtxManager; } DataDir& getDataDir() { return dataDir; } + Options& getOptions() { return config; } SessionManager& getSessionManager() { return sessionManager; } PreviewSessionManager& getPreviewSessionManager() { return previewSessionManager; } diff --git a/cpp/src/qpid/broker/PreviewConnection.cpp b/cpp/src/qpid/broker/PreviewConnection.cpp index 8901aa9f9d..6f411c99d6 100644 --- a/cpp/src/qpid/broker/PreviewConnection.cpp +++ b/cpp/src/qpid/broker/PreviewConnection.cpp @@ -18,6 +18,9 @@ * under the License. * */ + +#include "config.h" + #include "PreviewConnection.h" #include "SessionState.h" #include "BrokerAdapter.h" @@ -36,6 +39,10 @@ #include <iostream> #include <assert.h> +#if HAVE_SASL +#include <sasl/sasl.h> +#endif + using namespace boost; using namespace qpid::sys; using namespace qpid::framing; @@ -87,6 +94,9 @@ public: PreviewConnection::PreviewConnection(ConnectionOutputHandler* out_, Broker& broker_, const std::string& mgmtId_, bool isLink) : ConnectionState(out_, broker_), +#if HAVE_SASL + sasl_conn(NULL), +#endif adapter(*this, isLink), mgmtClosing(false), mgmtId(mgmtId_) @@ -108,7 +118,14 @@ PreviewConnection::PreviewConnection(ConnectionOutputHandler* out_, Broker& brok } } -PreviewConnection::~PreviewConnection () {} +PreviewConnection::~PreviewConnection () { +#if HAVE_LIBSASL2 + if (NULL != sasl_conn) { + sasl_dispose(&sasl_conn); + sasl_conn = NULL; + } +#endif +} void PreviewConnection::received(framing::AMQFrame& frame){ if (mgmtClosing) diff --git a/cpp/src/qpid/broker/PreviewConnection.h b/cpp/src/qpid/broker/PreviewConnection.h index 89b9907715..c9e8b115d3 100644 --- a/cpp/src/qpid/broker/PreviewConnection.h +++ b/cpp/src/qpid/broker/PreviewConnection.h @@ -21,6 +21,8 @@ #ifndef _PreviewConnection_ #define _PreviewConnection_ +#include "config.h" + #include <memory> #include <sstream> #include <vector> @@ -47,11 +49,19 @@ #include <boost/ptr_container/ptr_map.hpp> +#if HAVE_SASL +#include <sasl/sasl.h> +#endif + namespace qpid { namespace broker { class PreviewConnection : public sys::ConnectionInputHandler, public ConnectionState { +#if HAVE_SASL + friend class PreviewConnectionHandler; +#endif + public: PreviewConnection(sys::ConnectionOutputHandler* out, Broker& broker, const std::string& mgmtId, bool isLink = false); ~PreviewConnection (); @@ -76,6 +86,10 @@ class PreviewConnection : public sys::ConnectionInputHandler, public ConnectionS management::Manageable::status_t ManagementMethod (uint32_t methodId, management::Args& args); + protected: +#if HAVE_SASL + sasl_conn_t *sasl_conn; +#endif private: typedef boost::ptr_map<framing::ChannelId, PreviewSessionHandler> ChannelMap; diff --git a/cpp/src/qpid/broker/PreviewConnectionHandler.cpp b/cpp/src/qpid/broker/PreviewConnectionHandler.cpp index 78ea2f5523..5c5f2f263e 100644 --- a/cpp/src/qpid/broker/PreviewConnectionHandler.cpp +++ b/cpp/src/qpid/broker/PreviewConnectionHandler.cpp @@ -20,11 +20,18 @@ * */ +#include "config.h" + #include "PreviewConnectionHandler.h" #include "PreviewConnection.h" #include "qpid/framing/ConnectionStartBody.h" #include "qpid/framing/ClientInvoker.h" #include "qpid/framing/ServerInvoker.h" +#include "qpid/log/Statement.h" + +#if HAVE_SASL +#include <sasl/sasl.h> +#endif using namespace qpid; using namespace qpid::broker; @@ -81,15 +88,61 @@ void PreviewConnectionHandler::Handler::startOk(const framing::FieldTable& /*cli { //TODO: handle SASL mechanisms more cleverly if (mechanism == PLAIN) { + QPID_LOG(info, "SASL Plain: Attempting authentication"); 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); - //TODO: authentication + +#if HAVE_SASL + if (connection.getBroker().getOptions().auth) { + int code = sasl_server_new(BROKER_SASL_NAME, + NULL, NULL, NULL, NULL, NULL, 0, + &connection.sasl_conn); + + if (SASL_OK != code) { + QPID_LOG(info, "SASL Plain: Connection creation failed: " + << sasl_errdetail(connection.sasl_conn)); + + // TODO: Change this to an exception signaling + // server error, when one is available + throw CommandInvalidException("Unable to perform authentication"); + } + + code = sasl_checkpass(connection.sasl_conn, + uid.c_str(), uid.length(), + pwd.c_str(), pwd.length()); + if (SASL_OK == code) { + QPID_LOG(info, "SASL Plain: Authentication accepted for " << uid); + } else { + // See man sasl_errors(3) or sasl/sasl.h for possible errors + QPID_LOG(info, "SASL Plain: Authentication rejected for " + << uid << ": " + << sasl_errdetail(connection.sasl_conn)); + + // TODO: Change this to an exception signaling + // authentication failure, when one is available + throw ConnectionForcedException("Authentication failed"); + } + } else { +#endif + QPID_LOG(warning, + "SASL Plain Warning: No Authentication Performed for " + << uid); +#if HAVE_SASL + } +#endif + connection.setUserId(uid); } - } + } else { + // The 0-10 spec states that if the client requests a + // mechanism not proposed by the server the server MUST + // close the connection. Assumption here is if we proposed + // a mechanism we'd have a case for it above. + throw NotImplementedException("Unsupported authentication mechanism"); + } client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), connection.getHeartbeat()); } diff --git a/cpp/src/tests/BrokerFixture.h b/cpp/src/tests/BrokerFixture.h index fd350b77fe..83b3f621c7 100644 --- a/cpp/src/tests/BrokerFixture.h +++ b/cpp/src/tests/BrokerFixture.h @@ -47,6 +47,7 @@ struct BrokerFixture { opts.enableMgmt=false; opts.workerThreads=1; opts.dataDir=""; + opts.auth=false; broker = Broker::create(opts); // TODO aconway 2007-12-05: At one point BrokerFixture // tests could hang in Connection ctor if the following diff --git a/cpp/src/tests/run_federation_tests b/cpp/src/tests/run_federation_tests index 63f0baa1ae..1f5917af0e 100755 --- a/cpp/src/tests/run_federation_tests +++ b/cpp/src/tests/run_federation_tests @@ -4,9 +4,9 @@ trap stop_brokers EXIT start_brokers() { - ../qpidd --daemon --port 0 --no-data-dir > qpidd.port + ../qpidd --daemon --port 0 --no-data-dir --auth no > qpidd.port LOCAL_PORT=`cat qpidd.port` - ../qpidd --daemon --port 0 --no-data-dir > qpidd.port + ../qpidd --daemon --port 0 --no-data-dir --auth no > qpidd.port REMOTE_PORT=`cat qpidd.port` } diff --git a/cpp/src/tests/start_broker b/cpp/src/tests/start_broker index 0d4352644b..7d5cb7d73d 100755 --- a/cpp/src/tests/start_broker +++ b/cpp/src/tests/start_broker @@ -1,4 +1,4 @@ #!/bin/sh rm -f qpidd.vglog qpidd.log test -n "$VALGRIND" && VALGRIND="$VALGRIND --log-file-exactly=qpidd.vglog --" -exec libtool --mode=execute $VALGRIND ../qpidd --daemon --port 0 --log-output qpidd.log "$@" > qpidd.port +exec libtool --mode=execute $VALGRIND ../qpidd --auth no --daemon --port 0 --log-output qpidd.log "$@" > qpidd.port |