diff options
| author | Stephen D. Huston <shuston@apache.org> | 2010-01-23 00:16:34 +0000 |
|---|---|---|
| committer | Stephen D. Huston <shuston@apache.org> | 2010-01-23 00:16:34 +0000 |
| commit | 772484f911db95bbc0c1ac599ed72b2ee143bec0 (patch) | |
| tree | e5865eb45a96f31ae84027f44caed4baccda9f21 /cpp/src/qpid/client | |
| parent | 1b489dec1ea09cde9365602befb49eb958a62cdd (diff) | |
| download | qpid-python-772484f911db95bbc0c1ac599ed72b2ee143bec0.tar.gz | |
Add SSL support for Windows client and broker per QPID-1403. Adds new AsynchIO::BufferBase::squish() method that does what used to be done by in-place memmove() calls so it can be reused easily.
SSL support for Windows is in:
- Client: qpid/client/windows/SslConnector.cpp
qpid/client/TCPConnector.{h cpp} rearranged a bit to make pieces available to SslConnector
- Broker: qpid/broker/windows/SslProtocolFactory.cpp
- Common: qpid/sys/windows/SslAsynchIO contains all the Schannel stuff to negotiate a session, encrypt, and decrypt data. The SslAsynchIO acts as a shim between the layer above and the "regular" AsynchIO that actually handles read/write and completions.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@902318 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid/client')
| -rw-r--r-- | cpp/src/qpid/client/TCPConnector.cpp | 14 | ||||
| -rw-r--r-- | cpp/src/qpid/client/TCPConnector.h | 19 | ||||
| -rw-r--r-- | cpp/src/qpid/client/windows/SslConnector.cpp | 181 |
3 files changed, 203 insertions, 11 deletions
diff --git a/cpp/src/qpid/client/TCPConnector.cpp b/cpp/src/qpid/client/TCPConnector.cpp index 00584d168e..94c4a4cae0 100644 --- a/cpp/src/qpid/client/TCPConnector.cpp +++ b/cpp/src/qpid/client/TCPConnector.cpp @@ -108,15 +108,23 @@ void TCPConnector::connected(const Socket&) { 0, // closed 0, // nobuffs boost::bind(&TCPConnector::writebuff, this, _1)); + start(aio); + initAmqp(); + aio->start(poller); +} + +void TCPConnector::start(sys::AsynchIO* aio_) { + aio = aio_; for (int i = 0; i < 32; i++) { aio->queueReadBuffer(new Buff(maxFrameSize)); } identifier = str(format("[%1% %2%]") % socket.getLocalPort() % socket.getPeerAddress()); +} + +void TCPConnector::initAmqp() { ProtocolInitiation init(version); writeDataBlock(init); - - aio->start(poller); } void TCPConnector::connectFailed(const std::string& msg) { @@ -286,7 +294,7 @@ size_t TCPConnector::decode(const char* buffer, size_t size) } void TCPConnector::writeDataBlock(const AMQDataBlock& data) { - AsynchIO::BufferBase* buff = new Buff(maxFrameSize); + AsynchIO::BufferBase* buff = aio->getQueuedBuffer(); framing::Buffer out(buff->bytes, buff->byteCount); data.encode(out); buff->dataCount = data.encodedSize(); diff --git a/cpp/src/qpid/client/TCPConnector.h b/cpp/src/qpid/client/TCPConnector.h index 0de06de40c..6ca750f52f 100644 --- a/cpp/src/qpid/client/TCPConnector.h +++ b/cpp/src/qpid/client/TCPConnector.h @@ -76,19 +76,12 @@ class TCPConnector : public Connector, public sys::Codec boost::shared_ptr<sys::Poller> poller; std::auto_ptr<qpid::sys::SecurityLayer> securityLayer; - ~TCPConnector(); - void handleClosed(); bool closeInternal(); - void connected(const sys::Socket&); - void connectFailed(const std::string& msg); - bool readbuff(qpid::sys::AsynchIO&, qpid::sys::AsynchIOBufferBase*); - void writebuff(qpid::sys::AsynchIO&); + virtual void connected(const sys::Socket&); void writeDataBlock(const framing::AMQDataBlock& data); - void eof(qpid::sys::AsynchIO&); - void connect(const std::string& host, int port); void close(); void send(framing::AMQFrame& frame); void abort(); @@ -105,6 +98,16 @@ class TCPConnector : public Connector, public sys::Codec size_t encode(const char* buffer, size_t size); bool canEncode(); +protected: + virtual ~TCPConnector(); + void connect(const std::string& host, int port); + void start(sys::AsynchIO* aio_); + void initAmqp(); + virtual void connectFailed(const std::string& msg); + bool readbuff(qpid::sys::AsynchIO&, qpid::sys::AsynchIOBufferBase*); + void writebuff(qpid::sys::AsynchIO&); + void eof(qpid::sys::AsynchIO&); + public: TCPConnector(boost::shared_ptr<sys::Poller>, framing::ProtocolVersion pVersion, diff --git a/cpp/src/qpid/client/windows/SslConnector.cpp b/cpp/src/qpid/client/windows/SslConnector.cpp new file mode 100644 index 0000000000..d3df8a9c12 --- /dev/null +++ b/cpp/src/qpid/client/windows/SslConnector.cpp @@ -0,0 +1,181 @@ +/*
+ *
+ * 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/client/TCPConnector.h"
+
+#include "config.h"
+#include "qpid/Msg.h"
+#include "qpid/client/ConnectionImpl.h"
+#include "qpid/client/ConnectionSettings.h"
+#include "qpid/log/Statement.h"
+#include "qpid/sys/Dispatcher.h"
+#include "qpid/sys/Poller.h"
+#include "qpid/sys/Time.h"
+#include "qpid/sys/windows/check.h"
+#include "qpid/sys/windows/SslAsynchIO.h"
+
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/format.hpp>
+
+#include <memory.h>
+// security.h needs to see this to distinguish from kernel use.
+#define SECURITY_WIN32
+#include <security.h>
+#include <Schnlsp.h>
+#undef SECURITY_WIN32
+#include <winsock2.h>
+
+namespace qpid {
+namespace client {
+namespace windows {
+
+using namespace qpid::sys;
+using boost::format;
+using boost::str;
+
+
+class SslConnector : public qpid::client::TCPConnector
+{
+ qpid::sys::windows::ClientSslAsynchIO *shim;
+ boost::shared_ptr<qpid::sys::Poller> poller;
+ std::string brokerHost;
+ SCHANNEL_CRED cred;
+ CredHandle credHandle;
+ TimeStamp credExpiry;
+
+ virtual ~SslConnector();
+ void negotiationDone(SECURITY_STATUS status);
+
+ // A number of AsynchIO callbacks go right through to TCPConnector, but
+ // we can't boost::bind to a protected ancestor, so these methods redirect
+ // to those TCPConnector methods.
+ bool redirectReadbuff(qpid::sys::AsynchIO&, qpid::sys::AsynchIOBufferBase*);
+ void redirectWritebuff(qpid::sys::AsynchIO&);
+ void redirectEof(qpid::sys::AsynchIO&);
+
+public:
+ SslConnector(boost::shared_ptr<qpid::sys::Poller>,
+ framing::ProtocolVersion pVersion,
+ const ConnectionSettings&,
+ ConnectionImpl*);
+ virtual void connect(const std::string& host, int port);
+ virtual void connected(const Socket&);
+ unsigned int getSSF();
+};
+
+// Static constructor which registers connector here
+namespace {
+ Connector* create(boost::shared_ptr<qpid::sys::Poller> p,
+ framing::ProtocolVersion v,
+ const ConnectionSettings& s,
+ ConnectionImpl* c) {
+ return new SslConnector(p, v, s, c);
+ }
+
+ struct StaticInit {
+ StaticInit() {
+ try {
+ Connector::registerFactory("ssl", &create);
+ } catch (const std::exception& e) {
+ QPID_LOG(error, "Failed to initialise SSL connector: " << e.what());
+ }
+ };
+ ~StaticInit() { }
+ } init;
+}
+
+void SslConnector::negotiationDone(SECURITY_STATUS status)
+{
+ if (status == SEC_E_OK)
+ initAmqp();
+ else
+ connectFailed(QPID_MSG(qpid::sys::strError(status)));
+}
+
+bool SslConnector::redirectReadbuff(qpid::sys::AsynchIO& a,
+ qpid::sys::AsynchIOBufferBase* b) {
+ return readbuff(a, b);
+}
+
+void SslConnector::redirectWritebuff(qpid::sys::AsynchIO& a) {
+ writebuff(a);
+}
+
+void SslConnector::redirectEof(qpid::sys::AsynchIO& a) {
+ eof(a);
+}
+
+SslConnector::SslConnector(boost::shared_ptr<qpid::sys::Poller> p,
+ framing::ProtocolVersion ver,
+ const ConnectionSettings& settings,
+ ConnectionImpl* cimpl)
+ : TCPConnector(p, ver, settings, cimpl), shim(0), poller(p)
+{
+ memset(&cred, 0, sizeof(cred));
+ cred.dwVersion = SCHANNEL_CRED_VERSION;
+ SECURITY_STATUS status = ::AcquireCredentialsHandle(NULL,
+ UNISP_NAME,
+ SECPKG_CRED_OUTBOUND,
+ NULL,
+ &cred,
+ NULL,
+ NULL,
+ &credHandle,
+ &credExpiry);
+ if (status != SEC_E_OK)
+ throw QPID_WINDOWS_ERROR(status);
+ QPID_LOG(debug, "SslConnector created for " << ver.toString());
+}
+
+SslConnector::~SslConnector()
+{
+ ::FreeCredentialsHandle(&credHandle);
+}
+
+ // Will this get reach via virtual method via boost::bind????
+
+void SslConnector::connect(const std::string& host, int port) {
+ brokerHost = host;
+ TCPConnector::connect(host, port);
+}
+
+void SslConnector::connected(const Socket& s) {
+ shim = new qpid::sys::windows::ClientSslAsynchIO(brokerHost,
+ s,
+ credHandle,
+ boost::bind(&SslConnector::redirectReadbuff, this, _1, _2),
+ boost::bind(&SslConnector::redirectEof, this, _1),
+ boost::bind(&SslConnector::redirectEof, this, _1),
+ 0, // closed
+ 0, // nobuffs
+ boost::bind(&SslConnector::redirectWritebuff, this, _1),
+ boost::bind(&SslConnector::negotiationDone, this, _1));
+ start(shim);
+ shim->start(poller);
+}
+
+unsigned int SslConnector::getSSF()
+{
+ return shim->getSslKeySize();
+}
+
+}}} // namespace qpid::client::windows
|
