]> git.saurik.com Git - apple/security.git/blob - OSX/utilities/src/iCloudKeychainTrace.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / utilities / src / iCloudKeychainTrace.c
1 /*
2 * Copyright (c) 2013-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 "iCloudKeychainTrace.h"
26 #include <TargetConditionals.h>
27 #include <inttypes.h>
28 #include "SecCFWrappers.h"
29 #include <sys/time.h>
30 #include <CoreFoundation/CoreFoundation.h>
31
32 const CFStringRef kNumberOfiCloudKeychainPeers = CFSTR("numberOfPeers");
33 const CFStringRef kNumberOfiCloudKeychainItemsBeingSynced = CFSTR("numberOfItemsBeingSynced");
34 const CFStringRef kCloudKeychainNumberOfSyncingConflicts = CFSTR("conflictsCount");
35 const CFStringRef kCloudKeychainNumberOfTimesSyncFailed = CFSTR("syncFailureCount");
36 const CFStringRef kCloudKeychainNumberOfConflictsResolved = CFSTR("conflictsResolved");
37 const CFStringRef kCloudKeychainNumberOfTimesSyncedWithPeers = CFSTR("syncedWithPeers");
38
39 #if !TARGET_IPHONE_SIMULATOR
40 static const char* gTopLevelKeyForiCloudKeychainTracing = "com.apple.icdp";
41 #endif
42
43 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR))
44 #include <asl.h>
45
46 static const char* gMessageTracerSetPrefix = "com.apple.message.";
47
48 static const char* gMessageTracerDomainField = "com.apple.message.domain";
49
50 /* --------------------------------------------------------------------------
51 Function: OSX_BeginCloudKeychainLoggingTransaction
52
53 Description: For OSX the message tracer back end wants its logging
54 done in "bunches". This function allows for beginning
55 a 'transaction' of logging which will allow for putting
56 all of the transactions items into a single log making
57 the message tracer folks happy.
58
59 The work of this function is to create the aslmsg context
60 and set the domain field and then return the aslmsg
61 context as a void*
62 -------------------------------------------------------------------------- */
63 static void* OSX_BeginCloudKeychainLoggingTransaction()
64 {
65 void* result = NULL;
66 aslmsg mAsl = NULL;
67 mAsl = asl_new(ASL_TYPE_MSG);
68 if (NULL == mAsl)
69 {
70 return result;
71 }
72
73 asl_set(mAsl, gMessageTracerDomainField, gTopLevelKeyForiCloudKeychainTracing);
74
75 result = (void *)mAsl;
76 return result;
77 }
78
79 /* --------------------------------------------------------------------------
80 Function: OSX_AddKeyValuePairToKeychainLoggingTransaction
81
82 Description: Once a call to OSX_BeginCloudKeychainLoggingTransaction
83 is done, this call all allow for adding items to the
84 "bunch" of items being logged.
85
86 NOTE: The key should be a simple key such as
87 "numberOfPeers". This is because this function will
88 apptend the required prefix of "com.apple.message."
89 -------------------------------------------------------------------------- */
90 static bool OSX_AddKeyValuePairToKeychainLoggingTransaction(void* token, CFStringRef key, int64_t value)
91 {
92 if (NULL == token || NULL == key)
93 {
94 return false;
95 }
96
97 aslmsg mAsl = (aslmsg)token;
98
99 // Fix up the key
100 CFStringRef real_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%@"), gMessageTracerSetPrefix, key);
101 if (NULL == real_key)
102 {
103 return false;
104 }
105
106 CFIndex key_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(real_key), kCFStringEncodingUTF8);
107 key_length += 1; // For null
108 char key_buffer[key_length];
109 memset(key_buffer, 0,key_length);
110 if (!CFStringGetCString(real_key, key_buffer, key_length, kCFStringEncodingUTF8))
111 {
112 CFRelease(real_key);
113 return false;
114 }
115 CFRelease(real_key);
116
117 CFStringRef value_str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%lld"), value);
118 if (NULL == value_str)
119 {
120 return false;
121 }
122
123 CFIndex value_str_numBytes = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value_str), kCFStringEncodingUTF8);
124 value_str_numBytes += 1; // For null
125 char value_buffer[value_str_numBytes];
126 memset(value_buffer, 0, value_str_numBytes);
127 if (!CFStringGetCString(value_str, value_buffer, value_str_numBytes, kCFStringEncodingUTF8))
128 {
129 CFRelease(value_str);
130 return false;
131 }
132 CFRelease(value_str);
133
134 asl_set(mAsl, key_buffer, value_buffer);
135 return true;
136 }
137
138 /* --------------------------------------------------------------------------
139 Function: OSX_CloseCloudKeychainLoggingTransaction
140
141 Description: Once a call to OSX_BeginCloudKeychainLoggingTransaction
142 is done, and all of the items that are to be in the
143 "bunch" of items being logged, this function will do the
144 real logging and free the aslmsg context.
145 -------------------------------------------------------------------------- */
146 static void OSX_CloseCloudKeychainLoggingTransaction(void* token)
147 {
148 if (NULL != token)
149 {
150 aslmsg mAsl = (aslmsg)token;
151 asl_log(NULL, mAsl, ASL_LEVEL_NOTICE, "");
152 asl_free(mAsl);
153 }
154 }
155
156 /* --------------------------------------------------------------------------
157 Function: OSX_SetCloudKeychainTraceValueForKey
158
159 Description: If "bunching" of items either cannot be done or is not
160 desired, then this 'single shot' function shold be used.
161 It will create the aslmsg context, register the domain
162 fix up the key and log the key value pair and then
163 do the real logging and free the aslmsg context.
164 -------------------------------------------------------------------------- */
165 static bool OSX_SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value)
166 {
167 bool result = false;
168
169 if (NULL == key)
170 {
171 return result;
172 }
173
174 aslmsg mAsl = NULL;
175 mAsl = asl_new(ASL_TYPE_MSG);
176 if (NULL == mAsl)
177 {
178 return result;
179 }
180
181 // Fix up the key
182 CFStringRef real_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%@"), gMessageTracerSetPrefix, key);
183 if (NULL == real_key)
184 {
185 return false;
186 }
187
188 CFIndex key_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(real_key), kCFStringEncodingUTF8);
189 key_length += 1; // For null
190 char key_buffer[key_length];
191 memset(key_buffer, 0,key_length);
192 if (!CFStringGetCString(real_key, key_buffer, key_length, kCFStringEncodingUTF8))
193 {
194 CFRelease(real_key);
195 return false;
196 }
197 CFRelease(real_key);
198
199
200 CFStringRef value_str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%lld"), value);
201 if (NULL == value_str)
202 {
203 asl_free(mAsl);
204 return result;
205 }
206
207 CFIndex value_str_numBytes = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value_str), kCFStringEncodingUTF8);
208 value_str_numBytes += 1; // For null
209 char value_buffer[value_str_numBytes];
210 memset(value_buffer, 0, value_str_numBytes);
211 if (!CFStringGetCString(value_str, value_buffer, value_str_numBytes, kCFStringEncodingUTF8))
212 {
213 asl_free(mAsl);
214 CFRelease(value_str);
215 return result;
216 }
217 CFRelease(value_str);
218
219 asl_set(mAsl, gMessageTracerDomainField, gTopLevelKeyForiCloudKeychainTracing);
220
221 asl_set(mAsl, key_buffer, value_buffer);
222 asl_log(NULL, mAsl, ASL_LEVEL_NOTICE, "%s is %lld", key_buffer, value);
223 asl_free(mAsl);
224 return true;
225
226 }
227 #endif
228
229 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
230
231 typedef void (*type_ADClientClearScalarKey)(CFStringRef key);
232 typedef void (*type_ADClientSetValueForScalarKey)(CFStringRef key, int64_t value);
233
234 static type_ADClientClearScalarKey gADClientClearScalarKey = NULL;
235 static type_ADClientSetValueForScalarKey gADClientSetValueForScalarKey = NULL;
236
237 static dispatch_once_t gADFunctionPointersSet = 0;
238 static CFBundleRef gAggdBundleRef = NULL;
239 static bool gFunctionPointersAreLoaded = false;
240
241 /* --------------------------------------------------------------------------
242 Function: InitializeADFunctionPointers
243
244 Description: Linking to the Aggregate library causes a build cycle so
245 This function will dynamically load the needed function
246 pointers.
247 -------------------------------------------------------------------------- */
248 static bool InitializeADFunctionPointers()
249 {
250 if (gFunctionPointersAreLoaded)
251 {
252 return gFunctionPointersAreLoaded;
253 }
254
255 dispatch_once(&gADFunctionPointersSet,
256 ^{
257 CFStringRef path_to_aggd_framework = CFSTR("/System/Library/PrivateFrameworks/AggregateDictionary.framework");
258
259 CFURLRef aggd_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_to_aggd_framework, kCFURLPOSIXPathStyle, true);
260
261 if (NULL != aggd_url)
262 {
263 gAggdBundleRef = CFBundleCreate(kCFAllocatorDefault, aggd_url);
264 if (NULL != gAggdBundleRef)
265 {
266 gADClientClearScalarKey = (type_ADClientClearScalarKey)
267 CFBundleGetFunctionPointerForName(gAggdBundleRef, CFSTR("ADClientClearScalarKey"));
268
269 gADClientSetValueForScalarKey = (type_ADClientSetValueForScalarKey)
270 CFBundleGetFunctionPointerForName(gAggdBundleRef, CFSTR("ADClientSetValueForScalarKey"));
271 }
272 CFRelease(aggd_url);
273 }
274 });
275
276 gFunctionPointersAreLoaded = ((NULL != gADClientClearScalarKey) && (NULL != gADClientSetValueForScalarKey));
277 return gFunctionPointersAreLoaded;
278 }
279
280 /* --------------------------------------------------------------------------
281 Function: Internal_ADClientClearScalarKey
282
283 Description: This fucntion is a wrapper around calling the
284 ADClientClearScalarKey function.
285
286 NOTE: The key should be a simple key such as
287 "numberOfPeers". This is because this function will
288 apptend the required prefix of "com.apple.cloudkeychain"
289 -------------------------------------------------------------------------- */
290 static void Internal_ADClientClearScalarKey(CFStringRef key)
291 {
292 if (InitializeADFunctionPointers())
293 {
294 CFStringRef real_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s.%@"), gTopLevelKeyForiCloudKeychainTracing, key);
295 if (NULL == real_key)
296 {
297 return;
298 }
299
300 gADClientClearScalarKey(real_key);
301 CFRelease(real_key);
302 }
303 }
304
305 /* --------------------------------------------------------------------------
306 Function: Internal_ADClientSetValueForScalarKey
307
308 Description: This fucntion is a wrapper around calling the
309 ADClientSetValueForScalarKey function.
310
311 NOTE: The key should be a simple key such as
312 "numberOfPeers". This is because this function will
313 apptend the required prefix of "com.apple.cloudkeychain"
314 -------------------------------------------------------------------------- */
315 static void Internal_ADClientSetValueForScalarKey(CFStringRef key, int64_t value)
316 {
317 if (InitializeADFunctionPointers())
318 {
319 CFStringRef real_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s.%@"), gTopLevelKeyForiCloudKeychainTracing, key);
320 if (NULL == real_key)
321 {
322 return;
323 }
324
325 gADClientSetValueForScalarKey(real_key, value);
326 CFRelease(real_key);
327 }
328 }
329
330
331 /* --------------------------------------------------------------------------
332 Function: iOS_SetCloudKeychainTraceValueForKey
333
334 Description: This fucntion is a wrapper around calling either
335 ADClientSetValueForScalarKey or ADClientClearScalarKey
336 depending on if the value is 0.
337
338 NOTE: The key should be a simple key such as
339 "numberOfPeers". This is because this function will
340 apptend the required prefix of "com.apple.cloudkeychain"
341 -------------------------------------------------------------------------- */
342 static bool iOS_SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value)
343 {
344 if (NULL == key)
345 {
346 return false;
347 }
348
349 if (0LL == value)
350 {
351 Internal_ADClientClearScalarKey(key);
352 }
353 else
354 {
355 Internal_ADClientSetValueForScalarKey(key, value);
356 }
357 return true;
358 }
359
360 /* --------------------------------------------------------------------------
361 Function: iOS_AddKeyValuePairToKeychainLoggingTransaction
362
363 Description: For iOS the is no "bunching" This function will simply
364 call iOS_SetCloudKeychainTraceValueForKey to log the
365 key value pair
366 -------------------------------------------------------------------------- */
367 static bool iOS_AddKeyValuePairToKeychainLoggingTransaction(void* token, CFStringRef key, int64_t value)
368 {
369 #pragma unused(token)
370 return iOS_SetCloudKeychainTraceValueForKey(key, value);
371 }
372 #endif
373
374 /* --------------------------------------------------------------------------
375 Function: SetCloudKeychainTraceValueForKey
376
377 Description: SPI to log a single key value pair with the logging system
378 -------------------------------------------------------------------------- */
379 bool SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value)
380 {
381 #if (TARGET_IPHONE_SIMULATOR)
382 return false;
383 #endif
384
385 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
386 return OSX_SetCloudKeychainTraceValueForKey(key, value);
387 #endif
388
389 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
390 return iOS_SetCloudKeychainTraceValueForKey(key, value);
391 #endif
392 }
393
394 /* --------------------------------------------------------------------------
395 Function: BeginCloudKeychainLoggingTransaction
396
397 Description: SPI to begin a logging transaction
398 -------------------------------------------------------------------------- */
399 void* BeginCloudKeychainLoggingTransaction()
400 {
401 #if (TARGET_IPHONE_SIMULATOR)
402 return (void *)-1;
403 #endif
404
405 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
406 return OSX_BeginCloudKeychainLoggingTransaction();
407 #endif
408
409 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
410 return NULL;
411 #endif
412 }
413
414 /* --------------------------------------------------------------------------
415 Function: AddKeyValuePairToKeychainLoggingTransaction
416
417 Description: SPI to add a key value pair to an outstanding logging
418 tansaction
419 -------------------------------------------------------------------------- */
420 bool AddKeyValuePairToKeychainLoggingTransaction(void* token, CFStringRef key, int64_t value)
421 {
422 #if (TARGET_IPHONE_SIMULATOR)
423 return false;
424 #endif
425
426 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
427 return OSX_AddKeyValuePairToKeychainLoggingTransaction(token, key, value);
428 #endif
429
430 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
431 return iOS_AddKeyValuePairToKeychainLoggingTransaction(token, key, value);
432 #endif
433 }
434
435 /* --------------------------------------------------------------------------
436 Function: CloseCloudKeychainLoggingTransaction
437
438 Description: SPI to complete a logging transaction and clean up the
439 context
440 -------------------------------------------------------------------------- */
441 void CloseCloudKeychainLoggingTransaction(void* token)
442 {
443 #if (TARGET_IPHONE_SIMULATOR)
444 ; // nothing
445 #endif
446
447 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
448 OSX_CloseCloudKeychainLoggingTransaction(token);
449 #endif
450
451 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
452 ; // nothing
453 #endif
454 }
455