1/* 2 * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <security_utilities/seccfobject.h> 25#include <security_utilities/cfclass.h> 26#include <security_utilities/errors.h> 27#include <security_utilities/debugging.h> 28 29#include <list> 30#include <security_utilities/globalizer.h> 31#include <auto_zone.h> 32 33SecPointerBase::SecPointerBase(const SecPointerBase& p) 34{ 35 if (p.ptr) 36 { 37 CFRetain(p.ptr->operator CFTypeRef()); 38 } 39 ptr = p.ptr; 40} 41 42 43 44 45static void CheckForRelease(SecCFObject* ptr) 46{ 47 CFTypeRef tr = ptr->operator CFTypeRef(); 48 CFIndex retainCount = CFGetRetainCount(tr); 49 if (retainCount == 1 || retainCount == -1) 50 { 51 ptr->aboutToDestruct(); 52 } 53} 54 55 56 57SecPointerBase::SecPointerBase(SecCFObject *p) 58{ 59 if (p && !p->isNew()) 60 { 61 CFRetain(p->operator CFTypeRef()); 62 } 63 ptr = p; 64} 65 66 67 68SecPointerBase::~SecPointerBase() 69{ 70 if (ptr) 71 { 72 CheckForRelease(ptr); 73 CFRelease(ptr->operator CFTypeRef()); 74 } 75} 76 77 78 79SecPointerBase& SecPointerBase::operator = (const SecPointerBase& p) 80{ 81 if (p.ptr) 82 { 83 CFTypeRef tr = p.ptr->operator CFTypeRef(); 84 CFRetain(tr); 85 } 86 if (ptr) 87 { 88 CheckForRelease(ptr); 89 CFRelease(ptr->operator CFTypeRef()); 90 } 91 ptr = p.ptr; 92 return *this; 93} 94 95 96 97void SecPointerBase::assign(SecCFObject * p) 98{ 99 if (p && !p->isNew()) 100 { 101 CFRetain(p->operator CFTypeRef()); 102 } 103 if (ptr) 104 { 105 CheckForRelease(ptr); 106 CFRelease(ptr->operator CFTypeRef()); 107 } 108 ptr = p; 109} 110 111 112 113void SecPointerBase::copy(SecCFObject * p) 114{ 115 if (ptr) 116 { 117 CheckForRelease(ptr); 118 CFRelease(ptr->operator CFTypeRef()); 119 } 120 121 ptr = p; 122} 123 124 125 126// 127// SecCFObject 128// 129SecCFObject * 130SecCFObject::optional(CFTypeRef cfTypeRef) throw() 131{ 132 if (!cfTypeRef) 133 return NULL; 134 135 return const_cast<SecCFObject *>(reinterpret_cast<const SecCFObject *>(reinterpret_cast<const uint8_t *>(cfTypeRef) + kAlignedRuntimeSize)); 136} 137 138SecCFObject * 139SecCFObject::required(CFTypeRef cfTypeRef, OSStatus error) 140{ 141 SecCFObject *object = optional(cfTypeRef); 142 if (!object) 143 MacOSError::throwMe(error); 144 145 return object; 146} 147 148void * 149SecCFObject::allocate(size_t size, const CFClass &cfclass) throw(std::bad_alloc) 150{ 151 CFTypeRef p = _CFRuntimeCreateInstance(NULL, cfclass.typeID, 152 size + kAlignedRuntimeSize - sizeof(CFRuntimeBase), NULL); 153 if (p == NULL) 154 throw std::bad_alloc(); 155 156 ((SecRuntimeBase*) p)->isNew = true; 157 158 void *q = ((u_int8_t*) p) + kAlignedRuntimeSize; 159 160 if (SECURITY_DEBUG_SEC_CREATE_ENABLED()) { 161 const CFRuntimeClass *rtc = _CFRuntimeGetClassWithTypeID(cfclass.typeID); 162 SECURITY_DEBUG_SEC_CREATE(q, rtc ? (char *)rtc->className : NULL, (unsigned int)cfclass.typeID); 163 } 164 return q; 165} 166 167void 168SecCFObject::operator delete(void *object) throw() 169{ 170 CFTypeRef cfType = reinterpret_cast<CFTypeRef>(reinterpret_cast<const uint8_t *>(object) - kAlignedRuntimeSize); 171 if (CF_IS_COLLECTABLE(cfType)) 172 { 173 return; 174 } 175 176 CFAllocatorRef allocator = CFGetAllocator(cfType); 177 CFAllocatorDeallocate(allocator, (void*) cfType); 178} 179 180SecCFObject::SecCFObject() 181{ 182 mRetainCount = 1; 183 mRetainSpinLock = OS_SPINLOCK_INIT; 184} 185 186uint32_t SecCFObject::updateRetainCount(intptr_t direction, uint32_t *oldCount) 187{ 188 OSSpinLockLock(&mRetainSpinLock); 189 190 if (oldCount != NULL) 191 { 192 *oldCount = mRetainCount; 193 } 194 195 if (direction != -1 || mRetainCount != 0) 196 { 197 // if we are decrementing 198 if (direction == -1 || UINT32_MAX != mRetainCount) 199 { 200 mRetainCount += direction; 201 } 202 } 203 204 uint32_t result = mRetainCount; 205 206 OSSpinLockUnlock(&mRetainSpinLock); 207 208 return result; 209} 210 211 212 213SecCFObject::~SecCFObject() 214{ 215 SECURITY_DEBUG_SEC_DESTROY(this); 216} 217 218bool 219SecCFObject::equal(SecCFObject &other) 220{ 221 return this == &other; 222} 223 224CFHashCode 225SecCFObject::hash() 226{ 227 return CFHashCode(this); 228} 229 230CFStringRef 231SecCFObject::copyFormattingDesc(CFDictionaryRef dict) 232{ 233 return NULL; 234} 235 236CFStringRef 237SecCFObject::copyDebugDesc() 238{ 239 return NULL; 240} 241 242CFTypeRef 243SecCFObject::handle(bool retain) throw() 244{ 245 CFTypeRef cfType = *this; 246 if (retain && !isNew()) CFRetain(cfType); 247 return cfType; 248} 249 250 251 252void 253SecCFObject::aboutToDestruct() 254{ 255} 256 257 258 259Mutex* 260SecCFObject::getMutexForObject() 261{ 262 return NULL; // we only worry about descendants of KeychainImpl and ItemImpl 263} 264 265 266 267bool SecCFObject::mayDelete() 268{ 269 return true; 270} 271