]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSAuthKitHelpers.m
Security-59306.11.20.tar.gz
[apple/security.git] / keychain / SecureObjectSync / SOSAuthKitHelpers.m
1 //
2 // SOSAuthKitHelpers.m
3 // Security
4 //
5 //
6
7 #import <Foundation/Foundation.h>
8 #import "SOSAuthKitHelpers.h"
9 #import <utilities/debugging.h>
10 #import "keychain/SecureObjectSync/SOSAccount.h"
11 #import "keychain/SecureObjectSync/SOSAccountPriv.h"
12 #import "keychain/SecureObjectSync/SOSFullPeerInfo.h"
13 #import "keychain/SecureObjectSync/SOSPeerInfoV2.h"
14 #import "keychain/SecureObjectSync/SOSPeerInfoPriv.h"
15
16 #if !TARGET_OS_BRIDGE && !TARGET_OS_SIMULATOR && __OBJC2__
17 #import <AppleAccount/AppleAccount_Private.h>
18 #import <AuthKit/AuthKit.h>
19 #import <AuthKit/AuthKit_Private.h>
20 #import <SoftLinking/SoftLinking.h>
21
22 #define SUPPORT_MID 1
23
24 SOFT_LINK_FRAMEWORK(PrivateFrameworks, AuthKit);
25 SOFT_LINK_FRAMEWORK(Frameworks, Accounts);
26
27 #pragma clang diagnostic push
28 #pragma clang diagnostic ignored "-Wstrict-prototypes"
29 SOFT_LINK_CLASS(AuthKit, AKAccountManager);
30 SOFT_LINK_CLASS(AuthKit, AKAnisetteProvisioningController);
31 SOFT_LINK_CLASS(AuthKit, AKAppleIDAuthenticationController);
32 SOFT_LINK_CLASS(AuthKit, AKDeviceListRequestContext);
33 SOFT_LINK_CLASS(Accounts, Accounts);
34 SOFT_LINK_CLASS(Accounts, ACAccountStore);
35 SOFT_LINK_CONSTANT(AuthKit, AKServiceNameiCloud, const NSString *);
36 #pragma clang diagnostic pop
37
38 static void *accountsFramework = NULL;
39 static void *appleAccountFramework = NULL;
40
41 static void
42 initAccountsFramework(void) {
43 static dispatch_once_t onceToken;
44 dispatch_once(&onceToken, ^{
45 accountsFramework = dlopen("/System/Library/Frameworks/Accounts.framework/Accounts", RTLD_LAZY);
46 appleAccountFramework = dlopen("/System/Library/PrivateFrameworks/AppleAccount.framework/AppleAccount", RTLD_LAZY);
47 });
48 }
49
50 @implementation SOSAuthKitHelpers
51
52 @class SOSAuthKitHelpers;
53
54 + (NSString *) machineID {
55 NSError *error = nil;
56 NSString *retval = nil;
57 secnotice("sosauthkit", "Entering machineID");
58
59 AKAnisetteProvisioningController *anisetteController = [getAKAnisetteProvisioningControllerClass() new];
60 if(anisetteController) {
61 AKAnisetteData *anisetteData = [anisetteController anisetteDataWithError:&error];
62 if (anisetteData) {
63 retval = [anisetteData.machineID copy];
64 if(retval) {
65 secnotice("sosauthkit", "machineID is %@", retval);
66 } else {
67 secnotice("sosauthkit", "Failed to get machineID");
68 }
69 } else {
70 secnotice("sosauthkit", "can't get mID: %@", error);
71 }
72 } else {
73 secnotice("sosauthkit", "can't get controller");
74 }
75 return retval;
76 }
77
78 static ACAccount *GetPrimaryAccount(void) {
79 ACAccount *primaryAccount;
80
81 initAccountsFramework();
82
83 ACAccountStore *store = [getACAccountStoreClass() new];
84
85 if(!store) {
86 secnotice("sosauthkit", "can't get store");
87 return nil;
88 }
89
90 primaryAccount = [store aa_primaryAppleAccount];
91
92 return primaryAccount;
93 }
94
95
96 + (void)activeMIDs:(void(^_Nonnull)(NSSet <SOSTrustedDeviceAttributes *> *activeMIDs, NSError *error))complete {
97 ACAccount *primaryAccount;
98 AKDeviceListRequestContext *context;
99
100 primaryAccount = GetPrimaryAccount();
101
102 if(!primaryAccount) {
103 secnotice("sosauthkit", "can't get account");
104 complete(NULL, [NSError errorWithDomain:(__bridge NSString *)kSecErrorDomain code:errSecParam userInfo:@{NSLocalizedDescriptionKey : @"no primary account"}]);
105 return;
106 }
107
108 context = [getAKDeviceListRequestContextClass() new];
109 if (context == NULL) {
110 complete(NULL, [NSError errorWithDomain:(__bridge NSString *)kSecErrorDomain code:errSecParam userInfo:@{NSLocalizedDescriptionKey : @"can't get AKDeviceListRequestContextClass"}]);
111 return;
112 }
113 context.altDSID = primaryAccount.aa_altDSID;
114 context.services = @[ getAKServiceNameiCloud() ];
115
116 // -[AKAppleIDAuthenticationController fetchDeviceListWithContext:error:] is not exposed, use a semaphore
117 AKAppleIDAuthenticationController *authController = [getAKAppleIDAuthenticationControllerClass() new];
118 if(!authController) {
119 complete(NULL, [NSError errorWithDomain:(__bridge NSString *)kSecErrorDomain code:errSecParam userInfo:@{NSLocalizedDescriptionKey : @"can't get authController"}]);
120 return;
121 }
122
123 [authController fetchDeviceListWithContext:context completion:^(NSArray<AKRemoteDevice *> *deviceList, NSError *error) {
124 NSMutableSet *mids = [NSMutableSet new];
125 for(AKRemoteDevice *akdev in deviceList) {
126 SOSTrustedDeviceAttributes *newdev = [SOSTrustedDeviceAttributes new];
127 newdev.machineID = akdev.machineId;
128 newdev.serialNumber = akdev.serialNumber;
129 [mids addObject:newdev];
130 }
131 if([mids count] == 0) {
132 secnotice("sosauthkit", "found no devices in account");
133 mids = nil;
134 }
135 complete(mids, error);
136 }];
137 }
138
139 + (bool) peerinfoHasMID: (SOSAccount *) account {
140 SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(account.fullPeerInfo);
141 if(!pi) return true; // if there's no PI then just say "we don't need one"
142 return SOSPeerInfoV2DictionaryHasString(pi, sMachineIDKey);
143 }
144
145
146
147 + (bool) updateMIDInPeerInfo: (SOSAccount *) account {
148 NSString *mid = [SOSAuthKitHelpers machineID];
149 if(!mid) return true;
150 CFErrorRef error = NULL;
151 SOSAccountSetValue(account, sMachineIDKey, (__bridge CFStringRef)mid, &error);
152 bool peerUpdated = SOSAccountUpdatePeerInfoAndPush(account, CFSTR("Add Machine ID"), &error, ^bool(SOSPeerInfoRef pi, CFErrorRef *error) {
153 if(SOSPeerInfoV2DictionaryHasString(pi, sMachineIDKey)) {
154 return false;
155 }
156 secnotice("sosauthkit", "Setting PeerInfo MID to %@", mid);
157 SOSPeerInfoV2DictionarySetValue(pi, sMachineIDKey, (__bridge CFStringRef)mid);
158 return true;
159 });
160 if(!peerUpdated) {
161 secnotice("sosauthkit", "Failed to record MID in PeerInfo: %@", error);
162 }
163 CFReleaseNull(error);
164 return peerUpdated;
165 }
166
167
168 + (bool) accountIsHSA2 {
169 bool hsa2 = false;
170
171 ACAccount *primaryAccount = GetPrimaryAccount();
172 AKAccountManager *manager = [getAKAccountManagerClass() new];
173
174 if(manager && primaryAccount) {
175 ACAccount *account = [manager authKitAccountWithAltDSID:[manager altDSIDForAccount:primaryAccount]];
176 AKAppleIDSecurityLevel securityLevel = [manager securityLevelForAccount:account];
177 if(securityLevel == AKAppleIDSecurityLevelHSA2) {
178 hsa2 = true;
179 } else {
180 secnotice("sosauthkit", "Security level is %lu", (unsigned long)securityLevel);
181 }
182 secnotice("sosauthkit", "Account %s HSA2", (hsa2) ? "is": "isn't" );
183 } else {
184 secnotice("sosauthkit", "Failed to get manager");
185 }
186 return hsa2;
187 }
188
189
190 -(id) initWithActiveMIDS: (NSSet <SOSTrustedDeviceAttributes *> *) theMidList
191 {
192 self = [super init];
193 if(!self){
194 return nil;
195 }
196 NSMutableSet *MmachineIDs = [[NSMutableSet alloc] init];
197 NSMutableSet *MserialNumbers = [[NSMutableSet alloc] init];
198 _machineIDs = [[NSSet alloc] init];
199 _serialNumbers = [[NSSet alloc] init];
200
201 if(!theMidList) return nil;
202 _midList = theMidList;
203
204 for(SOSTrustedDeviceAttributes *dev in _midList) {
205 if(dev.machineID) {
206 [MmachineIDs addObject:dev.machineID];
207 }
208 if(dev.serialNumber) {
209 [MserialNumbers addObject:dev.serialNumber];
210 }
211
212 }
213 _machineIDs = MmachineIDs;
214 _serialNumbers = MserialNumbers;
215 return self;
216 }
217
218 // if the ID passed in is null, the peer doesn't have one, we'll say true - we can't tell from the list
219 - (bool) midIsValidInList: (NSString *) machineId {
220 return (machineId) ? [_machineIDs containsObject:machineId]: true;
221 }
222
223 - (bool) serialIsValidInList: (NSString *) serialNumber {
224 return (serialNumber) ? [_serialNumbers containsObject:serialNumber]: true;
225 }
226
227 - (bool) isUseful {
228 return [ _machineIDs count ] > 0;
229 }
230
231 #else
232
233
234 @implementation SOSAuthKitHelpers
235
236 @class SOSAuthKitHelpers;
237
238 + (NSString *) machineID {
239 return nil;
240 }
241
242 + (void)activeMIDs:(void(^_Nonnull)(NSSet<SOSTrustedDeviceAttributes*> *activeMIDs, NSError *error))complete {
243 complete(nil, nil);
244 }
245
246 + (bool) updateMIDInPeerInfo: (SOSAccount *) account {
247 return true;
248 }
249
250 + (bool) peerinfoHasMID: (SOSAccount *) account {
251 return true;
252 }
253
254 + (bool) accountIsHSA2 {
255 return false;
256 }
257
258 - (id _Nullable) initWithActiveMIDS: (NSSet *_Nullable) theMidList {
259 return nil;
260 }
261
262 - (bool) midIsValidInList: (NSString *_Nullable) machineId {
263 return true;
264 }
265
266 - (bool) serialIsValidInList: (NSString *_Nullable) serialNumber {
267 return true;
268 }
269
270 - (bool) isUseful {
271 return false;
272 }
273
274 #endif
275
276 @end
277