diff options
Diffstat (limited to 'cpp/src')
29 files changed, 168 insertions, 54 deletions
diff --git a/cpp/src/qpid/broker/Connection.cpp b/cpp/src/qpid/broker/Connection.cpp index 824a2ee75d..7aa632c5a5 100644 --- a/cpp/src/qpid/broker/Connection.cpp +++ b/cpp/src/qpid/broker/Connection.cpp @@ -71,8 +71,9 @@ struct ConnectionTimeoutTask : public sys::TimerTask { } }; -Connection::Connection(ConnectionOutputHandler* out_, Broker& broker_, const std::string& mgmtId_, bool isLink_, uint64_t objectId) : +Connection::Connection(ConnectionOutputHandler* out_, Broker& broker_, const std::string& mgmtId_, unsigned int ssf, bool isLink_, uint64_t objectId) : ConnectionState(out_, broker_), + ssf(ssf), adapter(*this, isLink_), isLink(isLink_), mgmtClosing(false), diff --git a/cpp/src/qpid/broker/Connection.h b/cpp/src/qpid/broker/Connection.h index 42409969b9..66ede59df5 100644 --- a/cpp/src/qpid/broker/Connection.h +++ b/cpp/src/qpid/broker/Connection.h @@ -78,7 +78,8 @@ class Connection : public sys::ConnectionInputHandler, virtual void connectionError(const std::string&) = 0; }; - Connection(sys::ConnectionOutputHandler* out, Broker& broker, const std::string& mgmtId, bool isLink = false, uint64_t objectId = 0); + Connection(sys::ConnectionOutputHandler* out, Broker& broker, const std::string& mgmtId, unsigned int ssf, + bool isLink = false, uint64_t objectId = 0); ~Connection (); /** Get the SessionHandler for channel. Create if it does not already exist */ @@ -138,11 +139,14 @@ class Connection : public sys::ConnectionInputHandler, // Used by cluster to update connection status sys::AggregateOutput& getOutputTasks() { return outputTasks; } + unsigned int getSSF() { return ssf; } + private: typedef boost::ptr_map<framing::ChannelId, SessionHandler> ChannelMap; typedef std::vector<Queue::shared_ptr>::iterator queue_iterator; ChannelMap channels; + unsigned int ssf; ConnectionHandler adapter; const bool isLink; bool mgmtClosing; diff --git a/cpp/src/qpid/broker/ConnectionFactory.cpp b/cpp/src/qpid/broker/ConnectionFactory.cpp index 93108b35f7..dd794d7d95 100644 --- a/cpp/src/qpid/broker/ConnectionFactory.cpp +++ b/cpp/src/qpid/broker/ConnectionFactory.cpp @@ -35,7 +35,8 @@ ConnectionFactory::ConnectionFactory(Broker& b) : broker(b) {} ConnectionFactory::~ConnectionFactory() {} sys::ConnectionCodec* -ConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, const std::string& id) { +ConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, const std::string& id, + unsigned int ) { if (v == ProtocolVersion(0, 10)) { ConnectionPtr c(new amqp_0_10::Connection(out, id, false)); c->setInputHandler(InputPtr(new broker::Connection(c.get(), broker, id, false))); @@ -45,7 +46,8 @@ ConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, const std: } sys::ConnectionCodec* -ConnectionFactory::create(sys::OutputControl& out, const std::string& id) { +ConnectionFactory::create(sys::OutputControl& out, const std::string& id, + unsigned int) { // used to create connections from one broker to another ConnectionPtr c(new amqp_0_10::Connection(out, id, true)); c->setInputHandler(InputPtr(new broker::Connection(c.get(), broker, id, true))); diff --git a/cpp/src/qpid/broker/ConnectionFactory.h b/cpp/src/qpid/broker/ConnectionFactory.h index c61da81024..d812292ad1 100644 --- a/cpp/src/qpid/broker/ConnectionFactory.h +++ b/cpp/src/qpid/broker/ConnectionFactory.h @@ -35,10 +35,12 @@ class ConnectionFactory : public sys::ConnectionCodec::Factory virtual ~ConnectionFactory(); sys::ConnectionCodec* - create(framing::ProtocolVersion, sys::OutputControl&, const std::string& id); + create(framing::ProtocolVersion, sys::OutputControl&, const std::string& id, + unsigned int conn_ssf); sys::ConnectionCodec* - create(sys::OutputControl&, const std::string& id); + create(sys::OutputControl&, const std::string& id, + unsigned int conn_ssf); private: Broker& broker; diff --git a/cpp/src/qpid/broker/SaslAuthenticator.cpp b/cpp/src/qpid/broker/SaslAuthenticator.cpp index 7e7334fda1..0e509c8d93 100644 --- a/cpp/src/qpid/broker/SaslAuthenticator.cpp +++ b/cpp/src/qpid/broker/SaslAuthenticator.cpp @@ -48,8 +48,9 @@ class NullAuthenticator : public SaslAuthenticator Connection& connection; framing::AMQP_ClientProxy::Connection client; std::string realm; + const bool encrypt; public: - NullAuthenticator(Connection& connection, bool dummy=false/*dummy arg to match CyrusAuthenticator*/); + NullAuthenticator(Connection& connection, bool encrypt); ~NullAuthenticator(); void getMechanisms(framing::Array& mechanisms); void start(const std::string& mechanism, const std::string& response); @@ -130,12 +131,12 @@ std::auto_ptr<SaslAuthenticator> SaslAuthenticator::createAuthenticator(Connecti } else { QPID_LOG(debug, "SASL: No Authentication Performed"); needWarning = false; - return std::auto_ptr<SaslAuthenticator>(new NullAuthenticator(c)); + return std::auto_ptr<SaslAuthenticator>(new NullAuthenticator(c, c.getBroker().getOptions().requireEncrypted)); } } - NullAuthenticator::NullAuthenticator(Connection& c, bool /*dummy*/) : connection(c), client(c.getOutput()), - realm(c.getBroker().getOptions().realm) {} +NullAuthenticator::NullAuthenticator(Connection& c, bool e) : connection(c), client(c.getOutput()), + realm(c.getBroker().getOptions().realm), encrypt(e) {} NullAuthenticator::~NullAuthenticator() {} void NullAuthenticator::getMechanisms(Array& mechanisms) @@ -146,6 +147,10 @@ void NullAuthenticator::getMechanisms(Array& mechanisms) void NullAuthenticator::start(const string& mechanism, const string& response) { + if (encrypt) { + QPID_LOG(error, "Rejected un-encrypted connection."); + throw ConnectionForcedException("Connection must be encrypted."); + } if (mechanism == "PLAIN") { // Old behavior if (response.size() > 0) { string uid; @@ -227,10 +232,24 @@ void CyrusAuthenticator::init() //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); - + // If the transport provides encryption, notify the SASL library of + // the key length and set the ssf range to prevent double encryption. + sasl_ssf_t external_ssf = (sasl_ssf_t) connection.getSSF(); + if (external_ssf) { + int result = sasl_setprop(sasl_conn, SASL_SSF_EXTERNAL, &external_ssf); + if (result != SASL_OK) { + throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external SSF: " << result)); + } + + secprops.max_ssf = secprops.min_ssf = 0; + } + + QPID_LOG(debug, "min_ssf: " << secprops.min_ssf << + ", max_ssf: " << secprops.max_ssf << + ", external_ssf: " << external_ssf ); + + secprops.maxbufsize = 65535; secprops.property_names = 0; secprops.property_values = 0; secprops.security_flags = 0; /* or SASL_SEC_NOANONYMOUS etc as appropriate */ diff --git a/cpp/src/qpid/broker/SecureConnectionFactory.cpp b/cpp/src/qpid/broker/SecureConnectionFactory.cpp index e1f003cb1c..4926851f95 100644 --- a/cpp/src/qpid/broker/SecureConnectionFactory.cpp +++ b/cpp/src/qpid/broker/SecureConnectionFactory.cpp @@ -36,11 +36,12 @@ 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) { +SecureConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, const std::string& id, + unsigned int conn_ssf ) { 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)); + ConnectionPtr i(new broker::Connection(c.get(), broker, id, conn_ssf, false)); i->setSecureConnection(sc.get()); c->setInputHandler(InputPtr(i.release())); sc->setCodec(std::auto_ptr<sys::ConnectionCodec>(c)); @@ -50,11 +51,12 @@ SecureConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, cons } sys::ConnectionCodec* -SecureConnectionFactory::create(sys::OutputControl& out, const std::string& id) { +SecureConnectionFactory::create(sys::OutputControl& out, const std::string& id, + unsigned int conn_ssf) { // 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)); + ConnectionPtr i(new broker::Connection(c.get(), broker, id, conn_ssf, true )); i->setSecureConnection(sc.get()); c->setInputHandler(InputPtr(i.release())); sc->setCodec(std::auto_ptr<sys::ConnectionCodec>(c)); diff --git a/cpp/src/qpid/broker/SecureConnectionFactory.h b/cpp/src/qpid/broker/SecureConnectionFactory.h index 048fb250d6..b1af6d4a0f 100644 --- a/cpp/src/qpid/broker/SecureConnectionFactory.h +++ b/cpp/src/qpid/broker/SecureConnectionFactory.h @@ -33,10 +33,12 @@ class SecureConnectionFactory : public sys::ConnectionCodec::Factory SecureConnectionFactory(Broker& b); sys::ConnectionCodec* - create(framing::ProtocolVersion, sys::OutputControl&, const std::string& id); + create(framing::ProtocolVersion, sys::OutputControl&, const std::string& id, + unsigned int conn_ssf); sys::ConnectionCodec* - create(sys::OutputControl&, const std::string& id); + create(sys::OutputControl&, const std::string& id, + unsigned int conn_ssf); private: Broker& broker; diff --git a/cpp/src/qpid/client/ConnectionHandler.cpp b/cpp/src/qpid/client/ConnectionHandler.cpp index bb348675c6..8f1cc7b03f 100644 --- a/cpp/src/qpid/client/ConnectionHandler.cpp +++ b/cpp/src/qpid/client/ConnectionHandler.cpp @@ -212,7 +212,8 @@ void ConnectionHandler::start(const FieldTable& /*serverProps*/, const Array& me } if (sasl.get()) { - string response = sasl->start(mechanism.empty() ? mechlist : mechanism); + string response = sasl->start(mechanism.empty() ? mechlist : mechanism, + getSSF ? getSSF() : 0); proxy.startOk(properties, sasl->getMechanism(), response, locale); } else { //TODO: verify that desired mechanism and locale are supported diff --git a/cpp/src/qpid/client/ConnectionHandler.h b/cpp/src/qpid/client/ConnectionHandler.h index e9cc5194ae..ed1e385dcf 100644 --- a/cpp/src/qpid/client/ConnectionHandler.h +++ b/cpp/src/qpid/client/ConnectionHandler.h @@ -94,7 +94,8 @@ class ConnectionHandler : private StateManager, public: using InputHandler::handle; typedef boost::function<void()> CloseListener; - typedef boost::function<void(uint16_t, const std::string&)> ErrorListener; + typedef boost::function<void(uint16_t, const std::string&)> ErrorListener; + typedef boost::function<unsigned int()> GetConnSSF; ConnectionHandler(const ConnectionSettings&, framing::ProtocolVersion&); @@ -122,6 +123,7 @@ public: static framing::connection::CloseCode convert(uint16_t replyCode); const std::string& getUserId() const { return operUserId; } + GetConnSSF getSSF; /** query the connection for its security strength factor */ }; }} diff --git a/cpp/src/qpid/client/ConnectionImpl.cpp b/cpp/src/qpid/client/ConnectionImpl.cpp index 4f35639c71..cede7f7310 100644 --- a/cpp/src/qpid/client/ConnectionImpl.cpp +++ b/cpp/src/qpid/client/ConnectionImpl.cpp @@ -79,6 +79,7 @@ ConnectionImpl::ConnectionImpl(framing::ProtocolVersion v, const ConnectionSetti CLOSE_CODE_NORMAL, std::string()); //only set error handler once open handler.onError = boost::bind(&ConnectionImpl::closed, this, _1, _2); + handler.getSSF = boost::bind(&Connector::getSSF, boost::ref(connector)); } const uint16_t ConnectionImpl::NEXT_CHANNEL = std::numeric_limits<uint16_t>::max(); diff --git a/cpp/src/qpid/client/Connector.cpp b/cpp/src/qpid/client/Connector.cpp index fbb571d40a..ad60c9d7e1 100644 --- a/cpp/src/qpid/client/Connector.cpp +++ b/cpp/src/qpid/client/Connector.cpp @@ -148,6 +148,7 @@ public: TCPConnector(framing::ProtocolVersion pVersion, const ConnectionSettings&, ConnectionImpl*); + unsigned int getSSF() { return 0; } }; // Static constructor which registers connector here diff --git a/cpp/src/qpid/client/Connector.h b/cpp/src/qpid/client/Connector.h index 78ddaa33cd..3a49ae9012 100644 --- a/cpp/src/qpid/client/Connector.h +++ b/cpp/src/qpid/client/Connector.h @@ -74,6 +74,8 @@ class Connector : public framing::OutputHandler virtual void activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer>); + virtual unsigned int getSSF() = 0; + }; }} diff --git a/cpp/src/qpid/client/RdmaConnector.cpp b/cpp/src/qpid/client/RdmaConnector.cpp index 0692c3d85c..77169db3a6 100644 --- a/cpp/src/qpid/client/RdmaConnector.cpp +++ b/cpp/src/qpid/client/RdmaConnector.cpp @@ -122,6 +122,7 @@ public: RdmaConnector(framing::ProtocolVersion pVersion, const ConnectionSettings&, ConnectionImpl*); + unsigned int getSSF() { return 0; } }; // Static constructor which registers connector here diff --git a/cpp/src/qpid/client/Sasl.h b/cpp/src/qpid/client/Sasl.h index d773609655..fcc8c1f1c6 100644 --- a/cpp/src/qpid/client/Sasl.h +++ b/cpp/src/qpid/client/Sasl.h @@ -42,7 +42,7 @@ struct ConnectionSettings; class Sasl { public: - virtual std::string start(const std::string& mechanisms) = 0; + virtual std::string start(const std::string& mechanisms, unsigned int ssf) = 0; virtual std::string step(const std::string& challenge) = 0; virtual std::string getMechanism() = 0; virtual std::string getUserId() = 0; diff --git a/cpp/src/qpid/client/SaslFactory.cpp b/cpp/src/qpid/client/SaslFactory.cpp index b699160066..5012b75c94 100644 --- a/cpp/src/qpid/client/SaslFactory.cpp +++ b/cpp/src/qpid/client/SaslFactory.cpp @@ -80,7 +80,7 @@ class CyrusSasl : public Sasl public: CyrusSasl(const ConnectionSettings&); ~CyrusSasl(); - std::string start(const std::string& mechanisms); + std::string start(const std::string& mechanisms, unsigned int ssf); std::string step(const std::string& challenge); std::string getMechanism(); std::string getUserId(); @@ -176,7 +176,7 @@ namespace { const std::string SSL("ssl"); } -std::string CyrusSasl::start(const std::string& mechanisms) +std::string CyrusSasl::start(const std::string& mechanisms, unsigned int ssf) { QPID_LOG(debug, "CyrusSasl::start(" << mechanisms << ")"); int result = sasl_client_new(settings.service.c_str(), @@ -189,7 +189,18 @@ std::string CyrusSasl::start(const std::string& mechanisms) if (result != SASL_OK) throw InternalErrorException(QPID_MSG("Sasl error: " << sasl_errdetail(conn))); sasl_security_properties_t secprops; - + + if (ssf) { + sasl_ssf_t external_ssf = (sasl_ssf_t) ssf; + if (external_ssf) { + int result = sasl_setprop(conn, SASL_SSF_EXTERNAL, &external_ssf); + if (result != SASL_OK) { + throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external SSF: " << result)); + } + QPID_LOG(debug, "external SSF detected and set to " << ssf); + } + } + secprops.min_ssf = settings.minSsf; secprops.max_ssf = settings.maxSsf; secprops.maxbufsize = 65535; diff --git a/cpp/src/qpid/client/SslConnector.cpp b/cpp/src/qpid/client/SslConnector.cpp index 80c53770a0..5cdaaa4615 100644 --- a/cpp/src/qpid/client/SslConnector.cpp +++ b/cpp/src/qpid/client/SslConnector.cpp @@ -135,6 +135,7 @@ public: SslConnector(framing::ProtocolVersion pVersion, const ConnectionSettings&, ConnectionImpl*); + unsigned int getSSF() { return socket.getKeyLen(); } }; // Static constructor which registers connector here diff --git a/cpp/src/qpid/cluster/Cluster.cpp b/cpp/src/qpid/cluster/Cluster.cpp index f5db692e92..3ced6263df 100644 --- a/cpp/src/qpid/cluster/Cluster.cpp +++ b/cpp/src/qpid/cluster/Cluster.cpp @@ -153,7 +153,7 @@ namespace _qmf = ::qmf::org::apache::qpid::cluster; * Currently use SVN revision to avoid clashes with versions from * different branches. */ -const uint32_t Cluster::CLUSTER_VERSION = 820783; +const uint32_t Cluster::CLUSTER_VERSION = 834052; struct ClusterDispatcher : public framing::AMQP_AllOperations::ClusterHandler { qpid::cluster::Cluster& cluster; @@ -250,7 +250,9 @@ void Cluster::addLocalConnection(const boost::intrusive_ptr<Connection>& c) { assert(c->getId().getMember() == self); // Announce the connection to the cluster. if (c->isLocalClient()) - mcast.mcastControl((ClusterConnectionAnnounceBody()), c->getId()); + mcast.mcastControl(ClusterConnectionAnnounceBody(ProtocolVersion(), + c->getBrokerConnection().getSSF() ), + c->getId()); } // Called in connection thread to insert an updated shadow connection. @@ -344,7 +346,13 @@ const ClusterUpdateOfferBody* castUpdateOffer(const framing::AMQBody* body) { body->getMethod()->isA<ClusterUpdateOfferBody>()) ? static_cast<const ClusterUpdateOfferBody*>(body) : 0; } - + +const ClusterConnectionAnnounceBody* castAnnounce( const framing::AMQBody *body) { + return (body && body->getMethod() && + body->getMethod()->isA<ClusterConnectionAnnounceBody>()) ? + static_cast<const ClusterConnectionAnnounceBody*>(body) : 0; +} + // Handler for deliverEventQueue. // This thread decodes frames from events. void Cluster::deliveredEvent(const Event& e) { @@ -452,8 +460,13 @@ ConnectionPtr Cluster::getConnection(const EventFrame& e, Lock&) { } else { // New remote connection, create a shadow. std::ostringstream mgmtId; + unsigned int ssf; + const ClusterConnectionAnnounceBody *announce = castAnnounce(e.frame.getBody()); + mgmtId << id; - cp = new Connection(*this, shadowOut, mgmtId.str(), id); + ssf = (announce && announce->hasSsf()) ? announce->getSsf() : 0; + QPID_LOG(debug, *this << "new connection's ssf =" << ssf ); + cp = new Connection(*this, shadowOut, mgmtId.str(), id, ssf ); } connections.insert(ConnectionMap::value_type(id, cp)); } diff --git a/cpp/src/qpid/cluster/Connection.cpp b/cpp/src/qpid/cluster/Connection.cpp index 841c3b610d..2eda84ae11 100644 --- a/cpp/src/qpid/cluster/Connection.cpp +++ b/cpp/src/qpid/cluster/Connection.cpp @@ -72,9 +72,10 @@ const std::string shadowPrefix("[shadow]"); // Shadow connection -Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out, const std::string& logId, const ConnectionId& id) + Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out, const std::string& logId, + const ConnectionId& id, unsigned int ssf) : cluster(c), self(id), catchUp(false), output(*this, out), - connection(&output, cluster.getBroker(), shadowPrefix+logId), expectProtocolHeader(false), + connection(&output, cluster.getBroker(), shadowPrefix+logId, ssf), expectProtocolHeader(false), mcastFrameHandler(cluster.getMulticast(), self), consumerNumbering(c.getUpdateReceiver().consumerNumbering) { init(); } @@ -82,10 +83,11 @@ Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out, const std: // Local connection Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out, const std::string& logId, MemberId member, - bool isCatchUp, bool isLink + bool isCatchUp, bool isLink, unsigned int ssf ) : cluster(c), self(member, ++idCounter), catchUp(isCatchUp), output(*this, out), connection(&output, cluster.getBroker(), isCatchUp ? shadowPrefix+logId : logId, + ssf, isLink, isCatchUp ? ++catchUpId : 0), expectProtocolHeader(isLink), mcastFrameHandler(cluster.getMulticast(), self), diff --git a/cpp/src/qpid/cluster/Connection.h b/cpp/src/qpid/cluster/Connection.h index 2799cc9fe1..57cca865db 100644 --- a/cpp/src/qpid/cluster/Connection.h +++ b/cpp/src/qpid/cluster/Connection.h @@ -63,10 +63,13 @@ class Connection : { public: + /** Local connection. */ - Connection(Cluster&, sys::ConnectionOutputHandler& out, const std::string& logId, MemberId, bool catchUp, bool isLink); + Connection(Cluster&, sys::ConnectionOutputHandler& out, const std::string& logId, MemberId, bool catchUp, bool isLink, + unsigned int ssf); /** Shadow connection. */ - Connection(Cluster&, sys::ConnectionOutputHandler& out, const std::string& logId, const ConnectionId& id); + Connection(Cluster&, sys::ConnectionOutputHandler& out, const std::string& logId, const ConnectionId& id, + unsigned int ssf); ~Connection(); ConnectionId getId() const { return self; } @@ -155,7 +158,7 @@ class Connection : void exchange(const std::string& encoded); void giveReadCredit(int credit); - void announce() {} // handled by Cluster. + void announce(uint32_t) {} // handled by Cluster. void abort(); void deliverClose(); diff --git a/cpp/src/qpid/cluster/ConnectionCodec.cpp b/cpp/src/qpid/cluster/ConnectionCodec.cpp index 4ff8b0a4a3..8f6f1d9ad5 100644 --- a/cpp/src/qpid/cluster/ConnectionCodec.cpp +++ b/cpp/src/qpid/cluster/ConnectionCodec.cpp @@ -36,25 +36,27 @@ namespace cluster { using namespace framing; sys::ConnectionCodec* -ConnectionCodec::Factory::create(ProtocolVersion v, sys::OutputControl& out, const std::string& id) { +ConnectionCodec::Factory::create(ProtocolVersion v, sys::OutputControl& out, const std::string& id, + unsigned int ssf) { if (v == ProtocolVersion(0, 10)) - return new ConnectionCodec(v, out, id, cluster, false, false); + return new ConnectionCodec(v, out, id, cluster, false, false, ssf); else if (v == ProtocolVersion(0x80 + 0, 0x80 + 10)) // Catch-up connection - return new ConnectionCodec(v, out, id, cluster, true, false); + return new ConnectionCodec(v, out, id, cluster, true, false, ssf); return 0; } // Used for outgoing Link connections sys::ConnectionCodec* -ConnectionCodec::Factory::create(sys::OutputControl& out, const std::string& logId) { - return new ConnectionCodec(ProtocolVersion(0,10), out, logId, cluster, false, true); +ConnectionCodec::Factory::create(sys::OutputControl& out, const std::string& logId, + unsigned int ssf) { + return new ConnectionCodec(ProtocolVersion(0,10), out, logId, cluster, false, true, ssf); } ConnectionCodec::ConnectionCodec( const ProtocolVersion& v, sys::OutputControl& out, - const std::string& logId, Cluster& cluster, bool catchUp, bool isLink + const std::string& logId, Cluster& cluster, bool catchUp, bool isLink, unsigned int ssf ) : codec(out, logId, isLink), - interceptor(new Connection(cluster, codec, logId, cluster.getId(), catchUp, isLink)) + interceptor(new Connection(cluster, codec, logId, cluster.getId(), catchUp, isLink, ssf)) { std::auto_ptr<sys::ConnectionInputHandler> ih(new ProxyInputHandler(interceptor)); codec.setInputHandler(ih); diff --git a/cpp/src/qpid/cluster/ConnectionCodec.h b/cpp/src/qpid/cluster/ConnectionCodec.h index 4ff738b603..74cb3c507d 100644 --- a/cpp/src/qpid/cluster/ConnectionCodec.h +++ b/cpp/src/qpid/cluster/ConnectionCodec.h @@ -52,12 +52,15 @@ class ConnectionCodec : public sys::ConnectionCodec { Cluster& cluster; Factory(boost::shared_ptr<sys::ConnectionCodec::Factory> f, Cluster& c) : next(f), cluster(c) {} - sys::ConnectionCodec* create(framing::ProtocolVersion, sys::OutputControl&, const std::string& id); - sys::ConnectionCodec* create(sys::OutputControl&, const std::string& id); + sys::ConnectionCodec* create(framing::ProtocolVersion, sys::OutputControl&, const std::string& id, + unsigned int conn_ssf); + sys::ConnectionCodec* create(sys::OutputControl&, const std::string& id, + unsigned int conn_ssf); }; ConnectionCodec(const framing::ProtocolVersion&, sys::OutputControl& out, - const std::string& logId, Cluster& c, bool catchUp, bool isLink); + const std::string& logId, Cluster& c, bool catchUp, bool isLink, + unsigned int ssf); ~ConnectionCodec(); // ConnectionCodec functions. diff --git a/cpp/src/qpid/sys/AsynchIOHandler.cpp b/cpp/src/qpid/sys/AsynchIOHandler.cpp index eb0f213547..f658b7d50f 100644 --- a/cpp/src/qpid/sys/AsynchIOHandler.cpp +++ b/cpp/src/qpid/sys/AsynchIOHandler.cpp @@ -144,7 +144,7 @@ void AsynchIOHandler::readbuff(AsynchIO& , AsynchIO::BufferBase* buff) { decoded = in.getPosition(); QPID_LOG(debug, "RECV [" << identifier << "] INIT(" << protocolInit << ")"); try { - codec = factory->create(protocolInit.getVersion(), *this, identifier); + codec = factory->create(protocolInit.getVersion(), *this, identifier, 0); if (!codec) { //TODO: may still want to revise this... //send valid version header & close connection. @@ -200,7 +200,7 @@ void AsynchIOHandler::nobuffs(AsynchIO&) { void AsynchIOHandler::idle(AsynchIO&){ if (isClient && codec == 0) { - codec = factory->create(*this, identifier); + codec = factory->create(*this, identifier, 0); write(framing::ProtocolInitiation(codec->getVersion())); return; } diff --git a/cpp/src/qpid/sys/ConnectionCodec.h b/cpp/src/qpid/sys/ConnectionCodec.h index 880d4f0013..7231b1daa6 100644 --- a/cpp/src/qpid/sys/ConnectionCodec.h +++ b/cpp/src/qpid/sys/ConnectionCodec.h @@ -45,18 +45,31 @@ class ConnectionCodec : public Codec { virtual bool isClosed() const = 0; virtual framing::ProtocolVersion getVersion() const = 0; - + struct Factory { virtual ~Factory() {} + /** Security Strength Factor - indicates the level of security provided + * by the underlying transport. If zero, the transport provides no + * security (e.g. TCP). If non-zero, the transport provides some level + * of security (e.g. SSL). The values for SSF can be interpreted as: + * + * 0 = No protection. + * 1 = Integrity checking only. + * >1 = Supports authentication, integrity and confidentiality. + * The number represents the encryption key length. + */ + /** Return 0 if version unknown */ virtual ConnectionCodec* create( - framing::ProtocolVersion, OutputControl&, const std::string& id + framing::ProtocolVersion, OutputControl&, const std::string& id, + unsigned int conn_ssf ) = 0; /** Return "preferred" codec for outbound connections. */ virtual ConnectionCodec* create( - OutputControl&, const std::string& id + OutputControl&, const std::string& id, + unsigned int conn_ssf ) = 0; }; }; diff --git a/cpp/src/qpid/sys/RdmaIOPlugin.cpp b/cpp/src/qpid/sys/RdmaIOPlugin.cpp index 28ff140237..bd19247124 100644 --- a/cpp/src/qpid/sys/RdmaIOPlugin.cpp +++ b/cpp/src/qpid/sys/RdmaIOPlugin.cpp @@ -139,7 +139,7 @@ void RdmaIOHandler::initProtocolOut() { // but we must be able to send assert( codec == 0 ); assert( aio->writable() && aio->bufferAvailable() ); - codec = factory->create(*this, identifier); + codec = factory->create(*this, identifier, 0); write(framing::ProtocolInitiation(codec->getVersion())); } @@ -186,7 +186,7 @@ void RdmaIOHandler::initProtocolIn(Rdma::Buffer* buff) { decoded = in.getPosition(); QPID_LOG(debug, "Rdma: RECV [" << identifier << "] INIT(" << protocolInit << ")"); - codec = factory->create(protocolInit.getVersion(), *this, identifier); + codec = factory->create(protocolInit.getVersion(), *this, identifier, 0); // If we failed to create the codec then we don't understand the offered protocol version if (!codec) { diff --git a/cpp/src/qpid/sys/ssl/SslHandler.cpp b/cpp/src/qpid/sys/ssl/SslHandler.cpp index 9cf74e4b6d..3469f88c0f 100644 --- a/cpp/src/qpid/sys/ssl/SslHandler.cpp +++ b/cpp/src/qpid/sys/ssl/SslHandler.cpp @@ -111,7 +111,7 @@ void SslHandler::readbuff(SslIO& , SslIO::BufferBase* buff) { decoded = in.getPosition(); QPID_LOG(debug, "RECV [" << identifier << "] INIT(" << protocolInit << ")"); try { - codec = factory->create(protocolInit.getVersion(), *this, identifier); + codec = factory->create(protocolInit.getVersion(), *this, identifier, aio->getKeyLen()); if (!codec) { //TODO: may still want to revise this... //send valid version header & close connection. @@ -166,7 +166,7 @@ void SslHandler::nobuffs(SslIO&) { void SslHandler::idle(SslIO&){ if (isClient && codec == 0) { - codec = factory->create(*this, identifier); + codec = factory->create(*this, identifier, aio->getKeyLen()); write(framing::ProtocolInitiation(codec->getVersion())); return; } diff --git a/cpp/src/qpid/sys/ssl/SslIo.cpp b/cpp/src/qpid/sys/ssl/SslIo.cpp index 282d77258f..c149d6ea74 100644 --- a/cpp/src/qpid/sys/ssl/SslIo.cpp +++ b/cpp/src/qpid/sys/ssl/SslIo.cpp @@ -436,3 +436,4 @@ void SslIO::close(DispatchHandle& h) { } } +int SslIO::getKeyLen() {return socket.getKeyLen();} diff --git a/cpp/src/qpid/sys/ssl/SslIo.h b/cpp/src/qpid/sys/ssl/SslIo.h index 2d0d5b296c..3162abac40 100644 --- a/cpp/src/qpid/sys/ssl/SslIo.h +++ b/cpp/src/qpid/sys/ssl/SslIo.h @@ -121,6 +121,7 @@ public: typedef boost::function1<void, SslIO&> BuffersEmptyCallback; typedef boost::function1<void, SslIO&> IdleCallback; + private: ReadCallback readCallback; EofCallback eofCallback; @@ -155,6 +156,8 @@ public: bool writeQueueEmpty() { return writeQueue.empty(); } BufferBase* getQueuedBuffer(); + int getKeyLen(); + private: ~SslIO(); void readable(qpid::sys::DispatchHandle& handle); diff --git a/cpp/src/qpid/sys/ssl/SslSocket.cpp b/cpp/src/qpid/sys/ssl/SslSocket.cpp index 9181f56b94..aa8cf127d7 100644 --- a/cpp/src/qpid/sys/ssl/SslSocket.cpp +++ b/cpp/src/qpid/sys/ssl/SslSocket.cpp @@ -274,4 +274,24 @@ void SslSocket::setTcpNoDelay(bool nodelay) const } } + +/** get the bit length of the current cipher's key */ +int SslSocket::getKeyLen() const +{ + int enabled = 0; + int keySize = 0; + SECStatus rc; + + rc = SSL_SecurityStatus( socket, + &enabled, + NULL, + NULL, + &keySize, + NULL, NULL ); + if (rc == SECSuccess && enabled) { + return keySize; + } + return 0; +} + }}} // namespace qpid::sys::ssl diff --git a/cpp/src/qpid/sys/ssl/SslSocket.h b/cpp/src/qpid/sys/ssl/SslSocket.h index a0e73e8181..f1f05e7a98 100644 --- a/cpp/src/qpid/sys/ssl/SslSocket.h +++ b/cpp/src/qpid/sys/ssl/SslSocket.h @@ -100,6 +100,8 @@ public: */ int getError() const; + int getKeyLen() const; + private: mutable std::string connectname; mutable PRFileDesc* socket; |