diff options
Diffstat (limited to 'qpid/cpp/src/qpid/client/windows/SslConnector.cpp')
-rw-r--r-- | qpid/cpp/src/qpid/client/windows/SslConnector.cpp | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/qpid/cpp/src/qpid/client/windows/SslConnector.cpp b/qpid/cpp/src/qpid/client/windows/SslConnector.cpp new file mode 100644 index 0000000000..dc82ece9d1 --- /dev/null +++ b/qpid/cpp/src/qpid/client/windows/SslConnector.cpp @@ -0,0 +1,147 @@ +/* + * + * 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/util.h" +#include "qpid/sys/windows/SslAsynchIO.h" +#include "qpid/sys/windows/SslCredential.h" + +#include <boost/bind.hpp> + +#include <memory.h> +#include <winsock2.h> + + + +namespace qpid { +namespace client { +namespace windows { + +using qpid::sys::Socket; + +class SslConnector : public qpid::client::TCPConnector +{ + qpid::sys::windows::ClientSslAsynchIO *shim; + boost::shared_ptr<qpid::sys::Poller> poller; + std::string brokerHost; + qpid::sys::windows::SslCredential sslCredential; + bool certLoaded; + + void negotiationDone(SECURITY_STATUS status); + + void connect(const std::string& host, const std::string& port); + void connected(const Socket&); + +public: + SslConnector(boost::shared_ptr<qpid::sys::Poller>, + framing::ProtocolVersion pVersion, + const ConnectionSettings&, + ConnectionImpl*); +}; + +// 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 { + CommonOptions common("", "", QPIDC_CONF_FILE); + qpid::sys::ssl::SslOptions options; + common.parse(0, 0, common.clientConfig, true); + options.parse (0, 0, common.clientConfig, true); + Connector::registerFactory("ssl", &create); + initWinSsl(options); + } 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 { + if (status == SEC_E_INCOMPLETE_CREDENTIALS && !certLoaded) { + // Server requested a client cert but we supplied none for the following reason: + connectFailed(QPID_MSG(sslCredential.error())); + } + else + connectFailed(QPID_MSG(qpid::sys::strError(status))); + } +} + +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) +{ + if (settings.sslIgnoreHostnameVerificationFailure) { + sslCredential.ignoreHostnameVerificationFailure(); + } + const std::string& name = (settings.sslCertName != "") ? + settings.sslCertName : qpid::sys::ssl::SslOptions::global.certName; + certLoaded = sslCredential.load(name); + QPID_LOG(debug, "SslConnector created for " << ver.toString()); +} + +void SslConnector::connect(const std::string& host, const std::string& port) { + brokerHost = host; + TCPConnector::connect(host, port); +} + +void SslConnector::connected(const Socket& s) { + shim = new qpid::sys::windows::ClientSslAsynchIO(brokerHost, + s, + sslCredential.handle(), + boost::bind(&SslConnector::readbuff, this, _1, _2), + boost::bind(&SslConnector::eof, this, _1), + boost::bind(&SslConnector::disconnected, this, _1), + boost::bind(&SslConnector::socketClosed, this, _1, _2), + 0, // nobuffs + boost::bind(&SslConnector::writebuff, this, _1), + boost::bind(&SslConnector::negotiationDone, this, _1)); + start(shim); + shim->start(poller); +} + +}}} // namespace qpid::client::windows |