]> git.saurik.com Git - apple/security.git/blob - SecurityTool/sharedTool/sos.m
Security-59306.41.2.tar.gz
[apple/security.git] / SecurityTool / sharedTool / sos.m
1 /*
2 * Copyright (c) 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 /*
25 * This is to fool os services to not provide the Keychain manager
26 * interface that doesn't work since we don't have unified headers
27 * between iOS and OS X. rdar://23405418/
28 */
29 #define __KEYCHAINCORE__ 1
30
31 #import <Foundation/Foundation.h>
32 #import <Foundation/NSXPCConnection_Private.h>
33 #import <Security/Security.h>
34 #import <Security/SecItemPriv.h>
35 #import <Security/SecureObjectSync/SOSTypes.h>
36 #include "keychain/SecureObjectSync/SOSControlHelper.h"
37 #import <ipc/securityd_client.h>
38 #import <err.h>
39 #import <getopt.h>
40
41 #include "builtin_commands.h"
42
43
44 @interface SOSStatus : NSObject
45 @property NSXPCConnection *connection;
46
47 - (void)printPerformanceCounters:(bool)asPList;
48 @end
49
50 @implementation SOSStatus
51
52 - (instancetype) init
53 {
54 if ((self = [super init]) == NULL)
55 return NULL;
56
57 NSXPCInterface *interface = [NSXPCInterface interfaceWithProtocol:@protocol(SOSControlProtocol)];
58 _SOSControlSetupInterface(interface);
59
60 self.connection = [[NSXPCConnection alloc] initWithMachServiceName:@(kSecuritydSOSServiceName) options:0];
61 if (self.connection == NULL){
62 return NULL;
63 }
64 self.connection.remoteObjectInterface = interface;
65
66 [self.connection resume];
67
68
69 return self;
70 }
71
72 - (void)printPerformanceCounters:(bool)asPList
73 {
74 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
75 dispatch_semaphore_t sema2 = dispatch_semaphore_create(0);
76 dispatch_semaphore_t sema3 = dispatch_semaphore_create(0);
77
78 NSMutableDictionary<NSString *, NSNumber *> *merged = [NSMutableDictionary dictionary];
79 __block NSMutableDictionary<NSString *, NSString *> *diagnostics = [NSMutableDictionary dictionary];
80
81 [[self.connection remoteObjectProxy] kvsPerformanceCounters:^(NSDictionary <NSString *, NSNumber *> *counters){
82 if (counters == NULL){
83 printf("no KVS counters!");
84 return;
85 }
86
87 [merged addEntriesFromDictionary:counters];
88 dispatch_semaphore_signal(sema1);
89 }];
90
91 [[self.connection remoteObjectProxy] rateLimitingPerformanceCounters:^(NSDictionary <NSString *, NSString *> *returnedDiagnostics){
92 if (returnedDiagnostics == NULL){
93 printf("no rate limiting counters!");
94 return;
95 }
96 diagnostics = [[NSMutableDictionary alloc]initWithDictionary:returnedDiagnostics];
97 dispatch_semaphore_signal(sema3);
98 }];
99 dispatch_semaphore_wait(sema1, DISPATCH_TIME_FOREVER);
100 dispatch_semaphore_wait(sema2, DISPATCH_TIME_FOREVER);
101 dispatch_semaphore_wait(sema3, DISPATCH_TIME_FOREVER);
102
103 if (asPList) {
104 NSData *data = [NSPropertyListSerialization dataWithPropertyList:merged format:NSPropertyListXMLFormat_v1_0 options:0 error:NULL];
105
106 printf("%.*s\n", (int)[data length], [data bytes]);
107 } else {
108 [merged enumerateKeysAndObjectsUsingBlock:^(NSString * key, NSNumber * obj, BOOL *stop) {
109 printf("%s - %lld\n", [key UTF8String], [obj longLongValue]);
110 }];
111 }
112 if(diagnostics){
113 [diagnostics enumerateKeysAndObjectsUsingBlock:^(NSString * key, NSString * obj, BOOL * stop) {
114 printf("%s - %s\n", [key UTF8String], [obj UTF8String]);
115 }];
116 }
117 }
118
119 @end
120
121 static void
122 usage(const char *command, struct option *options)
123 {
124 printf("%s %s [...options]\n", getprogname(), command);
125 for (unsigned n = 0; options[n].name; n++) {
126 printf("\t [-%c|--%s\n", options[n].val, options[n].name);
127 }
128
129 }
130
131 int
132 command_sos_stats(__unused int argc, __unused char * const * argv)
133 {
134 @autoreleasepool {
135 int option_index = 0, ch;
136
137 SOSStatus *control = [[SOSStatus alloc] init];
138
139 bool asPlist = false;
140 struct option long_options[] =
141 {
142 /* These options set a flag. */
143 {"plist", no_argument, NULL, 'p'},
144 {0, 0, 0, 0}
145 };
146
147 while ((ch = getopt_long(argc, argv, "p", long_options, &option_index)) != -1) {
148 switch (ch) {
149 case 'p': {
150 asPlist = true;
151 break;
152 }
153 case '?':
154 default:
155 {
156 usage("sos-stats", long_options);
157 return SHOW_USAGE_MESSAGE;
158 }
159 }
160 }
161
162 [control printPerformanceCounters:asPlist];
163 }
164
165 return 0;
166 }
167
168 static void printControlFailureMessage(NSError *error) {
169 printf("%s", [[NSString stringWithFormat:@"Failed to send messages to soscontrol object: %@\n", error] UTF8String]);
170 }
171
172 int
173 command_sos_control(__unused int argc, __unused char * const * argv)
174 {
175 @autoreleasepool {
176 int option_index = 0, ch;
177
178 bool assertStashAccountKey = false;
179 bool triggerSync = false;
180 NSString *syncingPeer = NULL;
181 SOSAccountGhostBustingOptions gboptions = 0;
182 bool gbinfo = false;
183 bool gbtriggered = false;
184 bool circleHash = false;
185
186 static struct option long_options[] =
187 {
188 /* These options set a flag. */
189 {"assertStashAccountKey", no_argument, NULL, 'a'},
190 {"trigger-sync", optional_argument, NULL, 's'},
191 {"circle-hash", optional_argument, NULL, 'H'},
192 {"ghostbustByMID", optional_argument, NULL, 'M'},
193 {"ghostbustBySerial", optional_argument, NULL, 'S'},
194 {"ghostbustiCloudIdentities", optional_argument, NULL, 'I'},
195 {"ghostbustByAge", optional_argument, NULL, 'A'},
196 {"ghostbustInfo", optional_argument, NULL, 'G'},
197 {"ghostbustTriggered", optional_argument, NULL, 'T'},
198 {0, 0, 0, 0}
199 };
200
201 while ((ch = getopt_long(argc, argv, "asGHAMSIT", long_options, &option_index)) != -1) {
202 switch (ch) {
203 case 'a': {
204 assertStashAccountKey = true;
205 break;
206 }
207 case 's': {
208 triggerSync = true;
209 if (optarg) {
210 syncingPeer = [NSString stringWithUTF8String:optarg];
211 }
212 break;
213 }
214 case 'A': {
215 gboptions |= SOSGhostBustSerialByAge;
216 break;
217 }
218 case 'G': {
219 gbinfo = true;
220 break;
221 }
222 case 'M': {
223 gboptions |= SOSGhostBustByMID;
224 break;
225 }
226 case 'S': {
227 gboptions |= SOSGhostBustBySerialNumber;
228 break;
229 }
230 case 'I': {
231 gboptions |= SOSGhostBustiCloudIdentities;
232 break;
233 }
234 case 'T': {
235 gbtriggered = true;
236 break;
237 }
238 case 'H':
239 circleHash = true;
240 break;
241 case '?':
242 default:
243 {
244 usage("sos-control", long_options);
245 return SHOW_USAGE_MESSAGE;
246 }
247 }
248 }
249
250 SOSStatus *control = [[SOSStatus alloc] init];
251 if (control == NULL)
252 errx(1, "no SOS control object");
253
254 if( gbtriggered) {
255 [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
256 printControlFailureMessage(error);
257 }] ghostBustTriggerTimed:gboptions complete:^(bool ghostBusted, NSError *error) {
258 if (ghostBusted) {
259 printf("ghostbusted devices\n");
260 } else if (error) {
261 printf("%s", [[NSString stringWithFormat:@"Failed ghostbusting: %@\n", error] UTF8String]);
262 } else {
263 printf("no ghosts found\n");
264 }
265 }];
266 } else if( gbinfo) {
267 [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
268 printControlFailureMessage(error);
269 }] ghostBustInfo: ^(NSData *json, NSError *error) {
270 printf("%s\n", [[[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding] UTF8String]);
271 }];
272 } else if (gboptions != 0) {
273 [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
274 printControlFailureMessage(error);
275 }] ghostBust:gboptions complete:^(bool ghostBusted, NSError *error) {
276 if (ghostBusted) {
277 printf("ghostbusted devices\n");
278 } else if (error) {
279 printf("%s", [[NSString stringWithFormat:@"Failed ghostbusting: %@\n", error] UTF8String]);
280 } else {
281 printf("no ghosts found\n");
282 }
283 }];
284 } else if (triggerSync) {
285 NSMutableArray<NSString *> *peers = [NSMutableArray array];
286 if (syncingPeer) {
287 [peers addObject:syncingPeer];
288 }
289
290 [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
291 printControlFailureMessage(error);
292 }] triggerSync:peers complete:^(bool res, NSError *error) {
293 if (res) {
294 printf("starting to sync was successful\n");
295 } else {
296 printf("%s", [[NSString stringWithFormat:@"Failed to start sync: %@\n", error] UTF8String]);
297 }
298 }];
299 } else if (assertStashAccountKey) {
300 [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
301 printControlFailureMessage(error);
302 }] assertStashedAccountCredential:^(BOOL res, NSError *error) {
303 if (res) {
304 printf("successfully asserted stashed credential\n");
305 } else {
306 printf("%s", [[NSString stringWithFormat:@"failed to assert stashed credential: %@\n", error] UTF8String]);
307 }
308 }];
309 } else if (circleHash) {
310 [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
311 printControlFailureMessage(error);
312 }] circleHash:^(NSString *hash, NSError *error) {
313 if (hash) {
314 printf("%s", [[NSString stringWithFormat:@"circle hash: %@\n", hash] UTF8String]);
315 } else {
316 printf("%s", [[NSString stringWithFormat:@"failed to get circle digest: %@\n", error] UTF8String]);
317 }
318 }];
319
320 } else {
321
322 [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
323 printControlFailureMessage(error);
324 }] userPublicKey:^(BOOL trusted, NSData *spki, NSError *error) {
325 printf("trusted: %s\n", trusted ? "yes" : "no");
326 printf("userPublicKey: %s\n", [[spki base64EncodedStringWithOptions:0] UTF8String]);
327 }];
328
329 [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
330 printControlFailureMessage(error);
331 }] stashedCredentialPublicKey:^(NSData *spki, NSError *error) {
332 NSString *pkey = [spki base64EncodedStringWithOptions:0];
333 if (pkey == NULL)
334 pkey = @"not available";
335 printf("cachedCredentialPublicKey: %s\n", [pkey UTF8String]);
336 }];
337 }
338
339 }
340 return 0;
341 }
342
343 int command_watchdog(int argc, char* const * argv)
344 {
345 SOSStatus* control = [[SOSStatus alloc] init];
346 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
347
348 if (argc < 3) {
349 printf("getting watchdog parameters...\n");
350 [[control.connection remoteObjectProxyWithErrorHandler:^(NSError* error) {
351 printControlFailureMessage(error);
352 dispatch_semaphore_signal(semaphore);
353 }] getWatchdogParameters:^(NSDictionary* parameters, NSError* error) {
354 if (error) {
355 printf("error getting watchdog parameters: %s", error.localizedDescription.UTF8String);
356 }
357 else {
358 printf("watchdog parameters:\n");
359 [parameters enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSObject* value, BOOL* stop) {
360 printf("\t%s - %s\n", key.description.UTF8String, value.description.UTF8String);
361 }];
362 }
363
364 dispatch_semaphore_signal(semaphore);
365 }];
366 }
367 else {
368 printf("attempting to set watchdog parameters...\n");
369 NSString* parameter = [[NSString alloc] initWithUTF8String:argv[1]];
370 NSInteger value = [[[NSString alloc] initWithUTF8String:argv[2]] integerValue];
371 [[control.connection remoteObjectProxyWithErrorHandler:^(NSError* error) {
372 printControlFailureMessage(error);
373 dispatch_semaphore_signal(semaphore);
374 }] setWatchdogParmeters:@{parameter : @(value)} complete:^(NSError* error) {
375 if (error) {
376 printf("error attempting to set watchdog parameters: %s\n", error.localizedDescription.UTF8String);
377 }
378 else {
379 printf("successfully set watchdog parameter\n");
380 }
381
382 dispatch_semaphore_signal(semaphore);
383 }];
384 }
385
386 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
387
388 return 0;
389 }