diff options
| author | Gordon Sim <gsim@apache.org> | 2009-01-06 19:50:59 +0000 |
|---|---|---|
| committer | Gordon Sim <gsim@apache.org> | 2009-01-06 19:50:59 +0000 |
| commit | ccd271e851f2bc2b52a7c8daaa54a06551d63dc0 (patch) | |
| tree | b0ebe5326ee6a15d0d3339c60805920911a77df5 /cpp/src/qpid/broker | |
| parent | 9b18a2b17aaa643001c54d48445ed0d8bb7f2a4c (diff) | |
| download | qpid-python-ccd271e851f2bc2b52a7c8daaa54a06551d63dc0.tar.gz | |
* Cyrus SASL intgeration for c++ client
* SASL security layer support for c++ client and broker
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@732082 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid/broker')
| -rw-r--r-- | cpp/src/qpid/broker/Broker.cpp | 3 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/Connection.cpp | 5 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/Connection.h | 3 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/ConnectionHandler.cpp | 18 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/ConnectionHandler.h | 3 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/SaslAuthenticator.cpp | 62 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/SaslAuthenticator.h | 2 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/SecureConnection.cpp | 87 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/SecureConnection.h | 60 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/SecureConnectionFactory.cpp | 65 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/SecureConnectionFactory.h | 48 |
11 files changed, 347 insertions, 9 deletions
diff --git a/cpp/src/qpid/broker/Broker.cpp b/cpp/src/qpid/broker/Broker.cpp index 64be104b98..37750f8352 100644 --- a/cpp/src/qpid/broker/Broker.cpp +++ b/cpp/src/qpid/broker/Broker.cpp @@ -27,6 +27,7 @@ #include "NullMessageStore.h" #include "RecoveryManagerImpl.h" #include "SaslAuthenticator.h" +#include "SecureConnectionFactory.h" #include "TopicExchange.h" #include "Link.h" @@ -135,7 +136,7 @@ Broker::Broker(const Broker::Options& conf) : acl(0), dataDir(conf.noDataDir ? std::string() : conf.dataDir), links(this), - factory(new ConnectionFactory(*this)), + factory(new SecureConnectionFactory(*this)), dtxManager(timer), sessionManager( qpid::SessionState::Configuration( diff --git a/cpp/src/qpid/broker/Connection.cpp b/cpp/src/qpid/broker/Connection.cpp index f0b9980861..eb54ddfd56 100644 --- a/cpp/src/qpid/broker/Connection.cpp +++ b/cpp/src/qpid/broker/Connection.cpp @@ -267,5 +267,10 @@ Manageable::status_t Connection::ManagementMethod(uint32_t methodId, Args&, stri return status; } +void Connection::setSecureConnection(SecureConnection* s) +{ + adapter.setSecureConnection(s); +} + }} diff --git a/cpp/src/qpid/broker/Connection.h b/cpp/src/qpid/broker/Connection.h index 350ed2c07f..acd9f94d9b 100644 --- a/cpp/src/qpid/broker/Connection.h +++ b/cpp/src/qpid/broker/Connection.h @@ -57,6 +57,7 @@ namespace qpid { namespace broker { class LinkRegistry; +class SecureConnection; class Connection : public sys::ConnectionInputHandler, public ConnectionState, @@ -105,7 +106,7 @@ class Connection : public sys::ConnectionInputHandler, } void sendClose(); - + void setSecureConnection(SecureConnection* secured); private: typedef boost::ptr_map<framing::ChannelId, SessionHandler> ChannelMap; typedef std::vector<Queue::shared_ptr>::iterator queue_iterator; diff --git a/cpp/src/qpid/broker/ConnectionHandler.cpp b/cpp/src/qpid/broker/ConnectionHandler.cpp index 7386ce7229..6f99b60cd8 100644 --- a/cpp/src/qpid/broker/ConnectionHandler.cpp +++ b/cpp/src/qpid/broker/ConnectionHandler.cpp @@ -22,17 +22,20 @@ #include "ConnectionHandler.h" #include "Connection.h" +#include "SecureConnection.h" +#include "qpid/Url.h" #include "qpid/framing/ClientInvoker.h" #include "qpid/framing/ServerInvoker.h" #include "qpid/framing/enum.h" #include "qpid/log/Statement.h" -#include "qpid/Url.h" +#include "qpid/sys/SecurityLayer.h" #include "AclModule.h" #include "qmf/org/apache/qpid/broker/EventClientConnectFail.h" using namespace qpid; using namespace qpid::broker; using namespace qpid::framing; +using qpid::sys::SecurityLayer; namespace _qmf = qmf::org::apache::qpid::broker; namespace @@ -70,11 +73,16 @@ void ConnectionHandler::handle(framing::AMQFrame& frame) } } +void ConnectionHandler::setSecureConnection(SecureConnection* secured) +{ + handler->secured = secured; +} + ConnectionHandler::ConnectionHandler(Connection& connection, bool isClient) : handler(new Handler(connection, isClient)) {} ConnectionHandler::Handler::Handler(Connection& c, bool isClient) : client(c.getOutput()), server(c.getOutput()), - connection(c), serverMode(!isClient), acl(0) + connection(c), serverMode(!isClient), acl(0), secured(0) { if (serverMode) { @@ -160,6 +168,12 @@ void ConnectionHandler::Handler::open(const string& /*virtualHost*/, for (std::vector<Url>::iterator i = urls.begin(); i < urls.end(); ++i) array.add(boost::shared_ptr<Str16Value>(new Str16Value(i->str()))); client.openOk(array); + + //install security layer if one has been negotiated: + if (secured) { + std::auto_ptr<SecurityLayer> sl = authenticator->getSecurityLayer(connection.getFrameMax()); + if (sl.get()) secured->activateSecurityLayer(sl); + } } diff --git a/cpp/src/qpid/broker/ConnectionHandler.h b/cpp/src/qpid/broker/ConnectionHandler.h index d3d5965dfc..6fd252b120 100644 --- a/cpp/src/qpid/broker/ConnectionHandler.h +++ b/cpp/src/qpid/broker/ConnectionHandler.h @@ -40,6 +40,7 @@ namespace qpid { namespace broker { class Connection; +class SecureConnection; class ConnectionHandler : public framing::FrameHandler { @@ -52,6 +53,7 @@ class ConnectionHandler : public framing::FrameHandler bool serverMode; std::auto_ptr<SaslAuthenticator> authenticator; AclModule* acl; + SecureConnection* secured; Handler(Connection& connection, bool isClient); ~Handler(); @@ -87,6 +89,7 @@ class ConnectionHandler : public framing::FrameHandler ConnectionHandler(Connection& connection, bool isClient); void close(framing::connection::CloseCode code, const std::string& text); void handle(framing::AMQFrame& frame); + void setSecureConnection(SecureConnection* secured); }; diff --git a/cpp/src/qpid/broker/SaslAuthenticator.cpp b/cpp/src/qpid/broker/SaslAuthenticator.cpp index 370de8a1d1..9fce1fbbd5 100644 --- a/cpp/src/qpid/broker/SaslAuthenticator.cpp +++ b/cpp/src/qpid/broker/SaslAuthenticator.cpp @@ -30,9 +30,12 @@ #if HAVE_SASL #include <sasl/sasl.h> +#include "qpid/sys/cyrus/CyrusSecurityLayer.h" +using qpid::sys::cyrus::CyrusSecurityLayer; #endif using namespace qpid::framing; +using qpid::sys::SecurityLayer; using boost::format; using boost::str; @@ -46,11 +49,12 @@ class NullAuthenticator : public SaslAuthenticator framing::AMQP_ClientProxy::Connection client; std::string realm; public: - NullAuthenticator(Connection& connection); + NullAuthenticator(Connection& connection, bool dummy=false/*dummy arg to match CyrusAuthenticator*/); ~NullAuthenticator(); void getMechanisms(framing::Array& mechanisms); void start(const std::string& mechanism, const std::string& response); void step(const std::string&) {} + std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize); }; #if HAVE_SASL @@ -60,11 +64,12 @@ class CyrusAuthenticator : public SaslAuthenticator sasl_conn_t *sasl_conn; Connection& connection; framing::AMQP_ClientProxy::Connection client; + const bool encrypt; void processAuthenticationStep(int code, const char *challenge, unsigned int challenge_len); public: - CyrusAuthenticator(Connection& connection); + CyrusAuthenticator(Connection& connection, bool encrypt); ~CyrusAuthenticator(); void init(); void getMechanisms(framing::Array& mechanisms); @@ -72,6 +77,7 @@ public: void step(const std::string& response); void getUid(std::string& uid); void getError(std::string& error); + std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize); }; bool SaslAuthenticator::available(void) @@ -120,7 +126,7 @@ std::auto_ptr<SaslAuthenticator> SaslAuthenticator::createAuthenticator(Connecti { static bool needWarning = true; if (c.getBroker().getOptions().auth) { - return std::auto_ptr<SaslAuthenticator>(new CyrusAuthenticator(c)); + return std::auto_ptr<SaslAuthenticator>(new CyrusAuthenticator(c, c.getBroker().getOptions().requireEncrypted)); } else { QPID_LOG(warning, "SASL: No Authentication Performed"); needWarning = false; @@ -128,7 +134,7 @@ std::auto_ptr<SaslAuthenticator> SaslAuthenticator::createAuthenticator(Connecti } } -NullAuthenticator::NullAuthenticator(Connection& c) : connection(c), client(c.getOutput()), + NullAuthenticator::NullAuthenticator(Connection& c, bool /*dummy*/) : connection(c), client(c.getOutput()), realm(c.getBroker().getOptions().realm) {} NullAuthenticator::~NullAuthenticator() {} @@ -158,9 +164,18 @@ void NullAuthenticator::start(const string& mechanism, const string& response) } +std::auto_ptr<SecurityLayer> NullAuthenticator::getSecurityLayer(uint16_t) +{ + std::auto_ptr<SecurityLayer> securityLayer; + return securityLayer; +} + + #if HAVE_SASL -CyrusAuthenticator::CyrusAuthenticator(Connection& c) : sasl_conn(0), connection(c), client(c.getOutput()) + +CyrusAuthenticator::CyrusAuthenticator(Connection& c, bool _encrypt) : + sasl_conn(0), connection(c), client(c.getOutput()), encrypt(_encrypt) { init(); } @@ -196,6 +211,25 @@ void CyrusAuthenticator::init() // server error, when one is available throw ConnectionForcedException("Unable to perform authentication"); } + + sasl_security_properties_t secprops; + + //TODO: should the actual SSF values be configurable here? + secprops.min_ssf = encrypt ? 10: 0; + secprops.max_ssf = 256; + secprops.maxbufsize = 65535; + + QPID_LOG(debug, "min_ssf: " << secprops.min_ssf << ", max_ssf: " << secprops.max_ssf); + + secprops.property_names = 0; + secprops.property_values = 0; + secprops.security_flags = 0; /* or SASL_SEC_NOANONYMOUS etc as appropriate */ + + int result = sasl_setprop(sasl_conn, SASL_SEC_PROPS, &secprops); + if (result != SASL_OK) { + throw framing::InternalErrorException(QPID_MSG("SASL error: " << result)); + } + } CyrusAuthenticator::~CyrusAuthenticator() @@ -332,6 +366,24 @@ void CyrusAuthenticator::processAuthenticationStep(int code, const char *challen } } } + +std::auto_ptr<SecurityLayer> CyrusAuthenticator::getSecurityLayer(uint16_t maxFrameSize) +{ + + const void* value(0); + int result = sasl_getprop(sasl_conn, SASL_SSF, &value); + if (result != SASL_OK) { + throw framing::InternalErrorException(QPID_MSG("SASL error: " << sasl_errdetail(sasl_conn))); + } + uint ssf = *(reinterpret_cast<const unsigned*>(value)); + std::auto_ptr<SecurityLayer> securityLayer; + if (ssf) { + QPID_LOG(info, "Installing security layer, SSF: "<< ssf); + securityLayer = std::auto_ptr<SecurityLayer>(new CyrusSecurityLayer(sasl_conn, maxFrameSize)); + } + return securityLayer; +} + #endif }} diff --git a/cpp/src/qpid/broker/SaslAuthenticator.h b/cpp/src/qpid/broker/SaslAuthenticator.h index 2598b6d177..8ddaeb19a4 100644 --- a/cpp/src/qpid/broker/SaslAuthenticator.h +++ b/cpp/src/qpid/broker/SaslAuthenticator.h @@ -24,6 +24,7 @@ #include "qpid/framing/amqp_types.h" #include "qpid/framing/AMQP_ClientProxy.h" #include "qpid/Exception.h" +#include "qpid/sys/SecurityLayer.h" #include <memory> namespace qpid { @@ -40,6 +41,7 @@ public: virtual void step(const std::string& response) = 0; virtual void getUid(std::string&) {} virtual void getError(std::string&) {} + virtual std::auto_ptr<qpid::sys::SecurityLayer> getSecurityLayer(uint16_t maxFrameSize) = 0; static bool available(void); diff --git a/cpp/src/qpid/broker/SecureConnection.cpp b/cpp/src/qpid/broker/SecureConnection.cpp new file mode 100644 index 0000000000..4a9946e176 --- /dev/null +++ b/cpp/src/qpid/broker/SecureConnection.cpp @@ -0,0 +1,87 @@ +/* + * + * 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 "SecureConnection.h" +#include "qpid/sys/SecurityLayer.h" +#include "qpid/framing/reply_exceptions.h" + +namespace qpid { +namespace broker { + +using qpid::sys::SecurityLayer; + +SecureConnection::SecureConnection() : secured(false) {} + +size_t SecureConnection::decode(const char* buffer, size_t size) +{ + if (!secured && securityLayer.get()) { + //security layer comes into effect on first read after its + //activated + secured = true; + } + if (secured) { + return securityLayer->decode(buffer, size); + } else { + return codec->decode(buffer, size); + } +} + +size_t SecureConnection::encode(const char* buffer, size_t size) +{ + if (secured) { + return securityLayer->encode(buffer, size); + } else { + return codec->encode(buffer, size); + } +} + +bool SecureConnection::canEncode() +{ + if (secured) return securityLayer->canEncode(); + else return codec->canEncode(); +} + +void SecureConnection::closed() +{ + codec->closed(); +} + +bool SecureConnection::isClosed() const +{ + return codec->isClosed(); +} + +framing::ProtocolVersion SecureConnection::getVersion() const +{ + return codec->getVersion(); +} + +void SecureConnection:: setCodec(std::auto_ptr<ConnectionCodec> c) +{ + codec = c; +} + +void SecureConnection::activateSecurityLayer(std::auto_ptr<SecurityLayer> sl) +{ + securityLayer = sl; + securityLayer->init(codec.get()); +} + +}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SecureConnection.h b/cpp/src/qpid/broker/SecureConnection.h new file mode 100644 index 0000000000..4a0cc50e34 --- /dev/null +++ b/cpp/src/qpid/broker/SecureConnection.h @@ -0,0 +1,60 @@ +#ifndef QPID_BROKER_SECURECONNECTION_H +#define QPID_BROKER_SECURECONNECTION_H + +/* + * + * 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/sys/ConnectionCodec.h" +#include <memory> + +namespace qpid { + +namespace sys { +class SecurityLayer; +} + +namespace broker { + +/** + * A ConnectionCodec 'wrapper' that allows a connection to be + * 'secured' e.g. encrypted based on settings negotiatiated at the + * time of establishment. + */ +class SecureConnection : public qpid::sys::ConnectionCodec +{ + public: + SecureConnection(); + size_t decode(const char* buffer, size_t size); + size_t encode(const char* buffer, size_t size); + bool canEncode(); + void closed(); + bool isClosed() const; + framing::ProtocolVersion getVersion() const; + void setCodec(std::auto_ptr<ConnectionCodec>); + void activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer>); + private: + std::auto_ptr<ConnectionCodec> codec; + std::auto_ptr<qpid::sys::SecurityLayer> securityLayer; + bool secured; +}; +}} // namespace qpid::broker + +#endif /*!QPID_BROKER_SECURECONNECTION_H*/ diff --git a/cpp/src/qpid/broker/SecureConnectionFactory.cpp b/cpp/src/qpid/broker/SecureConnectionFactory.cpp new file mode 100644 index 0000000000..38fd96bcba --- /dev/null +++ b/cpp/src/qpid/broker/SecureConnectionFactory.cpp @@ -0,0 +1,65 @@ +/* + * + * 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 "SecureConnectionFactory.h" +#include "qpid/framing/ProtocolVersion.h" +#include "qpid/amqp_0_10/Connection.h" +#include "qpid/broker/Connection.h" +#include "qpid/broker/SecureConnection.h" + +namespace qpid { +namespace broker { + +using framing::ProtocolVersion; +typedef std::auto_ptr<amqp_0_10::Connection> CodecPtr; +typedef std::auto_ptr<SecureConnection> SecureConnectionPtr; +typedef std::auto_ptr<Connection> ConnectionPtr; +typedef std::auto_ptr<sys::ConnectionInputHandler> InputPtr; + +SecureConnectionFactory::SecureConnectionFactory(Broker& b) : broker(b) {} + +sys::ConnectionCodec* +SecureConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, const std::string& id) { + if (v == ProtocolVersion(0, 10)) { + SecureConnectionPtr sc(new SecureConnection()); + CodecPtr c(new amqp_0_10::Connection(out, id, false)); + ConnectionPtr i(new broker::Connection(c.get(), broker, id, false)); + i->setSecureConnection(sc.get()); + c->setInputHandler(InputPtr(i.release())); + sc->setCodec(std::auto_ptr<sys::ConnectionCodec>(c)); + return sc.release(); + } + return 0; +} + +sys::ConnectionCodec* +SecureConnectionFactory::create(sys::OutputControl& out, const std::string& id) { + // used to create connections from one broker to another + SecureConnectionPtr sc(new SecureConnection()); + CodecPtr c(new amqp_0_10::Connection(out, id, true)); + ConnectionPtr i(new broker::Connection(c.get(), broker, id, true)); + i->setSecureConnection(sc.get()); + c->setInputHandler(InputPtr(i.release())); + sc->setCodec(std::auto_ptr<sys::ConnectionCodec>(c)); + return sc.release(); +} + + +}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SecureConnectionFactory.h b/cpp/src/qpid/broker/SecureConnectionFactory.h new file mode 100644 index 0000000000..048fb250d6 --- /dev/null +++ b/cpp/src/qpid/broker/SecureConnectionFactory.h @@ -0,0 +1,48 @@ +/* + * + * 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. + * + */ +#ifndef _SecureConnectionFactory_ +#define _SecureConnectionFactory_ + +#include "qpid/sys/ConnectionCodec.h" + +namespace qpid { +namespace broker { +class Broker; + +class SecureConnectionFactory : public sys::ConnectionCodec::Factory +{ + public: + SecureConnectionFactory(Broker& b); + + sys::ConnectionCodec* + create(framing::ProtocolVersion, sys::OutputControl&, const std::string& id); + + sys::ConnectionCodec* + create(sys::OutputControl&, const std::string& id); + + private: + Broker& broker; +}; + +}} + + +#endif |
