]> git.saurik.com Git - apple/security.git/blob - OSX/utilities/src/iCloudKeychainTrace.c
Security-58286.270.3.0.1.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 <msgtracer_client.h>
49
50 struct msgtracer_instance {
51 msgtracer_msg_t message;
52 msgtracer_domain_t domain;
53 };
54
55 static const char* gMessageTracerSetPrefix = "com.apple.message.";
56
57 /* --------------------------------------------------------------------------
58 Function: OSX_BeginCloudKeychainLoggingTransaction
59
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.
65
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()
70 {
71
72 struct msgtracer_instance *instance = calloc(1, sizeof *instance);
73 if (!instance) {
74 return NULL;
75 }
76
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;
82 }
83 msgtracer_domain_free(instance->domain);
84 }
85 free(instance);
86 return NULL;
87 }
88
89 /* --------------------------------------------------------------------------
90 Function: OSX_AddKeyValuePairToKeychainLoggingTransaction
91
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.
95
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)
101 {
102 if (NULL == token || NULL == key)
103 {
104 return false;
105 }
106
107 struct msgtracer_instance *instance = (struct msgtracer_instance *)token;
108 msgtracer_msg_t msg = instance->message;
109
110 // Fix up the key
111 __block char *real_key = NULL;
112 CFStringPerformWithCString(key, ^(const char *key_utf8) {
113 asprintf(&real_key, "%s%s", gMessageTracerSetPrefix, key_utf8);
114 });
115 if (NULL == real_key)
116 {
117 return false;
118 }
119
120 char value_buffer[32];
121 snprintf(value_buffer, sizeof(value_buffer), "%lld", value);
122
123 msgtracer_set(msg, real_key, value_buffer);
124 free(real_key);
125 return true;
126 }
127
128 /* --------------------------------------------------------------------------
129 Function: OSX_CloseCloudKeychainLoggingTransaction
130
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)
137 {
138 if (NULL != token)
139 {
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);
144 free(instance);
145 }
146 }
147
148 /* --------------------------------------------------------------------------
149 Function: OSX_SetCloudKeychainTraceValueForKey
150
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)
158 {
159 bool result = false;
160
161 if (NULL == key)
162 {
163 return result;
164 }
165
166 msgtracer_msg_t message = NULL;
167 msgtracer_domain_t domain = msgtracer_domain_new(gTopLevelKeyForiCloudKeychainTracing);
168
169 if (NULL == domain) {
170 return result;
171 }
172
173 message = msgtracer_msg_new(domain);
174 if (NULL == message) {
175 msgtracer_domain_free(domain);
176 return result;
177 }
178
179 // Fix up the key
180 __block char *real_key = NULL;
181 CFStringPerformWithCString(key, ^(const char *key_utf8) {
182 asprintf(&real_key, "%s%s", gMessageTracerSetPrefix, key_utf8);
183 });
184 if (NULL == real_key)
185 {
186 return false;
187 }
188
189 char value_buffer[32];
190 snprintf(value_buffer, sizeof(value_buffer), "%lld", value);
191
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);
196 free(real_key);
197 return true;
198
199 }
200 #endif
201
202 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
203
204 typedef void (*type_ADClientClearScalarKey)(CFStringRef key);
205 typedef void (*type_ADClientSetValueForScalarKey)(CFStringRef key, int64_t value);
206
207 static type_ADClientClearScalarKey gADClientClearScalarKey = NULL;
208 static type_ADClientSetValueForScalarKey gADClientSetValueForScalarKey = NULL;
209
210 static dispatch_once_t gADFunctionPointersSet = 0;
211 static CFBundleRef gAggdBundleRef = NULL;
212 static bool gFunctionPointersAreLoaded = false;
213
214 /* --------------------------------------------------------------------------
215 Function: InitializeADFunctionPointers
216
217 Description: Linking to the Aggregate library causes a build cycle so
218 This function will dynamically load the needed function
219 pointers.
220 -------------------------------------------------------------------------- */
221 static bool InitializeADFunctionPointers()
222 {
223 if (gFunctionPointersAreLoaded)
224 {
225 return gFunctionPointersAreLoaded;
226 }
227
228 dispatch_once(&gADFunctionPointersSet,
229 ^{
230 CFStringRef path_to_aggd_framework = CFSTR("/System/Library/PrivateFrameworks/AggregateDictionary.framework");
231
232 CFURLRef aggd_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_to_aggd_framework, kCFURLPOSIXPathStyle, true);
233
234 if (NULL != aggd_url)
235 {
236 gAggdBundleRef = CFBundleCreate(kCFAllocatorDefault, aggd_url);
237 if (NULL != gAggdBundleRef)
238 {
239 gADClientClearScalarKey = (type_ADClientClearScalarKey)
240 CFBundleGetFunctionPointerForName(gAggdBundleRef, CFSTR("ADClientClearScalarKey"));
241
242 gADClientSetValueForScalarKey = (type_ADClientSetValueForScalarKey)
243 CFBundleGetFunctionPointerForName(gAggdBundleRef, CFSTR("ADClientSetValueForScalarKey"));
244 }
245 CFRelease(aggd_url);
246 }
247 });
248
249 gFunctionPointersAreLoaded = ((NULL != gADClientClearScalarKey) && (NULL != gADClientSetValueForScalarKey));
250 return gFunctionPointersAreLoaded;
251 }
252
253 /* --------------------------------------------------------------------------
254 Function: Internal_ADClientClearScalarKey
255
256 Description: This fucntion is a wrapper around calling the
257 ADClientClearScalarKey function.
258
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)
264 {
265 if (InitializeADFunctionPointers())
266 {
267 CFStringRef real_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s.%@"), gTopLevelKeyForiCloudKeychainTracing, key);
268 if (NULL == real_key)
269 {
270 return;
271 }
272
273 gADClientClearScalarKey(real_key);
274 CFRelease(real_key);
275 }
276 }
277
278 /* --------------------------------------------------------------------------
279 Function: Internal_ADClientSetValueForScalarKey
280
281 Description: This fucntion is a wrapper around calling the
282 ADClientSetValueForScalarKey function.
283
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)
289 {
290 if (InitializeADFunctionPointers())
291 {
292 CFStringRef real_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s.%@"), gTopLevelKeyForiCloudKeychainTracing, key);
293 if (NULL == real_key)
294 {
295 return;
296 }
297
298 gADClientSetValueForScalarKey(real_key, value);
299 CFRelease(real_key);
300 }
301 }
302
303
304 /* --------------------------------------------------------------------------
305 Function: iOS_SetCloudKeychainTraceValueForKey
306
307 Description: This fucntion is a wrapper around calling either
308 ADClientSetValueForScalarKey or ADClientClearScalarKey
309 depending on if the value is 0.
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 bool iOS_SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value)
316 {
317 if (NULL == key)
318 {
319 return false;
320 }
321
322 if (0LL == value)
323 {
324 Internal_ADClientClearScalarKey(key);
325 }
326 else
327 {
328 Internal_ADClientSetValueForScalarKey(key, value);
329 }
330 return true;
331 }
332
333 /* --------------------------------------------------------------------------
334 Function: iOS_AddKeyValuePairToKeychainLoggingTransaction
335
336 Description: For iOS the is no "bunching" This function will simply
337 call iOS_SetCloudKeychainTraceValueForKey to log the
338 key value pair
339 -------------------------------------------------------------------------- */
340 static bool iOS_AddKeyValuePairToKeychainLoggingTransaction(void* token, CFStringRef key, int64_t value)
341 {
342 #pragma unused(token)
343 return iOS_SetCloudKeychainTraceValueForKey(key, value);
344 }
345 #endif
346
347 /* --------------------------------------------------------------------------
348 Function: SetCloudKeychainTraceValueForKey
349
350 Description: SPI to log a single key value pair with the logging system
351 -------------------------------------------------------------------------- */
352 bool SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value)
353 {
354 #if (TARGET_IPHONE_SIMULATOR)
355 return false;
356 #endif
357
358 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
359 return OSX_SetCloudKeychainTraceValueForKey(key, value);
360 #endif
361
362 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
363 return iOS_SetCloudKeychainTraceValueForKey(key, value);
364 #endif
365 }
366
367 /* --------------------------------------------------------------------------
368 Function: BeginCloudKeychainLoggingTransaction
369
370 Description: SPI to begin a logging transaction
371 -------------------------------------------------------------------------- */
372 void* BeginCloudKeychainLoggingTransaction()
373 {
374 #if (TARGET_IPHONE_SIMULATOR)
375 return (void *)-1;
376 #endif
377
378 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
379 return OSX_BeginCloudKeychainLoggingTransaction();
380 #endif
381
382 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
383 return NULL;
384 #endif
385 }
386
387 /* --------------------------------------------------------------------------
388 Function: AddKeyValuePairToKeychainLoggingTransaction
389
390 Description: SPI to add a key value pair to an outstanding logging
391 tansaction
392 -------------------------------------------------------------------------- */
393 bool AddKeyValuePairToKeychainLoggingTransaction(void* token, CFStringRef key, int64_t value)
394 {
395 #if (TARGET_IPHONE_SIMULATOR)
396 return false;
397 #endif
398
399 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
400 return OSX_AddKeyValuePairToKeychainLoggingTransaction(token, key, value);
401 #endif
402
403 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
404 return iOS_AddKeyValuePairToKeychainLoggingTransaction(token, key, value);
405 #endif
406 }
407
408 /* --------------------------------------------------------------------------
409 Function: CloseCloudKeychainLoggingTransaction
410
411 Description: SPI to complete a logging transaction and clean up the
412 context
413 -------------------------------------------------------------------------- */
414 void CloseCloudKeychainLoggingTransaction(void* token)
415 {
416 #if (TARGET_IPHONE_SIMULATOR)
417 ; // nothing
418 #endif
419
420 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
421 OSX_CloseCloudKeychainLoggingTransaction(token);
422 #endif
423
424 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
425 ; // nothing
426 #endif
427 }
428