4 #import "keychain/ot/OTUpdateTrustedDeviceListOperation.h"
6 #import <CloudKit/CloudKit_Private.h>
8 #import <Security/SecKey.h>
9 #import <Security/SecKeyPriv.h>
10 #import <SecurityFoundation/SFKey_Private.h>
12 #import "keychain/ckks/CKKSNearFutureScheduler.h"
13 #import "keychain/ckks/CloudKitCategories.h"
14 #import "keychain/ot/ObjCImprovements.h"
15 #import "keychain/ot/OTSOSUpgradeOperation.h"
16 #import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h"
17 #import "keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.h"
18 #import "keychain/ot/OTOperationDependencies.h"
20 @interface OTUpdateTrustedDeviceListOperation ()
21 @property OTOperationDependencies* deps;
23 @property OctagonState* stateIfListUpdates;
25 @property (nullable) OctagonFlag* retryFlag;
27 // Since we're making callback based async calls, use this operation trick to hold off the ending of this operation
28 @property NSOperation* finishedOp;
31 @implementation OTUpdateTrustedDeviceListOperation
32 @synthesize nextState = _nextState;
33 @synthesize intendedState = _intendedState;
35 - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies
36 intendedState:(OctagonState*)intendedState
37 listUpdatesState:(OctagonState*)stateIfListUpdates
38 errorState:(OctagonState*)errorState
39 retryFlag:(OctagonFlag*)retryFlag
42 if((self = [super init])) {
45 _intendedState = intendedState;
46 _nextState = errorState;
47 _stateIfListUpdates = stateIfListUpdates;
49 _retryFlag = retryFlag;
57 secnotice("octagon-authkit", "Attempting to update trusted device list");
59 self.finishedOp = [NSBlockOperation blockOperationWithBlock:^{
60 // If we errored in some unknown way, ask to try again!
64 if(self.retryFlag == nil) {
65 secerror("octagon-authkit: Received an error updating the trusted device list operation, but no retry flag present.");
69 OctagonPendingFlag* pendingFlag = nil;
71 if([self.deps.lockStateTracker isLockedError:self.error]) {
72 secnotice("octagon-authkit", "Setting the allowed device list failed due to lock state: %@", self.error);
73 self.nextState = OctagonStateWaitForUnlock;
74 pendingFlag = [[OctagonPendingFlag alloc] initWithFlag:self.retryFlag
75 conditions:OctagonPendingConditionsDeviceUnlocked];
78 secnotice("octagon-authkit", "Error is currently unknown, will not retry: %@", self.error);
82 secnotice("octagon-authkit", "Machine ID list error is not fatal: requesting retry: %@",
84 [self.deps.flagHandler handlePendingFlag:pendingFlag];
88 [self dependOnBeforeGroupFinished:self.finishedOp];
90 NSError* localError = nil;
91 BOOL isAccountDemo = [self.deps.authKitAdapter accountIsDemoAccount:&localError];
93 secerror("octagon-authkit: failed to fetch demo account flag: %@", localError);
96 [self.deps.authKitAdapter fetchCurrentDeviceList:^(NSSet<NSString *> * _Nullable machineIDs, NSError * _Nullable error) {
98 if(!machineIDs || error) {
99 secerror("octagon-authkit: Unable to fetch machine ID list: %@", error);
100 if (self.logForUpgrade) {
101 [[CKKSAnalytics logger] logRecoverableError:error
102 forEvent:OctagonEventUpgradeFetchDeviceIDs
103 withAttributes:NULL];
106 [self runBeforeGroupFinished:self.finishedOp];
109 if (self.logForUpgrade) {
110 [[CKKSAnalytics logger] logSuccessForEventNamed:OctagonEventUpgradeFetchDeviceIDs];
112 [self afterAuthKitFetch:machineIDs accountIsDemo:isAccountDemo];
117 - (void)afterAuthKitFetch:(NSSet<NSString *>*)allowedMachineIDs accountIsDemo:(BOOL)accountIsDemo
120 BOOL honorIDMSListChanges = accountIsDemo ? NO : YES;
122 [self.deps.cuttlefishXPCWrapper setAllowedMachineIDsWithContainer:self.deps.containerName
123 context:self.deps.contextID
124 allowedMachineIDs:allowedMachineIDs
125 honorIDMSListChanges:honorIDMSListChanges
126 reply:^(BOOL listDifferences, NSError * _Nullable error) {
129 if (self.logForUpgrade) {
130 [[CKKSAnalytics logger] logResultForEvent:OctagonEventUpgradeSetAllowList hardFailure:true result:error];
133 secnotice("octagon-authkit", "Unable to save machineID allow-list: %@", error);
136 secnotice("octagon-authkit", "Successfully saved machineID allow-list (%@ change)", listDifferences ? @"some" : @"no");
137 if(listDifferences) {
138 self.nextState = self.stateIfListUpdates;
140 self.nextState = self.intendedState;
144 [self runBeforeGroupFinished:self.finishedOp];