]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SecurityTool/sos.m
Security-58286.1.32.tar.gz
[apple/security.git] / OSX / sec / SecurityTool / 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 #import <Security/SecureObjectSync/SOSControlHelper.h>
37 #import <err.h>
38 #import <getopt.h>
39
40 #include "builtin_commands.h"
41
42
43 @interface SOSStatus : NSObject
44 @property NSXPCConnection *connection;
45
46 - (void)printPerformanceCounters:(bool)asPList;
47 @end
48
49 @implementation SOSStatus
50
51 - (instancetype) initWithEndpoint:(xpc_endpoint_t)endpoint
52 {
53 if ((self = [super init]) == NULL)
54 return NULL;
55
56 NSXPCInterface *interface = [NSXPCInterface interfaceWithProtocol:@protocol(SOSControlProtocol)];
57 _SOSControlSetupInterface(interface);
58 NSXPCListenerEndpoint *listenerEndpoint = [[NSXPCListenerEndpoint alloc] init];
59
60 [listenerEndpoint _setEndpoint:endpoint];
61
62 self.connection = [[NSXPCConnection alloc] initWithListenerEndpoint:listenerEndpoint];
63 if (self.connection == NULL)
64 return NULL;
65
66 self.connection.remoteObjectInterface = interface;
67
68 [self.connection resume];
69
70
71 return self;
72 }
73
74 - (void)printPerformanceCounters:(bool)asPList
75 {
76 dispatch_semaphore_t sema1 = dispatch_semaphore_create(0);
77 dispatch_semaphore_t sema2 = dispatch_semaphore_create(0);
78 dispatch_semaphore_t sema3 = dispatch_semaphore_create(0);
79
80 NSMutableDictionary<NSString *, NSNumber *> *merged = [NSMutableDictionary dictionary];
81 __block NSMutableDictionary<NSString *, NSString *> *diagnostics = [NSMutableDictionary dictionary];
82
83 [[self.connection remoteObjectProxy] kvsPerformanceCounters:^(NSDictionary <NSString *, NSNumber *> *counters){
84 if (counters == NULL){
85 printf("no KVS counters!");
86 return;
87 }
88
89 [merged addEntriesFromDictionary:counters];
90 dispatch_semaphore_signal(sema1);
91 }];
92
93
94 [[self.connection remoteObjectProxy] idsPerformanceCounters:^(NSDictionary <NSString *, NSNumber *> *counters){
95 if (counters == NULL){
96 printf("no IDS counters!");
97 return;
98 }
99 [merged addEntriesFromDictionary:counters];
100 dispatch_semaphore_signal(sema2);
101 }];
102
103 [[self.connection remoteObjectProxy] rateLimitingPerformanceCounters:^(NSDictionary <NSString *, NSString *> *returnedDiagnostics){
104 if (returnedDiagnostics == NULL){
105 printf("no rate limiting counters!");
106 return;
107 }
108 diagnostics = [[NSMutableDictionary alloc]initWithDictionary:returnedDiagnostics];
109 dispatch_semaphore_signal(sema3);
110 }];
111 dispatch_semaphore_wait(sema1, DISPATCH_TIME_FOREVER);
112 dispatch_semaphore_wait(sema2, DISPATCH_TIME_FOREVER);
113 dispatch_semaphore_wait(sema3, DISPATCH_TIME_FOREVER);
114
115 if (asPList) {
116 NSData *data = [NSPropertyListSerialization dataWithPropertyList:merged format:NSPropertyListXMLFormat_v1_0 options:0 error:NULL];
117
118 printf("%.*s\n", (int)[data length], [data bytes]);
119 } else {
120 [merged enumerateKeysAndObjectsUsingBlock:^(NSString * key, NSNumber * obj, BOOL *stop) {
121 printf("%s - %lld\n", [key UTF8String], [obj longLongValue]);
122 }];
123 }
124 if(diagnostics){
125 [diagnostics enumerateKeysAndObjectsUsingBlock:^(NSString * key, NSString * obj, BOOL * stop) {
126 printf("%s - %s\n", [key UTF8String], [obj UTF8String]);
127 }];
128 }
129 }
130
131 @end
132
133 static void
134 usage(const char *command, struct option *options)
135 {
136 printf("%s %s [...options]\n", getprogname(), command);
137 for (unsigned n = 0; options[n].name; n++) {
138 printf("\t [-%c|--%s\n", options[n].val, options[n].name);
139 }
140
141 }
142
143 int
144 command_sos_stats(__unused int argc, __unused char * const * argv)
145 {
146 @autoreleasepool {
147 int option_index = 0, ch;
148
149 xpc_endpoint_t endpoint = _SecSecuritydCopySOSStatusEndpoint(NULL);
150 if (endpoint == NULL)
151 errx(1, "no SOS endpoint");
152
153 SOSStatus *control = [[SOSStatus alloc] initWithEndpoint:endpoint];
154
155 bool asPlist = false;
156 struct option long_options[] =
157 {
158 /* These options set a flag. */
159 {"plist", no_argument, NULL, 'p'},
160 {0, 0, 0, 0}
161 };
162
163 while ((ch = getopt_long(argc, argv, "p", long_options, &option_index)) != -1) {
164 switch (ch) {
165 case 'p': {
166 asPlist = true;
167 break;
168 }
169 case '?':
170 default:
171 {
172 usage("sos-stats", long_options);
173 return 2;
174 }
175 }
176 }
177
178 [control printPerformanceCounters:asPlist];
179 }
180
181 return 0;
182 }
183
184 int
185 command_sos_control(__unused int argc, __unused char * const * argv)
186 {
187 @autoreleasepool {
188 int option_index = 0, ch;
189
190 bool assertStashAccountKey = false;
191 bool triggerSync = false;
192 NSString *syncingPeer = NULL;
193
194 static struct option long_options[] =
195 {
196 /* These options set a flag. */
197 {"assertStashAccountKey", no_argument, NULL, 'A'},
198 {"trigger-sync", optional_argument, NULL, 's'},
199 {0, 0, 0, 0}
200 };
201
202 while ((ch = getopt_long(argc, argv, "A", long_options, &option_index)) != -1) {
203 switch (ch) {
204 case 'A': {
205 assertStashAccountKey = true;
206 break;
207 }
208 case 's': {
209 triggerSync = true;
210 if (optarg) {
211 syncingPeer = [NSString stringWithUTF8String:optarg];
212 }
213 break;
214 }
215 case '?':
216 default:
217 {
218 usage("sos-control", long_options);
219 return 2;
220 }
221 }
222 }
223
224 xpc_endpoint_t endpoint = _SecSecuritydCopySOSStatusEndpoint(NULL);
225 if (endpoint == NULL)
226 errx(1, "no SOS endpoint");
227
228 SOSStatus *control = [[SOSStatus alloc] initWithEndpoint:endpoint];
229 if (control == NULL)
230 errx(1, "no SOS control object");
231
232 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
233
234 if (triggerSync) {
235 NSMutableArray<NSString *> *peers = [NSMutableArray array];
236 if (syncingPeer) {
237 [peers addObject:syncingPeer];
238 }
239
240 [[control.connection remoteObjectProxyWithErrorHandler:^(NSError *error) {
241 printf("%s", [[NSString stringWithFormat:@"Failed to sending messages to soscontrol object: %@\n", error] UTF8String]);
242 dispatch_semaphore_signal(sema);
243 }] triggerSync:peers complete:^(bool res, NSError *error) {
244 if (res) {
245 printf("starting to sync was successful\n");
246 } else {
247 printf("%s", [[NSString stringWithFormat:@"Failed to start sync: %@\n", error] UTF8String]);
248 }
249 dispatch_semaphore_signal(sema);
250 }];
251 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
252 } else if (assertStashAccountKey) {
253 [[control.connection remoteObjectProxyWithErrorHandler:^(NSError *error) {
254 printf("%s", [[NSString stringWithFormat:@"Failed to sending messages to soscontrol object: %@\n", error] UTF8String]);
255 dispatch_semaphore_signal(sema);
256 }] assertStashedAccountCredential:^(BOOL res, NSError *error) {
257 if (res) {
258 printf("successfully asserted stashed credential\n");
259 } else {
260 printf("%s", [[NSString stringWithFormat:@"failed to assert stashed credential: %@\n", error] UTF8String]);
261 }
262 dispatch_semaphore_signal(sema);
263 }];
264 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
265
266 } else {
267
268 [[control.connection remoteObjectProxyWithErrorHandler:^(NSError *error) {
269 printf("%s", [[NSString stringWithFormat:@"Failed to sending messages to soscontrol object: %@\n", error] UTF8String]);
270 dispatch_semaphore_signal(sema);
271 }] userPublicKey:^(BOOL trusted, NSData *spki, NSError *error) {
272 printf("trusted: %s\n", trusted ? "yes" : "no");
273 printf("userPublicKey: %s\n", [[spki base64EncodedStringWithOptions:0] UTF8String]);
274 dispatch_semaphore_signal(sema);
275 }];
276 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
277
278 [[control.connection remoteObjectProxyWithErrorHandler:^(NSError *error) {
279 printf("%s", [[NSString stringWithFormat:@"Failed to sending messages to soscontrol object: %@\n", error] UTF8String]);
280 dispatch_semaphore_signal(sema);
281 }] stashedCredentialPublicKey:^(NSData *spki, NSError *error) {
282 NSString *pkey = [spki base64EncodedStringWithOptions:0];
283 if (pkey == NULL)
284 pkey = @"no available";
285 printf("cachedCredentialPublicKey: %s\n", [pkey UTF8String]);
286 dispatch_semaphore_signal(sema);
287 }];
288 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
289 }
290
291 }
292 return 0;
293 }
294
295 int command_watchdog(int argc, char* const * argv)
296 {
297 xpc_endpoint_t endpoint = _SecSecuritydCopySOSStatusEndpoint(NULL);
298 if (!endpoint) {
299 errx(1, "no SOS endpoint");
300 return 0;
301 }
302
303 SOSStatus* control = [[SOSStatus alloc] initWithEndpoint:endpoint];
304 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
305
306 if (argc < 3) {
307 printf("getting watchdog parameters...\n");
308 [[control.connection remoteObjectProxyWithErrorHandler:^(NSError* error) {
309 printf("%s", [[NSString stringWithFormat:@"Failed to sending messages to soscontrol object: %@\n", error] UTF8String]);
310 dispatch_semaphore_signal(semaphore);
311 }] getWatchdogParameters:^(NSDictionary* parameters, NSError* error) {
312 if (error) {
313 printf("error getting watchdog parameters: %s", error.localizedDescription.UTF8String);
314 }
315 else {
316 printf("watchdog parameters:\n");
317 [parameters enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSObject* value, BOOL* stop) {
318 printf("\t%s - %s\n", key.description.UTF8String, value.description.UTF8String);
319 }];
320 }
321
322 dispatch_semaphore_signal(semaphore);
323 }];
324 }
325 else {
326 printf("attempting to set watchdog parameters...\n");
327 NSString* parameter = [[NSString alloc] initWithUTF8String:argv[1]];
328 NSInteger value = [[[NSString alloc] initWithUTF8String:argv[2]] integerValue];
329 [[control.connection remoteObjectProxyWithErrorHandler:^(NSError* error) {
330 printf("%s", [[NSString stringWithFormat:@"Failed to sending messages to soscontrol object: %@\n", error] UTF8String]);
331 dispatch_semaphore_signal(semaphore);
332 }] setWatchdogParmeters:@{parameter : @(value)} complete:^(NSError* error) {
333 if (error) {
334 printf("error attempting to set watchdog parameters: %s\n", error.localizedDescription.UTF8String);
335 }
336 else {
337 printf("successfully set watchdog parameter\n");
338 }
339
340 dispatch_semaphore_signal(semaphore);
341 }];
342 }
343
344 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
345
346 return 0;
347 }