KeychainSyncAccountNotification.m [plain text]
//
// KeychainSyncAccountNotification.m
// Security
//
#import "KeychainSyncAccountNotification.h"
#import <Accounts/Accounts.h>
#import <Accounts/Accounts_Private.h>
#import <AppleAccount/ACAccount+AppleAccount.h>
#import <AccountsDaemon/ACDAccountStore.h>
#import <Security/SecureObjectSync/SOSCloudCircle.h>
#import <AuthKit/AuthKit.h>
#import <AuthKit/AuthKit_Private.h>
#if OCTAGON
#import <keychain/ot/OTControl.h>
#include <utilities/SecCFRelease.h>
#endif
#import "utilities/debugging.h"
#import "OT.h"
@implementation KeychainSyncAccountNotification
- (bool)accountIsPrimary:(ACAccount *)account
{
return [account aa_isAccountClass:AAAccountClassPrimary];
}
// this is where we initialize SOS and OT for account sign-in
// 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
// was asked to file this radar for accounts: <rdar://problem/40176124> Invoke DataclassOwner when enabling or signing into an account
- (void)account:(ACAccount *)account didChangeWithType:(ACAccountChangeType)changeType inStore:(ACDAccountStore *)store oldAccount:(ACAccount *)oldAccount {
if((changeType == kACAccountChangeTypeAdded || changeType == kACAccountChangeTypeModified || changeType == kACAccountChangeTypeWarmingUp) &&
[account.accountType.identifier isEqualToString: ACAccountTypeIdentifierAppleAccount] &&
[self accountIsPrimary:account]) {
SOSCCLoggedIntoAccount(NULL);
#if OCTAGON
if(OctagonIsEnabled()){
NSString* altDSID = [account aa_altDSID];
secnotice("octagon-account", "Received an primary Apple account modification (altDSID
__block NSError* error = nil;
// Use asynchronous XPC here for speed and just hope it works
OTControl* otcontrol = [OTControl controlObject:false error:&error];
if (nil == otcontrol) {
secerror("octagon-account: Failed to get OTControl: } else {
[otcontrol signIn:altDSID container:nil context:OTDefaultContext reply:^(NSError * _Nullable signedInError) {
// take a retain on otcontrol so it won't invalidate the connection
(void)otcontrol;
if(signedInError) {
secerror("octagon-account: error signing in: } else {
secnotice("octagon-account", "account now signed in for octagon operation");
}
}];
}
}else{
secerror("Octagon not enabled; not signing in");
}
#endif
}
// If there is any change to any AuthKit account's security level, notify octagon
#if OCTAGON
if([account.accountType.identifier isEqualToString: ACAccountTypeIdentifierIDMS]) {
NSString* altDSID = [account aa_altDSID];;
secnotice("octagon-authkit", "Received an IDMS account modification (altDSID:
AKAccountManager *manager = [AKAccountManager sharedInstance];
AKAppleIDSecurityLevel oldSecurityLevel = [manager securityLevelForAccount:oldAccount];
AKAppleIDSecurityLevel newSecurityLevel = [manager securityLevelForAccount:account];
if(oldSecurityLevel != newSecurityLevel) {
secnotice("octagon-authkit", "IDMS security level has now moved to
__block NSError* error = nil;
// Use an asynchronous otcontrol for Speed But Not Necessarily Correctness
OTControl* otcontrol = [OTControl controlObject:false error:&error];
if(!otcontrol || error) {
secerror("octagon-authkit: Failed to get OTControl: } else {
[otcontrol notifyIDMSTrustLevelChangeForContainer:nil context:OTDefaultContext reply:^(NSError * _Nullable idmsError) {
// take a retain on otcontrol so it won't invalidate the connection
(void)otcontrol;
if(idmsError) {
secerror("octagon-authkit: error with idms trust level change in: } else {
secnotice("octagon-authkit", "informed octagon of IDMS trust level change");
}
}];
}
} else {
secnotice("octagon-authkit", "No change to IDMS security level ( }
}
#endif
if ((changeType == kACAccountChangeTypeDeleted) && [oldAccount.accountType.identifier isEqualToString:ACAccountTypeIdentifierAppleAccount]) {
NSString* altDSID = [oldAccount aa_altDSID];
secnotice("octagon-account", "Received an Apple account deletion (altDSID
NSString *accountIdentifier = oldAccount.identifier;
NSString *username = oldAccount.username;
if(accountIdentifier != NULL && username !=NULL) {
if ([self accountIsPrimary:oldAccount]) {
CFErrorRef removalError = NULL;
secinfo("accounts", "Performing SOS circle credential removal for account
if (!SOSCCLoggedOutOfAccount(&removalError)) {
secerror("Account }
#if OCTAGON
if(OctagonIsEnabled()){
__block NSError* error = nil;
// Use an asynchronous control for Speed
OTControl* otcontrol = [OTControl controlObject:false error:&error];
if (nil == otcontrol) {
secerror("octagon-account: Failed to get OTControl: } else {
[otcontrol signOut:nil context:OTDefaultContext reply:^(NSError * _Nullable signedInError) {
// take a retain on otcontrol so it won't invalidate the connection
(void)otcontrol;
if(signedInError) {
secerror("octagon-account: error signing out: } else {
secnotice("octagon-account", "signed out of octagon trust");
}
}];
}
} else {
secerror("Octagon not enabled; not signing out");
}
#endif
}
}
}
}
@end