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/sys | |
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/sys')
-rw-r--r-- | cpp/src/qpid/sys/AsynchIOHandler.cpp | 23 | ||||
-rw-r--r-- | cpp/src/qpid/sys/Codec.h | 52 | ||||
-rw-r--r-- | cpp/src/qpid/sys/ConnectionCodec.h | 16 | ||||
-rw-r--r-- | cpp/src/qpid/sys/SecurityLayer.h | 42 | ||||
-rw-r--r-- | cpp/src/qpid/sys/TCPIOPlugin.cpp | 12 | ||||
-rw-r--r-- | cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp | 119 | ||||
-rw-r--r-- | cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.h | 66 |
7 files changed, 299 insertions, 31 deletions
diff --git a/cpp/src/qpid/sys/AsynchIOHandler.cpp b/cpp/src/qpid/sys/AsynchIOHandler.cpp index 83b6329889..35b75c1fe8 100644 --- a/cpp/src/qpid/sys/AsynchIOHandler.cpp +++ b/cpp/src/qpid/sys/AsynchIOHandler.cpp @@ -184,16 +184,21 @@ void AsynchIOHandler::idle(AsynchIO&){ return; } if (codec == 0) return; - if (codec->canEncode()) { - // Try and get a queued buffer if not then construct new one - AsynchIO::BufferBase* buff = aio->getQueuedBuffer(); - if (!buff) buff = new Buff; - size_t encoded=codec->encode(buff->bytes, buff->byteCount); - buff->dataCount = encoded; - aio->queueWrite(buff); - } - if (codec->isClosed()) + try { + if (codec->canEncode()) { + // Try and get a queued buffer if not then construct new one + AsynchIO::BufferBase* buff = aio->getQueuedBuffer(); + if (!buff) buff = new Buff; + size_t encoded=codec->encode(buff->bytes, buff->byteCount); + buff->dataCount = encoded; + aio->queueWrite(buff); + } + if (codec->isClosed()) + aio->queueWriteClose(); + } catch (const std::exception& e) { + QPID_LOG(error, e.what()); aio->queueWriteClose(); + } } }} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/Codec.h b/cpp/src/qpid/sys/Codec.h new file mode 100644 index 0000000000..f9645f554e --- /dev/null +++ b/cpp/src/qpid/sys/Codec.h @@ -0,0 +1,52 @@ +#ifndef QPID_SYS_CODEC_H +#define QPID_SYS_CODEC_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 <cstddef> + +namespace qpid { +namespace sys { + +/** + * Generic codec interface + */ +class Codec +{ + public: + virtual ~Codec() {} + + /** Decode from buffer, return number of bytes decoded. + * @return may be less than size if there was incomplete + * data at the end of the buffer. + */ + virtual size_t decode(const char* buffer, size_t size) = 0; + + + /** Encode into buffer, return number of bytes encoded */ + virtual size_t encode(const char* buffer, size_t size) = 0; + + /** Return true if we have data to encode */ + virtual bool canEncode() = 0; +}; +}} // namespace qpid::sys + +#endif /*!QPID_SYS_CODEC_H*/ diff --git a/cpp/src/qpid/sys/ConnectionCodec.h b/cpp/src/qpid/sys/ConnectionCodec.h index b1b047d2cc..7f5e2f831c 100644 --- a/cpp/src/qpid/sys/ConnectionCodec.h +++ b/cpp/src/qpid/sys/ConnectionCodec.h @@ -21,6 +21,7 @@ * under the License. * */ +#include "Codec.h" #include "qpid/framing/ProtocolVersion.h" namespace qpid { @@ -34,23 +35,10 @@ class OutputControl; * Interface of coder/decoder for a connection of a specific protocol * version. */ -class ConnectionCodec { +class ConnectionCodec : public Codec { public: virtual ~ConnectionCodec() {} - /** Decode from buffer, return number of bytes decoded. - * @return may be less than size if there was incomplete - * data at the end of the buffer. - */ - virtual size_t decode(const char* buffer, size_t size) = 0; - - - /** Encode into buffer, return number of bytes encoded */ - virtual size_t encode(const char* buffer, size_t size) = 0; - - /** Return true if we have data to encode */ - virtual bool canEncode() = 0; - /** Network connection was closed from other end. */ virtual void closed() = 0; diff --git a/cpp/src/qpid/sys/SecurityLayer.h b/cpp/src/qpid/sys/SecurityLayer.h new file mode 100644 index 0000000000..6ad29eea80 --- /dev/null +++ b/cpp/src/qpid/sys/SecurityLayer.h @@ -0,0 +1,42 @@ +#ifndef QPID_SYS_SECURITYLAYER_H +#define QPID_SYS_SECURITYLAYER_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 "Codec.h" + +namespace qpid { +namespace sys { + +/** + * Defines interface to a SASL negotiated Security Layer (for + * encryption/integrity) + */ +class SecurityLayer : public Codec +{ + public: + virtual void init(Codec*) = 0; + virtual ~SecurityLayer() {} +}; + +}} // namespace qpid::sys + +#endif /*!QPID_SYS_SECURITYLAYER_H*/ diff --git a/cpp/src/qpid/sys/TCPIOPlugin.cpp b/cpp/src/qpid/sys/TCPIOPlugin.cpp index be091f86d8..c6e45b8fa4 100644 --- a/cpp/src/qpid/sys/TCPIOPlugin.cpp +++ b/cpp/src/qpid/sys/TCPIOPlugin.cpp @@ -65,14 +65,10 @@ static class TCPIOPlugin : public Plugin { // Only provide to a Broker if (broker) { const broker::Broker::Options& opts = broker->getOptions(); - if (opts.requireEncrypted) { - QPID_LOG(info, "Not accepting unencrypted connections on TCP"); - } else { - ProtocolFactory::shared_ptr protocol(new AsynchIOProtocolFactory(opts.port, opts.connectionBacklog, - opts.tcpNoDelay)); - QPID_LOG(notice, "Listening on TCP port " << protocol->getPort()); - broker->registerProtocolFactory("tcp", protocol); - } + ProtocolFactory::shared_ptr protocol(new AsynchIOProtocolFactory(opts.port, opts.connectionBacklog, + opts.tcpNoDelay)); + QPID_LOG(notice, "Listening on TCP port " << protocol->getPort()); + broker->registerProtocolFactory("tcp", protocol); } } } tcpPlugin; diff --git a/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp b/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp new file mode 100644 index 0000000000..e906d22cae --- /dev/null +++ b/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp @@ -0,0 +1,119 @@ +/* + * + * 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 "CyrusSecurityLayer.h" +#include <algorithm> +#include "qpid/framing/reply_exceptions.h" +#include "qpid/log/Statement.h" + +namespace qpid { +namespace sys { +namespace cyrus { + +CyrusSecurityLayer::CyrusSecurityLayer(sasl_conn_t* c, uint16_t maxFrameSize) : + conn(c), decrypted(0), decryptedSize(0), encrypted(0), encryptedSize(0), codec(0), maxInputSize(0), decodeBuffer(maxFrameSize) +{ + const void* value(0); + int result = sasl_getprop(conn, SASL_MAXOUTBUF, &value); + if (result != SASL_OK) { + throw framing::InternalErrorException(QPID_MSG("SASL encode error: " << sasl_errdetail(conn))); + } + maxInputSize = *(reinterpret_cast<const unsigned*>(value)); +} + +size_t CyrusSecurityLayer::decode(const char* input, size_t size) +{ + size_t inStart = 0; + do { + size_t inSize = std::min(size - inStart, maxInputSize); + int result = sasl_decode(conn, input + inStart, inSize, &decrypted, &decryptedSize); + if (result != SASL_OK) { + throw framing::InternalErrorException(QPID_MSG("SASL encode error: " << sasl_errdetail(conn))); + } + inStart += inSize; + size_t copied = 0; + do { + size_t count = std::min(decryptedSize - copied, decodeBuffer.size - decodeBuffer.position); + ::memcpy(decodeBuffer.data + decodeBuffer.position, decrypted + copied, count); + copied += count; + decodeBuffer.position += count; + size_t decodedSize = codec->decode(decodeBuffer.data, decodeBuffer.position); + if (decodedSize < decodeBuffer.position) { + ::memmove(decodeBuffer.data, decodeBuffer.data + decodedSize, decodeBuffer.position - decodedSize); + } + decodeBuffer.position -= decodedSize; + } while (copied < decryptedSize); + } while (inStart < size); + return size; +} + +size_t CyrusSecurityLayer::encode(const char* buffer, size_t size) +{ + size_t processed = 0;//records how many bytes have been written to buffer + do { + if (!encrypted) { + DataBuffer encodeBuffer(maxInputSize);//make sure maxInputSize > maxFrameSize + size_t encoded = codec->encode(encodeBuffer.data, encodeBuffer.size); + if (!encoded) break;//nothing more to do + int result = sasl_encode(conn, encodeBuffer.data, encoded, &encrypted, &encryptedSize); + if (result != SASL_OK) { + throw framing::InternalErrorException(QPID_MSG("SASL encode error: " << sasl_errdetail(conn))); + } + } + size_t remaining = size - processed; + if (remaining < encryptedSize) { + //can't fit all encrypted data in the buffer we've + //been given, copy in what we can and hold on to the + //rest until the next call + ::memcpy(const_cast<char*>(buffer + processed), encrypted, remaining); + processed += remaining; + encrypted += remaining; + encryptedSize -= remaining; + } else { + ::memcpy(const_cast<char*>(buffer + processed), encrypted, encryptedSize); + processed += encryptedSize; + encrypted = 0; + encryptedSize = 0; + } + } while (processed < size); + return processed; +} + +bool CyrusSecurityLayer::canEncode() +{ + return encrypted || codec->canEncode(); +} + +void CyrusSecurityLayer::init(qpid::sys::Codec* c) +{ + codec = c; +} + +CyrusSecurityLayer::DataBuffer::DataBuffer(size_t s) : position(0), size(s) +{ + data = new char[size]; +} + +CyrusSecurityLayer::DataBuffer::~DataBuffer() +{ + delete[] data; +} + +}}} // namespace qpid::sys::cyrus diff --git a/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.h b/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.h new file mode 100644 index 0000000000..3c00d496a9 --- /dev/null +++ b/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.h @@ -0,0 +1,66 @@ +#ifndef QPID_SYS_CYRUS_CYRUSSECURITYLAYER_H +#define QPID_SYS_CYRUS_CYRUSSECURITYLAYER_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/IntegerTypes.h" +#include "qpid/sys/SecurityLayer.h" +#include <sasl/sasl.h> + +namespace qpid { +namespace sys { +namespace cyrus { + + +/** + * Implementation of SASL security layer using cyrus-sasl library + */ +class CyrusSecurityLayer : public qpid::sys::SecurityLayer +{ + public: + CyrusSecurityLayer(sasl_conn_t*, uint16_t maxFrameSize); + size_t decode(const char* buffer, size_t size); + size_t encode(const char* buffer, size_t size); + bool canEncode(); + void init(qpid::sys::Codec*); + private: + struct DataBuffer + { + char* data; + size_t position; + const size_t size; + DataBuffer(size_t); + ~DataBuffer(); + }; + + sasl_conn_t* conn; + const char* decrypted; + unsigned decryptedSize; + const char* encrypted; + unsigned encryptedSize; + qpid::sys::Codec* codec; + size_t maxInputSize; + DataBuffer decodeBuffer; +}; +}}} // namespace qpid::sys::cyrus + +#endif /*!QPID_SYS_CYRUS_CYRUSSECURITYLAYER_H*/ |