/* * libjingle * Copyright 2004--2005, Google Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // @file Contains utility classes that make it easier to use SecBuffers #ifndef TALK_BASE_SEC_BUFFER_H__ #define TALK_BASE_SEC_BUFFER_H__ namespace talk_base { // A base class for CSecBuffer<T>. Contains // all implementation that does not require // template arguments. class CSecBufferBase : public SecBuffer { public: CSecBufferBase() { Clear(); } // Uses the SSPI to free a pointer, must be // used for buffers returned from SSPI APIs. static void FreeSSPI(void *ptr) { if ( ptr ) { SECURITY_STATUS status; status = ::FreeContextBuffer(ptr); ASSERT(SEC_E_OK == status); // "Freeing context buffer" } } // Deletes a buffer with operator delete static void FreeDelete(void *ptr) { delete [] reinterpret_cast<char*>(ptr); } // A noop delete, for buffers over other // people's memory static void FreeNone(void *ptr) { } protected: // Clears the buffer to EMPTY & NULL void Clear() { this->BufferType = SECBUFFER_EMPTY; this->cbBuffer = 0; this->pvBuffer = NULL; } }; // Wrapper class for SecBuffer to take care // of initialization and destruction. template <void (*pfnFreeBuffer)(void *ptr)> class CSecBuffer: public CSecBufferBase { public: // Initializes buffer to empty & NULL CSecBuffer() { } // Frees any allocated memory ~CSecBuffer() { Release(); } // Frees the buffer appropriately, and re-nulls void Release() { pfnFreeBuffer(this->pvBuffer); Clear(); } private: // A placeholder function for compile-time asserts on the class void CompileAsserts() { // never invoked... assert(false); // _T("Notreached") // This class must not extend the size of SecBuffer, since // we use arrays of CSecBuffer in CSecBufferBundle below cassert(sizeof(CSecBuffer<SSPIFree> == sizeof(SecBuffer))); } }; // Contains all generic implementation for the // SecBufferBundle class class SecBufferBundleBase { public: }; // A template class that bundles a SecBufferDesc with // one or more SecBuffers for convenience. Can take // care of deallocating buffers appropriately, as indicated // by pfnFreeBuffer function. // By default does no deallocation. template <int num_buffers, void (*pfnFreeBuffer)(void *ptr) = CSecBufferBase::FreeNone> class CSecBufferBundle : public SecBufferBundleBase { public: // Constructs a security buffer bundle with num_buffers // buffers, all of which are empty and nulled. CSecBufferBundle() { desc_.ulVersion = SECBUFFER_VERSION; desc_.cBuffers = num_buffers; desc_.pBuffers = buffers_; } // Frees all currently used buffers. ~CSecBufferBundle() { Release(); } // Accessor for the descriptor PSecBufferDesc desc() { return &desc_; } // Accessor for the descriptor const PSecBufferDesc desc() const { return &desc_; } // returns the i-th security buffer SecBuffer &operator[] (size_t num) { ASSERT(num < num_buffers); // "Buffer index out of bounds" return buffers_[num]; } // returns the i-th security buffer const SecBuffer &operator[] (size_t num) const { ASSERT(num < num_buffers); // "Buffer index out of bounds" return buffers_[num]; } // Frees all non-NULL security buffers, // using the deallocation function void Release() { for ( size_t i = 0; i < num_buffers; ++i ) { buffers_[i].Release(); } } private: // Our descriptor SecBufferDesc desc_; // Our bundled buffers, each takes care of its own // initialization and destruction CSecBuffer<pfnFreeBuffer> buffers_[num_buffers]; }; } // namespace talk_base #endif // TALK_BASE_SEC_BUFFER_H__