2 * Copyright (c) 2009-2010,2012-2015 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@
24 #import <Foundation/Foundation.h>
25 #import <Foundation/NSXPCConnection_Private.h>
26 #import <Security/Security.h>
28 #import "keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.h"
30 #import <dispatch/dispatch.h>
32 #import <utilities/debugging.h>
33 #import <utilities/SecCFWrappers.h>
35 #import "keychain/SecureObjectSync/SOSInternal.h"
36 #import <Security/CKKSControlProtocol.h>
37 #include <Security/SecureObjectSync/SOSCloudCircle.h>
39 #include "secToolFileIO.h"
40 #include "accountCirclesViewsPrint.h"
41 #import "CKKSControlProtocol.h"
42 #import "SecItemPriv.h"
43 #import "supdProtocol.h"
47 @interface NSString (FileOutput)
48 - (void) writeToStdOut;
49 - (void) writeToStdErr;
52 @implementation NSString (FileOutput)
54 - (void) writeToStdOut {
55 fputs([self UTF8String], stdout);
57 - (void) writeToStdErr {
58 fputs([self UTF8String], stderr);
63 @interface NSData (Hexinization)
65 - (NSString*) asHexString;
69 @implementation NSData (Hexinization)
71 - (NSString*) asHexString {
72 return (__bridge_transfer NSString*) CFDataCopyHexString((__bridge CFDataRef)self);
77 static NSString *dictionaryToString(NSDictionary *dict) {
78 NSMutableString *result = [NSMutableString stringWithCapacity:0];
79 [dict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
80 [result appendFormat:@"%@=%@,", key, obj];
82 return [result substringToIndex:result.length-(result.length>0)];
85 @implementation NSDictionary (OneLiner)
87 - (NSString*) asOneLineString {
88 return dictionaryToString(self);
94 circle_sysdiagnose(void)
96 SOSLogSetOutputTo(NULL,NULL);
97 SOSCCDumpCircleInformation();
101 engine_sysdiagnose(void)
103 SOSCCDumpEngineInformation();
107 Here are the commands to dump out all keychain entries used by HomeKit:
108 security item class=genp,sync=1,agrp=com.apple.hap.pairing;
109 security item class=genp,sync=0,agrp=com.apple.hap.pairing;
110 security item class=genp,sync=0,agrp=com.apple.hap.metadata
113 static void printSecItems(NSString *subsystem, CFTypeRef result) {
115 if (CFGetTypeID(result) == CFArrayGetTypeID()) {
116 NSArray *items = (__bridge NSArray *)(result);
118 for (item in items) {
119 if ([item respondsToSelector:@selector(asOneLineString)]) {
120 [[NSString stringWithFormat: @"%@: %@\n", subsystem, [(NSMutableDictionary *)item asOneLineString]] writeToStdOut];
124 NSObject *item = (__bridge NSObject *)(result);
125 if ([item respondsToSelector:@selector(asOneLineString)]) {
126 [[NSString stringWithFormat: @"%@: %@\n", subsystem, [(NSMutableDictionary *)item asOneLineString]] writeToStdOut];
133 homekit_sysdiagnose(void)
135 NSString *kAccessGroupHapPairing = @"com.apple.hap.pairing";
136 NSString *kAccessGroupHapMetadata = @"com.apple.hap.metadata";
138 [@"HomeKit keychain state:\n" writeToStdOut];
140 // First look for syncable hap.pairing items
141 NSMutableDictionary* query = [@{
142 (id)kSecClass : (id)kSecClassGenericPassword,
143 (id)kSecAttrAccessGroup : kAccessGroupHapPairing,
144 (id)kSecAttrSynchronizable: (id)kCFBooleanTrue,
145 (id)kSecMatchLimit : (id)kSecMatchLimitAll,
146 (id)kSecReturnAttributes: @YES,
147 (id)kSecReturnData: @NO,
148 (id)kSecUseDataProtectionKeychain : @YES,
151 CFTypeRef result = NULL;
152 OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &result);
153 if (status == noErr) {
154 printSecItems(@"HomeKit", result);
156 CFReleaseNull(result);
158 // Now look for non-syncable hap.pairing items
159 query[(id)kSecAttrSynchronizable] = @NO;
160 status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &result);
161 if (status == noErr) {
162 printSecItems(@"HomeKit", result);
164 CFReleaseNull(result);
166 // Finally look for non-syncable hap.metadata items
167 query[(id)kSecAttrAccessGroup] = kAccessGroupHapMetadata;
168 status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &result);
169 if (status == noErr) {
170 printSecItems(@"HomeKit", result);
172 CFReleaseNull(result);
176 unlock_sysdiagnose(void)
178 NSString *kAccessGroupAutoUnlock = @"com.apple.continuity.unlock";
180 [@"AutoUnlock keychain state:\n" writeToStdOut];
182 NSDictionary* query = @{
183 (id)kSecClass : (id)kSecClassGenericPassword,
184 (id)kSecAttrAccessGroup : kAccessGroupAutoUnlock,
185 (id)kSecAttrAccount : @"com.apple.continuity.auto-unlock.sync",
186 (id)kSecAttrSynchronizable: (id)kCFBooleanTrue,
187 (id)kSecMatchLimit : (id)kSecMatchLimitAll,
188 (id)kSecReturnAttributes: @YES,
189 (id)kSecReturnData: @NO,
192 CFTypeRef result = NULL;
193 OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &result);
194 if (status == noErr) {
195 printSecItems(@"AutoUnlock", result);
197 CFReleaseNull(result);
202 analytics_sysdiagnose(void)
204 NSXPCConnection* xpcConnection = [[NSXPCConnection alloc] initWithMachServiceName:@"com.apple.securityuploadd" options:0];
205 if (!xpcConnection) {
206 [@"failed to setup xpc connection for securityuploadd\n" writeToStdErr];
209 xpcConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(supdProtocol)];
210 [xpcConnection resume];
212 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
213 [[xpcConnection remoteObjectProxyWithErrorHandler:^(NSError* rpcError) {
214 [[NSString stringWithFormat:@"Error talking with daemon: %@\n", rpcError] writeToStdErr];
215 dispatch_semaphore_signal(semaphore);
216 }] getSysdiagnoseDumpWithReply:^(NSString* sysdiagnose) {
218 [[NSString stringWithFormat:@"\nAnalytics sysdiagnose:\n\n%@\n", sysdiagnose] writeToStdOut];
220 dispatch_semaphore_signal(semaphore);
223 if (dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 60)) != 0) {
224 [@"\n\nError: timed out waiting for response\n" writeToStdErr];
229 kvs_sysdiagnose(void) {
230 SOSLogSetOutputTo(NULL,NULL);
231 SOSCCDumpCircleKVSInformation(NULL);
235 main(int argc, const char ** argv)
238 printf("sysdiagnose keychain\n");
240 circle_sysdiagnose();
241 engine_sysdiagnose();
242 homekit_sysdiagnose();
243 unlock_sysdiagnose();
244 analytics_sysdiagnose();
246 // Keep this one last