]> git.saurik.com Git - apple/security.git/blame - OSX/sec/SOSCircle/Tool/keychain_sync.c
Security-57740.51.3.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / Tool / keychain_sync.c
CommitLineData
5c19dc3a
A
1/*
2 * Copyright (c) 2003-2007,2009-2010,2013-2014 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 * keychain_add.c
24 */
25
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <unistd.h>
e3d460c9
A
31#include <sys/utsname.h>
32#include <sys/stat.h>
33#include <time.h>
5c19dc3a
A
34
35#include <Security/SecItem.h>
36
37#include <CoreFoundation/CFNumber.h>
38#include <CoreFoundation/CFString.h>
39
40#include <Security/SecureObjectSync/SOSCloudCircle.h>
41#include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
42#include <Security/SecureObjectSync/SOSPeerInfo.h>
43#include <Security/SecureObjectSync/SOSPeerInfoPriv.h>
44#include <Security/SecureObjectSync/SOSPeerInfoV2.h>
45#include <Security/SecureObjectSync/SOSUserKeygen.h>
46#include <Security/SecureObjectSync/SOSKVSKeys.h>
47#include <securityd/SOSCloudCircleServer.h>
48#include <Security/SecureObjectSync/SOSBackupSliceKeyBag.h>
49#include <Security/SecOTRSession.h>
50#include <SOSCircle/CKBridge/SOSCloudKeychainClient.h>
51
52#include <utilities/SecCFWrappers.h>
53#include <utilities/debugging.h>
54
55#include <SecurityTool/readline.h>
56#include <notify.h>
57
e3d460c9
A
58#include "keychain_sync.h"
59#include "keychain_log.h"
fa7225c8
A
60#include "syncbackup.h"
61
e3d460c9 62#include "secToolFileIO.h"
fa7225c8 63#include "secViewDisplay.h"
5c19dc3a
A
64
65#include <Security/SecPasswordGenerate.h>
66
5c19dc3a
A
67#define MAXKVSKEYTYPE kUnknownKey
68#define DATE_LENGTH 18
69
5c19dc3a
A
70
71static bool clearAllKVS(CFErrorRef *error)
72{
73 __block bool result = false;
74 const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC;
75 dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
76 dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
77 dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
78
79 SOSCloudKeychainClearAll(processQueue, ^(CFDictionaryRef returnedValues, CFErrorRef cerror)
80 {
81 result = (cerror != NULL);
82 dispatch_semaphore_signal(waitSemaphore);
83 });
84
85 dispatch_semaphore_wait(waitSemaphore, finishTime);
86 dispatch_release(waitSemaphore);
87
88 return result;
89}
90
91static const char *getSOSCCStatusDescription(SOSCCStatus ccstatus)
92{
93 switch (ccstatus)
94 {
95 case kSOSCCInCircle: return "In Circle";
96 case kSOSCCNotInCircle: return "Not in Circle";
97 case kSOSCCRequestPending: return "Request pending";
98 case kSOSCCCircleAbsent: return "Circle absent";
99 case kSOSCCError: return "Circle error";
100
101 default:
102 return "<unknown ccstatus>";
103 break;
104 }
105}
106
107static void printPeerInfos(char *label, CFArrayRef (^getArray)(CFErrorRef *error)) {
108 CFErrorRef error = NULL;
109 CFArrayRef ppi = getArray(&error);
110 SOSPeerInfoRef me = SOSCCCopyMyPeerInfo(NULL);
111 CFStringRef mypeerID = SOSPeerInfoGetPeerID(me);
112
113 if(ppi) {
114 printmsg(CFSTR("%s count: %ld\n"), label, (long)CFArrayGetCount(ppi));
115 CFArrayForEach(ppi, ^(const void *value) {
116 char buf[160];
117 SOSPeerInfoRef peer = (SOSPeerInfoRef)value;
118 CFIndex version = SOSPeerInfoGetVersion(peer);
119 CFStringRef peerName = SOSPeerInfoGetPeerName(peer);
120 CFStringRef devtype = SOSPeerInfoGetPeerDeviceType(peer);
121 CFStringRef peerID = SOSPeerInfoGetPeerID(peer);
122 CFStringRef transportType = CFSTR("KVS");
123 CFStringRef deviceID = CFSTR("");
124 CFDictionaryRef gestalt = SOSPeerInfoCopyPeerGestalt(peer);
125 CFStringRef osVersion = CFDictionaryGetValue(gestalt, CFSTR("OSVersion"));
126 CFReleaseNull(gestalt);
127
128
129 if(version >= 2){
130 CFDictionaryRef v2Dictionary = peer->v2Dictionary;
131 transportType = CFDictionaryGetValue(v2Dictionary, sTransportType);
132 deviceID = CFDictionaryGetValue(v2Dictionary, sDeviceID);
133 }
134 char *pname = CFStringToCString(peerName);
135 char *dname = CFStringToCString(devtype);
136 char *tname = CFStringToCString(transportType);
137 char *iname = CFStringToCString(deviceID);
138 char *osname = CFStringToCString(osVersion);
139 const char *me = CFEqualSafe(mypeerID, peerID) ? "me>" : " ";
140
141
142 snprintf(buf, 160, "%s %s: %-16s %-16s %-16s %-16s", me, label, pname, dname, tname, iname);
143
144 free(pname);
145 free(dname);
146 CFStringRef pid = SOSPeerInfoGetPeerID(peer);
147 CFIndex vers = SOSPeerInfoGetVersion(peer);
148 printmsg(CFSTR("%s %@ V%d OS:%s\n"), buf, pid, vers, osname);
149 free(osname);
150 });
151 } else {
152 printmsg(CFSTR("No %s, error: %@\n"), label, error);
153 }
154 CFReleaseNull(ppi);
155 CFReleaseNull(error);
156}
157
158static void dumpCircleInfo()
159{
160 CFErrorRef error = NULL;
161 CFArrayRef generations = NULL;
162 CFArrayRef confirmedDigests = NULL;
163 bool is_user_public_trusted = false;
164 __block int count = 0;
165
166 SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error);
167 if(ccstatus == kSOSCCError) {
168 printmsg(CFSTR("End of Dump - unable to proceed due to ccstatus (%s) error: %@\n"), getSOSCCStatusDescription(ccstatus), error);
169 return;
170 }
171 printmsg(CFSTR("ccstatus: %s (%d)\n"), getSOSCCStatusDescription(ccstatus), ccstatus, error);
172
173 is_user_public_trusted = SOSCCValidateUserPublic(&error);
174 if(is_user_public_trusted)
175 printmsg(CFSTR("Account user public is trusted%@"),CFSTR("\n"));
176 else
177 printmsg(CFSTR("Account user public is not trusted error:(%@)\n"), error);
178 CFReleaseNull(error);
179
180 generations = SOSCCCopyGenerationPeerInfo(&error);
181 if(generations) {
182 CFArrayForEach(generations, ^(const void *value) {
183 count++;
184 if(count%2 == 0)
185 printmsg(CFSTR("Circle name: %@, "),value);
186
187 if(count%2 != 0) {
188 CFStringRef genDesc = SOSGenerationCountCopyDescription(value);
189 printmsg(CFSTR("Generation Count: %@"), genDesc);
190 CFReleaseNull(genDesc);
191 }
192 printmsg(CFSTR("%s\n"), "");
193 });
194 } else {
195 printmsg(CFSTR("No generation count: %@\n"), error);
196 }
197 CFReleaseNull(generations);
198 CFReleaseNull(error);
199
200 printPeerInfos(" Peers", ^(CFErrorRef *error) { return SOSCCCopyValidPeerPeerInfo(error); });
201 printPeerInfos(" Invalid", ^(CFErrorRef *error) { return SOSCCCopyNotValidPeerPeerInfo(error); });
202 printPeerInfos(" Retired", ^(CFErrorRef *error) { return SOSCCCopyRetirementPeerInfo(error); });
203 printPeerInfos(" Concur", ^(CFErrorRef *error) { return SOSCCCopyConcurringPeerPeerInfo(error); });
204 printPeerInfos("Applicants", ^(CFErrorRef *error) { return SOSCCCopyApplicantPeerInfo(error); });
205
6b200bc3
A
206 if (!SOSCCForEachEngineStateAsString(&error, ^(CFStringRef oneStateString) {
207 printmsg(CFSTR("%@\n"), oneStateString);
208 })) {
5c19dc3a 209 printmsg(CFSTR("No engine peers: %@\n"), error);
6b200bc3
A
210 }
211
212 CFReleaseNull(error);
5c19dc3a
A
213 CFReleaseNull(confirmedDigests);
214}
215
e0e0d90e
A
216static bool enableDefaultViews()
217{
218 bool result = false;
fa7225c8 219 CFMutableSetRef viewsToEnable = SOSViewCopyViewSet(kViewSetV0);
e0e0d90e 220 CFMutableSetRef viewsToDisable = CFSetCreateMutable(NULL, 0, NULL);
e0e0d90e
A
221
222 result = SOSCCViewSet(viewsToEnable, viewsToDisable);
223 CFRelease(viewsToEnable);
224 CFRelease(viewsToDisable);
225 return result;
226}
227
5c19dc3a
A
228static bool requestToJoinCircle(CFErrorRef *error)
229{
230 // Set the visual state of switch based on membership in circle
231 bool hadError = false;
232 SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(error);
233
234 switch (ccstatus)
235 {
236 case kSOSCCCircleAbsent:
237 hadError = !SOSCCResetToOffering(error);
e0e0d90e 238 hadError &= enableDefaultViews();
5c19dc3a
A
239 break;
240 case kSOSCCNotInCircle:
241 hadError = !SOSCCRequestToJoinCircle(error);
e0e0d90e 242 hadError &= enableDefaultViews();
5c19dc3a
A
243 break;
244 default:
245 printerr(CFSTR("Request to join circle with bad status: %@ (%d)\n"), SOSCCGetStatusDescription(ccstatus), ccstatus);
246 break;
247 }
248 return hadError;
249}
250
251static bool setPassword(char *labelAndPassword, CFErrorRef *err)
252{
253 char *last = NULL;
254 char *token0 = strtok_r(labelAndPassword, ":", &last);
255 char *token1 = strtok_r(NULL, "", &last);
256 CFStringRef label = token1 ? CFStringCreateWithCString(NULL, token0, kCFStringEncodingUTF8) : CFSTR("security command line tool");
257 char *password_token = token1 ? token1 : token0;
258 password_token = password_token ? password_token : "";
259 CFDataRef password = CFDataCreate(NULL, (const UInt8*) password_token, strlen(password_token));
260 bool returned = !SOSCCSetUserCredentials(label, password, err);
261 CFRelease(label);
262 CFRelease(password);
263 return returned;
264}
265
266static bool tryPassword(char *labelAndPassword, CFErrorRef *err)
267{
268 char *last = NULL;
269 char *token0 = strtok_r(labelAndPassword, ":", &last);
270 char *token1 = strtok_r(NULL, "", &last);
271 CFStringRef label = token1 ? CFStringCreateWithCString(NULL, token0, kCFStringEncodingUTF8) : CFSTR("security command line tool");
272 char *password_token = token1 ? token1 : token0;
273 password_token = password_token ? password_token : "";
274 CFDataRef password = CFDataCreate(NULL, (const UInt8*) password_token, strlen(password_token));
275 bool returned = !SOSCCTryUserCredentials(label, password, err);
276 CFRelease(label);
277 CFRelease(password);
278 return returned;
279}
280
281static CFTypeRef getObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t processQueue, dispatch_group_t dgroup)
282{
283 __block CFTypeRef object = NULL;
284
285 const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC;
286 dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
287 dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
288
289 dispatch_group_enter(dgroup);
290
291 CloudKeychainReplyBlock replyBlock =
292 ^ (CFDictionaryRef returnedValues, CFErrorRef error)
293 {
294 secinfo("sync", "SOSCloudKeychainGetObjectsFromCloud returned: %@", returnedValues);
295 object = returnedValues;
296 if (object)
297 CFRetain(object);
298 if (error)
299 {
300 secerror("SOSCloudKeychainGetObjectsFromCloud returned error: %@", error);
5c19dc3a
A
301 }
302 dispatch_group_leave(dgroup);
303 secinfo("sync", "SOSCloudKeychainGetObjectsFromCloud block exit: %@", object);
304 dispatch_semaphore_signal(waitSemaphore);
305 };
306
307 if (!keysToGet)
308 SOSCloudKeychainGetAllObjectsFromCloud(processQueue, replyBlock);
309 else
310 SOSCloudKeychainGetObjectsFromCloud(keysToGet, processQueue, replyBlock);
311
312 dispatch_semaphore_wait(waitSemaphore, finishTime);
313 dispatch_release(waitSemaphore);
314 if (object && (CFGetTypeID(object) == CFNullGetTypeID())) // return a NULL instead of a CFNull
315 {
316 CFRelease(object);
317 object = NULL;
318 }
319 secerror("returned: %@", object);
320 return object;
321}
322
323static CFStringRef printFullDataString(CFDataRef data){
324 __block CFStringRef fullData = NULL;
325
326 BufferPerformWithHexString(CFDataGetBytePtr(data), CFDataGetLength(data), ^(CFStringRef dataHex) {
327 fullData = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@"), dataHex);
328 });
329
330 return fullData;
331}
332
333static void displayLastKeyParameters(CFTypeRef key, CFTypeRef value)
334{
335 CFDataRef valueAsData = asData(value, NULL);
336 if(valueAsData){
337 CFDataRef dateData = CFDataCreateCopyFromRange(kCFAllocatorDefault, valueAsData, CFRangeMake(0, DATE_LENGTH));
338 CFDataRef keyParameterData = CFDataCreateCopyFromPositions(kCFAllocatorDefault, valueAsData, DATE_LENGTH, CFDataGetLength(valueAsData));
339 CFStringRef dateString = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, dateData, kCFStringEncodingUTF8);
340 CFStringRef keyParameterDescription = UserParametersDescription(keyParameterData);
341 if(keyParameterDescription)
342 printmsg(CFSTR("%@: %@: %@\n"), key, dateString, keyParameterDescription);
343 else
344 printmsg(CFSTR("%@: %@\n"), key, printFullDataString(value));
345 CFReleaseNull(dateString);
346 CFReleaseNull(keyParameterData);
347 CFReleaseNull(dateData);
348 CFReleaseNull(keyParameterDescription);
349 }
350 else{
351 printmsg(CFSTR("%@: %@\n"), key, value);
352 }
353}
354
355static void displayKeyParameters(CFTypeRef key, CFTypeRef value)
356{
357 if(isData(value)){
358 CFStringRef keyParameterDescription = UserParametersDescription((CFDataRef)value);
359
360 if(keyParameterDescription)
361 printmsg(CFSTR("%@: %@\n"), key, keyParameterDescription);
362 else
363 printmsg(CFSTR("%@: %@\n"), key, value);
364
365 CFReleaseNull(keyParameterDescription);
366 }
367 else{
368 printmsg(CFSTR("%@: %@\n"), key, value);
369 }
370}
371
372static void displayLastCircle(CFTypeRef key, CFTypeRef value)
373{
374 CFDataRef valueAsData = asData(value, NULL);
375 if(valueAsData){
376 CFErrorRef localError = NULL;
377
378 CFDataRef dateData = CFDataCreateCopyFromRange(kCFAllocatorDefault, valueAsData, CFRangeMake(0, DATE_LENGTH));
379 CFDataRef circleData = CFDataCreateCopyFromPositions(kCFAllocatorDefault, valueAsData, DATE_LENGTH, CFDataGetLength(valueAsData));
380 CFStringRef dateString = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, dateData, kCFStringEncodingUTF8);
381 SOSCircleRef circle = SOSCircleCreateFromData(NULL, (CFDataRef) circleData, &localError);
382
383 if(circle){
384 CFIndex size = 5;
385 CFNumberRef idLength = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &size);
386 CFDictionaryRef format = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, CFSTR("SyncD"), CFSTR("SyncD"), CFSTR("idLength"), idLength, NULL);
387 printmsgWithFormatOptions(format, CFSTR("%@: %@: %@\n"), key, dateString, circle);
388 CFReleaseNull(idLength);
389 CFReleaseNull(format);
390
391 }
392 else
393 printmsg(CFSTR("%@: %@\n"), key, printFullDataString(circleData));
394
395 CFReleaseNull(dateString);
396 CFReleaseNull(circleData);
397 CFReleaseSafe(circle);
398 CFReleaseNull(dateData);
399 CFReleaseNull(localError);
400 }
401 else{
402 printmsg(CFSTR("%@: %@\n"), key, value);
403 }
404}
405
406static void displayCircle(CFTypeRef key, CFTypeRef value)
407{
408 CFDataRef circleData = (CFDataRef)value;
409
410 CFErrorRef localError = NULL;
411 if (isData(circleData))
412 {
413 CFIndex size = 5;
414 CFNumberRef idLength = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &size);
415 CFDictionaryRef format = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, CFSTR("SyncD"), CFSTR("SyncD"), CFSTR("idLength"), idLength, NULL);
416 SOSCircleRef circle = SOSCircleCreateFromData(NULL, circleData, &localError);
417 printmsgWithFormatOptions(format, CFSTR("%@: %@\n"), key, circle);
418 CFReleaseSafe(circle);
419 CFReleaseNull(idLength);
420 CFReleaseNull(format);
421
422 }
423 else
424 printmsg(CFSTR("%@: %@\n"), key, value);
425}
426
427static void displayMessage(CFTypeRef key, CFTypeRef value)
428{
429 CFDataRef message = (CFDataRef)value;
430 if(isData(message)){
431 const char* messageType = SecOTRPacketTypeString(message);
432 printmsg(CFSTR("%@: %s: %ld\n"), key, messageType, CFDataGetLength(message));
433 }
434 else
435 printmsg(CFSTR("%@: %@\n"), key, value);
436}
437
438static void printEverything(CFTypeRef objects)
439{
440 CFDictionaryForEach(objects, ^(const void *key, const void *value) {
441 if (isData(value))
442 {
443 printmsg(CFSTR("%@: %@\n\n"), key, printFullDataString(value));
444 }
445 else
446 printmsg(CFSTR("%@: %@\n"), key, value);
447 });
448
449}
450
451static void decodeForKeyType(CFTypeRef key, CFTypeRef value, SOSKVSKeyType type){
452 switch (type) {
453 case kCircleKey:
454 displayCircle(key, value);
455 break;
456 case kRetirementKey:
457 case kMessageKey:
458 displayMessage(key, value);
459 break;
460 case kParametersKey:
461 displayKeyParameters(key, value);
462 break;
463 case kLastKeyParameterKey:
464 displayLastKeyParameters(key, value);
465 break;
466 case kLastCircleKey:
467 displayLastCircle(key, value);
468 break;
469 case kInitialSyncKey:
470 case kAccountChangedKey:
471 case kDebugInfoKey:
472 case kRingKey:
473 case kPeerInfoKey:
474 default:
475 printmsg(CFSTR("%@: %@\n"), key, value);
476 break;
477 }
478}
479
480static void decodeAllTheValues(CFTypeRef objects){
481 SOSKVSKeyType keyType = 0;
482 __block bool didPrint = false;
483
484 for (keyType = 0; keyType <= MAXKVSKEYTYPE; keyType++){
485 CFDictionaryForEach(objects, ^(const void *key, const void *value) {
486 if(SOSKVSKeyGetKeyType(key) == keyType){
487 decodeForKeyType(key, value, keyType);
488 didPrint = true;
489 }
490 });
491 if(didPrint)
492 printmsg(CFSTR("%@\n"), CFSTR(""));
493 didPrint = false;
494 }
495}
496static bool dumpKVS(char *itemName, CFErrorRef *err)
497{
498 CFArrayRef keysToGet = NULL;
499 if (itemName)
500 {
501 CFStringRef itemStr = CFStringCreateWithCString(kCFAllocatorDefault, itemName, kCFStringEncodingUTF8);
e3d460c9 502 fprintf(outFile, "Retrieving %s from KVS\n", itemName);
5c19dc3a
A
503 keysToGet = CFArrayCreateForCFTypes(kCFAllocatorDefault, itemStr, NULL);
504 CFReleaseSafe(itemStr);
505 }
506 dispatch_queue_t generalq = dispatch_queue_create("general", DISPATCH_QUEUE_SERIAL);
507 dispatch_group_t work_group = dispatch_group_create();
508 CFTypeRef objects = getObjectsFromCloud(keysToGet, generalq, work_group);
509 CFReleaseSafe(keysToGet);
510 if (objects)
511 {
e3d460c9 512 fprintf(outFile, "All keys and values straight from KVS\n");
5c19dc3a 513 printEverything(objects);
e3d460c9 514 fprintf(outFile, "\nAll values in decoded form...\n");
5c19dc3a
A
515 decodeAllTheValues(objects);
516 }
e3d460c9 517 fprintf(outFile, "\n");
5c19dc3a
A
518 return true;
519}
520
fa7225c8 521static bool syncAndWait(CFErrorRef *err)
5c19dc3a 522{
5c19dc3a 523 __block CFTypeRef objects = NULL;
5c19dc3a
A
524
525 dispatch_queue_t generalq = dispatch_queue_create("general", DISPATCH_QUEUE_SERIAL);
526
527 const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC;
528 dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
529 dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
530
531 CloudKeychainReplyBlock replyBlock = ^ (CFDictionaryRef returnedValues, CFErrorRef error)
532 {
533 secinfo("sync", "SOSCloudKeychainSynchronizeAndWait returned: %@", returnedValues);
534 if (error)
535 secerror("SOSCloudKeychainSynchronizeAndWait returned error: %@", error);
fa7225c8
A
536 objects = CFRetainSafe(returnedValues);
537
5c19dc3a
A
538 secinfo("sync", "SOSCloudKeychainGetObjectsFromCloud block exit: %@", objects);
539 dispatch_semaphore_signal(waitSemaphore);
540 };
541
fa7225c8 542 SOSCloudKeychainSynchronizeAndWait(generalq, replyBlock);
5c19dc3a
A
543
544 dispatch_semaphore_wait(waitSemaphore, finishTime);
545 dispatch_release(waitSemaphore);
546
5c19dc3a 547 dumpKVS(NULL, NULL);
e3d460c9 548 fprintf(outFile, "\n");
5c19dc3a
A
549 return false;
550}
551
5c19dc3a
A
552static CFStringRef convertStringToProperty(char *propertyname) {
553 CFStringRef propertyspec = NULL;
554
555 if(strcmp(propertyname, "hasentropy") == 0) {
556 propertyspec = kSOSSecPropertyHasEntropy;
557 } else if(strcmp(propertyname, "screenlock") == 0) {
558 propertyspec = kSOSSecPropertyScreenLock;
559 } else if(strcmp(propertyname, "SEP") == 0) {
560 propertyspec = kSOSSecPropertySEP;
561 } else if(strcmp(propertyname, "IOS") == 0) {
562 propertyspec = kSOSSecPropertyIOS;
563 }
564 return propertyspec;
565}
566
567
568static CFStringRef convertPropertyReturnCodeToString(SOSSecurityPropertyResultCode ac) {
569 CFStringRef retval = NULL;
570 switch(ac) {
571 case kSOSCCGeneralSecurityPropertyError:
572 retval = CFSTR("General Error"); break;
573 case kSOSCCSecurityPropertyValid:
574 retval = CFSTR("Is Member of Security Property"); break;
575 case kSOSCCSecurityPropertyNotValid:
576 retval = CFSTR("Is Not Member of Security Property"); break;
577 case kSOSCCSecurityPropertyNotQualified:
578 retval = CFSTR("Is not qualified for Security Property"); break;
579 case kSOSCCNoSuchSecurityProperty:
580 retval = CFSTR("No Such Security Property"); break;
581 }
582 return retval;
583}
584
585
586static bool SecPropertycmd(char *itemName, CFErrorRef *err) {
587 char *cmd, *propertyname;
588 SOSSecurityPropertyActionCode ac = kSOSCCSecurityPropertyQuery;
589 CFStringRef propertyspec;
590
591 propertyname = strchr(itemName, ':');
592 if(propertyname == NULL) return false;
593 *propertyname = 0;
594 propertyname++;
595 cmd = itemName;
596
597 if(strcmp(cmd, "enable") == 0) {
598 ac = kSOSCCSecurityPropertyEnable;
599 } else if(strcmp(cmd, "disable") == 0) {
600 ac = kSOSCCSecurityPropertyDisable;
601 } else if(strcmp(cmd, "query") == 0) {
602 ac = kSOSCCSecurityPropertyQuery;
603 } else {
604 return false;
605 }
606
607 propertyspec = convertStringToProperty(propertyname);
608 if(!propertyspec) return false;
609
610 SOSSecurityPropertyResultCode rc = SOSCCSecurityProperty(propertyspec, ac, err);
611 CFStringRef resultString = convertPropertyReturnCodeToString(rc);
612
613 printmsg(CFSTR("Property Result: %@ : %@\n"), resultString, propertyspec);
614 return true;
615}
616
617
618static void dumpStringSet(CFStringRef label, CFSetRef s) {
619 if(!s || !label) return;
620
621 printmsg(CFSTR("%@: { "), label);
622 __block bool first = true;
623 CFSetForEach(s, ^(const void *p) {
624 CFStringRef fmt = CFSTR(", %@");
625 if(first) {
626 fmt = CFSTR("%@");
627 }
628 CFStringRef string = (CFStringRef) p;
629 printmsg(fmt, string);
630 first=false;
631 });
632 printmsg(CFSTR(" }\n"), NULL);
633}
634
635static bool dumpMyPeer(CFErrorRef *error) {
636 SOSPeerInfoRef myPeer = SOSCCCopyMyPeerInfo(error);
637
638 if (!myPeer) return false;
639
640 CFStringRef peerID = SOSPeerInfoGetPeerID(myPeer);
641 CFStringRef peerName = SOSPeerInfoGetPeerName(myPeer);
642 CFIndex peerVersion = SOSPeerInfoGetVersion(myPeer);
643 bool retirement = SOSPeerInfoIsRetirementTicket(myPeer);
644
645 printmsg(CFSTR("Peer Name: %@ PeerID: %@ Version: %d\n"), peerName, peerID, peerVersion);
646 if(retirement) {
647 CFDateRef retdate = SOSPeerInfoGetRetirementDate(myPeer);
648 printmsg(CFSTR("Retired: %@\n"), retdate);
649
650 }
651
652 if(peerVersion >= 2) {
653 CFMutableSetRef views = SOSPeerInfoV2DictionaryCopySet(myPeer, sViewsKey);
654 CFStringRef serialNumber = SOSPeerInfoV2DictionaryCopyString(myPeer, sSerialNumberKey);
655 CFBooleanRef preferIDS = SOSPeerInfoV2DictionaryCopyBoolean(myPeer, sPreferIDS);
fa7225c8 656 CFBooleanRef preferIDSFragmentation = SOSPeerInfoV2DictionaryCopyBoolean(myPeer, sPreferIDSFragmentation);
6b200bc3 657 CFBooleanRef preferIDSACKModel = SOSPeerInfoV2DictionaryCopyBoolean(myPeer, sPreferIDSACKModel);
5c19dc3a
A
658 CFStringRef transportType = SOSPeerInfoV2DictionaryCopyString(myPeer, sTransportType);
659 CFStringRef idsDeviceID = SOSPeerInfoV2DictionaryCopyString(myPeer, sDeviceID);
660 CFMutableSetRef properties = SOSPeerInfoV2DictionaryCopySet(myPeer, sSecurityPropertiesKey);
661
6b200bc3
A
662 printmsg(CFSTR("Serial#: %@ PrefIDS#: %@ PrefFragmentation#: %@ PrefACK#: %@ transportType#: %@ idsDeviceID#: %@\n"),
663 serialNumber, preferIDS, preferIDSFragmentation, preferIDSACKModel, transportType, idsDeviceID);
5c19dc3a
A
664 dumpStringSet(CFSTR(" Views: "), views);
665 dumpStringSet(CFSTR("SecurityProperties: "), properties);
666
667 CFReleaseSafe(serialNumber);
668 CFReleaseSafe(preferIDS);
fa7225c8 669 CFReleaseSafe(preferIDSFragmentation);
5c19dc3a
A
670 CFReleaseSafe(views);
671 CFReleaseSafe(transportType);
672 CFReleaseSafe(idsDeviceID);
673 CFReleaseSafe(properties);
674
675 }
676
677 return myPeer != NULL;
678}
679
680static bool setBag(char *itemName, CFErrorRef *err)
681{
682 __block bool success = false;
683 __block CFErrorRef error = NULL;
684
685 CFStringRef random = SecPasswordCreateWithRandomDigits(10, NULL);
686
687 CFStringPerformWithUTF8CFData(random, ^(CFDataRef stringAsData) {
688 if (0 == strncasecmp(optarg, "single", 6) || 0 == strncasecmp(optarg, "all", 3)) {
689 bool includeV0 = (0 == strncasecmp(optarg, "all", 3));
690 printmsg(CFSTR("Setting iCSC single using entropy from string: %@\n"), random);
691 CFDataRef aks_bag = SecAKSCopyBackupBagWithSecret(CFDataGetLength(stringAsData), (uint8_t*)CFDataGetBytePtr(stringAsData), &error);
692
693 if (aks_bag) {
694 success = SOSCCRegisterSingleRecoverySecret(aks_bag, includeV0, &error);
695 if (!success) {
696 printmsg(CFSTR("Failed registering single secret %@"), error);
697 CFReleaseNull(aks_bag);
698 }
699 } else {
700 printmsg(CFSTR("Failed to create aks_bag: %@"), error);
701 }
702 CFReleaseNull(aks_bag);
703 } else if (0 == strncasecmp(optarg, "device", 6)) {
704 printmsg(CFSTR("Setting Device Secret using entropy from string: %@\n"), random);
705
706 SOSPeerInfoRef me = SOSCCCopyMyPeerWithNewDeviceRecoverySecret(stringAsData, &error);
707
708 success = me != NULL;
709
710 if (!success)
711 printmsg(CFSTR("Failed: %@\n"), err);
712 CFReleaseNull(me);
713 } else {
714 printmsg(CFSTR("Unrecognized argument to -b %s\n"), optarg);
715 }
716 });
717
718
719 return success;
720}
721
722static void prClientViewState(char *label, bool result) {
e3d460c9 723 fprintf(outFile, "Sync Status for %s: %s\n", label, (result) ? "enabled": "not enabled");
5c19dc3a
A
724}
725
726static bool clientViewStatus(CFErrorRef *error) {
727 prClientViewState("KeychainV0", SOSCCIsIcloudKeychainSyncing());
728 prClientViewState("Safari", SOSCCIsSafariSyncing());
729 prClientViewState("AppleTV", SOSCCIsAppleTVSyncing());
730 prClientViewState("HomeKit", SOSCCIsHomeKitSyncing());
731 prClientViewState("Wifi", SOSCCIsWiFiSyncing());
fa7225c8 732 prClientViewState("AlwaysOnNoInitialSync", SOSCCIsContinuityUnlockSyncing());
5c19dc3a
A
733 return false;
734}
735
736
737static bool dumpYetToSync(CFErrorRef *error) {
738 CFArrayRef yetToSyncViews = SOSCCCopyYetToSyncViewsList(error);
739
740 bool hadError = yetToSyncViews;
741
742 if (yetToSyncViews) {
743 __block CFStringRef separator = CFSTR("");
744
745 printmsg(CFSTR("Yet to sync views: ["), NULL);
746
747 CFArrayForEach(yetToSyncViews, ^(const void *value) {
748 if (isString(value)) {
749 printmsg(CFSTR("%@%@"), separator, value);
750
751 separator = CFSTR(", ");
752 }
753 });
754 printmsg(CFSTR("]\n"), NULL);
755 }
756
757 return !hadError;
758}
759
760
761// enable, disable, accept, reject, status, Reset, Clear
762int
763keychain_sync(int argc, char * const *argv)
764{
765 /*
766 "Keychain Syncing"
767 " -d disable"
768 " -e enable (join/create circle)"
769 " -i info (current status)"
770 " -m dump my peer"
5c19dc3a
A
771 "
772 "Account/Circle Management"
773 " -a accept all applicants"
774 " -l [reason] sign out of circle + set custom departure reason"
775 " -q sign out of circle"
776 " -r reject all applicants"
777 " -E ensure fresh parameters"
778 " -b device|all|single Register a backup bag - THIS RESETS BACKUPS!\n"
779 " -A Apply to a ring\n"
780 " -B Withdrawl from a ring\n"
781 " -G Enable Ring\n"
782 " -F Ring Status\n"
783 " -I Dump Ring Information\n"
784
785 " -N (re-)set to new account (USE WITH CARE: device will not leave circle before resetting account!)"
786 " -O reset to offering"
787 " -R reset circle"
788 " -X [limit] best effort bail from circle in limit seconds"
e0e0d90e
A
789 " -o list view unaware peers in circle"
790 " -0 boot view unaware peers from circle"
e3d460c9
A
791 " -1 grab account state from the keychain"
792 " -2 delete account state from the keychain"
793 " -3 grab engine state from the keychain"
794 " -4 delete engine state from the keychain"
5c19dc3a
A
795 "
796 "IDS"
797 " -g set IDS device id"
798 " -p retrieve IDS device id"
799 " -x ping all devices in an IDS account"
800 " -w check IDS availability"
6b200bc3 801 " -z retrieve IDS id through KeychainSyncingOverIDSProxy"
5c19dc3a
A
802 "
803 "Password"
804 " -P [label:]password set password (optionally for a given label) for sync"
805 " -T [label:]password try password (optionally for a given label) for sync"
806 "
807 "KVS"
808 " -k pend all registered kvs keys"
809 " -C clear all values from KVS"
810 " -D [itemName] dump contents of KVS"
fa7225c8 811 " -W sync and dump"
5c19dc3a
A
812 "
813 "Misc"
814 " -v [enable|disable|query:viewname] enable, disable, or query my PeerInfo's view set"
815 " viewnames are: keychain|masterkey|iclouddrive|photos|cloudkit|escrow|fde|maildrop|icloudbackup|notes|imessage|appletv|homekit|"
816 " wifi|passwords|creditcards|icloudidentity|othersyncable"
817 " -L list all known view and their status"
818 " -S [enable|disable|propertyname] enable, disable, or query my PeerInfo's Security Property set"
819 " propertynames are: hasentropy|screenlock|SEP|IOS\n"
820 " -U purge private key material cache\n"
821 " -V Report View Sync Status on all known clients.\n"
e0e0d90e
A
822 " -H Set escrow record.\n"
823 " -J Get the escrow record.\n"
824 " -M Check peer availability.\n"
5c19dc3a
A
825 */
826 int ch, result = 0;
827 CFErrorRef error = NULL;
828 bool hadError = false;
6b200bc3 829 SOSLogSetOutputTo(NULL, NULL);
e3d460c9 830
6b200bc3 831 while ((ch = getopt(argc, argv, "ab:deg:hikl:mopq:rSv:w:x:zA:B:MNJCDEF:HG:ILOP:RT:UWX:VY01234")) != -1)
5c19dc3a
A
832 switch (ch) {
833 case 'l':
834 {
e3d460c9 835 fprintf(outFile, "Signing out of circle\n");
5c19dc3a
A
836 hadError = !SOSCCSignedOut(true, &error);
837 if (!hadError) {
838 errno = 0;
839 int reason = (int) strtoul(optarg, NULL, 10);
840 if (errno != 0 ||
841 reason < kSOSDepartureReasonError ||
842 reason >= kSOSNumDepartureReasons) {
e3d460c9 843 fprintf(errFile, "Invalid custom departure reason %s\n", optarg);
5c19dc3a 844 } else {
e3d460c9 845 fprintf(outFile, "Setting custom departure reason %d\n", reason);
5c19dc3a
A
846 hadError = !SOSCCSetLastDepartureReason(reason, &error);
847 notify_post(kSOSCCCircleChangedNotification);
848 }
849 }
850 break;
851 }
852
853 case 'q':
854 {
e3d460c9 855 fprintf(outFile, "Signing out of circle\n");
5c19dc3a
A
856 bool signOutImmediately = false;
857 if (strcasecmp(optarg, "true") == 0) {
858 signOutImmediately = true;
859 } else if (strcasecmp(optarg, "false") == 0) {
860 signOutImmediately = false;
861 } else {
e3d460c9 862 fprintf(outFile, "Please provide a \"true\" or \"false\" whether you'd like to leave the circle immediately\n");
5c19dc3a
A
863 }
864 hadError = !SOSCCSignedOut(signOutImmediately, &error);
865 notify_post(kSOSCCCircleChangedNotification);
866 break;
867 }
868
869 case 'p':
870 {
e3d460c9 871 fprintf(outFile, "Grabbing DS ID\n");
e0e0d90e 872 CFStringRef deviceID = SOSCCCopyDeviceID(&error);
5c19dc3a
A
873 if (error) {
874 hadError = true;
875 break;
876 }
877 if (!isNull(deviceID)) {
878 const char *id = CFStringGetCStringPtr(deviceID, kCFStringEncodingUTF8);
879 if (id)
e3d460c9 880 fprintf(outFile, "IDS Device ID: %s\n", id);
5c19dc3a 881 else
e3d460c9 882 fprintf(outFile, "IDS Device ID is null!\n");
5c19dc3a 883 }
e0e0d90e 884 CFReleaseNull(deviceID);
5c19dc3a
A
885 break;
886 }
887
888 case 'g':
889 {
e3d460c9 890 fprintf(outFile, "Setting DS ID: %s\n", optarg);
5c19dc3a
A
891 CFStringRef deviceID = CFStringCreateWithCString(kCFAllocatorDefault, optarg, kCFStringEncodingUTF8);
892 hadError = SOSCCSetDeviceID(deviceID, &error);
893 CFReleaseNull(deviceID);
894 break;
895 }
896
897 case 'w':
898 {
e3d460c9 899 fprintf(outFile, "Attempting to send this message over IDS: %s\n", optarg);
5c19dc3a
A
900 CFStringRef message = CFStringCreateWithCString(kCFAllocatorDefault, optarg, kCFStringEncodingUTF8);
901 hadError = SOSCCIDSServiceRegistrationTest(message, &error);
902 if (error) {
903 printerr(CFSTR("IDS is not ready: %@\n"), error);
904 CFRelease(error);
905 }
906 CFReleaseNull(message);
907 break;
908 }
909
910 case 'x':
911 {
e3d460c9 912 fprintf(outFile, "Starting ping test using this message: %s\n", optarg);
5c19dc3a
A
913 CFStringRef message = CFStringCreateWithCString(kCFAllocatorDefault, optarg, kCFStringEncodingUTF8);
914 hadError = SOSCCIDSPingTest(message, &error);
915 if (error) {
916 printerr(CFSTR("Ping test failed to start: %@\n"), error);
917 CFRelease(error);
918 }
919 CFReleaseNull(message);
920 break;
921 }
922
923 case 'z':
924 hadError = SOSCCIDSDeviceIDIsAvailableTest(&error);
925 if (error) {
926 printerr(CFSTR("Failed to retrieve IDS device ID: %@\n"), error);
927 CFRelease(error);
928 }
929 break;
930
931 case 'e':
e3d460c9 932 fprintf(outFile, "Turning ON keychain syncing\n");
5c19dc3a
A
933 hadError = requestToJoinCircle(&error);
934 break;
935
936 case 'd':
e3d460c9 937 fprintf(outFile, "Turning OFF keychain syncing\n");
5c19dc3a
A
938 hadError = !SOSCCRemoveThisDeviceFromCircle(&error);
939 break;
940
941 case 'a':
942 {
943 CFArrayRef applicants = SOSCCCopyApplicantPeerInfo(NULL);
944 if (applicants) {
945 hadError = !SOSCCAcceptApplicants(applicants, &error);
946 CFRelease(applicants);
947 } else {
e3d460c9 948 fprintf(errFile, "No applicants to accept\n");
5c19dc3a
A
949 }
950 break;
951 }
952
953 case 'r':
954 {
955 CFArrayRef applicants = SOSCCCopyApplicantPeerInfo(NULL);
956 if (applicants) {
957 hadError = !SOSCCRejectApplicants(applicants, &error);
958 CFRelease(applicants);
959 } else {
e3d460c9 960 fprintf(errFile, "No applicants to reject\n");
5c19dc3a
A
961 }
962 break;
963 }
964
965 case 'i':
966 dumpCircleInfo();
967 break;
968
969 case 'k':
970 notify_post("com.apple.security.cloudkeychain.forceupdate");
971 break;
e0e0d90e
A
972
973 case 'o':
974 {
975 printPeerInfos("view-unaware", ^(CFErrorRef *error) { return SOSCCCopyViewUnawarePeerInfo(error); });
976 break;
977 }
978
979 case '0':
980 {
981 CFArrayRef unawares = SOSCCCopyViewUnawarePeerInfo(&error);
982 if (unawares) {
983 hadError = !SOSCCRemovePeersFromCircle(unawares, &error);
984 } else {
985 hadError = true;
986 }
987 CFReleaseNull(unawares);
e3d460c9
A
988 break;
989 }
990 case '1':
991 {
992 CFDataRef accountState = SOSCCCopyAccountState(&error);
993 if (accountState) {
994 printmsg(CFSTR(" %@\n"), CFDataCopyHexString(accountState));
995 } else {
996 hadError = true;
997 }
998 CFReleaseNull(accountState);
999 break;
1000 }
1001 case '2':
1002 {
1003 bool status = SOSCCDeleteAccountState(&error);
1004 if (status) {
1005 printmsg(CFSTR("Deleted account from the keychain %d\n"), status);
1006 } else {
1007 hadError = true;
1008 }
1009 break;
1010 }
1011 case '3':
1012 {
1013 CFDataRef engineState = SOSCCCopyEngineData(&error);
1014 if (engineState) {
1015 printmsg(CFSTR(" %@\n"), CFDataCopyHexString(engineState));
1016 } else {
1017 hadError = true;
1018 }
1019 CFReleaseNull(engineState);
1020 break;
1021 }
1022 case '4':
1023 {
1024 bool status = SOSCCDeleteEngineState(&error);
1025 if (status) {
1026 printmsg(CFSTR("Deleted engine-state from the keychain %d\n"), status);
1027 } else {
1028 hadError = true;
1029 }
1030 break;
e0e0d90e
A
1031 }
1032
5c19dc3a
A
1033 case 'E':
1034 {
e3d460c9 1035 fprintf(outFile, "Ensuring Fresh Parameters\n");
5c19dc3a
A
1036 bool result = SOSCCRequestEnsureFreshParameters(&error);
1037 if (error) {
1038 hadError = true;
1039 break;
1040 }
1041 if (result) {
e3d460c9 1042 fprintf(outFile, "Refreshed Parameters Ensured!\n");
5c19dc3a 1043 } else {
e3d460c9 1044 fprintf(outFile, "Problem trying to ensure fresh parameters\n");
5c19dc3a
A
1045 }
1046 break;
1047 }
1048 case 'A':
1049 {
e3d460c9 1050 fprintf(outFile, "Applying to Ring\n");
5c19dc3a
A
1051 CFStringRef ringName = CFStringCreateWithCString(kCFAllocatorDefault, (char *)optarg, kCFStringEncodingUTF8);
1052 hadError = SOSCCApplyToARing(ringName, &error);
6b200bc3 1053 CFReleaseNull(ringName);
5c19dc3a
A
1054 break;
1055 }
1056 case 'B':
1057 {
e3d460c9 1058 fprintf(outFile, "Withdrawing from Ring\n");
5c19dc3a
A
1059 CFStringRef ringName = CFStringCreateWithCString(kCFAllocatorDefault, (char *)optarg, kCFStringEncodingUTF8);
1060 hadError = SOSCCWithdrawlFromARing(ringName, &error);
6b200bc3 1061 CFReleaseNull(ringName);
5c19dc3a
A
1062 break;
1063 }
1064 case 'F':
1065 {
e3d460c9 1066 fprintf(outFile, "Status of this device in the Ring\n");
5c19dc3a
A
1067 CFStringRef ringName = CFStringCreateWithCString(kCFAllocatorDefault, (char *)optarg, kCFStringEncodingUTF8);
1068 hadError = SOSCCRingStatus(ringName, &error);
6b200bc3 1069 CFReleaseNull(ringName);
5c19dc3a
A
1070 break;
1071 }
1072 case 'G':
1073 {
e3d460c9 1074 fprintf(outFile, "Enabling Ring\n");
5c19dc3a
A
1075 CFStringRef ringName = CFStringCreateWithCString(kCFAllocatorDefault, (char *)optarg, kCFStringEncodingUTF8);
1076 hadError = SOSCCEnableRing(ringName, &error);
6b200bc3 1077 CFReleaseNull(ringName);
5c19dc3a
A
1078 break;
1079 }
e0e0d90e
A
1080 case 'H':
1081 {
e3d460c9 1082 fprintf(outFile, "Setting random escrow record\n");
e0e0d90e
A
1083 bool success = SOSCCSetEscrowRecord(CFSTR("label"), 8, &error);
1084 if(success)
1085 hadError = false;
1086 else
1087 hadError = true;
1088 break;
1089 }
1090 case 'J':
1091 {
1092 CFDictionaryRef attempts = SOSCCCopyEscrowRecord(&error);
1093 if(attempts){
1094 CFDictionaryForEach(attempts, ^(const void *key, const void *value) {
1095 if(isString(key)){
1096 char *keyString = CFStringToCString(key);
e3d460c9 1097 fprintf(outFile, "%s:\n", keyString);
e0e0d90e
A
1098 free(keyString);
1099 }
1100 if(isDictionary(value)){
1101 CFDictionaryForEach(value, ^(const void *key, const void *value) {
1102 if(isString(key)){
1103 char *keyString = CFStringToCString(key);
e3d460c9 1104 fprintf(outFile, "%s: ", keyString);
e0e0d90e
A
1105 free(keyString);
1106 }
1107 if(isString(value)){
1108 char *time = CFStringToCString(value);
e3d460c9 1109 fprintf(outFile, "timestamp: %s\n", time);
e0e0d90e
A
1110 free(time);
1111 }
1112 else if(isNumber(value)){
1113 uint64_t tries;
1114 CFNumberGetValue(value, kCFNumberLongLongType, &tries);
e3d460c9 1115 fprintf(outFile, "date: %llu\n", tries);
e0e0d90e
A
1116 }
1117 });
1118 }
1119
1120 });
1121 }
1122 CFReleaseNull(attempts);
1123 hadError = false;
1124 break;
1125 }
1126 case 'M':
1127 {
1128 bool success = SOSCCCheckPeerAvailability(&error);
1129 if(success)
1130 hadError = false;
1131 else
1132 hadError = true;
1133 break;
1134 }
5c19dc3a
A
1135 case 'I':
1136 {
e3d460c9 1137 fprintf(outFile, "Printing all the rings\n");
5c19dc3a
A
1138 CFStringRef ringdescription = SOSCCGetAllTheRings(&error);
1139 if(!ringdescription)
1140 hadError = true;
1141 else
e3d460c9 1142 fprintf(outFile, "Rings: %s", CFStringToCString(ringdescription));
5c19dc3a
A
1143
1144 break;
1145 }
1146
1147 case 'N':
1148 hadError = !SOSCCAccountSetToNew(&error);
1149 if (!hadError)
1150 notify_post(kSOSCCCircleChangedNotification);
1151 break;
1152
1153 case 'R':
1154 hadError = !SOSCCResetToEmpty(&error);
1155 break;
1156
1157 case 'O':
1158 hadError = !SOSCCResetToOffering(&error);
1159 break;
1160
1161 case 'm':
1162 hadError = !dumpMyPeer(&error);
1163 break;
1164
1165 case 'C':
1166 hadError = clearAllKVS(&error);
1167 break;
1168
1169 case 'P':
1170 hadError = setPassword(optarg, &error);
1171 break;
1172
1173 case 'T':
1174 hadError = tryPassword(optarg, &error);
1175 break;
1176
1177 case 'X':
1178 {
1179 uint64_t limit = strtoul(optarg, NULL, 10);
1180 hadError = !SOSCCBailFromCircle_BestEffort(limit, &error);
1181 break;
1182 }
1183
1184 case 'U':
1185 hadError = !SOSCCPurgeUserCredentials(&error);
1186 break;
1187
1188 case 'D':
1189 hadError = !dumpKVS(optarg, &error);
1190 break;
1191
1192 case 'W':
fa7225c8 1193 hadError = syncAndWait(&error);
5c19dc3a
A
1194 break;
1195
1196 case 'v':
1197 hadError = !viewcmd(optarg, &error);
1198 break;
1199
1200 case 'V':
1201 hadError = clientViewStatus(&error);
1202 break;
1203 case 'L':
1204 hadError = !listviewcmd(&error);
1205 break;
1206
1207 case 'S':
1208 hadError = !SecPropertycmd(optarg, &error);
1209 break;
1210
1211 case 'b':
1212 hadError = setBag(optarg, &error);
1213 break;
1214
1215 case 'Y':
1216 hadError = dumpYetToSync(&error);
1217 break;
6b200bc3 1218 case '?':
5c19dc3a
A
1219 default:
1220 return 2; /* Return 2 triggers usage message. */
1221 }
1222
1223 if (hadError)
1224 printerr(CFSTR("Error: %@\n"), error);
1225
1226 return result;
1227}