From dd5fb164cf5b32c462296bc65e289e100f74b59a Mon Sep 17 00:00:00 2001 From: Apple Date: Thu, 1 Feb 2018 00:36:23 +0000 Subject: [PATCH] Security-58286.20.16.tar.gz --- KeychainCircle/PairingChannel.m | 7 +- OSX/authd/authd-Entitlements.plist | 2 + .../lib/trampolineClient.cpp | 73 ++++++--- .../lib/trampolineServer.cpp | 42 ++++-- .../SOSCircle/SecureObjectSync/SOSAccount.m | 3 + .../SOSCircle/SecureObjectSync/SOSEngine.c | 9 +- .../SecureObjectSync/SOSEnsureBackup.h | 30 ++++ .../SecureObjectSync/SOSEnsureBackup.m | 75 +++++++++ OSX/sec/SOSCircle/SecureObjectSync/SOSTypes.h | 7 +- OSX/sec/Security/SecPolicy.c | 4 +- .../swcagent-entitlements.plist | 4 + OSX/sec/SharedWebCredential/swcagent.m | 32 ++-- OSX/sec/securityd/SecItemServer.c | 25 ++- OSX/sec/securityd/SecItemServer.h | 7 +- OSX/sec/securityd/SecRevocationServer.c | 20 ++- .../PinningPolicyTrustTest.plist | 21 +++ .../baa_ucrt_leaf.cer | Bin 0 -> 1033 bytes .../baa_user_root.cer | Bin 0 -> 542 bytes .../baa_user_subca1.cer | Bin 0 -> 551 bytes OSX/utilities/src/SecDb.c | 34 ++--- Security.xcodeproj/project.pbxproj | 22 ++- .../awd/AWDKeychainSOSKeychainBackupFailed.h | 38 +++++ .../awd/AWDKeychainSOSKeychainBackupFailed.m | 142 ++++++++++++++++++ .../analytics/awd/AWDMetricIds_Keychain.h | 5 +- .../awd/AwdMetadata-0x60-Keychain.bin | Bin 924 -> 1067 bytes keychain/ckks/CKKSGroupOperation.h | 3 + keychain/ckks/CKKSGroupOperation.m | 26 ++++ keychain/ckks/CKKSKeychainView.m | 3 +- keychain/ckks/tests/CKKSTests.m | 43 ++++++ .../securityd_service/main.c | 42 +++++- securityd/src/agentquery.cpp | 30 +++- securityd/src/localdatabase.cpp | 2 +- securityd/src/session.cpp | 10 +- securityd/src/session.h | 2 +- 34 files changed, 649 insertions(+), 114 deletions(-) create mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.h create mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.m create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/baa_ucrt_leaf.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/baa_user_root.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/baa_user_subca1.cer create mode 100644 keychain/analytics/awd/AWDKeychainSOSKeychainBackupFailed.h create mode 100644 keychain/analytics/awd/AWDKeychainSOSKeychainBackupFailed.m diff --git a/KeychainCircle/PairingChannel.m b/KeychainCircle/PairingChannel.m index 166ad460..7d353e57 100644 --- a/KeychainCircle/PairingChannel.m +++ b/KeychainCircle/PairingChannel.m @@ -375,9 +375,14 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; { secnotice("pairing", "acceptor packet 3"); + const uint32_t initialSyncCredentialsFlags = + SOSControlInitialSyncFlagTLK| + SOSControlInitialSyncFlagPCS| + SOSControlInitialSyncFlagBluetoothMigration; + [[self.connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { complete(true, NULL, error); - }] initialSyncCredentials:(SOSControlInitialSyncFlagTLK|SOSControlInitialSyncFlagPCS) complete:^(NSArray *items, NSError *error2) { + }] initialSyncCredentials:initialSyncCredentialsFlags complete:^(NSArray *items, NSError *error2) { NSMutableDictionary *reply = [NSMutableDictionary dictionary]; secnotice("pairing", "acceptor initialSyncCredentials complete: items %u: %@", (unsigned)[items count], error2); diff --git a/OSX/authd/authd-Entitlements.plist b/OSX/authd/authd-Entitlements.plist index 126b1f63..7ef4f57c 100644 --- a/OSX/authd/authd-Entitlements.plist +++ b/OSX/authd/authd-Entitlements.plist @@ -4,5 +4,7 @@ com.apple.private.LocalAuthentication.ExtractCredential + com.apple.keystore.console + diff --git a/OSX/libsecurity_authorization/lib/trampolineClient.cpp b/OSX/libsecurity_authorization/lib/trampolineClient.cpp index f544bb8c..672768f5 100644 --- a/OSX/libsecurity_authorization/lib/trampolineClient.cpp +++ b/OSX/libsecurity_authorization/lib/trampolineClient.cpp @@ -100,22 +100,8 @@ OSStatus AuthorizationExecuteWithPrivilegesExternalForm(const AuthorizationExter if (flags != 0) return errAuthorizationInvalidFlags; - // create the mailbox file - FILE *mbox = tmpfile(); - if (!mbox) - return errAuthorizationInternal; - if (fwrite(extForm, sizeof(*extForm), 1, mbox) != 1) { - fclose(mbox); - return errAuthorizationInternal; - } - fflush(mbox); - // compute the argument vector here because we can't allocate memory once we fork. - // make text representation of the temp-file descriptor - char mboxFdText[20]; - snprintf(mboxFdText, sizeof(mboxFdText), "auth %d", fileno(mbox)); - // where is the trampoline? #if defined(NDEBUG) const char *trampoline = TRAMPOLINE; @@ -125,13 +111,26 @@ OSStatus AuthorizationExecuteWithPrivilegesExternalForm(const AuthorizationExter trampoline = TRAMPOLINE; #endif //NDEBUG - const char **argv = argVector(trampoline, pathToTool, mboxFdText, arguments); + // make a data exchange pipe + int dataPipe[2]; + if (pipe(dataPipe)) { + secinfo("authexec", "data pipe failure"); + return errAuthorizationToolExecuteFailure; + } + + // make text representation of the pipe handle + char pipeFdText[20]; + snprintf(pipeFdText, sizeof(pipeFdText), "auth %d", dataPipe[READ]); + const char **argv = argVector(trampoline, pathToTool, pipeFdText, arguments); // make a notifier pipe int notify[2]; if (pipe(notify)) { - fclose(mbox); - if(argv) { free(argv); } + close(dataPipe[READ]); close(dataPipe[WRITE]); + if(argv) { + free(argv); + } + secinfo("authexec", "notify pipe failure"); return errAuthorizationToolExecuteFailure; } @@ -139,8 +138,11 @@ OSStatus AuthorizationExecuteWithPrivilegesExternalForm(const AuthorizationExter int comm[2]; if (communicationsPipe && socketpair(AF_UNIX, SOCK_STREAM, 0, comm)) { close(notify[READ]); close(notify[WRITE]); - fclose(mbox); - if(argv) { free(argv); } + close(dataPipe[READ]); close(dataPipe[WRITE]); + if(argv) { + free(argv); + } + secinfo("authexec", "comm pipe failure"); return errAuthorizationToolExecuteFailure; } @@ -169,10 +171,20 @@ OSStatus AuthorizationExecuteWithPrivilegesExternalForm(const AuthorizationExter close(notify[WRITE]); if (communicationsPipe) close(comm[WRITE]); - - // close mailbox file (child has it open now) - fclose(mbox); - + + close(dataPipe[READ]); + if (write(dataPipe[WRITE], extForm, sizeof(*extForm)) != sizeof(*extForm)) { + secinfo("authexec", "fwrite data failed (errno=%d)", errno); + status = errAuthorizationInternal; + close(notify[READ]); + close(dataPipe[WRITE]); + if (communicationsPipe) { + close(comm[READ]); + close(comm[WRITE]); + } + goto exit_point; + } + close(dataPipe[WRITE]); // get status notification from child secinfo("authexec", "parent waiting for status"); ssize_t rc = read(notify[READ], &status, sizeof(status)); @@ -185,10 +197,15 @@ OSStatus AuthorizationExecuteWithPrivilegesExternalForm(const AuthorizationExter case sizeof(status): // read succeeded: child reported an error secinfo("authexec", "parent received status=%d", (int)status); close(notify[READ]); - if (communicationsPipe) { close(comm[READ]); close(comm[WRITE]); } + close(dataPipe[WRITE]); + if (communicationsPipe) { + close(comm[READ]); + close(comm[WRITE]); + } goto exit_point; case 0: // end of file: exec succeeded close(notify[READ]); + close(dataPipe[WRITE]); if (communicationsPipe) *communicationsPipe = fdopen(comm[READ], "r+"); secinfo("authexec", "parent resumes (no error)"); @@ -202,7 +219,10 @@ OSStatus AuthorizationExecuteWithPrivilegesExternalForm(const AuthorizationExter close(notify[READ]); if (communicationsPipe) close(comm[READ]); - + + // close write end of the data PIPE + close(dataPipe[WRITE]); + // fd 1 (stdout) holds the notify write end dup2(notify[WRITE], 1); close(notify[WRITE]); @@ -222,6 +242,9 @@ OSStatus AuthorizationExecuteWithPrivilegesExternalForm(const AuthorizationExter // execute failed - tell the parent { + // in case of failure, close read end of the data pipe as well + close(dataPipe[WRITE]); + close(dataPipe[READ]); OSStatus error = errAuthorizationToolExecuteFailure; error = h2n(error); write(1, &error, sizeof(error)); diff --git a/OSX/libsecurity_authorization/lib/trampolineServer.cpp b/OSX/libsecurity_authorization/lib/trampolineServer.cpp index bf25a801..139e4756 100644 --- a/OSX/libsecurity_authorization/lib/trampolineServer.cpp +++ b/OSX/libsecurity_authorization/lib/trampolineServer.cpp @@ -29,6 +29,7 @@ #include #include #include +#include // // In a tool launched via AuthorizationCopyPrivilegedReference, retrieve a copy @@ -43,26 +44,39 @@ OSStatus AuthorizationCopyPrivilegedReference(AuthorizationRef *authorization, // retrieve hex form of external form from environment const char *mboxFdText = getenv("__AUTHORIZATION"); - if (!mboxFdText) + if (!mboxFdText) { return errAuthorizationInvalidRef; + } - // retrieve mailbox file and read external form - AuthorizationExternalForm extForm; - int fd; - if (sscanf(mboxFdText, "auth %d", &fd) != 1) - return errAuthorizationInvalidRef; - if (lseek(fd, 0, SEEK_SET) || - read(fd, &extForm, sizeof(extForm)) != sizeof(extForm)) { - close(fd); - return errAuthorizationInvalidRef; - } + static AuthorizationExternalForm extForm; + static OSStatus result = errAuthorizationInvalidRef; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // retrieve the pipe and read external form + int fd; + if (sscanf(mboxFdText, "auth %d", &fd) != 1) { + return; + } + ssize_t numOfBytes = read(fd, &extForm, sizeof(extForm)); + close(fd); + if (numOfBytes == sizeof(extForm)) { + result = errAuthorizationSuccess; + } + }); + + if (result) { + // we had some trouble with reading the extform + return result; + } // internalize the authorization AuthorizationRef auth; if (OSStatus error = AuthorizationCreateFromExternalForm(&extForm, &auth)) return error; - // well, here you go - *authorization = auth; - return errSecSuccess; + if (authorization) { + *authorization = auth; + } + + return errAuthorizationSuccess; } diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccount.m b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccount.m index 90bf2549..ba3b67ff 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccount.m +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccount.m @@ -719,6 +719,9 @@ static bool Flush(CFErrorRef *error) { isflags |= SecServerInitialSyncCredentialFlagPCS; if (flags & SOSControlInitialSyncFlagPCSNonCurrent) isflags |= SecServerInitialSyncCredentialFlagPCSNonCurrent; + if (flags & SOSControlInitialSyncFlagBluetoothMigration) + isflags |= SecServerInitialSyncCredentialFlagBluetoothMigration; + NSArray *array = CFBridgingRelease(_SecServerCopyInitialSyncCredentials(isflags, &error)); complete(array, (__bridge NSError *)error); diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.c index 29c6464d..c6fa97b2 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2012-2017 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -68,6 +68,8 @@ #include +#include + // // MARK: SOSEngine The Keychain database with syncable keychain support. // @@ -174,6 +176,7 @@ static bool SOSEngineLoadCoders(SOSEngineRef engine, SOSTransactionRef txn, CFEr #if !TARGET_IPHONE_SIMULATOR static bool SOSEngineDeleteV0State(SOSEngineRef engine, SOSTransactionRef txn, CFErrorRef *error); #endif + static CFStringRef SOSPeerIDArrayCreateString(CFArrayRef peerIDs) { return peerIDs ? CFStringCreateByCombiningStrings(kCFAllocatorDefault, peerIDs, CFSTR(" ")) : CFSTR(""); } @@ -2889,6 +2892,10 @@ bool SOSEngineSetPeerConfirmedManifest(SOSEngineRef engine, CFStringRef backupNa // Write data for this peer if we can, technically not needed for non legacy protocol support all the time. ok = SOSEngineWriteToBackup_locked(engine, peer, true, &dirty, &incomplete, error); + if (!ok && error && SecErrorGetOSStatus(*error) == errSecInteractionNotAllowed) { + SOSEnsureBackupWhileUnlocked(); + } + CFReleaseSafe(confirmed); CFReleaseSafe(computedKeybagDigest); }); diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.h new file mode 100644 index 00000000..0b03f92d --- /dev/null +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef SOSEnsureBackup_h +#define SOSEnsureBackup_h + +void SOSEnsureBackupWhileUnlocked(void); + +#endif /* SOSEnsureBackup_h */ diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.m b/OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.m new file mode 100644 index 00000000..710ed742 --- /dev/null +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.m @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import "SOSEnsureBackup.h" +#include + +#if TARGET_OS_OSX || TARGET_OS_IOS +#import "keychain/ckks/CKKSLockStateTracker.h" +#include +#import +#import "keychain/analytics/awd/AWDMetricIds_Keychain.h" + +static NSOperationQueue *backupOperationQueue; +static CKKSLockStateTracker *lockStateTracker; + +void SOSEnsureBackupWhileUnlocked(void) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + backupOperationQueue = [NSOperationQueue new]; + lockStateTracker = [CKKSLockStateTracker new]; + }); + + // CKKSLockStateTracker does not use @synchronized(self). If it ever starts to this needs to be updated. + @synchronized(lockStateTracker) { + if ([backupOperationQueue operationCount] > 0) { + secnotice("engine", "SOSEnsureBackup: Backup already scheduled for next unlock"); + } else { + secnotice("engine", "SOSEnsureBackup: Scheduling a backup for next unlock"); + NSBlockOperation *backupOperation = [NSBlockOperation blockOperationWithBlock:^{ + secnotice("engine", "Performing keychain backup after unlock because backing up while locked failed"); + SOSAccount *account = (__bridge SOSAccount *)(SOSKeychainAccountGetSharedAccount()); + SOSAccountTransaction* transaction = [SOSAccountTransaction transactionWithAccount:account]; + CFErrorRef error = NULL; + CFSetRef set = SOSAccountCopyBackupPeersAndForceSync(transaction, &error); + if (set) { + secnotice("engine", "SOSEnsureBackup: SOS made a backup of views: %@", set); + } else { + secerror("engine: SOSEnsureBackup: encountered an error while making backup (%@)", error); + } + + CFReleaseNull(error); + CFReleaseNull(set); + }]; + [backupOperation addDependency:lockStateTracker.unlockDependency]; + [backupOperationQueue addOperation:backupOperation]; + AWDPostSimpleMetric(AWDMetricId_Keychain_SOSKeychainBackupFailed); + } + } +} +#else +void SOSEnsureBackupWhileUnlocked(void) { + secnotice("engine", "SOSEnsureBackup not available on this platform"); +} +#endif diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSTypes.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSTypes.h index 3736f5ac..a8a58b07 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSTypes.h +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSTypes.h @@ -121,9 +121,10 @@ typedef int SOSSecurityPropertyActionCode; #import -#define SOSControlInitialSyncFlagTLK 1 -#define SOSControlInitialSyncFlagPCS 2 -#define SOSControlInitialSyncFlagPCSNonCurrent 4 +#define SOSControlInitialSyncFlagTLK (1 << 0) +#define SOSControlInitialSyncFlagPCS (1 << 1) +#define SOSControlInitialSyncFlagPCSNonCurrent (1 << 2) +#define SOSControlInitialSyncFlagBluetoothMigration (1 << 3) @protocol SOSControlProtocol - (void)userPublicKey:(void ((^))(BOOL trusted, NSData *spki, NSError *error))complete; diff --git a/OSX/sec/Security/SecPolicy.c b/OSX/sec/Security/SecPolicy.c index 56eb9426..ef7ba8b3 100644 --- a/OSX/sec/Security/SecPolicy.c +++ b/OSX/sec/Security/SecPolicy.c @@ -4267,8 +4267,8 @@ const uint8_t BASystemRootCA_SHA256[kSecPolicySHA256Size] = { /* Not Before: Apr 19 21:41:56 2017 GMT, Not After : Mar 22 00:00:00 2032 GMT */ /* Signature Algorithm: ecdsa-with-SHA384 */ const uint8_t BAUserRootCA_SHA256[kSecPolicySHA256Size] = { - 0x29, 0x75, 0x9b, 0x53, 0x8a, 0xd1, 0xcb, 0x4f, 0x3b, 0xa5, 0x20, 0x4d, 0x60, 0x4b, 0x25, 0x81, - 0x8d, 0x18, 0x9f, 0x62, 0xe3, 0x94, 0x2d, 0x99, 0x52, 0x54, 0x22, 0x5a, 0xe5, 0x7f, 0x42, 0xca + 0x03, 0x75, 0x1c, 0x80, 0xfc, 0xbe, 0x58, 0x19, 0xd1, 0x70, 0xd2, 0x67, 0xce, 0x1a, 0xd6, 0xd0, + 0x94, 0x40, 0x7c, 0x91, 0xd8, 0x73, 0xd7, 0xa6, 0x56, 0x2d, 0xe3, 0x66, 0x6d, 0x35, 0x94, 0xc6 }; SecPolicyRef SecPolicyCreateAppleBasicAttestationSystem(CFDataRef testRootHash) { diff --git a/OSX/sec/SharedWebCredential/swcagent-entitlements.plist b/OSX/sec/SharedWebCredential/swcagent-entitlements.plist index f6fbb897..85c4cfae 100644 --- a/OSX/sec/SharedWebCredential/swcagent-entitlements.plist +++ b/OSX/sec/SharedWebCredential/swcagent-entitlements.plist @@ -6,5 +6,9 @@ com.apple.swcagent com.apple.private.associated-domains + com.apple.private.tcc.allow + + kTCCServiceFaceID + diff --git a/OSX/sec/SharedWebCredential/swcagent.m b/OSX/sec/SharedWebCredential/swcagent.m index 071eb041..3466a748 100644 --- a/OSX/sec/SharedWebCredential/swcagent.m +++ b/OSX/sec/SharedWebCredential/swcagent.m @@ -81,7 +81,12 @@ typedef WBSAutoFillDataClasses (*WBUAutoFillGetEnabledDataClasses_f)(void); #include #include +#if TARGET_OS_IOS #import +#import +#import +#import +#endif static NSString *swca_string_table = @"SharedWebCredentials"; @@ -703,15 +708,24 @@ static void swca_xpc_dictionary_handler(const xpc_connection_t connection, xpc_o CFTypeRef result = NULL; // select a dictionary from an input array of dictionaries if (swca_select_item(items, client, accessGroups, &result, &error) && result) { - LAContext *ctx = [LAContext new]; - NSString *subTitle = NSLocalizedStringFromTableInBundle(@"SWC_FILLPWD", swca_string_table, swca_get_security_bundle(), nil); - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - [ctx evaluatePolicy:LAPolicyDeviceOwnerAuthentication localizedReason:subTitle reply:^(BOOL success, NSError * _Nullable laError) { - if (success || ([laError.domain isEqual:LAErrorDomain] && laError.code == LAErrorPasscodeNotSet)) - SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); - dispatch_semaphore_signal(sema); - }]; - dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); +#if TARGET_OS_IOS + if (MGGetBoolAnswer(kMGOPearlIDCapability) && + [[MCProfileConnection sharedConnection] isAuthenticationBeforeAutoFillRequired]) { + LAContext *ctx = [LAContext new]; + NSString *subTitle = NSLocalizedStringFromTableInBundle(@"SWC_FILLPWD", swca_string_table, swca_get_security_bundle(), nil); + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + [ctx evaluatePolicy:LAPolicyDeviceOwnerAuthentication localizedReason:subTitle reply:^(BOOL success, NSError * _Nullable laError) { + if (success || ([laError.domain isEqual:LAErrorDomain] && laError.code == LAErrorPasscodeNotSet)) + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + dispatch_semaphore_signal(sema); + }]; + dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); + } else { +#endif + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); +#if TARGET_OS_IOS + } +#endif CFRelease(result); } CFRelease(items); diff --git a/OSX/sec/securityd/SecItemServer.c b/OSX/sec/securityd/SecItemServer.c index 030b4892..9121fbf7 100644 --- a/OSX/sec/securityd/SecItemServer.c +++ b/OSX/sec/securityd/SecItemServer.c @@ -3010,7 +3010,7 @@ bool _SecServerRollKeys(bool force, SecurityClient *client, CFErrorRef *error) { } static bool -InitialSyncItems(CFMutableArrayRef items, bool limitToCurrent, CFStringRef agrp, const SecDbClass *qclass, CFErrorRef *error) +InitialSyncItems(CFMutableArrayRef items, bool limitToCurrent, CFStringRef agrp, CFStringRef svce, const SecDbClass *qclass, CFErrorRef *error) { bool result = false; Query *q = NULL; @@ -3025,6 +3025,8 @@ InitialSyncItems(CFMutableArrayRef items, bool limitToCurrent, CFStringRef agrp, query_add_attribute(kSecAttrAccessGroup, agrp, q); query_add_attribute(kSecAttrSynchronizable, kCFBooleanTrue, q); query_add_attribute(kSecAttrTombstone, kCFBooleanFalse, q); + if (svce) + query_add_attribute(kSecAttrService, svce, q); result = kc_with_dbt(false, error, ^(SecDbConnectionRef dbt) { return kc_transaction(dbt, error, ^{ @@ -3039,11 +3041,11 @@ InitialSyncItems(CFMutableArrayRef items, bool limitToCurrent, CFStringRef agrp, CFMutableDictionaryRef attrs = SecDbItemCopyPListWithMask(item, kSecDbSyncFlag, &error3); if (attrs) { int match = true; - CFStringRef vwht = CFDictionaryGetValue(attrs, kSecAttrSyncViewHint); + CFStringRef itemvwht = CFDictionaryGetValue(attrs, kSecAttrSyncViewHint); /* * Saying its a SOS viewhint is really not the right answer post Triangle */ - if (isString(vwht) && !SOSViewInSOSSystem(vwht)) { + if (isString(itemvwht) && !SOSViewInSOSSystem(itemvwht)) { match = false; } /* @@ -3090,17 +3092,24 @@ _SecServerCopyInitialSyncCredentials(uint32_t flags, CFErrorRef *error) CFMutableArrayRef items = CFArrayCreateMutableForCFTypes(NULL); if (flags & SecServerInitialSyncCredentialFlagTLK) { - require_action(InitialSyncItems(items, false, CFSTR("com.apple.security.ckks"), inet_class(), error), fail, - secerror("failed to collect PCS-inet keys: %@", error ? *error : NULL)); + require_action(InitialSyncItems(items, false, CFSTR("com.apple.security.ckks"), NULL, inet_class(), error), fail, + secerror("failed to collect CKKS-inet keys: %@", error ? *error : NULL)); } if (flags & SecServerInitialSyncCredentialFlagPCS) { bool onlyCurrent = !(flags & SecServerInitialSyncCredentialFlagPCSNonCurrent); - require_action(InitialSyncItems(items, false, CFSTR("com.apple.ProtectedCloudStorage"), genp_class(), error), fail, - secerror("failed to collect PCS-inet keys: %@", error ? *error : NULL)); - require_action(InitialSyncItems(items, onlyCurrent, CFSTR("com.apple.ProtectedCloudStorage"), inet_class(), error), fail, + require_action(InitialSyncItems(items, false, CFSTR("com.apple.ProtectedCloudStorage"), NULL, genp_class(), error), fail, + secerror("failed to collect PCS-genp keys: %@", error ? *error : NULL)); + require_action(InitialSyncItems(items, onlyCurrent, CFSTR("com.apple.ProtectedCloudStorage"), NULL, inet_class(), error), fail, secerror("failed to collect PCS-inet keys: %@", error ? *error : NULL)); } + if (flags & SecServerInitialSyncCredentialFlagBluetoothMigration) { + require_action(InitialSyncItems(items, false, CFSTR("com.apple.nanoregistry.migration"), NULL, genp_class(), error), fail, + secerror("failed to collect com.apple.nanoregistry.migration-genp item: %@", error ? *error : NULL)); + require_action(InitialSyncItems(items, false, CFSTR("com.apple.bluetooth"), CFSTR("BluetoothLESync"), genp_class(), error), fail, + secerror("failed to collect com.apple.bluetooth-genp item: %@", error ? *error : NULL)); + + } fail: return items; diff --git a/OSX/sec/securityd/SecItemServer.h b/OSX/sec/securityd/SecItemServer.h index 3249d8da..a4196ce0 100644 --- a/OSX/sec/securityd/SecItemServer.h +++ b/OSX/sec/securityd/SecItemServer.h @@ -106,9 +106,10 @@ bool _SecServerRollKeysGlue(bool force, CFErrorRef *error); /* initial sync */ -#define SecServerInitialSyncCredentialFlagTLK 1 -#define SecServerInitialSyncCredentialFlagPCS 2 -#define SecServerInitialSyncCredentialFlagPCSNonCurrent 4 +#define SecServerInitialSyncCredentialFlagTLK (1 << 0) +#define SecServerInitialSyncCredentialFlagPCS (1 << 1) +#define SecServerInitialSyncCredentialFlagPCSNonCurrent (1 << 2) +#define SecServerInitialSyncCredentialFlagBluetoothMigration (1 << 3) CFArrayRef _SecServerCopyInitialSyncCredentials(uint32_t flags, CFErrorRef *error); bool _SecServerImportInitialSyncCredentials(CFArrayRef array, CFErrorRef *error); diff --git a/OSX/sec/securityd/SecRevocationServer.c b/OSX/sec/securityd/SecRevocationServer.c index 60abe20a..a0400b49 100644 --- a/OSX/sec/securityd/SecRevocationServer.c +++ b/OSX/sec/securityd/SecRevocationServer.c @@ -694,15 +694,18 @@ void SecRVCDelete(SecRVCRef rvc) { if (rvc->orvc) { SecORVCFinish(rvc->orvc); free(rvc->orvc); + rvc->orvc = NULL; } #if ENABLE_CRLS if (rvc->crvc) { SecCRVCFinish(rvc->crvc); free(rvc->crvc); + rvc->crvc = NULL; } #endif if (rvc->valid_info) { SecValidInfoRelease(rvc->valid_info); + rvc->valid_info = NULL; } } @@ -714,7 +717,16 @@ static void SecRVCInit(SecRVCRef rvc, SecPathBuilderRef builder, CFIndex certIX) #if ENABLE_CRLS rvc->crvc = SecCRVCCreate(rvc, builder, certIX); #endif - rvc->done = false; + if (!rvc->orvc +#if ENABLE_CRLS + || !rvc->crvc +#endif + ) { + SecRVCDelete(rvc); + rvc->done = true; + } else { + rvc->done = false; + } } #if ENABLE_CRLS @@ -905,9 +917,9 @@ static void SecRVCCheckRevocationCaches(SecRVCRef rvc) { static void SecRVCUpdatePVC(SecRVCRef rvc) { SecRVCProcessValidInfoResults(rvc); /* restore the results we got from Valid */ - SecORVCUpdatePVC(rvc->orvc); + if (rvc->orvc) { SecORVCUpdatePVC(rvc->orvc); } #if ENABLE_CRLS - SecCRVCUpdatePVC(rvc->crvc); + if (rvc->crvc) { SecCRVCUpdatePVC(rvc->crvc); } #endif } @@ -1034,7 +1046,7 @@ bool SecPathBuilderCheckRevocation(SecPathBuilderRef builder) { /* The check is done if we found cached responses from either method. */ if (rvc->orvc->done #if ENABLE_CRLS - || rvc->orvc->done + || rvc->crvc->done #endif ) { secdebug("rvc", "found cached response for cert: %ld", certIX); diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/PinningPolicyTrustTest.plist b/OSX/shared_regressions/si-20-sectrust-policies-data/PinningPolicyTrustTest.plist index 0f63cc19..7ab213a3 100644 --- a/OSX/shared_regressions/si-20-sectrust-policies-data/PinningPolicyTrustTest.plist +++ b/OSX/shared_regressions/si-20-sectrust-policies-data/PinningPolicyTrustTest.plist @@ -2856,5 +2856,26 @@ ExpectedResult 5 + + MajorTestName + BAA_UCRT + MinorTestName + Positive + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.85 + + Leaf + baa_ucrt_leaf + Intermediates + baa_user_subca1 + Anchors + baa_user_root + VerifyDate + 2017-08-10T06:00:00Z + ExpectedResult + 4 + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/baa_ucrt_leaf.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/baa_ucrt_leaf.cer new file mode 100644 index 0000000000000000000000000000000000000000..423dd1e0305e307391deb75921a41fb2656a7b1a GIT binary patch literal 1033 zcma)5OK1~87|!la)0nO;p?1?)t6QtJsFi;<3$2RyK~vPa*Z$EesyF1_=r?qc~z%=oJ>;a&UljC2T5`-(5B4tVuCOb2^J_! zqoOo2`-{Fnk|?t-GXpwRAyW|HhAjK0aUBXtfa zVo-gkp^nU7)jPJXdZ5ZkotvJO%D}~-NQWpPhYSH;4fvFRmk)US0p4w-o=(qeE^snP z>rgaQR@06gW@s01JQMj2b*@{ z=Fl!rYm?DGHM}5m01WDq&9l`I5j_#F>~l+s;PZ++rz)xhs;sI!Cn~ZaxmBM6ve)Rp zwpG^=ktzHV&;ek8`#x%*+PChUx~YY|No7%sg^V ziN%@83XUZusl_FUC7Jno3ZccRMG8Ur`6UX@j)uYpf*^%lJY0?i1v#k-o_Wc7FhLF; zF6YFY%(VQXyv#%cIdNV?a|07YOCv)QLsPRTab9C117jm212Bl9jiqG<0&MJHe=#w# zv1&K6Feou6F|fR@cMKga{%}wl*@W1N%D(s^^3$M__ z*YC|^=f^H~GH@{92L_C+FeBrC7FGjhAY~v665wMIV-ab7x>#}EhLXcS6DRzg?x!qJ zwq)@q13r*6KS(_bFmBk8V}v=K!61dnz^Sux$FB8PRd0OBEs)hI6KoREiS*udOn9!1 zv{#sae@^Sy6Dse8{66lnnro@rRQQm|Ai?Oj()z6|;WpO0CI6f*Y^%RCi6gXfV}W&i*H literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/baa_user_subca1.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/baa_user_subca1.cer new file mode 100644 index 0000000000000000000000000000000000000000..a5cb2a9395b3a5a8487699d45375ead483d0e5ce GIT binary patch literal 551 zcmXqLVp29}VqCF+nTe5!iKF7iL+RV;JQ)UDY#dr`9_MUXn3)WM4b=@)*_cCFn0e%! z5{omF6&y=SQj1FxOEUBG6hezrixh(L^Gg(*9SwyI1VIY9c(@!33UX2vJoA$EV1gVx zT+WF(nQ8e&d6|g@a^k#(<_0E41_odvN}Si&$iUbL#0P>XVk`|VO#;~oGoJ`cBMpSv z*unl{VuX5-nUS5@iGgLITK%>AaV(6Y%ct$J+j^@g?O6Vqv)rNIy)K>j+Po{-q5JJl z_nC^zdQvAJuoL*D%Xvf0{O9K5J}E`aH;%Cv3*|0OGe|KI0{UH6n33^63x@$4kYZwF zFpvj{DYHlzh&6~bKV7UiZ$ru9pNSLxPWMw5C|k1llYuNq0UwJPi^#Lo`B%)ieM@DX z@1$AOzgzh@i2tksA4r-XWF{~w7}<~`hB=eLAdSh8VY_kN7Mu=IXFheU0RSmisCorrupted) { - /* SecDbHandleCorrupt must be executed on the db queue so nobody - can acquire a new connection while it is running. */ - if (dispatch_get_current_queue() == dbconn->db->queue) { - ok = SecDbHandleCorrupt(dbconn, 0, error); - } else { - /* We aren't on the db queue already when we get here. It may be - unsafe to dispatch this work from the current queue, so log - and return false without attempting recovery. */ - secerror("WARNING: unable to call SecDbHandleCorrupt (not on db queue)"); - ok = false; - } + ok = SecDbHandleCorrupt(dbconn, 0, error); } secinfo("#SecDB", "#SecDB starting maintenance"); @@ -472,11 +462,17 @@ static bool SecDbConnectionCheckCode(SecDbConnectionRef dbconn, int code, CFErro /* If it's already corrupted, don't try to recover */ if (dbconn->isCorrupted) { CFStringRef reason = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, - CFSTR("SQL DB %@ is corrupted already. Not trying to recover, corruption error was: %d (previously %d)"), + CFSTR("SQL DB %@ is corrupted already. Corruption error was: %d (previously %d)"), dbconn->db->db_path, code, dbconn->maybeCorruptedCode); secerror("%@",reason); __security_simulatecrash(reason, __sec_exception_code_TwiceCorruptDb(knownDbPathIndex(dbconn))); CFReleaseSafe(reason); + // We can't fall through to the checking case because it eventually calls SecDbConnectionCheckCode again. + // However, this is the second time we're seeing corruption so let's take the ultimate measure. + if ((SQLITE_CORRUPT == code) || (SQLITE_NOTADB == code)) { + secerror("SecDbConnectionCheckCode detected corruption twice: going to handle corrupt DB"); + (void)SecDbHandleCorrupt(dbconn, code, error); + } return false; } @@ -489,16 +485,7 @@ static bool SecDbConnectionCheckCode(SecDbConnectionRef dbconn, int code, CFErro dbconn->isCorrupted = SecDbCheckCorrupted(dbconn); if (dbconn->isCorrupted) { secerror("operation returned code: %d integrity check=fail", code); - /* SecDbHandleCorrupt must be executed on the db queue so nobody - can acquire a new connection while it is running. */ - if (dispatch_get_current_queue() == dbconn->db->queue) { - (void)SecDbHandleCorrupt(dbconn, code, error); - } else { - /* We aren't on the db queue already when we get here. It may be - unsafe to dispatch this work from the current queue, so log - and return false without attempting recovery. */ - secerror("WARNING: unable to call SecDbHandleCorrupt (not on db queue)"); - } + (void)SecDbHandleCorrupt(dbconn, code, error); } else { secerror("operation returned code: %d: integrity check=pass", code); } @@ -1546,8 +1533,7 @@ bool SecDbForEach(SecDbConnectionRef dbconn, sqlite3_stmt *stmt, CFErrorRef *err if (s3e == SQLITE_DONE) { result = true; } else { - dbconn->hasIOFailure |= (s3e == SQLITE_IOERR); - SecDbErrorWithStmt(s3e, stmt, error, CFSTR("step[%d]"), row_ix); + SecDbConnectionCheckCode(dbconn, s3e, error, CFSTR("SecDbForEach step[%d]"), row_ix); } break; } diff --git a/Security.xcodeproj/project.pbxproj b/Security.xcodeproj/project.pbxproj index 585a52c8..1f22215a 100644 --- a/Security.xcodeproj/project.pbxproj +++ b/Security.xcodeproj/project.pbxproj @@ -968,6 +968,10 @@ 6C588D811EAA20AC00D7E322 /* RateLimiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CC7F5B31E9F99EE0014AE63 /* RateLimiter.m */; }; 6C5B36BA1E2F9B95008AD443 /* WirelessDiagnostics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C0B0C3D1E2537C6007F95E5 /* WirelessDiagnostics.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 6C5B36C01E2F9BEA008AD443 /* WirelessDiagnostics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C0B0C3D1E2537C6007F95E5 /* WirelessDiagnostics.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 6C869A751F50CAF400957298 /* SOSEnsureBackup.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C860C7A1F4F63DB004100A1 /* SOSEnsureBackup.m */; }; + 6C869A761F50CAF500957298 /* SOSEnsureBackup.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C860C7A1F4F63DB004100A1 /* SOSEnsureBackup.m */; }; + 6C869A791F54C37900957298 /* AWDKeychainSOSKeychainBackupFailed.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C869A771F54C2D700957298 /* AWDKeychainSOSKeychainBackupFailed.m */; }; + 6C869A7A1F54C37A00957298 /* AWDKeychainSOSKeychainBackupFailed.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C869A771F54C2D700957298 /* AWDKeychainSOSKeychainBackupFailed.m */; }; 6C8CC3AB1E2F913C009025C5 /* AWDKeychainCKKSRateLimiterAggregatedScores.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C3446501E2534E800F9522B /* AWDKeychainCKKSRateLimiterAggregatedScores.m */; }; 6C8CC3AC1E2F913C009025C5 /* AWDKeychainCKKSRateLimiterOverload.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C3446521E2534E800F9522B /* AWDKeychainCKKSRateLimiterOverload.m */; }; 6C8CC3AD1E2F913C009025C5 /* AWDKeychainCKKSRateLimiterTopWriters.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C3446541E2534E800F9522B /* AWDKeychainCKKSRateLimiterTopWriters.m */; }; @@ -1214,7 +1218,6 @@ D40B6A9B1E2B690E00CD6EE5 /* SecuritydXPC.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E9A1D8085FC00865A7C /* SecuritydXPC.c */; }; D40B6A9D1E2B6A2700CD6EE5 /* login.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E8271D7A4F0E00AFB96E /* login.framework */; }; D40B6A9E1E2B6A6F00CD6EE5 /* libtrustd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D4ADA3191E2B41670031CEA3 /* libtrustd.a */; }; - D40C2C241E94342A009D793B /* AggregateDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDA43D251DFCA0790038E038 /* AggregateDictionary.framework */; }; D41257D01E9410A300781F23 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D40B6A881E2B5F9900CD6EE5 /* Foundation.framework */; }; D41257D91E9412B800781F23 /* trustd.c in Sources */ = {isa = PBXBuildFile; fileRef = D4BEECE61E93093A00F76D1A /* trustd.c */; }; D41257DA1E9412DC00781F23 /* libtrustd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D4ADA3191E2B41670031CEA3 /* libtrustd.a */; }; @@ -8825,6 +8828,10 @@ 6C3446561E2534E800F9522B /* AWDMetricIds_Keychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AWDMetricIds_Keychain.h; path = analytics/awd/AWDMetricIds_Keychain.h; sourceTree = ""; }; 6C5232D41E3C183F00330DB1 /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/CloudKit.framework; sourceTree = DEVELOPER_DIR; }; 6C588D791EAA149F00D7E322 /* RateLimiterTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RateLimiterTests.m; sourceTree = ""; }; + 6C860C741F4F63AD004100A1 /* SOSEnsureBackup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSEnsureBackup.h; sourceTree = ""; }; + 6C860C7A1F4F63DB004100A1 /* SOSEnsureBackup.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SOSEnsureBackup.m; sourceTree = ""; }; + 6C869A771F54C2D700957298 /* AWDKeychainSOSKeychainBackupFailed.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AWDKeychainSOSKeychainBackupFailed.m; path = analytics/awd/AWDKeychainSOSKeychainBackupFailed.m; sourceTree = ""; }; + 6C869A781F54C2D700957298 /* AWDKeychainSOSKeychainBackupFailed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AWDKeychainSOSKeychainBackupFailed.h; path = analytics/awd/AWDKeychainSOSKeychainBackupFailed.h; sourceTree = ""; }; 6C9808611E788AEB00E70590 /* CKKSCloudKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CKKSCloudKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 6C98089D1E788AFD00E70590 /* CKKSCloudKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CKKSCloudKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 6CA2B9431E9F9F5700C43444 /* RateLimiter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RateLimiter.h; sourceTree = ""; }; @@ -12483,7 +12490,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D40C2C241E94342A009D793B /* AggregateDictionary.framework in Frameworks */, D41258011E94230400781F23 /* IOKit.framework in Frameworks */, D41257E01E94136000781F23 /* libz.dylib in Frameworks */, D41257DF1E94133600781F23 /* CFNetwork.framework in Frameworks */, @@ -14170,6 +14176,8 @@ 6C34464E1E2534D200F9522B /* AWD */ = { isa = PBXGroup; children = ( + 6C869A781F54C2D700957298 /* AWDKeychainSOSKeychainBackupFailed.h */, + 6C869A771F54C2D700957298 /* AWDKeychainSOSKeychainBackupFailed.m */, 6CD8D3B11EB22114009AC7DC /* AWDKeychainSecDbMarkedCorrupt.h */, 6CD8D3B21EB22114009AC7DC /* AWDKeychainSecDbMarkedCorrupt.m */, 6C34464F1E2534E800F9522B /* AWDKeychainCKKSRateLimiterAggregatedScores.h */, @@ -17445,6 +17453,8 @@ 0CD8CB041ECA50780076F37F /* SOSPeerOTRTimer.m */, 0CD8CB0C1ECA50D10076F37F /* SOSPeerOTRTimer.h */, DC24B5821DA420D700330B48 /* SOSPersist.h */, + 6C860C741F4F63AD004100A1 /* SOSEnsureBackup.h */, + 6C860C7A1F4F63DB004100A1 /* SOSEnsureBackup.m */, ); name = Engine; sourceTree = ""; @@ -26794,6 +26804,8 @@ DCBDB3B81E57C82300B61300 /* CKKSKeychainView.m in Sources */, DC222C5A1E034D1F00B09171 /* iCloudTrace.c in Sources */, DC5BB5011E0C98320010F836 /* CKKSOutgoingQueueOperation.m in Sources */, + 6C869A7A1F54C37A00957298 /* AWDKeychainSOSKeychainBackupFailed.m in Sources */, + 6C869A761F50CAF500957298 /* SOSEnsureBackup.m in Sources */, 5269658E1E6A154800627F9D /* SecBackupKeybagEntry.m in Sources */, DC222C5D1E034D1F00B09171 /* CKKSMirrorEntry.m in Sources */, DC54DD101EA7D9E800108E92 /* CKKSManifestLeafRecord.m in Sources */, @@ -26912,6 +26924,8 @@ 5269658D1E6A154700627F9D /* SecBackupKeybagEntry.m in Sources */, DC52E7D41D80BD1D00B0A59C /* iCloudTrace.c in Sources */, DCEA5D871E2F14810089CF55 /* CKKSAPSReceiver.m in Sources */, + 6C869A791F54C37900957298 /* AWDKeychainSOSKeychainBackupFailed.m in Sources */, + 6C869A751F50CAF400957298 /* SOSEnsureBackup.m in Sources */, DCEA5D571E2826DB0089CF55 /* CKKSSIV.m in Sources */, 6C8CC3AB1E2F913C009025C5 /* AWDKeychainCKKSRateLimiterAggregatedScores.m in Sources */, DC9082C41EA0277600D0C1C5 /* CKKSZoneChangeFetcher.m in Sources */, @@ -32987,6 +33001,8 @@ "$(OTHER_LDFLAGS)", "-framework", SpringBoardServices, + "-framework", + ManagedConfiguration, ); PRODUCT_NAME = swcagent; }; @@ -33003,6 +33019,8 @@ "$(OTHER_LDFLAGS)", "-framework", SpringBoardServices, + "-framework", + ManagedConfiguration, ); PRODUCT_NAME = swcagent; }; diff --git a/keychain/analytics/awd/AWDKeychainSOSKeychainBackupFailed.h b/keychain/analytics/awd/AWDKeychainSOSKeychainBackupFailed.h new file mode 100644 index 00000000..4786d223 --- /dev/null +++ b/keychain/analytics/awd/AWDKeychainSOSKeychainBackupFailed.h @@ -0,0 +1,38 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from stdin + +#import +#import + +#ifdef __cplusplus +#define AWDKEYCHAINSOSKEYCHAINBACKUPFAILED_FUNCTION extern "C" +#else +#define AWDKEYCHAINSOSKEYCHAINBACKUPFAILED_FUNCTION extern +#endif + +@interface AWDKeychainSOSKeychainBackupFailed : PBCodable +{ + uint64_t _timestamp; + struct { + int timestamp:1; + } _has; +} + + +@property (nonatomic) BOOL hasTimestamp; +@property (nonatomic) uint64_t timestamp; + +// Performs a shallow copy into other +- (void)copyTo:(AWDKeychainSOSKeychainBackupFailed *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(AWDKeychainSOSKeychainBackupFailed *)other; + +AWDKEYCHAINSOSKEYCHAINBACKUPFAILED_FUNCTION BOOL AWDKeychainSOSKeychainBackupFailedReadFrom(__unsafe_unretained AWDKeychainSOSKeychainBackupFailed *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/analytics/awd/AWDKeychainSOSKeychainBackupFailed.m b/keychain/analytics/awd/AWDKeychainSOSKeychainBackupFailed.m new file mode 100644 index 00000000..bf93f6ee --- /dev/null +++ b/keychain/analytics/awd/AWDKeychainSOSKeychainBackupFailed.m @@ -0,0 +1,142 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from stdin + +#import +#if !TARGET_OS_BRIDGE + +#import "AWDKeychainSOSKeychainBackupFailed.h" +#import +#import +#import + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation AWDKeychainSOSKeychainBackupFailed + +@synthesize timestamp = _timestamp; +- (void)setTimestamp:(uint64_t)v +{ + _has.timestamp = YES; + _timestamp = v; +} +- (void)setHasTimestamp:(BOOL)f +{ + _has.timestamp = f; +} +- (BOOL)hasTimestamp +{ + return _has.timestamp; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_has.timestamp) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_timestamp] forKey:@"timestamp"]; + } + return dict; +} + +BOOL AWDKeychainSOSKeychainBackupFailedReadFrom(__unsafe_unretained AWDKeychainSOSKeychainBackupFailed *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* timestamp */: + { + self->_has.timestamp = YES; + self->_timestamp = PBReaderReadUint64(reader); + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return AWDKeychainSOSKeychainBackupFailedReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* timestamp */ + { + if (self->_has.timestamp) + { + PBDataWriterWriteUint64Field(writer, self->_timestamp, 1); + } + } +} + +- (void)copyTo:(AWDKeychainSOSKeychainBackupFailed *)other +{ + if (self->_has.timestamp) + { + other->_timestamp = _timestamp; + other->_has.timestamp = YES; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + AWDKeychainSOSKeychainBackupFailed *copy = [[[self class] allocWithZone:zone] init]; + if (self->_has.timestamp) + { + copy->_timestamp = _timestamp; + copy->_has.timestamp = YES; + } + return copy; +} + +- (BOOL)isEqual:(id)object +{ + AWDKeychainSOSKeychainBackupFailed *other = (AWDKeychainSOSKeychainBackupFailed *)object; + return [other isMemberOfClass:[self class]] + && + ((self->_has.timestamp && other->_has.timestamp && self->_timestamp == other->_timestamp) || (!self->_has.timestamp && !other->_has.timestamp)) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + (self->_has.timestamp ? PBHashInt((NSUInteger)self->_timestamp) : 0) + ; +} + +- (void)mergeFrom:(AWDKeychainSOSKeychainBackupFailed *)other +{ + if (other->_has.timestamp) + { + self->_timestamp = other->_timestamp; + self->_has.timestamp = YES; + } +} + +@end +#endif diff --git a/keychain/analytics/awd/AWDMetricIds_Keychain.h b/keychain/analytics/awd/AWDMetricIds_Keychain.h index 1c49d40e..e96ab84c 100644 --- a/keychain/analytics/awd/AWDMetricIds_Keychain.h +++ b/keychain/analytics/awd/AWDMetricIds_Keychain.h @@ -20,8 +20,11 @@ enum { // Simple Metrics: // --------------- -// This component currently has no metrics compatible with the 'simple metric' API. +// The following metrics are compatible with the 'simple metric' API: +enum { + AWDMetricId_Keychain_SOSKeychainBackupFailed = 0x600004 +}; // General Metrics: // ---------------- diff --git a/keychain/analytics/awd/AwdMetadata-0x60-Keychain.bin b/keychain/analytics/awd/AwdMetadata-0x60-Keychain.bin index d47965cdf6e4c83e44c59526fa2e177382195d72..2201be299b555e5de84e9645e2bb7e4bbed4b43c 100644 GIT binary patch delta 285 zcmbQkzM8|$G2F$Mk%5tcnSp_UiGhV70Z6+5@l_x`tzz(x87d~p$iQ%fiGksI%`rX} zpvt>I4Sqm1Aixzm(anWlh@YdSp@CUIT7uDnHGpYiM=39t5C;dN0E+~J2P4=2iT}DX7!rWA3lQ%B;=)5)8=0YEe}McbCI$xUu(?VsK$T(4 z3=D2SF%aN#nds&+adt7|*~!w3=Qc|-bu+qZSXde-o0+5~Sy-l|85vllm{}y7n #include "securityd_service/securityd_service/securityd_service_client.h" +// Includes for Always require the user's password on keychain approval dialogs +#include "server.h" + #define SECURITYAGENT_BOOTSTRAP_NAME_BASE "com.apple.security.agent" #define SECURITYAGENT_LOGINWINDOW_BOOTSTRAP_NAME_BASE "com.apple.security.agent.login" @@ -486,7 +489,9 @@ QueryKeychainUse::QueryKeychainUse(bool needPass, const Database *db) { // if passphrase checking requested, save KeychainDatabase reference // (will quietly disable check if db isn't a keychain) - if (needPass) + + // Always require password, Always require the user's password on keychain approval dialogs + // if (needPass) mPassphraseCheck = dynamic_cast(db); setTerminateOnSleep(true); @@ -506,7 +511,7 @@ Reason QueryKeychainUse::queryUser (const char *database, const char *descriptio // item name into hints - hints.insert(AuthItemRef(AGENT_HINT_KEYCHAIN_ITEM_NAME, AuthValueOverlay(description ? (uint32_t)strlen(description) : 0, const_cast(description)))); + hints.insert(AuthItemRef(AGENT_HINT_KEYCHAIN_ITEM_NAME, AuthValueOverlay(description ? (uint32_t)strlen(description) : 0, const_cast(description)))); // keychain name into hints hints.insert(AuthItemRef(AGENT_HINT_KEYCHAIN_PATH, AuthValueOverlay(database ? (uint32_t)strlen(database) : 0, const_cast(database)))); @@ -548,20 +553,29 @@ Reason QueryKeychainUse::queryUser (const char *database, const char *descriptio passwordItem->getCssmData(data); } while ((reason = (const_cast(mPassphraseCheck)->decode(data) ? SecurityAgent::noReason : SecurityAgent::invalidPassphrase))); + + readChoice(); } else { - create("builtin", "confirm-access"); - setInput(hints, context); - invoke(); +// create("builtin", "confirm-access"); +// setInput(hints, context); +// invoke(); + + // This is a hack to support , we can never simply prompt for confirmation + secerror("ACL validation fallback case! Must ask user for account password because we have no database"); + Session &session = Server::session(); + try{ + session.verifyKeyStorePassphrase(1, true, description); + } catch (...) { + return SecurityAgent::invalidPassphrase; + } + SecurityAgentXPCQuery::allow = true; } - readChoice(); - return reason; } - // // Obtain passphrases and submit them to the accept() method until it is accepted // or we can't get another passphrase. Accept() should consume the passphrase diff --git a/securityd/src/localdatabase.cpp b/securityd/src/localdatabase.cpp index 1be58018..2217294c 100644 --- a/securityd/src/localdatabase.cpp +++ b/securityd/src/localdatabase.cpp @@ -200,7 +200,7 @@ void LocalDatabase::wrapKey(const Context &context, const AccessCredentials *cre { keyToBeWrapped.validate(context.algorithm() == CSSM_ALGID_NONE ? CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR : CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED, - cred); + cred, &keyToBeWrapped.database()); if (wrappingKey) { context.replace(CSSM_ATTRIBUTE_KEY, myKey(*wrappingKey).cssmKey()); wrappingKey->validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context); diff --git a/securityd/src/session.cpp b/securityd/src/session.cpp index da54bbe0..8ec65653 100644 --- a/securityd/src/session.cpp +++ b/securityd/src/session.cpp @@ -177,10 +177,18 @@ void Session::updateAudit() const mAudit = info; } -void Session::verifyKeyStorePassphrase(int32_t retries) +// Second and third arguments defaults to false +void Session::verifyKeyStorePassphrase(int32_t retries, bool useForACLFallback, const char *itemname) { QueryKeybagPassphrase keybagQuery(*this, retries); keybagQuery.inferHints(Server::process()); + + // Parasitic takeover to enable user confirmation when ACL validation ends up without a database + if (useForACLFallback) { + keybagQuery.addHint("acl-fallback", &useForACLFallback, sizeof(useForACLFallback)); + keybagQuery.addHint("keychain-item-name", itemname, itemname ? (uint32_t)strlen(itemname) : 0, 0); + } + if (keybagQuery.query() != SecurityAgent::noReason) { CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); } diff --git a/securityd/src/session.h b/securityd/src/session.h index 1c2e4da7..a40069ae 100644 --- a/securityd/src/session.h +++ b/securityd/src/session.h @@ -112,7 +112,7 @@ protected: void kill(); public: - void verifyKeyStorePassphrase(int32_t retries); + void verifyKeyStorePassphrase(int32_t retries, bool useForACLFallback = false, const char *itemname = NULL); void changeKeyStorePassphrase(); void resetKeyStorePassphrase(const CssmData &passphrase); service_context_t get_current_service_context(); -- 2.45.2