2  * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  25 #include <utilities/SecCFError.h> 
  26 #include <utilities/SecCFRelease.h> 
  27 #include <utilities/debugging.h> 
  32 // OSStatus values we magically know 
  35     parameterError                
= -50,     /* One or more parameters passed to a function were not valid. */ 
  36     allocationError               
= -108,    /* Failed to allocate memory. */ 
  39 bool SecKernError(kern_return_t result
, CFErrorRef 
*error
, CFStringRef format
, ...) { 
  40     if (!result
) return true; 
  43         CFIndex code 
= result
; 
  44         CFErrorRef previousError 
= *error
; 
  47         va_start(args
, format
); 
  48         SecCFCreateErrorWithFormatAndArguments(code
, kSecKernDomain
, previousError
, error
, NULL
, format
, args
); 
  54 bool SecCheckErrno(int result
, CFErrorRef 
*error
, CFStringRef format
, ...) { 
  55     if (result 
== 0) return true; 
  59         CFIndex code 
= errnum
; 
  60         CFErrorRef previousError 
= *error
; 
  63         va_start(args
, format
); 
  64         CFStringRef message 
= CFStringCreateWithFormatAndArguments(kCFAllocatorDefault
, NULL
, format
, args
); 
  66         SecCFCreateErrorWithFormat(code
, kSecErrnoDomain
, previousError
, error
, NULL
, CFSTR("%@: [%d] %s"), message
, errnum
, strerror(errnum
)); 
  67         CFReleaseSafe(message
); 
  72 bool SecPOSIXError(int error
, CFErrorRef 
*cferror
, CFStringRef format
, ...) 
  74         if (error 
== 0) return true; 
  78                 CFErrorRef previousError 
= *cferror
; 
  81                 va_start(args
, format
); 
  82                 SecCFCreateErrorWithFormatAndArguments(code
, kSecErrnoDomain
, previousError
, cferror
, NULL
, format
, args
); 
  88 bool SecCoreCryptoError(int error
, CFErrorRef 
*cferror
, CFStringRef format
, ...) 
  90         if (error 
== 0) return true; 
  94                 CFErrorRef previousError 
= *cferror
; 
  97                 va_start(args
, format
); 
  98                 SecCFCreateErrorWithFormatAndArguments(code
, kSecCoreCryptoDomain
, previousError
, cferror
, NULL
, format
, args
); 
 105 bool SecNotifyError(uint32_t result
, CFErrorRef 
*error
, CFStringRef format
, ...) { 
 106     if (result 
== NOTIFY_STATUS_OK
) return true; 
 109         CFIndex code 
= result
; 
 110         CFErrorRef previousError 
= *error
; 
 113         va_start(args
, format
); 
 114         SecCFCreateErrorWithFormatAndArguments(code
, kSecNotifyDomain
, previousError
, error
, NULL
, format
, args
); 
 120 bool SecError(OSStatus status
, CFErrorRef 
*error
, CFStringRef format
, ...) { 
 121     if (status 
== 0) return true; 
 124         CFIndex code 
= status
; 
 125         CFErrorRef previousError 
= *error
; 
 128         va_start(args
, format
); 
 129         SecCFCreateErrorWithFormatAndArguments(code
, kSecErrorDomain
, previousError
, error
, NULL
, format
, args
); 
 136 bool SecRequirementError(bool requirement
, CFErrorRef 
*error
, CFStringRef format
, ...) { 
 137     if (requirement
) return true; 
 140         CFErrorRef previousError 
= *error
; 
 143         va_start(args
, format
); 
 144         SecCFCreateErrorWithFormatAndArguments(parameterError
, kSecErrorDomain
, previousError
, error
, NULL
, format
, args
); 
 150 // Allocation failure 
 151 bool SecAllocationError(const void *allocated
, CFErrorRef 
*error
, CFStringRef format
, ...) { 
 152     if (allocated
) return true; 
 155         CFErrorRef previousError 
= *error
; 
 158         va_start(args
, format
); 
 159         SecCFCreateErrorWithFormatAndArguments(allocationError
, kSecErrorDomain
, previousError
, error
, NULL
, format
, args
); 
 166 bool SecCFCreateError(CFIndex errorCode
, CFStringRef domain
, CFStringRef descriptionString
, 
 167                       CFErrorRef previousError
, CFErrorRef 
*newError
) 
 169 #pragma clang diagnostic push 
 170 #pragma GCC diagnostic ignored "-Wformat-security" 
 171     return SecCFCreateErrorWithFormat(errorCode
, domain
, previousError
, newError
, NULL
, descriptionString
); 
 172 #pragma clang diagnostic pop 
 175 bool SecCFCreateErrorWithFormat(CFIndex errorCode
, CFStringRef domain
, CFErrorRef previousError
, CFErrorRef 
*newError
, 
 176                                 CFDictionaryRef formatoptions
, CFStringRef format
, ...) 
 179     va_start(args
, format
); 
 181     bool result 
= SecCFCreateErrorWithFormatAndArguments(errorCode
, domain
, previousError
, newError
, formatoptions
, format
, args
); 
 188 bool SecCFCreateErrorWithFormatAndArguments(CFIndex errorCode
, CFStringRef domain
, 
 189                                             CFErrorRef previousError
, CFErrorRef 
*newError
, 
 190                                             CFDictionaryRef formatoptions
, CFStringRef format
, va_list args
) 
 192     if (newError 
&& !(*newError
)) { 
 193         CFStringRef formattedString 
= CFStringCreateWithFormatAndArguments(NULL
, formatoptions
, format
, args
); 
 195         const void* keys
[2] =   { kCFErrorDescriptionKey
,   kCFErrorUnderlyingErrorKey
}; 
 196         const void* values
[2] = { formattedString
,          previousError 
}; 
 197         const CFIndex numEntriesToUse 
= (previousError 
!= NULL
) ? 2 : 1; 
 199         *newError 
= CFErrorCreateWithUserInfoKeysAndValues(kCFAllocatorDefault
, domain
, errorCode
, 
 200                                                            keys
, values
, numEntriesToUse
); 
 202         CFReleaseNull(formattedString
); 
 204             secdebug("error_thee_well", "encapsulated %@ with new error: %@", previousError
, *newError
); 
 206         if (previousError 
&& newError 
&& (previousError 
!= *newError
)) { 
 207             secdebug("error_thee_well", "dropping %@", previousError
); 
 208             CFRelease(previousError
); 
 213         secdebug("error_thee_well", "SecError: %@", *newError
);