]> git.saurik.com Git - apple/security.git/blob - security-sysdiagnose/security-sysdiagnose.m
Security-59306.61.1.tar.gz
[apple/security.git] / security-sysdiagnose / security-sysdiagnose.m
1 /*
2 * Copyright (c) 2009-2010,2012-2015 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 #import <Foundation/Foundation.h>
25 #import <Foundation/NSXPCConnection_Private.h>
26 #import <Security/Security.h>
27
28 #import "keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.h"
29
30 #import <dispatch/dispatch.h>
31
32 #import <utilities/debugging.h>
33 #import <utilities/SecCFWrappers.h>
34
35 #import "keychain/SecureObjectSync/SOSInternal.h"
36 #import <Security/CKKSControlProtocol.h>
37 #include <Security/SecureObjectSync/SOSCloudCircle.h>
38
39 #include "secToolFileIO.h"
40 #include "accountCirclesViewsPrint.h"
41 #import "CKKSControlProtocol.h"
42 #import "SecItemPriv.h"
43 #import "supdProtocol.h"
44
45 #include <stdio.h>
46
47 @interface NSString (FileOutput)
48 - (void) writeToStdOut;
49 - (void) writeToStdErr;
50 @end
51
52 @implementation NSString (FileOutput)
53
54 - (void) writeToStdOut {
55 fputs([self UTF8String], stdout);
56 }
57 - (void) writeToStdErr {
58 fputs([self UTF8String], stderr);
59 }
60
61 @end
62
63 @interface NSData (Hexinization)
64
65 - (NSString*) asHexString;
66
67 @end
68
69 @implementation NSData (Hexinization)
70
71 - (NSString*) asHexString {
72 return (__bridge_transfer NSString*) CFDataCopyHexString((__bridge CFDataRef)self);
73 }
74
75 @end
76
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];
81 }];
82 return [result substringToIndex:result.length-(result.length>0)];
83 }
84
85 @implementation NSDictionary (OneLiner)
86
87 - (NSString*) asOneLineString {
88 return dictionaryToString(self);
89 }
90
91 @end
92
93 static void
94 circle_sysdiagnose(void)
95 {
96 SOSLogSetOutputTo(NULL,NULL);
97 SOSCCDumpCircleInformation();
98 }
99
100 static void
101 engine_sysdiagnose(void)
102 {
103 SOSCCDumpEngineInformation();
104 }
105
106 /*
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
111 */
112
113 static void printSecItems(NSString *subsystem, CFTypeRef result) {
114 if (result) {
115 if (CFGetTypeID(result) == CFArrayGetTypeID()) {
116 NSArray *items = (__bridge NSArray *)(result);
117 NSObject *item;
118 for (item in items) {
119 if ([item respondsToSelector:@selector(asOneLineString)]) {
120 [[NSString stringWithFormat: @"%@: %@\n", subsystem, [(NSMutableDictionary *)item asOneLineString]] writeToStdOut];
121 }
122 }
123 } else {
124 NSObject *item = (__bridge NSObject *)(result);
125 if ([item respondsToSelector:@selector(asOneLineString)]) {
126 [[NSString stringWithFormat: @"%@: %@\n", subsystem, [(NSMutableDictionary *)item asOneLineString]] writeToStdOut];
127 }
128 }
129 }
130 }
131
132 static void
133 homekit_sysdiagnose(void)
134 {
135 NSString *kAccessGroupHapPairing = @"com.apple.hap.pairing";
136 NSString *kAccessGroupHapMetadata = @"com.apple.hap.metadata";
137
138 [@"HomeKit keychain state:\n" writeToStdOut];
139
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,
149 } mutableCopy];
150
151 CFTypeRef result = NULL;
152 OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &result);
153 if (status == noErr) {
154 printSecItems(@"HomeKit", result);
155 }
156 CFReleaseNull(result);
157
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);
163 }
164 CFReleaseNull(result);
165
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);
171 }
172 CFReleaseNull(result);
173 }
174
175 static void
176 unlock_sysdiagnose(void)
177 {
178 NSString *kAccessGroupAutoUnlock = @"com.apple.continuity.unlock";
179
180 [@"AutoUnlock keychain state:\n" writeToStdOut];
181
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,
190 };
191
192 CFTypeRef result = NULL;
193 OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &result);
194 if (status == noErr) {
195 printSecItems(@"AutoUnlock", result);
196 }
197 CFReleaseNull(result);
198 }
199
200
201 static void
202 analytics_sysdiagnose(void)
203 {
204 NSXPCConnection* xpcConnection = [[NSXPCConnection alloc] initWithMachServiceName:@"com.apple.securityuploadd" options:0];
205 if (!xpcConnection) {
206 [@"failed to setup xpc connection for securityuploadd\n" writeToStdErr];
207 return;
208 }
209 xpcConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(supdProtocol)];
210 [xpcConnection resume];
211
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) {
217 if (sysdiagnose) {
218 [[NSString stringWithFormat:@"\nAnalytics sysdiagnose:\n\n%@\n", sysdiagnose] writeToStdOut];
219 }
220 dispatch_semaphore_signal(semaphore);
221 }];
222
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];
225 }
226 }
227
228 static void
229 kvs_sysdiagnose(void) {
230 SOSLogSetOutputTo(NULL,NULL);
231 SOSCCDumpCircleKVSInformation(NULL);
232 }
233
234 int
235 main(int argc, const char ** argv)
236 {
237 @autoreleasepool {
238 printf("sysdiagnose keychain\n");
239
240 circle_sysdiagnose();
241 engine_sysdiagnose();
242 homekit_sysdiagnose();
243 unlock_sysdiagnose();
244 analytics_sysdiagnose();
245
246 // Keep this one last
247 kvs_sysdiagnose();
248 }
249 return 0;
250 }