]> git.saurik.com Git - apple/security.git/blob - OSX/utilities/SecCFError.c
Security-59306.11.20.tar.gz
[apple/security.git] / OSX / utilities / SecCFError.c
1 /*
2 * Copyright (c) 2012-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
25 #include <utilities/SecCFError.h>
26 #include <utilities/SecCFRelease.h>
27 #include <utilities/debugging.h>
28 #include <notify.h>
29
30
31 //
32 // OSStatus values we magically know
33 //
34 enum {
35 parameterError = -50, /* One or more parameters passed to a function were not valid. */
36 allocationError = -108, /* Failed to allocate memory. */
37 };
38
39 bool SecKernError(kern_return_t result, CFErrorRef *error, CFStringRef format, ...) {
40 if (!result) return true;
41 if (error) {
42 va_list args;
43 CFIndex code = result;
44 CFErrorRef previousError = *error;
45
46 *error = NULL;
47 va_start(args, format);
48 SecCFCreateErrorWithFormatAndArguments(code, kSecKernDomain, previousError, error, NULL, format, args);
49 va_end(args);
50 }
51 return false;
52 }
53
54 bool SecCheckErrno(int result, CFErrorRef *error, CFStringRef format, ...) {
55 if (result == 0) return true;
56 if (error) {
57 va_list args;
58 int errnum = errno;
59 CFIndex code = errnum;
60 CFErrorRef previousError = *error;
61
62 *error = NULL;
63 va_start(args, format);
64 CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, format, args);
65 va_end(args);
66 SecCFCreateErrorWithFormat(code, kSecErrnoDomain, previousError, error, NULL, CFSTR("%@: [%d] %s"), message, errnum, strerror(errnum));
67 CFReleaseSafe(message);
68 }
69 return false;
70 }
71
72 bool SecPOSIXError(int error, CFErrorRef *cferror, CFStringRef format, ...)
73 {
74 if (error == 0) return true;
75 if (error) {
76 va_list args;
77 CFIndex code = error;
78 CFErrorRef previousError = *cferror;
79
80 *cferror = NULL;
81 va_start(args, format);
82 SecCFCreateErrorWithFormatAndArguments(code, kSecErrnoDomain, previousError, cferror, NULL, format, args);
83 va_end(args);
84 }
85 return false;
86 }
87
88 bool SecCoreCryptoError(int error, CFErrorRef *cferror, CFStringRef format, ...)
89 {
90 if (error == 0) return true;
91 if (error) {
92 va_list args;
93 CFIndex code = error;
94 CFErrorRef previousError = *cferror;
95
96 *cferror = NULL;
97 va_start(args, format);
98 SecCFCreateErrorWithFormatAndArguments(code, kSecCoreCryptoDomain, previousError, cferror, NULL, format, args);
99 va_end(args);
100 }
101 return false;
102 }
103
104
105 bool SecNotifyError(uint32_t result, CFErrorRef *error, CFStringRef format, ...) {
106 if (result == NOTIFY_STATUS_OK) return true;
107 if (error) {
108 va_list args;
109 CFIndex code = result;
110 CFErrorRef previousError = *error;
111
112 *error = NULL;
113 va_start(args, format);
114 SecCFCreateErrorWithFormatAndArguments(code, kSecNotifyDomain, previousError, error, NULL, format, args);
115 va_end(args);
116 }
117 return false;
118 }
119
120 bool SecError(OSStatus status, CFErrorRef *error, CFStringRef format, ...) {
121 if (status == 0) return true;
122 if (error) {
123 va_list args;
124 CFIndex code = status;
125 CFErrorRef previousError = *error;
126
127 *error = NULL;
128 va_start(args, format);
129 SecCFCreateErrorWithFormatAndArguments(code, kSecErrorDomain, previousError, error, NULL, format, args);
130 va_end(args);
131 }
132 return false;
133 }
134
135 // Parameter error
136 bool SecRequirementError(bool requirement, CFErrorRef *error, CFStringRef format, ...) {
137 if (requirement) return true;
138 if (error) {
139 va_list args;
140 CFErrorRef previousError = *error;
141
142 *error = NULL;
143 va_start(args, format);
144 SecCFCreateErrorWithFormatAndArguments(parameterError, kSecErrorDomain, previousError, error, NULL, format, args);
145 va_end(args);
146 }
147 return false;
148 }
149
150 // Allocation failure
151 bool SecAllocationError(const void *allocated, CFErrorRef *error, CFStringRef format, ...) {
152 if (allocated) return true;
153 if (error) {
154 va_list args;
155 CFErrorRef previousError = *error;
156
157 *error = NULL;
158 va_start(args, format);
159 SecCFCreateErrorWithFormatAndArguments(allocationError, kSecErrorDomain, previousError, error, NULL, format, args);
160 va_end(args);
161 }
162 return false;
163 }
164
165 bool SecCFCreateErrorWithFormat(CFIndex errorCode, CFStringRef domain, CFErrorRef previousError, CFErrorRef *newError,
166 CFDictionaryRef formatoptions, CFStringRef format, ...)
167 {
168 va_list args;
169 va_start(args, format);
170
171 bool result = SecCFCreateErrorWithFormatAndArguments(errorCode, domain, previousError, newError, formatoptions, format, args);
172
173 va_end(args);
174
175 return result;
176 }
177
178 // Also consumes whatever newError points to
179 bool SecCFCreateErrorWithFormatAndArguments(CFIndex errorCode, CFStringRef domain,
180 CF_CONSUMED CFErrorRef previousError, CFErrorRef *newError,
181 CFDictionaryRef formatoptions, CFStringRef format, va_list args)
182 {
183 if (newError && !(*newError)) {
184 CFStringRef formattedString = CFStringCreateWithFormatAndArguments(NULL, formatoptions, format, args);
185
186 const void* keys[2] = { kCFErrorDescriptionKey, kCFErrorUnderlyingErrorKey};
187 const void* values[2] = { formattedString, previousError };
188 const CFIndex numEntriesToUse = (previousError != NULL) ? 2 : 1;
189
190 // Prepare to release whatever we replaced, as long as they didn't tell us to do so via previousError
191 // In a sane world, this function wouldn't have a previousError argument, since it should always release what it's replacing,
192 // but changing all callsites is a huge change
193 CFErrorRef replacing = ((*newError) == previousError) ? NULL : *newError;
194
195 *newError = CFErrorCreateWithUserInfoKeysAndValues(kCFAllocatorDefault, domain, errorCode,
196 keys, values, numEntriesToUse);
197
198 CFReleaseNull(formattedString);
199 if (previousError)
200 secdebug("error_thee_well", "encapsulated %@ with new error: %@", previousError, *newError);
201
202 CFReleaseNull(replacing);
203 CFReleaseNull(previousError);
204 } else {
205 if (previousError && newError && (previousError != *newError)) {
206 secdebug("error_thee_well", "dropping %@", previousError);
207 CFRelease(previousError);
208 }
209 }
210
211 if (newError)
212 secdebug("error_thee_well", "SecError: %@", *newError);
213
214
215 return false;
216 }