2 // KeychainSyncAccountNotification.m
5 // Created by keith on 5/2/13.
9 #import "KeychainSyncAccountNotification.h"
10 #import <Accounts/ACLogging.h>
11 #import <Accounts/Accounts.h>
12 #import <Accounts/Accounts_Private.h>
13 #pragma clang diagnostic push
14 #pragma clang diagnostic ignored "-Wnewline-eof"
15 #import <AppleAccount/ACAccount+AppleAccount.h>
16 #pragma clang diagnostic pop
17 #import <AccountsDaemon/ACDAccountStore.h>
18 #import <AccountsDaemon/ACDClientAuthorizationManager.h>
19 #import <AccountsDaemon/ACDClientAuthorization.h>
20 #import <Security/SOSCloudCircle.h>
22 @implementation KeychainSyncAccountNotification
24 - (BOOL)account:(ACAccount *)account willChangeWithType:(ACAccountChangeType)changeType inStore:(ACDAccountStore *)store oldAccount:(ACAccount *)oldAccount {
25 if ((changeType == kACAccountChangeTypeDeleted) && [oldAccount.accountType.identifier isEqualToString:ACAccountTypeIdentifierAppleAccount]) {
26 if ([account aa_isPrimaryAccount]) {
28 CFErrorRef removalError = NULL;
30 ACLogDebug(@"Performing SOS circle credential removal for account %@: %@", oldAccount.identifier, oldAccount.username);
32 if (!SOSCCRemoveThisDeviceFromCircle(&removalError)) {
33 ACLogError(@"Account %@ could not leave the SOS circle: %@", oldAccount.identifier, removalError);
36 ACLogDebug(@"NOT performing SOS circle credential removal for secondary account %@: %@", account.identifier, account.username);
43 - (void)account:(ACAccount *)account didChangeWithType:(ACAccountChangeType)changeType inStore:(ACDAccountStore *)store oldAccount:(ACAccount *)oldAccount {
44 if ((changeType == kACAccountChangeTypeAdded || changeType == kACAccountChangeTypeModified) && [account.accountType.identifier isEqualToString:ACAccountTypeIdentifierAppleAccount]) {
45 if ([account aa_isPrimaryAccount]) {
47 ACAccountCredential *accountCred = [store credentialForAccount:account error:&errObject];
48 if (accountCred != NULL) {
49 CFErrorRef authenticateError = NULL;
50 if (accountCred.password != NULL) {
51 const char *accountPassword = [accountCred.password cStringUsingEncoding:NSUTF8StringEncoding];
52 CFDataRef passwordData = CFDataCreate(kCFAllocatorDefault, (const uint8_t *)accountPassword, strlen(accountPassword));
53 if (NULL != passwordData) {
54 ACLogDebug(@"Performing SOS circle credential set for account %@: %@", account.identifier, account.username);
55 if (!SOSCCSetUserCredentials((__bridge CFStringRef)(account.username), passwordData, &authenticateError)) {
56 ACLogError(@"Unable to set SOS circle credentials for account %@: %@", account.identifier, authenticateError);
57 if (NULL != authenticateError) {
58 CFRelease(authenticateError);
61 CFRelease(passwordData);
64 if (!SOSCCCanAuthenticate(&authenticateError)) {
65 ACLogError(@"Account %@ did not present a password and we could not authenticate the SOS circle: %@", account.identifier, authenticateError);
66 if (NULL != authenticateError) {
67 CFRelease(authenticateError);
72 ACLogError(@"Account %@ did not present a credential for SOS circle: %@", account.identifier, errObject);
75 ACLogDebug(@"NOT performing SOS circle credential set for secondary account %@: %@", account.identifier, account.username);