]> git.saurik.com Git - apple/security.git/blob - KeychainSyncAccountNotification/KeychainSyncAccountNotification.m
Security-59306.11.20.tar.gz
[apple/security.git] / KeychainSyncAccountNotification / 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) &&
34 [account.accountType.identifier isEqualToString: ACAccountTypeIdentifierAppleAccount] &&
35 [self accountIsPrimary:account]) {
36
37 #if OCTAGON
38 if(OctagonIsEnabled()){
39 __block NSError* error = nil;
40
41 NSString* altDSID = [account aa_altDSID];
42
43 OTControl* otcontrol = [OTControl controlObject:&error];
44
45 if (nil == otcontrol) {
46 secerror("octagon: Failed to get OTControl: %@", error.localizedDescription);
47 } else {
48 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
49
50 [otcontrol signIn:altDSID container:nil context:OTDefaultContext reply:^(NSError * _Nullable signedInError) {
51 if(signedInError) {
52 secerror("octagon: error signing in: %s", [[signedInError description] UTF8String]);
53 } else {
54 secnotice("octagon", "account now signed in for octagon operation");
55 }
56 dispatch_semaphore_signal(sema);
57
58 }];
59 if (0 != dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 60 * 5))) {
60 secerror("octagon: Timed out signing in");
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 secnotice("octagon-authkit", "Received an IDMS account modification");
74
75 AKAccountManager *manager = [AKAccountManager sharedInstance];
76
77 AKAppleIDSecurityLevel oldSecurityLevel = [manager securityLevelForAccount:oldAccount];
78 AKAppleIDSecurityLevel newSecurityLevel = [manager securityLevelForAccount:account];
79
80 if(oldSecurityLevel != newSecurityLevel) {
81 NSString* identifier = account.identifier;
82 secnotice("octagon-authkit", "IDMS security level has now moved to %ld for %@", (unsigned long)newSecurityLevel, identifier);
83
84 __block NSError* error = nil;
85 OTControl* otcontrol = [OTControl controlObject:&error];
86 if(!otcontrol || error) {
87 secerror("octagon-authkit: Failed to get OTControl: %@", error);
88 } else {
89 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
90
91 [otcontrol notifyIDMSTrustLevelChangeForContainer:nil context:OTDefaultContext reply:^(NSError * _Nullable idmsError) {
92 if(idmsError) {
93 secerror("octagon-authkit: error with idms trust level change in: %s", [[idmsError description] UTF8String]);
94 } else {
95 secnotice("octagon-authkit", "informed octagon of IDMS trust level change");
96 }
97 dispatch_semaphore_signal(sema);
98 }];
99
100 if (0 != dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 5))) {
101 secerror("octagon-authkit: Timed out altering IDMS change in");
102 }
103 }
104
105 } else {
106 secnotice("octagon-authkit", "No change to IDMS security level");
107 }
108 }
109 #endif
110
111 if ((changeType == kACAccountChangeTypeDeleted) && [oldAccount.accountType.identifier isEqualToString:ACAccountTypeIdentifierAppleAccount]) {
112
113 NSString *accountIdentifier = oldAccount.identifier;
114 NSString *username = oldAccount.username;
115
116 if(accountIdentifier != NULL && username !=NULL) {
117 if ([self accountIsPrimary:oldAccount]) {
118 CFErrorRef removalError = NULL;
119
120 secinfo("accounts", "Performing SOS circle credential removal for account %@: %@", accountIdentifier, username);
121
122 if (!SOSCCLoggedOutOfAccount(&removalError)) {
123 secerror("Account %@ could not leave the SOS circle: %@", accountIdentifier, removalError);
124 }
125
126 #if OCTAGON
127 if(OctagonIsEnabled()){
128 __block NSError* error = nil;
129
130 OTControl* otcontrol = [OTControl controlObject:&error];
131
132 if (nil == otcontrol) {
133 secerror("octagon: Failed to get OTControl: %@", error.localizedDescription);
134 } else {
135 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
136
137 [otcontrol signOut:nil context:OTDefaultContext reply:^(NSError * _Nullable signedInError) {
138 if(signedInError) {
139 secerror("octagon: error signing out: %s", [[signedInError description] UTF8String]);
140 } else {
141 secnotice("octagon", "signed out of octagon trust");
142 }
143 dispatch_semaphore_signal(sema);
144
145 }];
146 if (0 != dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 60 * 5))) {
147 secerror("octagon: Timed out signing out");
148 }
149 }
150 } else {
151 secerror("Octagon not enabled; not signing out");
152 }
153 #endif
154 }
155 }
156 }
157 }
158
159 @end