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))
48 #include <msgtracer_client.h>
50 struct msgtracer_instance
{
51 msgtracer_msg_t message
;
52 msgtracer_domain_t domain
;
55 static const char* gMessageTracerSetPrefix
= "com.apple.message.";
57 /* --------------------------------------------------------------------------
58 Function: OSX_BeginCloudKeychainLoggingTransaction
60 Description: For OSX the message tracer back end wants its logging
61 done in "bunches". This function allows for beginning
62 a 'transaction' of logging which will allow for putting
63 all of the transactions items into a single log making
64 the message tracer folks happy.
66 The work of this function is to ask msgtracer for a domain,
67 create a message and return the pair as a void *.
68 -------------------------------------------------------------------------- */
69 static void *OSX_BeginCloudKeychainLoggingTransaction()
72 struct msgtracer_instance
*instance
= calloc(1, sizeof *instance
);
77 instance
->domain
= msgtracer_domain_new(gTopLevelKeyForiCloudKeychainTracing
);
78 if (instance
->domain
) {
79 instance
->message
= msgtracer_msg_new(instance
->domain
);
80 if (instance
->message
) {
81 return (void *)instance
;
83 msgtracer_domain_free(instance
->domain
);
89 /* --------------------------------------------------------------------------
90 Function: OSX_AddKeyValuePairToKeychainLoggingTransaction
92 Description: Once a call to OSX_BeginCloudKeychainLoggingTransaction
93 is done, this call all allow for adding items to the
94 "bunch" of items being logged.
96 NOTE: The key should be a simple key such as
97 "numberOfPeers". This is because this function will
98 prepend the required prefix of "com.apple.message."
99 -------------------------------------------------------------------------- */
100 static bool OSX_AddKeyValuePairToKeychainLoggingTransaction(void *token
, CFStringRef key
, int64_t value
)
102 if (NULL
== token
|| NULL
== key
)
107 struct msgtracer_instance
*instance
= (struct msgtracer_instance
*)token
;
108 msgtracer_msg_t msg
= instance
->message
;
111 __block
char *real_key
= NULL
;
112 CFStringPerformWithCString(key
, ^(const char *key_utf8
) {
113 asprintf(&real_key
, "%s%s", gMessageTracerSetPrefix
, key_utf8
);
115 if (NULL
== real_key
)
120 char value_buffer
[32];
121 snprintf(value_buffer
, sizeof(value_buffer
), "%lld", value
);
123 msgtracer_set(msg
, real_key
, value_buffer
);
128 /* --------------------------------------------------------------------------
129 Function: OSX_CloseCloudKeychainLoggingTransaction
131 Description: Once a call to OSX_BeginCloudKeychainLoggingTransaction
132 is done, and all of the items that are to be in the
133 "bunch" of items being logged, this function will do the
134 real logging and free the aslmsg context.
135 -------------------------------------------------------------------------- */
136 static void OSX_CloseCloudKeychainLoggingTransaction(void *token
)
140 struct msgtracer_instance
*instance
= (struct msgtracer_instance
*)token
;
141 msgtracer_log(instance
->message
, ASL_LEVEL_NOTICE
, "");
142 msgtracer_msg_free(instance
->message
);
143 msgtracer_domain_free(instance
->domain
);
148 /* --------------------------------------------------------------------------
149 Function: OSX_SetCloudKeychainTraceValueForKey
151 Description: If "bunching" of items either cannot be done or is not
152 desired, then this 'single shot' function shold be used.
153 It will create the aslmsg context, register the domain
154 fix up the key and log the key value pair and then
155 do the real logging and free the aslmsg context.
156 -------------------------------------------------------------------------- */
157 static bool OSX_SetCloudKeychainTraceValueForKey(CFStringRef key
, int64_t value
)
166 msgtracer_msg_t message
= NULL
;
167 msgtracer_domain_t domain
= msgtracer_domain_new(gTopLevelKeyForiCloudKeychainTracing
);
169 if (NULL
== domain
) {
173 message
= msgtracer_msg_new(domain
);
174 if (NULL
== message
) {
175 msgtracer_domain_free(domain
);
180 __block
char *real_key
= NULL
;
181 CFStringPerformWithCString(key
, ^(const char *key_utf8
) {
182 asprintf(&real_key
, "%s%s", gMessageTracerSetPrefix
, key_utf8
);
184 if (NULL
== real_key
)
189 char value_buffer
[32];
190 snprintf(value_buffer
, sizeof(value_buffer
), "%lld", value
);
192 msgtracer_set(message
, real_key
, value_buffer
);
193 msgtracer_log(message
, ASL_LEVEL_NOTICE
, "%s is %lld", real_key
, value
);
194 msgtracer_msg_free(message
);
195 msgtracer_domain_free(domain
);
202 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
204 typedef void (*type_ADClientClearScalarKey
)(CFStringRef key
);
205 typedef void (*type_ADClientSetValueForScalarKey
)(CFStringRef key
, int64_t value
);
207 static type_ADClientClearScalarKey gADClientClearScalarKey
= NULL
;
208 static type_ADClientSetValueForScalarKey gADClientSetValueForScalarKey
= NULL
;
210 static dispatch_once_t gADFunctionPointersSet
= 0;
211 static CFBundleRef gAggdBundleRef
= NULL
;
212 static bool gFunctionPointersAreLoaded
= false;
214 /* --------------------------------------------------------------------------
215 Function: InitializeADFunctionPointers
217 Description: Linking to the Aggregate library causes a build cycle so
218 This function will dynamically load the needed function
220 -------------------------------------------------------------------------- */
221 static bool InitializeADFunctionPointers()
223 if (gFunctionPointersAreLoaded
)
225 return gFunctionPointersAreLoaded
;
228 dispatch_once(&gADFunctionPointersSet
,
230 CFStringRef path_to_aggd_framework
= CFSTR("/System/Library/PrivateFrameworks/AggregateDictionary.framework");
232 CFURLRef aggd_url
= CFURLCreateWithFileSystemPath(kCFAllocatorDefault
, path_to_aggd_framework
, kCFURLPOSIXPathStyle
, true);
234 if (NULL
!= aggd_url
)
236 gAggdBundleRef
= CFBundleCreate(kCFAllocatorDefault
, aggd_url
);
237 if (NULL
!= gAggdBundleRef
)
239 gADClientClearScalarKey
= (type_ADClientClearScalarKey
)
240 CFBundleGetFunctionPointerForName(gAggdBundleRef
, CFSTR("ADClientClearScalarKey"));
242 gADClientSetValueForScalarKey
= (type_ADClientSetValueForScalarKey
)
243 CFBundleGetFunctionPointerForName(gAggdBundleRef
, CFSTR("ADClientSetValueForScalarKey"));
249 gFunctionPointersAreLoaded
= ((NULL
!= gADClientClearScalarKey
) && (NULL
!= gADClientSetValueForScalarKey
));
250 return gFunctionPointersAreLoaded
;
253 /* --------------------------------------------------------------------------
254 Function: Internal_ADClientClearScalarKey
256 Description: This fucntion is a wrapper around calling the
257 ADClientClearScalarKey function.
259 NOTE: The key should be a simple key such as
260 "numberOfPeers". This is because this function will
261 apptend the required prefix of "com.apple.cloudkeychain"
262 -------------------------------------------------------------------------- */
263 static void Internal_ADClientClearScalarKey(CFStringRef key
)
265 if (InitializeADFunctionPointers())
267 CFStringRef real_key
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%s.%@"), gTopLevelKeyForiCloudKeychainTracing
, key
);
268 if (NULL
== real_key
)
273 gADClientClearScalarKey(real_key
);
278 /* --------------------------------------------------------------------------
279 Function: Internal_ADClientSetValueForScalarKey
281 Description: This fucntion is a wrapper around calling the
282 ADClientSetValueForScalarKey function.
284 NOTE: The key should be a simple key such as
285 "numberOfPeers". This is because this function will
286 apptend the required prefix of "com.apple.cloudkeychain"
287 -------------------------------------------------------------------------- */
288 static void Internal_ADClientSetValueForScalarKey(CFStringRef key
, int64_t value
)
290 if (InitializeADFunctionPointers())
292 CFStringRef real_key
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%s.%@"), gTopLevelKeyForiCloudKeychainTracing
, key
);
293 if (NULL
== real_key
)
298 gADClientSetValueForScalarKey(real_key
, value
);
304 /* --------------------------------------------------------------------------
305 Function: iOS_SetCloudKeychainTraceValueForKey
307 Description: This fucntion is a wrapper around calling either
308 ADClientSetValueForScalarKey or ADClientClearScalarKey
309 depending on if the value is 0.
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 bool iOS_SetCloudKeychainTraceValueForKey(CFStringRef key
, int64_t value
)
324 Internal_ADClientClearScalarKey(key
);
328 Internal_ADClientSetValueForScalarKey(key
, value
);
333 /* --------------------------------------------------------------------------
334 Function: iOS_AddKeyValuePairToKeychainLoggingTransaction
336 Description: For iOS the is no "bunching" This function will simply
337 call iOS_SetCloudKeychainTraceValueForKey to log the
339 -------------------------------------------------------------------------- */
340 static bool iOS_AddKeyValuePairToKeychainLoggingTransaction(void* token
, CFStringRef key
, int64_t value
)
342 #pragma unused(token)
343 return iOS_SetCloudKeychainTraceValueForKey(key
, value
);
347 /* --------------------------------------------------------------------------
348 Function: SetCloudKeychainTraceValueForKey
350 Description: SPI to log a single key value pair with the logging system
351 -------------------------------------------------------------------------- */
352 bool SetCloudKeychainTraceValueForKey(CFStringRef key
, int64_t value
)
354 #if (TARGET_IPHONE_SIMULATOR)
358 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
359 return OSX_SetCloudKeychainTraceValueForKey(key
, value
);
362 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
363 return iOS_SetCloudKeychainTraceValueForKey(key
, value
);
367 /* --------------------------------------------------------------------------
368 Function: BeginCloudKeychainLoggingTransaction
370 Description: SPI to begin a logging transaction
371 -------------------------------------------------------------------------- */
372 void* BeginCloudKeychainLoggingTransaction()
374 #if (TARGET_IPHONE_SIMULATOR)
378 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
379 return OSX_BeginCloudKeychainLoggingTransaction();
382 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
387 /* --------------------------------------------------------------------------
388 Function: AddKeyValuePairToKeychainLoggingTransaction
390 Description: SPI to add a key value pair to an outstanding logging
392 -------------------------------------------------------------------------- */
393 bool AddKeyValuePairToKeychainLoggingTransaction(void* token
, CFStringRef key
, int64_t value
)
395 #if (TARGET_IPHONE_SIMULATOR)
399 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
400 return OSX_AddKeyValuePairToKeychainLoggingTransaction(token
, key
, value
);
403 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
404 return iOS_AddKeyValuePairToKeychainLoggingTransaction(token
, key
, value
);
408 /* --------------------------------------------------------------------------
409 Function: CloseCloudKeychainLoggingTransaction
411 Description: SPI to complete a logging transaction and clean up the
413 -------------------------------------------------------------------------- */
414 void CloseCloudKeychainLoggingTransaction(void* token
)
416 #if (TARGET_IPHONE_SIMULATOR)
420 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
421 OSX_CloseCloudKeychainLoggingTransaction(token
);
424 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)