2 * Copyright (c) 2013-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 "iCloudKeychainTrace.h"
26 #include <TargetConditionals.h>
28 #include "SecCFWrappers.h"
30 #include <CoreFoundation/CoreFoundation.h>
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");
39 #if !TARGET_IPHONE_SIMULATOR
41 static const char* gTopLevelKeyForiCloudKeychainTracing
= "com.apple.icdp";
43 static const char* gTopLevelKeyForiCloudKeychainTracing
= "com.apple.icdp.KeychainStats";
47 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR))
50 static const char* gMessageTracerSetPrefix
= "com.apple.message.";
52 static const char* gMessageTracerDomainField
= "com.apple.message.domain";
54 /* --------------------------------------------------------------------------
55 Function: OSX_BeginCloudKeychainLoggingTransaction
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.
63 The work of this function is to create the aslmsg context
64 and set the domain field and then return the aslmsg
66 -------------------------------------------------------------------------- */
67 static void* OSX_BeginCloudKeychainLoggingTransaction()
71 mAsl
= asl_new(ASL_TYPE_MSG
);
77 asl_set(mAsl
, gMessageTracerDomainField
, gTopLevelKeyForiCloudKeychainTracing
);
79 result
= (void *)mAsl
;
83 /* --------------------------------------------------------------------------
84 Function: OSX_AddKeyValuePairToKeychainLoggingTransaction
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.
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
)
96 if (NULL
== token
|| NULL
== key
)
101 aslmsg mAsl
= (aslmsg
)token
;
104 CFStringRef real_key
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%s%@"), gMessageTracerSetPrefix
, key
);
105 if (NULL
== real_key
)
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
))
121 CFStringRef value_str
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%lld"), value
);
122 if (NULL
== value_str
)
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
))
133 CFRelease(value_str
);
136 CFRelease(value_str
);
138 asl_set(mAsl
, key_buffer
, value_buffer
);
142 /* --------------------------------------------------------------------------
143 Function: OSX_CloseCloudKeychainLoggingTransaction
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
)
154 aslmsg mAsl
= (aslmsg
)token
;
155 asl_log(NULL
, mAsl
, ASL_LEVEL_NOTICE
, "");
160 /* --------------------------------------------------------------------------
161 Function: OSX_SetCloudKeychainTraceValueForKey
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
)
179 mAsl
= asl_new(ASL_TYPE_MSG
);
186 CFStringRef real_key
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%s%@"), gMessageTracerSetPrefix
, key
);
187 if (NULL
== real_key
)
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
))
204 CFStringRef value_str
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%lld"), value
);
205 if (NULL
== value_str
)
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
))
218 CFRelease(value_str
);
221 CFRelease(value_str
);
223 asl_set(mAsl
, gMessageTracerDomainField
, gTopLevelKeyForiCloudKeychainTracing
);
225 asl_set(mAsl
, key_buffer
, value_buffer
);
226 asl_log(NULL
, mAsl
, ASL_LEVEL_NOTICE
, "%s is %lld", key_buffer
, value
);
233 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
235 typedef void (*type_ADClientClearScalarKey
)(CFStringRef key
);
236 typedef void (*type_ADClientSetValueForScalarKey
)(CFStringRef key
, int64_t value
);
238 static type_ADClientClearScalarKey gADClientClearScalarKey
= NULL
;
239 static type_ADClientSetValueForScalarKey gADClientSetValueForScalarKey
= NULL
;
241 static dispatch_once_t gADFunctionPointersSet
= 0;
242 static CFBundleRef gAggdBundleRef
= NULL
;
243 static bool gFunctionPointersAreLoaded
= false;
245 /* --------------------------------------------------------------------------
246 Function: InitializeADFunctionPointers
248 Description: Linking to the Aggregate library causes a build cycle so
249 This function will dynamically load the needed function
251 -------------------------------------------------------------------------- */
252 static bool InitializeADFunctionPointers()
254 if (gFunctionPointersAreLoaded
)
256 return gFunctionPointersAreLoaded
;
259 dispatch_once(&gADFunctionPointersSet
,
261 CFStringRef path_to_aggd_framework
= CFSTR("/System/Library/PrivateFrameworks/AggregateDictionary.framework");
263 CFURLRef aggd_url
= CFURLCreateWithFileSystemPath(kCFAllocatorDefault
, path_to_aggd_framework
, kCFURLPOSIXPathStyle
, true);
265 if (NULL
!= aggd_url
)
267 gAggdBundleRef
= CFBundleCreate(kCFAllocatorDefault
, aggd_url
);
268 if (NULL
!= gAggdBundleRef
)
270 gADClientClearScalarKey
= (type_ADClientClearScalarKey
)
271 CFBundleGetFunctionPointerForName(gAggdBundleRef
, CFSTR("ADClientClearScalarKey"));
273 gADClientSetValueForScalarKey
= (type_ADClientSetValueForScalarKey
)
274 CFBundleGetFunctionPointerForName(gAggdBundleRef
, CFSTR("ADClientSetValueForScalarKey"));
280 gFunctionPointersAreLoaded
= ((NULL
!= gADClientClearScalarKey
) && (NULL
!= gADClientSetValueForScalarKey
));
281 return gFunctionPointersAreLoaded
;
284 /* --------------------------------------------------------------------------
285 Function: Internal_ADClientClearScalarKey
287 Description: This fucntion is a wrapper around calling the
288 ADClientClearScalarKey function.
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
)
296 if (InitializeADFunctionPointers())
298 CFStringRef real_key
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%s.%@"), gTopLevelKeyForiCloudKeychainTracing
, key
);
299 if (NULL
== real_key
)
304 gADClientClearScalarKey(real_key
);
309 /* --------------------------------------------------------------------------
310 Function: Internal_ADClientSetValueForScalarKey
312 Description: This fucntion is a wrapper around calling the
313 ADClientSetValueForScalarKey function.
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
)
321 if (InitializeADFunctionPointers())
323 CFStringRef real_key
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%s.%@"), gTopLevelKeyForiCloudKeychainTracing
, key
);
324 if (NULL
== real_key
)
329 gADClientSetValueForScalarKey(real_key
, value
);
335 /* --------------------------------------------------------------------------
336 Function: iOS_SetCloudKeychainTraceValueForKey
338 Description: This fucntion is a wrapper around calling either
339 ADClientSetValueForScalarKey or ADClientClearScalarKey
340 depending on if the value is 0.
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
)
355 Internal_ADClientClearScalarKey(key
);
359 Internal_ADClientSetValueForScalarKey(key
, value
);
364 /* --------------------------------------------------------------------------
365 Function: iOS_AddKeyValuePairToKeychainLoggingTransaction
367 Description: For iOS the is no "bunching" This function will simply
368 call iOS_SetCloudKeychainTraceValueForKey to log the
370 -------------------------------------------------------------------------- */
371 static bool iOS_AddKeyValuePairToKeychainLoggingTransaction(void* token
, CFStringRef key
, int64_t value
)
373 #pragma unused(token)
374 return iOS_SetCloudKeychainTraceValueForKey(key
, value
);
378 /* --------------------------------------------------------------------------
379 Function: SetCloudKeychainTraceValueForKey
381 Description: SPI to log a single key value pair with the logging system
382 -------------------------------------------------------------------------- */
383 bool SetCloudKeychainTraceValueForKey(CFStringRef key
, int64_t value
)
385 #if (TARGET_IPHONE_SIMULATOR)
389 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
390 return OSX_SetCloudKeychainTraceValueForKey(key
, value
);
393 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
394 return iOS_SetCloudKeychainTraceValueForKey(key
, value
);
398 /* --------------------------------------------------------------------------
399 Function: BeginCloudKeychainLoggingTransaction
401 Description: SPI to begin a logging transaction
402 -------------------------------------------------------------------------- */
403 void* BeginCloudKeychainLoggingTransaction()
405 #if (TARGET_IPHONE_SIMULATOR)
409 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
410 return OSX_BeginCloudKeychainLoggingTransaction();
413 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
418 /* --------------------------------------------------------------------------
419 Function: AddKeyValuePairToKeychainLoggingTransaction
421 Description: SPI to add a key value pair to an outstanding logging
423 -------------------------------------------------------------------------- */
424 bool AddKeyValuePairToKeychainLoggingTransaction(void* token
, CFStringRef key
, int64_t value
)
426 #if (TARGET_IPHONE_SIMULATOR)
430 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
431 return OSX_AddKeyValuePairToKeychainLoggingTransaction(token
, key
, value
);
434 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
435 return iOS_AddKeyValuePairToKeychainLoggingTransaction(token
, key
, value
);
439 /* --------------------------------------------------------------------------
440 Function: CloseCloudKeychainLoggingTransaction
442 Description: SPI to complete a logging transaction and clean up the
444 -------------------------------------------------------------------------- */
445 void CloseCloudKeychainLoggingTransaction(void* token
)
447 #if (TARGET_IPHONE_SIMULATOR)
451 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
452 OSX_CloseCloudKeychainLoggingTransaction(token
);
455 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)