/ KeychainSyncAccountNotification / KeychainSyncAccountNotification.m
KeychainSyncAccountNotification.m
1 // 2 // KeychainSyncAccountNotification.m 3 // Security 4 // 5 6 #import "KeychainSyncAccountNotification.h" 7 #import <Accounts/Accounts.h> 8 #import <Accounts/Accounts_Private.h> 9 #import <AppleAccount/ACAccount+AppleAccount.h> 10 #import <AccountsDaemon/ACDAccountStore.h> 11 #import <Security/SecureObjectSync/SOSCloudCircle.h> 12 #import <AuthKit/AuthKit.h> 13 #import <AuthKit/AuthKit_Private.h> 14 #if OCTAGON 15 #import <keychain/ot/OTControl.h> 16 #include <utilities/SecCFRelease.h> 17 #endif 18 #import "utilities/debugging.h" 19 #import "OT.h" 20 21 @implementation KeychainSyncAccountNotification 22 23 - (bool)accountIsPrimary:(ACAccount *)account 24 { 25 return [account aa_isAccountClass:AAAccountClassPrimary]; 26 } 27 28 // this is where we initialize SOS and OT for account sign-in 29 // in the future we may bring this logic over to KeychainDataclassOwner and delete KeychainSyncAccountNotification, but accounts people say that's a change that today would require coordination across multiple teams 30 // was asked to file this radar for accounts: <rdar://problem/40176124> Invoke DataclassOwner when enabling or signing into an account 31 - (void)account:(ACAccount *)account didChangeWithType:(ACAccountChangeType)changeType inStore:(ACDAccountStore *)store oldAccount:(ACAccount *)oldAccount { 32 33 if((changeType == kACAccountChangeTypeAdded || changeType == kACAccountChangeTypeModified || changeType == kACAccountChangeTypeWarmingUp) && 34 [account.accountType.identifier isEqualToString: ACAccountTypeIdentifierAppleAccount] && 35 [self accountIsPrimary:account]) { 36 37 SOSCCLoggedIntoAccount(NULL); 38 39 #if OCTAGON 40 if(OctagonIsEnabled()){ 41 NSString* altDSID = [account aa_altDSID]; 42 secnotice("octagon-account", "Received an primary Apple account modification (altDSID %@)", altDSID); 43 44 __block NSError* error = nil; 45 46 // Use asynchronous XPC here for speed and just hope it works 47 OTControl* otcontrol = [OTControl controlObject:false error:&error]; 48 49 if (nil == otcontrol) { 50 secerror("octagon-account: Failed to get OTControl: %@", error.localizedDescription); 51 } else { 52 [otcontrol signIn:altDSID container:nil context:OTDefaultContext reply:^(NSError * _Nullable signedInError) { 53 // take a retain on otcontrol so it won't invalidate the connection 54 (void)otcontrol; 55 56 if(signedInError) { 57 secerror("octagon-account: error signing in: %s", [[signedInError description] UTF8String]); 58 } else { 59 secnotice("octagon-account", "account now signed in for octagon operation"); 60 } 61 }]; 62 } 63 }else{ 64 secerror("Octagon not enabled; not signing in"); 65 } 66 #endif 67 } 68 69 // If there is any change to any AuthKit account's security level, notify octagon 70 71 #if OCTAGON 72 if([account.accountType.identifier isEqualToString: ACAccountTypeIdentifierIDMS]) { 73 NSString* altDSID = [account aa_altDSID];; 74 secnotice("octagon-authkit", "Received an IDMS account modification (altDSID: %@)", altDSID); 75 76 AKAccountManager *manager = [AKAccountManager sharedInstance]; 77 78 AKAppleIDSecurityLevel oldSecurityLevel = [manager securityLevelForAccount:oldAccount]; 79 AKAppleIDSecurityLevel newSecurityLevel = [manager securityLevelForAccount:account]; 80 81 if(oldSecurityLevel != newSecurityLevel) { 82 secnotice("octagon-authkit", "IDMS security level has now moved to %ld for altDSID %@", (unsigned long)newSecurityLevel, altDSID); 83 84 __block NSError* error = nil; 85 // Use an asynchronous otcontrol for Speed But Not Necessarily Correctness 86 OTControl* otcontrol = [OTControl controlObject:false error:&error]; 87 if(!otcontrol || error) { 88 secerror("octagon-authkit: Failed to get OTControl: %@", error); 89 } else { 90 [otcontrol notifyIDMSTrustLevelChangeForContainer:nil context:OTDefaultContext reply:^(NSError * _Nullable idmsError) { 91 // take a retain on otcontrol so it won't invalidate the connection 92 (void)otcontrol; 93 94 if(idmsError) { 95 secerror("octagon-authkit: error with idms trust level change in: %s", [[idmsError description] UTF8String]); 96 } else { 97 secnotice("octagon-authkit", "informed octagon of IDMS trust level change"); 98 } 99 }]; 100 } 101 102 } else { 103 secnotice("octagon-authkit", "No change to IDMS security level (%lu) for altDSID %@", (unsigned long)newSecurityLevel, altDSID); 104 } 105 } 106 #endif 107 108 if ((changeType == kACAccountChangeTypeDeleted) && [oldAccount.accountType.identifier isEqualToString:ACAccountTypeIdentifierAppleAccount]) { 109 NSString* altDSID = [oldAccount aa_altDSID]; 110 secnotice("octagon-account", "Received an Apple account deletion (altDSID %@)", altDSID); 111 112 NSString *accountIdentifier = oldAccount.identifier; 113 NSString *username = oldAccount.username; 114 115 if(accountIdentifier != NULL && username !=NULL) { 116 if ([self accountIsPrimary:oldAccount]) { 117 CFErrorRef removalError = NULL; 118 119 secinfo("accounts", "Performing SOS circle credential removal for account %@: %@", accountIdentifier, username); 120 121 if (!SOSCCLoggedOutOfAccount(&removalError)) { 122 secerror("Account %@ could not leave the SOS circle: %@", accountIdentifier, removalError); 123 } 124 125 #if OCTAGON 126 if(OctagonIsEnabled()){ 127 __block NSError* error = nil; 128 129 // Use an asynchronous control for Speed 130 OTControl* otcontrol = [OTControl controlObject:false error:&error]; 131 132 if (nil == otcontrol) { 133 secerror("octagon-account: Failed to get OTControl: %@", error.localizedDescription); 134 } else { 135 [otcontrol signOut:nil context:OTDefaultContext reply:^(NSError * _Nullable signedInError) { 136 // take a retain on otcontrol so it won't invalidate the connection 137 (void)otcontrol; 138 139 if(signedInError) { 140 secerror("octagon-account: error signing out: %s", [[signedInError description] UTF8String]); 141 } else { 142 secnotice("octagon-account", "signed out of octagon trust"); 143 } 144 }]; 145 } 146 } else { 147 secerror("Octagon not enabled; not signing out"); 148 } 149 #endif 150 } 151 } 152 } 153 } 154 155 @end