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