summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorGordon Sim <gsim@apache.org>2008-04-14 09:54:16 +0000
committerGordon Sim <gsim@apache.org>2008-04-14 09:54:16 +0000
commitf58096364147d54676f520efc003c58fa7897d0f (patch)
tree2e1954201b139d6cca7beae9f703a46be2cda922 /cpp/src
parent1bf367821416484ebbb14480a5b68d1e6110b4c9 (diff)
downloadqpid-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.cpp37
-rw-r--r--cpp/src/qpid/broker/Broker.h4
-rw-r--r--cpp/src/qpid/broker/PreviewConnection.cpp19
-rw-r--r--cpp/src/qpid/broker/PreviewConnection.h14
-rw-r--r--cpp/src/qpid/broker/PreviewConnectionHandler.cpp57
-rw-r--r--cpp/src/tests/BrokerFixture.h1
-rwxr-xr-xcpp/src/tests/run_federation_tests4
-rwxr-xr-xcpp/src/tests/start_broker2
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