1 /* 2 * libjingle 3 * Copyright 2004--2005, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 // @file Contains utility classes that make it easier to use SecBuffers 29 30 #ifndef TALK_BASE_SEC_BUFFER_H__ 31 #define TALK_BASE_SEC_BUFFER_H__ 32 33 namespace talk_base { 34 35 // A base class for CSecBuffer<T>. Contains 36 // all implementation that does not require 37 // template arguments. 38 class CSecBufferBase : public SecBuffer { 39 public: 40 CSecBufferBase() { 41 Clear(); 42 } 43 44 // Uses the SSPI to free a pointer, must be 45 // used for buffers returned from SSPI APIs. 46 static void FreeSSPI(void *ptr) { 47 if ( ptr ) { 48 SECURITY_STATUS status; 49 status = ::FreeContextBuffer(ptr); 50 ASSERT(SEC_E_OK == status); // "Freeing context buffer" 51 } 52 } 53 54 // Deletes a buffer with operator delete 55 static void FreeDelete(void *ptr) { 56 delete [] reinterpret_cast<char*>(ptr); 57 } 58 59 // A noop delete, for buffers over other 60 // people's memory 61 static void FreeNone(void *ptr) { 62 } 63 64 protected: 65 // Clears the buffer to EMPTY & NULL 66 void Clear() { 67 this->BufferType = SECBUFFER_EMPTY; 68 this->cbBuffer = 0; 69 this->pvBuffer = NULL; 70 } 71 }; 72 73 // Wrapper class for SecBuffer to take care 74 // of initialization and destruction. 75 template <void (*pfnFreeBuffer)(void *ptr)> 76 class CSecBuffer: public CSecBufferBase { 77 public: 78 // Initializes buffer to empty & NULL 79 CSecBuffer() { 80 } 81 82 // Frees any allocated memory 83 ~CSecBuffer() { 84 Release(); 85 } 86 87 // Frees the buffer appropriately, and re-nulls 88 void Release() { 89 pfnFreeBuffer(this->pvBuffer); 90 Clear(); 91 } 92 93 private: 94 // A placeholder function for compile-time asserts on the class 95 void CompileAsserts() { 96 // never invoked... 97 assert(false); // _T("Notreached") 98 99 // This class must not extend the size of SecBuffer, since 100 // we use arrays of CSecBuffer in CSecBufferBundle below 101 cassert(sizeof(CSecBuffer<SSPIFree> == sizeof(SecBuffer))); 102 } 103 }; 104 105 // Contains all generic implementation for the 106 // SecBufferBundle class 107 class SecBufferBundleBase { 108 public: 109 }; 110 111 // A template class that bundles a SecBufferDesc with 112 // one or more SecBuffers for convenience. Can take 113 // care of deallocating buffers appropriately, as indicated 114 // by pfnFreeBuffer function. 115 // By default does no deallocation. 116 template <int num_buffers, 117 void (*pfnFreeBuffer)(void *ptr) = CSecBufferBase::FreeNone> 118 class CSecBufferBundle : public SecBufferBundleBase { 119 public: 120 // Constructs a security buffer bundle with num_buffers 121 // buffers, all of which are empty and nulled. 122 CSecBufferBundle() { 123 desc_.ulVersion = SECBUFFER_VERSION; 124 desc_.cBuffers = num_buffers; 125 desc_.pBuffers = buffers_; 126 } 127 128 // Frees all currently used buffers. 129 ~CSecBufferBundle() { 130 Release(); 131 } 132 133 // Accessor for the descriptor 134 PSecBufferDesc desc() { 135 return &desc_; 136 } 137 138 // Accessor for the descriptor 139 const PSecBufferDesc desc() const { 140 return &desc_; 141 } 142 143 // returns the i-th security buffer 144 SecBuffer &operator[] (size_t num) { 145 ASSERT(num < num_buffers); // "Buffer index out of bounds" 146 return buffers_[num]; 147 } 148 149 // returns the i-th security buffer 150 const SecBuffer &operator[] (size_t num) const { 151 ASSERT(num < num_buffers); // "Buffer index out of bounds" 152 return buffers_[num]; 153 } 154 155 // Frees all non-NULL security buffers, 156 // using the deallocation function 157 void Release() { 158 for ( size_t i = 0; i < num_buffers; ++i ) { 159 buffers_[i].Release(); 160 } 161 } 162 163 private: 164 // Our descriptor 165 SecBufferDesc desc_; 166 // Our bundled buffers, each takes care of its own 167 // initialization and destruction 168 CSecBuffer<pfnFreeBuffer> buffers_[num_buffers]; 169 }; 170 171 } // namespace talk_base 172 173 #endif // TALK_BASE_SEC_BUFFER_H__ 174