]> git.saurik.com Git - apple/security.git/blob - SOSCCAuthPlugin/SOSCCAuthPlugin.m
Security-58286.251.4.tar.gz
[apple/security.git] / SOSCCAuthPlugin / SOSCCAuthPlugin.m
1 //
2 // SOSCCAuthPlugin.m
3 // Security
4 //
5 // Created by Christian Schmidt on 7/8/15.
6 // Copyright 2015 Apple, Inc. All rights reserved.
7 //
8
9 #import <SOSCCAuthPlugin.h>
10 #import <Foundation/Foundation.h>
11 #import <Accounts/Accounts.h>
12 #import <Accounts/Accounts_Private.h>
13 #import <AccountsDaemon/ACDAccountStore.h>
14 #import <AppleAccount/ACAccount+AppleAccount.h>
15 #import <AppleAccount/ACAccountStore+AppleAccount.h>
16 #import <AuthKit/AuthKit.h>
17 #import <AuthKit/AuthKit_Private.h>
18 #import <Security/SecureObjectSync/SOSCloudCircle.h>
19 #import "utilities/SecCFRelease.h"
20 #import "utilities/debugging.h"
21
22
23 #if !TARGET_OS_SIMULATOR
24 SOFT_LINK_FRAMEWORK(PrivateFrameworks, AuthKit);
25
26 #pragma clang diagnostic push
27 #pragma clang diagnostic ignored "-Wstrict-prototypes"
28 SOFT_LINK_CLASS(AuthKit, AKAccountManager);
29 #pragma clang diagnostic pop
30 #endif
31
32 @implementation SOSCCAuthPlugin
33
34 static bool accountIsHSA2(ACAccount *account) {
35 bool hsa2 = false;
36
37 #if !TARGET_OS_SIMULATOR
38 AKAccountManager *manager = [getAKAccountManagerClass() sharedInstance];
39 if(manager != nil) {
40 #if TARGET_OS_OSX
41 ACAccount *aka = [manager authKitAccountWithAltDSID:account.icaAltDSID];
42 #else
43 ACAccount *aka = [manager authKitAccountWithAltDSID:account.aa_altDSID];
44 #endif
45 if (aka) {
46 AKAppleIDSecurityLevel securityLevel = [manager securityLevelForAccount: aka];
47 if(securityLevel == AKAppleIDSecurityLevelHSA2) {
48 hsa2 = true;
49 }
50 }
51 }
52 #endif
53 secnotice("accounts", "Account %s HSA2", (hsa2) ? "is": "isn't" );
54 return hsa2;
55 }
56
57 - (void) didReceiveAuthenticationResponseParameters: (NSDictionary *) parameters
58 accountStore: (ACDAccountStore *) store
59 account: (ACAccount *) account
60 completion: (dispatch_block_t) completion
61 {
62 BOOL do_auth = NO;
63 NSString* accountIdentifier = account.identifier; // strong reference
64 secinfo("accounts", "parameters %@", parameters);
65 secinfo("accounts", "account %@", account);
66
67 if ([account.accountType.identifier isEqualToString:ACAccountTypeIdentifierIdentityServices]) {
68 ACAccount *icloud = [store aa_primaryAppleAccount];
69 NSString *dsid = [parameters[@"com.apple.private.ids"][@"service-data"][@"profile-id"] substringFromIndex:2]; // remove "D:" prefix
70 secinfo("accounts", "IDS account: iCloud %@ (personID %@)", icloud, icloud.aa_personID);
71 do_auth = icloud && icloud.aa_personID && [icloud.aa_personID isEqualToString:dsid];
72 } else if ([account.accountType.identifier isEqualToString:ACAccountTypeIdentifierAppleAccount]) {
73 secinfo("accounts", "AppleID account: primary %@", @([account aa_isPrimaryAccount]));
74 do_auth = [account aa_isPrimaryAccount];
75 }
76
77 if(do_auth && !accountIsHSA2(account)) {
78 NSString *rawPassword = [account _aa_rawPassword];
79
80 if (rawPassword != NULL) {
81 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
82 CFErrorRef asyncError = NULL;
83 NSString *dsid = [account aa_personID];
84 const char *password = [rawPassword cStringUsingEncoding:NSUTF8StringEncoding];
85 CFDataRef passwordData = CFDataCreate(kCFAllocatorDefault, (const uint8_t *) password, strlen(password));
86
87 if (passwordData) {
88 secinfo("accounts", "Performing async SOS circle credential set for account %@: %@", accountIdentifier, account.username);
89
90 if (!SOSCCSetUserCredentialsAndDSID((__bridge CFStringRef) account.username, passwordData, (__bridge CFStringRef) dsid, &asyncError)) {
91 secerror("Unable to set SOS circle credentials for account %@: %@", accountIdentifier, asyncError);
92 secinfo("accounts", "Returning from failed async call to SOSCCSetUserCredentialsAndDSID");
93 CFReleaseNull(asyncError);
94 } else {
95 secinfo("accounts", "Returning from successful async call to SOSCCSetUserCredentialsAndDSID");
96 }
97 CFRelease(passwordData);
98 } else {
99 secinfo("accounts", "Failed to create string for call to SOSCCSetUserCredentialsAndDSID");
100 }
101 });
102 } else {
103 CFErrorRef authError = NULL;
104 if (!SOSCCCanAuthenticate(&authError)) {
105 secerror("Account %@ did not present a password and we could not authenticate the SOS circle: %@", accountIdentifier, authError);
106 CFReleaseNull(authError);
107 }
108 }
109 } else {
110 secinfo("accounts", "NOT performing SOS circle credential set for account %@: %@", accountIdentifier, account.username);
111 }
112
113 completion();
114 }
115
116 @end