summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorGordon Sim <gsim@apache.org>2009-11-09 15:30:18 +0000
committerGordon Sim <gsim@apache.org>2009-11-09 15:30:18 +0000
commit58efa10f3ed794dac024a1995e871a1368faeddc (patch)
tree7a96ce8642acfdc19546512fadfc8783fbc252d3 /cpp/src
parentbb32d235be89547bb7e8621ce56c66e4dabdd43a (diff)
downloadqpid-python-58efa10f3ed794dac024a1995e871a1368faeddc.tar.gz
QPID-1899: Applied patch from Ken Giusti to tie in SASL enctryption to the handling of the --require-encrypted option
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@834108 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/qpid/broker/Connection.cpp3
-rw-r--r--cpp/src/qpid/broker/Connection.h6
-rw-r--r--cpp/src/qpid/broker/ConnectionFactory.cpp6
-rw-r--r--cpp/src/qpid/broker/ConnectionFactory.h6
-rw-r--r--cpp/src/qpid/broker/SaslAuthenticator.cpp33
-rw-r--r--cpp/src/qpid/broker/SecureConnectionFactory.cpp10
-rw-r--r--cpp/src/qpid/broker/SecureConnectionFactory.h6
-rw-r--r--cpp/src/qpid/client/ConnectionHandler.cpp3
-rw-r--r--cpp/src/qpid/client/ConnectionHandler.h4
-rw-r--r--cpp/src/qpid/client/ConnectionImpl.cpp1
-rw-r--r--cpp/src/qpid/client/Connector.cpp1
-rw-r--r--cpp/src/qpid/client/Connector.h2
-rw-r--r--cpp/src/qpid/client/RdmaConnector.cpp1
-rw-r--r--cpp/src/qpid/client/Sasl.h2
-rw-r--r--cpp/src/qpid/client/SaslFactory.cpp17
-rw-r--r--cpp/src/qpid/client/SslConnector.cpp1
-rw-r--r--cpp/src/qpid/cluster/Cluster.cpp21
-rw-r--r--cpp/src/qpid/cluster/Connection.cpp8
-rw-r--r--cpp/src/qpid/cluster/Connection.h9
-rw-r--r--cpp/src/qpid/cluster/ConnectionCodec.cpp16
-rw-r--r--cpp/src/qpid/cluster/ConnectionCodec.h9
-rw-r--r--cpp/src/qpid/sys/AsynchIOHandler.cpp4
-rw-r--r--cpp/src/qpid/sys/ConnectionCodec.h19
-rw-r--r--cpp/src/qpid/sys/RdmaIOPlugin.cpp4
-rw-r--r--cpp/src/qpid/sys/ssl/SslHandler.cpp4
-rw-r--r--cpp/src/qpid/sys/ssl/SslIo.cpp1
-rw-r--r--cpp/src/qpid/sys/ssl/SslIo.h3
-rw-r--r--cpp/src/qpid/sys/ssl/SslSocket.cpp20
-rw-r--r--cpp/src/qpid/sys/ssl/SslSocket.h2
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;