]> git.saurik.com Git - apple/security.git/blob - security-sysdiagnose/security-sysdiagnose.m
Security-58286.51.6.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 <SOSCircle/CKBridge/SOSCloudKeychainClient.h>
29
30 #import <dispatch/dispatch.h>
31
32 #import <utilities/debugging.h>
33 #import <utilities/SecCFWrappers.h>
34
35 #import <Security/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 } mutableCopy];
149
150 CFTypeRef result = NULL;
151 OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &result);
152 if (status == noErr) {
153 printSecItems(@"HomeKit", result);
154 }
155 CFReleaseNull(result);
156
157 // Now look for non-syncable hap.pairing items
158 query[(id)kSecAttrSynchronizable] = @NO;
159 status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &result);
160 if (status == noErr) {
161 printSecItems(@"HomeKit", result);
162 }
163 CFReleaseNull(result);
164
165 // Finally look for non-syncable hap.metadata items
166 query[(id)kSecAttrAccessGroup] = kAccessGroupHapMetadata;
167 status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &result);
168 if (status == noErr) {
169 printSecItems(@"HomeKit", result);
170 }
171 CFReleaseNull(result);
172 }
173
174 static void
175 unlock_sysdiagnose(void)
176 {
177 NSString *kAccessGroupAutoUnlock = @"com.apple.continuity.unlock";
178
179 [@"AutoUnlock keychain state:\n" writeToStdOut];
180
181 NSDictionary* query = @{
182 (id)kSecClass : (id)kSecClassGenericPassword,
183 (id)kSecAttrAccessGroup : kAccessGroupAutoUnlock,
184 (id)kSecAttrAccount : @"com.apple.continuity.auto-unlock.sync",
185 (id)kSecAttrSynchronizable: (id)kCFBooleanTrue,
186 (id)kSecMatchLimit : (id)kSecMatchLimitAll,
187 (id)kSecReturnAttributes: @YES,
188 (id)kSecReturnData: @NO,
189 };
190
191 CFTypeRef result = NULL;
192 OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &result);
193 if (status == noErr) {
194 printSecItems(@"AutoUnlock", result);
195 }
196 CFReleaseNull(result);
197 }
198
199 static void idsproxy_print_message(CFDictionaryRef messages)
200 {
201 NSDictionary<NSString*, NSDictionary*> *idsMessages = (__bridge NSDictionary *)messages;
202
203 printf("IDS messages in flight: %d\n", (int)[idsMessages count]);
204
205 [idsMessages enumerateKeysAndObjectsUsingBlock:^(NSString* _Nonnull identifier, NSDictionary* _Nonnull messageDictionary, BOOL * _Nonnull stop) {
206 printf("message identifier: %s\n", [identifier cStringUsingEncoding:NSUTF8StringEncoding]);
207
208 NSDictionary *messageDataAndPeerID = [messageDictionary valueForKey:(__bridge NSString*)kIDSMessageToSendKey];
209 [messageDataAndPeerID enumerateKeysAndObjectsUsingBlock:^(NSString* _Nonnull peerID, NSData* _Nonnull messageData, BOOL * _Nonnull stop1) {
210 if(messageData)
211 printf("size of message to recipient: %lu\n", (unsigned long)[messageData length]);
212 }];
213
214 NSString *deviceID = [messageDictionary valueForKey:(__bridge NSString*)kIDSMessageRecipientDeviceID];
215 if(deviceID)
216 printf("recipient device id: %s\n", [deviceID cStringUsingEncoding:NSUTF8StringEncoding]);
217
218 }];
219 }
220
221 static void
222 idsproxy_sysdiagnose(void)
223 {
224
225 dispatch_semaphore_t wait_for = dispatch_semaphore_create(0);
226 __block CFDictionaryRef returned = NULL;
227
228 dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
229 SOSCloudKeychainRetrievePendingMessageFromProxy(processQueue, ^(CFDictionaryRef returnedValues, CFErrorRef error) {
230 secdebug("SOSCloudKeychainRetrievePendingMessageFromProxy", "returned: %@", returnedValues);
231 CFRetainAssign(returned, returnedValues);
232 dispatch_semaphore_signal(wait_for);
233 });
234
235 dispatch_semaphore_wait(wait_for, dispatch_time(DISPATCH_TIME_NOW, 2ull * NSEC_PER_SEC));
236 secdebug("idsproxy sysdiagnose", "messages: %@", returned);
237
238 idsproxy_print_message(returned);
239 }
240
241 static void
242 analytics_sysdiagnose(void)
243 {
244 NSXPCConnection* xpcConnection = [[NSXPCConnection alloc] initWithMachServiceName:@"com.apple.securityuploadd" options:NSXPCConnectionPrivileged];
245 if (!xpcConnection) {
246 [@"failed to setup xpc connection for securityuploadd\n" writeToStdErr];
247 return;
248 }
249 xpcConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(supdProtocol)];
250 [xpcConnection resume];
251
252 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
253 [[xpcConnection remoteObjectProxyWithErrorHandler:^(NSError* rpcError) {
254 [[NSString stringWithFormat:@"Error talking with daemon: %@\n", rpcError] writeToStdErr];
255 dispatch_semaphore_signal(semaphore);
256 }] getSysdiagnoseDumpWithReply:^(NSString* sysdiagnose) {
257 if (sysdiagnose) {
258 [[NSString stringWithFormat:@"\nAnalytics sysdiagnose:\n\n%@\n", sysdiagnose] writeToStdOut];
259 }
260 dispatch_semaphore_signal(semaphore);
261 }];
262
263 if (dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 60)) != 0) {
264 [@"\n\nError: timed out waiting for response\n" writeToStdErr];
265 }
266 }
267
268 static void
269 kvs_sysdiagnose(void) {
270 SOSLogSetOutputTo(NULL,NULL);
271 SOSCCDumpCircleKVSInformation(NULL);
272 }
273
274 int
275 main(int argc, const char ** argv)
276 {
277 @autoreleasepool {
278 printf("sysdiagnose keychain\n");
279
280 circle_sysdiagnose();
281 engine_sysdiagnose();
282 homekit_sysdiagnose();
283 unlock_sysdiagnose();
284 idsproxy_sysdiagnose();
285 analytics_sysdiagnose();
286
287 // Keep this one last
288 kvs_sysdiagnose();
289 }
290 return 0;
291 }