]> git.saurik.com Git - apple/security.git/commitdiff
Security-58286.20.16.tar.gz macos-10131 v58286.20.16
authorApple <opensource@apple.com>
Thu, 1 Feb 2018 00:36:23 +0000 (00:36 +0000)
committerApple <opensource@apple.com>
Thu, 1 Feb 2018 00:36:23 +0000 (00:36 +0000)
34 files changed:
KeychainCircle/PairingChannel.m
OSX/authd/authd-Entitlements.plist
OSX/libsecurity_authorization/lib/trampolineClient.cpp
OSX/libsecurity_authorization/lib/trampolineServer.cpp
OSX/sec/SOSCircle/SecureObjectSync/SOSAccount.m
OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.c
OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.h [new file with mode: 0644]
OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.m [new file with mode: 0644]
OSX/sec/SOSCircle/SecureObjectSync/SOSTypes.h
OSX/sec/Security/SecPolicy.c
OSX/sec/SharedWebCredential/swcagent-entitlements.plist
OSX/sec/SharedWebCredential/swcagent.m
OSX/sec/securityd/SecItemServer.c
OSX/sec/securityd/SecItemServer.h
OSX/sec/securityd/SecRevocationServer.c
OSX/shared_regressions/si-20-sectrust-policies-data/PinningPolicyTrustTest.plist
OSX/shared_regressions/si-20-sectrust-policies-data/baa_ucrt_leaf.cer [new file with mode: 0644]
OSX/shared_regressions/si-20-sectrust-policies-data/baa_user_root.cer [new file with mode: 0644]
OSX/shared_regressions/si-20-sectrust-policies-data/baa_user_subca1.cer [new file with mode: 0644]
OSX/utilities/src/SecDb.c
Security.xcodeproj/project.pbxproj
keychain/analytics/awd/AWDKeychainSOSKeychainBackupFailed.h [new file with mode: 0644]
keychain/analytics/awd/AWDKeychainSOSKeychainBackupFailed.m [new file with mode: 0644]
keychain/analytics/awd/AWDMetricIds_Keychain.h
keychain/analytics/awd/AwdMetadata-0x60-Keychain.bin
keychain/ckks/CKKSGroupOperation.h
keychain/ckks/CKKSGroupOperation.m
keychain/ckks/CKKSKeychainView.m
keychain/ckks/tests/CKKSTests.m
securityd/securityd_service/securityd_service/main.c
securityd/src/agentquery.cpp
securityd/src/localdatabase.cpp
securityd/src/session.cpp
securityd/src/session.h

index 166ad460cf847b598567e409595037cb5ebeaa2d..7d353e574cfd29a63e159c5940d7b014fe788866 100644 (file)
@@ -375,9 +375,14 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE;
 {
     secnotice("pairing", "acceptor packet 3");
 
 {
     secnotice("pairing", "acceptor packet 3");
 
+    const uint32_t initialSyncCredentialsFlags =
+        SOSControlInitialSyncFlagTLK|
+        SOSControlInitialSyncFlagPCS|
+        SOSControlInitialSyncFlagBluetoothMigration;
+
     [[self.connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) {
         complete(true, NULL, error);
     [[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);
         NSMutableDictionary *reply = [NSMutableDictionary dictionary];
 
         secnotice("pairing", "acceptor initialSyncCredentials complete: items %u: %@", (unsigned)[items count], error2);
index 126b1f639a4a80ad440003ff2ccc5a6ba673eeca..7ef4f57c7622eb871b025d425d6ff731e3f5e22d 100644 (file)
@@ -4,5 +4,7 @@
 <dict>
        <key>com.apple.private.LocalAuthentication.ExtractCredential</key>
        <true/>
 <dict>
        <key>com.apple.private.LocalAuthentication.ExtractCredential</key>
        <true/>
+       <key>com.apple.keystore.console</key>
+       <true/>
 </dict>
 </plist>
 </dict>
 </plist>
index f544bb8c7557c060e239d86a5b2cbd80046eb3c2..672768f56412b489571d04a143d740a417cf90c0 100644 (file)
@@ -100,22 +100,8 @@ OSStatus AuthorizationExecuteWithPrivilegesExternalForm(const AuthorizationExter
        if (flags != 0)
                return errAuthorizationInvalidFlags;
 
        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.
 
        // 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;
        // where is the trampoline?
 #if defined(NDEBUG)
        const char *trampoline = TRAMPOLINE;
@@ -125,13 +111,26 @@ OSStatus AuthorizationExecuteWithPrivilegesExternalForm(const AuthorizationExter
                trampoline = TRAMPOLINE;
 #endif //NDEBUG
 
                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)) {
        
        // 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;
     }
 
                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]);
        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;
        }
 
                return errAuthorizationToolExecuteFailure;
        }
 
@@ -169,10 +171,20 @@ OSStatus AuthorizationExecuteWithPrivilegesExternalForm(const AuthorizationExter
                        close(notify[WRITE]);
                        if (communicationsPipe)
                                close(comm[WRITE]);
                        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));
                        // 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]);
                        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]);
                                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)");
                                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(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]);
                        // 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
                        {
 
                        // 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));
                                OSStatus error = errAuthorizationToolExecuteFailure;
                                error = h2n(error);
                                write(1, &error, sizeof(error));
index bf25a801d53eab9874abe4113ab9426466f40332..139e47565b6f6bc76b368afa1f7bbbeb60a4fbc6 100644 (file)
@@ -29,6 +29,7 @@
 #include <unistd.h>
 #include <Security/Authorization.h>
 #include <Security/SecBase.h>
 #include <unistd.h>
 #include <Security/Authorization.h>
 #include <Security/SecBase.h>
+#include <dispatch/dispatch.h>
 
 //
 // In a tool launched via AuthorizationCopyPrivilegedReference, retrieve a copy
 
 //
 // 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");
 
        // retrieve hex form of external form from environment
        const char *mboxFdText = getenv("__AUTHORIZATION");
-       if (!mboxFdText)
+       if (!mboxFdText) {
                return errAuthorizationInvalidRef;
                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;
 
 
        // 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;
 }
 }
index 90bf2549cef9e7488bb6e06907a8e1c1494df0cf..ba3b67ffb45472828f0d4c0f1e1099eba2865665 100644 (file)
@@ -719,6 +719,9 @@ static bool Flush(CFErrorRef *error) {
         isflags |= SecServerInitialSyncCredentialFlagPCS;
     if (flags & SOSControlInitialSyncFlagPCSNonCurrent)
         isflags |= SecServerInitialSyncCredentialFlagPCSNonCurrent;
         isflags |= SecServerInitialSyncCredentialFlagPCS;
     if (flags & SOSControlInitialSyncFlagPCSNonCurrent)
         isflags |= SecServerInitialSyncCredentialFlagPCSNonCurrent;
+    if (flags & SOSControlInitialSyncFlagBluetoothMigration)
+        isflags |= SecServerInitialSyncCredentialFlagBluetoothMigration;
+
 
     NSArray *array = CFBridgingRelease(_SecServerCopyInitialSyncCredentials(isflags, &error));
     complete(array, (__bridge NSError *)error);
 
     NSArray *array = CFBridgingRelease(_SecServerCopyInitialSyncCredentials(isflags, &error));
     complete(array, (__bridge NSError *)error);
index 29c6464d54be1db16c1520a0e3114b1f04902c87..c6fa97b2da336196181b8a319bf0ec27f1ff1b3d 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -68,6 +68,8 @@
 
 #include <CoreFoundation/CFURL.h>
 
 
 #include <CoreFoundation/CFURL.h>
 
+#include <Security/SecureObjectSync/SOSEnsureBackup.h>
+
 //
 // MARK: SOSEngine The Keychain database with syncable keychain support.
 //
 //
 // 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
 #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("");
 }
 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);
 
         // 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);
     });
         CFReleaseSafe(confirmed);
         CFReleaseSafe(computedKeybagDigest);
     });
diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSEnsureBackup.h
new file mode 100644 (file)
index 0000000..0b03f92
--- /dev/null
@@ -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 (file)
index 0000000..710ed74
--- /dev/null
@@ -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 <Foundation/Foundation.h>
+#import "SOSEnsureBackup.h"
+#include <utilities/debugging.h>
+
+#if TARGET_OS_OSX || TARGET_OS_IOS
+#import "keychain/ckks/CKKSLockStateTracker.h"
+#include <Security/SecureObjectSync/SOSAccount.h>
+#import <WirelessDiagnostics/WirelessDiagnostics.h>
+#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
index 3736f5ac70e44187cacbc8688716aea95a0aabce..a8a58b07ea2112d023e949a80e75a3c3475b5335 100644 (file)
@@ -121,9 +121,10 @@ typedef int SOSSecurityPropertyActionCode;
 
 #import <Foundation/Foundation.h>
 
 
 #import <Foundation/Foundation.h>
 
-#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;
 
 @protocol SOSControlProtocol
 - (void)userPublicKey:(void ((^))(BOOL trusted, NSData *spki, NSError *error))complete;
index 56eb94265eaf25e5f50e586234fe5e191e091ffb..ef7ba8b3b98eeb19acc10cfd7924fb3755155c45 100644 (file)
@@ -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] = {
 /* 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) {
 };
 
 SecPolicyRef SecPolicyCreateAppleBasicAttestationSystem(CFDataRef testRootHash) {
index f6fbb8974546a1ff8bfe834fd1db8126733b77d8..85c4cfae142a840171ceb75bc68278e8ea5699f5 100644 (file)
@@ -6,5 +6,9 @@
        <string>com.apple.swcagent</string>
        <key>com.apple.private.associated-domains</key>
        <true/>
        <string>com.apple.swcagent</string>
        <key>com.apple.private.associated-domains</key>
        <true/>
+       <key>com.apple.private.tcc.allow</key>
+       <array>
+               <string>kTCCServiceFaceID</string>
+       </array>
 </dict>
 </plist>
 </dict>
 </plist>
index 071eb04107105b572f10bcbb227940c01ab7d2f2..3466a748060b817a929d0a2397a29a81ca4f4f9b 100644 (file)
@@ -81,7 +81,12 @@ typedef WBSAutoFillDataClasses (*WBUAutoFillGetEnabledDataClasses_f)(void);
 #include <xpc/connection_private.h>
 #include <AssertMacros.h>
 
 #include <xpc/connection_private.h>
 #include <AssertMacros.h>
 
+#if TARGET_OS_IOS
 #import <LocalAuthentication/LocalAuthentication.h>
 #import <LocalAuthentication/LocalAuthentication.h>
+#import <LocalAuthentication/LAContext+Private.h>
+#import <MobileGestalt.h>
+#import <ManagedConfiguration/MCProfileConnection.h>
+#endif
 
 static NSString *swca_string_table = @"SharedWebCredentials";
 
 
 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) {
                     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);
                         CFRelease(result);
                     }
                     CFRelease(items);
index 030b4892cb4dfca594721c2ac27b5d49d5c25cd3..9121fbf71c169c2b6a674af956d64b8426dae1da 100644 (file)
@@ -3010,7 +3010,7 @@ bool _SecServerRollKeys(bool force, SecurityClient *client, CFErrorRef *error) {
 }
 
 static bool
 }
 
 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;
 {
     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);
     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, ^{
 
     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;
                 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
                      */
                     /*
                      * 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;
                     }
                     /*
                         match = false;
                     }
                     /*
@@ -3090,17 +3092,24 @@ _SecServerCopyInitialSyncCredentials(uint32_t flags, CFErrorRef *error)
     CFMutableArrayRef items = CFArrayCreateMutableForCFTypes(NULL);
 
     if (flags & SecServerInitialSyncCredentialFlagTLK) {
     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);
 
     }
     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));
     }
                        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;
 
 fail:
     return items;
index 3249d8daf4d16cf6e61c3158b408c9d4ac474f0b..a4196ce04b13745386d734a8bc1dd8ab8eaad46b 100644 (file)
@@ -106,9 +106,10 @@ bool _SecServerRollKeysGlue(bool force, CFErrorRef *error);
 
 
 /* initial sync */
 
 
 /* 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);
 
 CFArrayRef _SecServerCopyInitialSyncCredentials(uint32_t flags, CFErrorRef *error);
 bool _SecServerImportInitialSyncCredentials(CFArrayRef array, CFErrorRef *error);
index 60abe20a7e61162d45659e090e661711e23d5638..a0400b49b58effcd459e0883c191d3116b7401a8 100644 (file)
@@ -694,15 +694,18 @@ void SecRVCDelete(SecRVCRef rvc) {
     if (rvc->orvc) {
         SecORVCFinish(rvc->orvc);
         free(rvc->orvc);
     if (rvc->orvc) {
         SecORVCFinish(rvc->orvc);
         free(rvc->orvc);
+        rvc->orvc = NULL;
     }
 #if ENABLE_CRLS
     if (rvc->crvc) {
         SecCRVCFinish(rvc->crvc);
         free(rvc->crvc);
     }
 #if ENABLE_CRLS
     if (rvc->crvc) {
         SecCRVCFinish(rvc->crvc);
         free(rvc->crvc);
+        rvc->crvc = NULL;
     }
 #endif
     if (rvc->valid_info) {
         SecValidInfoRelease(rvc->valid_info);
     }
 #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
 #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
 }
 
 #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 */
 
 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
 #if ENABLE_CRLS
-    SecCRVCUpdatePVC(rvc->crvc);
+    if (rvc->crvc) { SecCRVCUpdatePVC(rvc->crvc); }
 #endif
 }
 
 #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
         /* 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);
 #endif
             ) {
             secdebug("rvc", "found cached response for cert: %ld", certIX);
index 0f63cc19afc7417d1cc291f1b13782f6e5e4aa03..7ab213a33a0d153fb11ec605776ae567906bfa5e 100644 (file)
                <key>ExpectedResult</key>
                <integer>5</integer>
        </dict>
                <key>ExpectedResult</key>
                <integer>5</integer>
        </dict>
+       <dict>
+               <key>MajorTestName</key>
+               <string>BAA_UCRT</string>
+               <key>MinorTestName</key>
+               <string>Positive</string>
+               <key>Policies</key>
+               <dict>
+                       <key>PolicyIdentifier</key>
+                       <string>1.2.840.113635.100.1.85</string>
+               </dict>
+               <key>Leaf</key>
+               <string>baa_ucrt_leaf</string>
+               <key>Intermediates</key>
+               <string>baa_user_subca1</string>
+               <key>Anchors</key>
+               <string>baa_user_root</string>
+               <key>VerifyDate</key>
+               <date>2017-08-10T06:00:00Z</date>
+               <key>ExpectedResult</key>
+               <integer>4</integer>
+       </dict>
 </array>
 </plist>
 </array>
 </plist>
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 (file)
index 0000000..423dd1e
Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/baa_ucrt_leaf.cer differ
diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/baa_user_root.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/baa_user_root.cer
new file mode 100644 (file)
index 0000000..57b735c
Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/baa_user_root.cer differ
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 (file)
index 0000000..a5cb2a9
Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/baa_user_subca1.cer differ
index 01cb53a07851cf3074d43931689d5a19e5f27c9b..f9e75861b2e613d51545b162c1df97fbb712fc4e 100644 (file)
@@ -397,17 +397,7 @@ static bool SecDbDidCreateFirstConnection(SecDbConnectionRef dbconn, bool didCre
     }
 
     if (dbconn->isCorrupted) {
     }
 
     if (dbconn->isCorrupted) {
-        /* 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");
     }
 
     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,
     /* 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);
                                                       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;
     }
 
         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);
         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);
         }
         } 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 {
             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;
         }
             }
             break;
         }
index 585a52c840901c512f67bc78398a939193fe6437..1f22215a3cd7c60e4d18f01c8b332f0f271e5ac3 100644 (file)
                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, ); }; };
                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 */; };
                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 */; };
                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 */; };
                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 */; };
                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 */; };
                6C3446561E2534E800F9522B /* AWDMetricIds_Keychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AWDMetricIds_Keychain.h; path = analytics/awd/AWDMetricIds_Keychain.h; sourceTree = "<group>"; };
                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 = "<group>"; };
                6C3446561E2534E800F9522B /* AWDMetricIds_Keychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AWDMetricIds_Keychain.h; path = analytics/awd/AWDMetricIds_Keychain.h; sourceTree = "<group>"; };
                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 = "<group>"; };
+               6C860C741F4F63AD004100A1 /* SOSEnsureBackup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSEnsureBackup.h; sourceTree = "<group>"; };
+               6C860C7A1F4F63DB004100A1 /* SOSEnsureBackup.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SOSEnsureBackup.m; sourceTree = "<group>"; };
+               6C869A771F54C2D700957298 /* AWDKeychainSOSKeychainBackupFailed.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AWDKeychainSOSKeychainBackupFailed.m; path = analytics/awd/AWDKeychainSOSKeychainBackupFailed.m; sourceTree = "<group>"; };
+               6C869A781F54C2D700957298 /* AWDKeychainSOSKeychainBackupFailed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AWDKeychainSOSKeychainBackupFailed.h; path = analytics/awd/AWDKeychainSOSKeychainBackupFailed.h; sourceTree = "<group>"; };
                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 = "<group>"; };
                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 = "<group>"; };
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        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 */,
                                D41258011E94230400781F23 /* IOKit.framework in Frameworks */,
                                D41257E01E94136000781F23 /* libz.dylib in Frameworks */,
                                D41257DF1E94133600781F23 /* CFNetwork.framework in Frameworks */,
                6C34464E1E2534D200F9522B /* AWD */ = {
                        isa = PBXGroup;
                        children = (
                6C34464E1E2534D200F9522B /* AWD */ = {
                        isa = PBXGroup;
                        children = (
+                               6C869A781F54C2D700957298 /* AWDKeychainSOSKeychainBackupFailed.h */,
+                               6C869A771F54C2D700957298 /* AWDKeychainSOSKeychainBackupFailed.m */,
                                6CD8D3B11EB22114009AC7DC /* AWDKeychainSecDbMarkedCorrupt.h */,
                                6CD8D3B21EB22114009AC7DC /* AWDKeychainSecDbMarkedCorrupt.m */,
                                6C34464F1E2534E800F9522B /* AWDKeychainCKKSRateLimiterAggregatedScores.h */,
                                6CD8D3B11EB22114009AC7DC /* AWDKeychainSecDbMarkedCorrupt.h */,
                                6CD8D3B21EB22114009AC7DC /* AWDKeychainSecDbMarkedCorrupt.m */,
                                6C34464F1E2534E800F9522B /* AWDKeychainCKKSRateLimiterAggregatedScores.h */,
                                0CD8CB041ECA50780076F37F /* SOSPeerOTRTimer.m */,
                                0CD8CB0C1ECA50D10076F37F /* SOSPeerOTRTimer.h */,
                                DC24B5821DA420D700330B48 /* SOSPersist.h */,
                                0CD8CB041ECA50780076F37F /* SOSPeerOTRTimer.m */,
                                0CD8CB0C1ECA50D10076F37F /* SOSPeerOTRTimer.h */,
                                DC24B5821DA420D700330B48 /* SOSPersist.h */,
+                               6C860C741F4F63AD004100A1 /* SOSEnsureBackup.h */,
+                               6C860C7A1F4F63DB004100A1 /* SOSEnsureBackup.m */,
                        );
                        name = Engine;
                        sourceTree = "<group>";
                        );
                        name = Engine;
                        sourceTree = "<group>";
                                DCBDB3B81E57C82300B61300 /* CKKSKeychainView.m in Sources */,
                                DC222C5A1E034D1F00B09171 /* iCloudTrace.c in Sources */,
                                DC5BB5011E0C98320010F836 /* CKKSOutgoingQueueOperation.m in Sources */,
                                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 */,
                                5269658E1E6A154800627F9D /* SecBackupKeybagEntry.m in Sources */,
                                DC222C5D1E034D1F00B09171 /* CKKSMirrorEntry.m in Sources */,
                                DC54DD101EA7D9E800108E92 /* CKKSManifestLeafRecord.m in Sources */,
                                5269658D1E6A154700627F9D /* SecBackupKeybagEntry.m in Sources */,
                                DC52E7D41D80BD1D00B0A59C /* iCloudTrace.c in Sources */,
                                DCEA5D871E2F14810089CF55 /* CKKSAPSReceiver.m in Sources */,
                                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 */,
                                DCEA5D571E2826DB0089CF55 /* CKKSSIV.m in Sources */,
                                6C8CC3AB1E2F913C009025C5 /* AWDKeychainCKKSRateLimiterAggregatedScores.m in Sources */,
                                DC9082C41EA0277600D0C1C5 /* CKKSZoneChangeFetcher.m in Sources */,
                                        "$(OTHER_LDFLAGS)",
                                        "-framework",
                                        SpringBoardServices,
                                        "$(OTHER_LDFLAGS)",
                                        "-framework",
                                        SpringBoardServices,
+                                       "-framework",
+                                       ManagedConfiguration,
                                );
                                PRODUCT_NAME = swcagent;
                        };
                                );
                                PRODUCT_NAME = swcagent;
                        };
                                        "$(OTHER_LDFLAGS)",
                                        "-framework",
                                        SpringBoardServices,
                                        "$(OTHER_LDFLAGS)",
                                        "-framework",
                                        SpringBoardServices,
+                                       "-framework",
+                                       ManagedConfiguration,
                                );
                                PRODUCT_NAME = swcagent;
                        };
                                );
                                PRODUCT_NAME = swcagent;
                        };
diff --git a/keychain/analytics/awd/AWDKeychainSOSKeychainBackupFailed.h b/keychain/analytics/awd/AWDKeychainSOSKeychainBackupFailed.h
new file mode 100644 (file)
index 0000000..4786d22
--- /dev/null
@@ -0,0 +1,38 @@
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from stdin
+
+#import <Foundation/Foundation.h>
+#import <ProtocolBuffer/PBCodable.h>
+
+#ifdef __cplusplus
+#define AWDKEYCHAINSOSKEYCHAINBACKUPFAILED_FUNCTION extern "C"
+#else
+#define AWDKEYCHAINSOSKEYCHAINBACKUPFAILED_FUNCTION extern
+#endif
+
+@interface AWDKeychainSOSKeychainBackupFailed : PBCodable <NSCopying>
+{
+    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 (file)
index 0000000..bf93f6e
--- /dev/null
@@ -0,0 +1,142 @@
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from stdin
+
+#import <TargetConditionals.h>
+#if !TARGET_OS_BRIDGE
+
+#import "AWDKeychainSOSKeychainBackupFailed.h"
+#import <ProtocolBuffer/PBConstants.h>
+#import <ProtocolBuffer/PBHashUtil.h>
+#import <ProtocolBuffer/PBDataReader.h>
+
+#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
index 1c49d40eb0348ec598beda3a7ba42cb307966bac..e96ab84c2cf6550c0532a5346a56586e25497821 100644 (file)
@@ -20,8 +20,11 @@ enum {
 
 // Simple Metrics:
 // ---------------
 
 // 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:
 // ----------------
 
 // General Metrics:
 // ----------------
index d47965cdf6e4c83e44c59526fa2e177382195d72..2201be299b555e5de84e9645e2bb7e4bbed4b43c 100644 (file)
Binary files a/keychain/analytics/awd/AwdMetadata-0x60-Keychain.bin and b/keychain/analytics/awd/AwdMetadata-0x60-Keychain.bin differ
index 452cd271fc2f61ae359e75e1e758b8ccf2a0d763..f366093b8c203472c7841fff59d71abd0c6efe58 100644 (file)
@@ -39,6 +39,9 @@
 
 // Add all operations in this collection as dependencies, then add yourself to the collection
 -(void)linearDependencies:(NSHashTable*)collection;
 
 // Add all operations in this collection as dependencies, then add yourself to the collection
 -(void)linearDependencies:(NSHashTable*)collection;
+
+// Insert yourself as high up the linearized list of dependencies as possible
+-(void)linearDependenciesWithSelfFirst: (NSHashTable*) collection;
 @end
 
 @interface NSBlockOperation (CKKSUsefulConstructorOperation)
 @end
 
 @interface NSBlockOperation (CKKSUsefulConstructorOperation)
index 79c5851395f051e14c6dd65fad2fd37b9e2c421d..443ef471c817192ba4517674c6b87e0e0547fc6f 100644 (file)
     }
 }
 
     }
 }
 
+-(void)linearDependenciesWithSelfFirst: (NSHashTable*) collection {
+    @synchronized(collection) {
+        for(NSOperation* existingop in collection) {
+            if(existingop == self) {
+                // don't depend on yourself
+                continue;
+            }
+
+            if([existingop isPending]) {
+                [existingop addDependency: self];
+                if([existingop isPending]) {
+                    // Good, we're ahead of this one.
+                } else {
+                    // It started before we told it to wait on us. Reverse the dependency.
+                    [existingop removeDependency: self];
+                    [self addDependency:existingop];
+                }
+            } else {
+                // Not a pending op? We depend on it.
+                [self addDependency: existingop];
+            }
+        }
+        [collection addObject:self];
+    }
+}
+
 -(NSString*)pendingDependenciesString:(NSString*)prefix {
     NSArray* dependencies = [self.dependencies copy];
     dependencies = [dependencies objectsAtIndexes: [dependencies indexesOfObjectsPassingTest: ^BOOL (id obj,
 -(NSString*)pendingDependenciesString:(NSString*)prefix {
     NSArray* dependencies = [self.dependencies copy];
     dependencies = [dependencies objectsAtIndexes: [dependencies indexesOfObjectsPassingTest: ^BOOL (id obj,
index f176f2ed08ed65f3bf75aa965dd2ee506f28177e..0f7416717931d2855d71e785cd755ffb1f1ba110 100644 (file)
 
     // op modifies the CloudKit zone, so it should insert itself into the list of OutgoingQueueOperations.
     // Then, we won't have simultaneous zone-modifying operations and confuse ourselves.
 
     // op modifies the CloudKit zone, so it should insert itself into the list of OutgoingQueueOperations.
     // Then, we won't have simultaneous zone-modifying operations and confuse ourselves.
-    [op linearDependencies:self.outgoingQueueOperations];
+    // However, since we might have pending OQOs, it should try to insert itself at the beginning of the linearized list
+    [op linearDependenciesWithSelfFirst:self.outgoingQueueOperations];
 
     // CKKSUpdateDeviceStateOperations are special: they should fire even if we don't believe we're in an iCloud account.
     [self scheduleAccountStatusOperation:op];
 
     // CKKSUpdateDeviceStateOperations are special: they should fire even if we don't believe we're in an iCloud account.
     [self scheduleAccountStatusOperation:op];
index 1f946199dc263685d41b2d9005a49d6b5e39d4f8..d43b2c895022d80e6a09343b147818d4338a4f98 100644 (file)
     OCMVerifyAllWithDelay(self.mockDatabase, 8);
 }
 
     OCMVerifyAllWithDelay(self.mockDatabase, 8);
 }
 
+- (void)testDeviceStateUploadBadKeyStateAfterRestart {
+    // This test has stuff in CloudKit, but no TLKs. It should become very sad.
+    [self putFakeKeyHierarchyInCloudKit: self.keychainZoneID];
+
+    [self startCKKSSubsystem];
+    XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:8*NSEC_PER_SEC], "CKKS entered waitfortlk");
+    XCTAssertEqual(self.keychainView.keyHierarchyState, SecCKKSZoneKeyStateWaitForTLK, "CKKS entered waitfortlk");
+
+    // And restart CKKS...
+    self.keychainView = [[CKKSViewManager manager] restartZone: self.keychainZoneID.zoneName];
+    XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:8*NSEC_PER_SEC], "CKKS entered waitfortlk");
+    XCTAssertEqual(self.keychainView.keyHierarchyState, SecCKKSZoneKeyStateWaitForTLK, "CKKS entered waitfortlk");
+
+    __weak __typeof(self) weakSelf = self;
+    [self expectCKModifyRecords: @{SecCKRecordDeviceStateType: [NSNumber numberWithInt:1]}
+        deletedRecordTypeCounts:nil
+                         zoneID:self.keychainZoneID
+            checkModifiedRecord: ^BOOL (CKRecord* record){
+                if([record.recordType isEqualToString: SecCKRecordDeviceStateType]) {
+                    // Check that all the things matches
+                    __strong __typeof(weakSelf) strongSelf = weakSelf;
+                    XCTAssertNotNil(strongSelf, "self exists");
+
+                    XCTAssertEqualObjects(record[SecCKRecordCirclePeerID], @"fake-circle-id", "peer ID matches what we gave it");
+                    XCTAssertEqualObjects(record[SecCKRecordCircleStatus], [NSNumber numberWithInt:kSOSCCInCircle], "device is in circle");
+                    XCTAssertEqualObjects(record[SecCKRecordKeyState], CKKSZoneKeyToNumber(SecCKKSZoneKeyStateWaitForTLK), "Device is in waitfortlk");
+
+                    XCTAssertNil(record[SecCKRecordCurrentTLK]   , "No TLK");
+                    XCTAssertNil(record[SecCKRecordCurrentClassA], "No class A key");
+                    XCTAssertNil(record[SecCKRecordCurrentClassC], "No class C key");
+                    return YES;
+                } else {
+                    return NO;
+                }
+            }
+           runAfterModification:nil];
+
+    [self.keychainView updateDeviceState:false ckoperationGroup:nil];
+
+    OCMVerifyAllWithDelay(self.mockDatabase, 8);
+}
+
+
 - (void)testDeviceStateUploadBadCircleState {
     self.circleStatus = kSOSCCNotInCircle;
     [self.accountStateTracker notifyCircleStatusChangeAndWaitForSignal];
 - (void)testDeviceStateUploadBadCircleState {
     self.circleStatus = kSOSCCNotInCircle;
     [self.accountStateTracker notifyCircleStatusChangeAndWaitForSignal];
index 63a2a894c7ddb4dfd3920b470a7cd2612cb26ee5..93f27603736bfa13278da62ca7f37fb925444853 100644 (file)
@@ -333,6 +333,25 @@ done:
     return result;
 }
 
     return result;
 }
 
+static void
+_kb_invalidate_bag(service_user_record_t *ur, const char * bag_file)
+{
+    uint8_t *buf = NULL;
+    size_t buf_size = 0;
+
+    require(ur, out);
+
+    if (_kb_load_bag_from_disk(ur, bag_file, &buf, &buf_size)) {
+        require_action(buf && buf_size <= INT_MAX, out, os_log(OS_LOG_DEFAULT, "failed to read: %s", bag_file));
+        require_noerr_action(aks_invalidate_bag(buf, (int)buf_size), out, os_log(OS_LOG_DEFAULT, "failed to invalidate file: %s", bag_file));
+    } else {
+        os_log(OS_LOG_DEFAULT, "failed to read file: %s", bag_file);
+    }
+
+out:
+    free(buf);
+}
+
 static void
 _kb_rename_bag_on_disk(service_user_record_t * ur, const char * bag_file)
 {
 static void
 _kb_rename_bag_on_disk(service_user_record_t * ur, const char * bag_file)
 {
@@ -342,6 +361,7 @@ _kb_rename_bag_on_disk(service_user_record_t * ur, const char * bag_file)
         snprintf(new_file, sizeof(new_file), "%s-invalid", bag_file);
         unlink(new_file);
         rename(bag_file, new_file);
         snprintf(new_file, sizeof(new_file), "%s-invalid", bag_file);
         unlink(new_file);
         rename(bag_file, new_file);
+        _kb_invalidate_bag(ur, new_file);
         _clear_thread_credentials();
     }
 }
         _clear_thread_credentials();
     }
 }
@@ -351,6 +371,7 @@ _kb_delete_bag_on_disk(service_user_record_t * ur, const char * bag_file)
 {
     if (bag_file) {
         _set_thread_credentials(ur);
 {
     if (bag_file) {
         _set_thread_credentials(ur);
+        _kb_invalidate_bag(ur, bag_file);
         unlink(bag_file);
         _clear_thread_credentials();
     }
         unlink(bag_file);
         _clear_thread_credentials();
     }
@@ -526,11 +547,22 @@ _service_kb_load_uid(uid_t s_uid)
             require_action(bag_file = _kb_copy_bag_filename(ur, kb_bag_type_user), done, rc = KB_GeneralError; _stage = 2);
             require_action_quiet(_kb_load_bag_from_disk(ur, bag_file, &buf, &buf_size), done, rc = KB_BagNotFound; _stage = 3);
             rc = aks_load_bag(buf, (int)buf_size, &private_handle);
             require_action(bag_file = _kb_copy_bag_filename(ur, kb_bag_type_user), done, rc = KB_GeneralError; _stage = 2);
             require_action_quiet(_kb_load_bag_from_disk(ur, bag_file, &buf, &buf_size), done, rc = KB_BagNotFound; _stage = 3);
             rc = aks_load_bag(buf, (int)buf_size, &private_handle);
-            if (rc == kIOReturnNotPermitted || rc == kAKSReturnBadDeviceKey) {
-                os_log(OS_LOG_DEFAULT, "bag load failed %d for uid (%i)", rc, s_uid);
-                _kb_rename_bag_on_disk(ur, bag_file);
-                rc = KB_BagNotFound;
-            }
+            switch (rc) {
+                case kAKSReturnBadDeviceKey:
+                case kAKSReturnBadSignature:
+                case kAKSReturnDecodeError:
+                case kAKSReturnPolicyInvalid:
+                    os_log(OS_LOG_DEFAULT, "bag load failed 0x%x for uid (%i), discarding", rc, s_uid);
+                    _kb_rename_bag_on_disk(ur, bag_file);
+                    rc = KB_BagNotFound;
+                    break;
+                case kAKSReturnSuccess:
+                    /* nothing to do */
+                    break;
+                default:
+                    os_log(OS_LOG_DEFAULT, "bag load failed 0x%x for uid (%i)", rc, s_uid);
+                    break;
+             }
             require_noerr(rc, done; _stage = 4);
             require_noerr(rc = _service_kb_set_system(private_handle, s_uid), done; _stage = 5);
         }
             require_noerr(rc, done; _stage = 4);
             require_noerr(rc = _service_kb_set_system(private_handle, s_uid), done; _stage = 5);
         }
index 908fc16869ddc513b6ce4c78dd630a04bbdbbf1b..afacd8b3ce09d2a2e75b7c4c8c6060cbc2e5bb15 100644 (file)
@@ -46,6 +46,9 @@
 #include <xpc/private.h>
 #include "securityd_service/securityd_service/securityd_service_client.h"
 
 #include <xpc/private.h>
 #include "securityd_service/securityd_service/securityd_service_client.h"
 
+// Includes for <rdar://problem/34677969> 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"
 
 #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 passphrase checking requested, save KeychainDatabase reference
        // (will quietly disable check if db isn't a keychain)
-       if (needPass)
+
+    // Always require password, <rdar://problem/34677969> Always require the user's password on keychain approval dialogs
+       // if (needPass)
                mPassphraseCheck = dynamic_cast<const KeychainDatabase *>(db);
 
     setTerminateOnSleep(true);
                mPassphraseCheck = dynamic_cast<const KeychainDatabase *>(db);
 
     setTerminateOnSleep(true);
@@ -506,7 +511,7 @@ Reason QueryKeychainUse::queryUser (const char *database, const char *descriptio
 
        // item name into hints
 
 
        // item name into hints
 
-       hints.insert(AuthItemRef(AGENT_HINT_KEYCHAIN_ITEM_NAME, AuthValueOverlay(description ? (uint32_t)strlen(description) : 0, const_cast<char*>(description))));
+    hints.insert(AuthItemRef(AGENT_HINT_KEYCHAIN_ITEM_NAME, AuthValueOverlay(description ? (uint32_t)strlen(description) : 0, const_cast<char*>(description))));
 
        // keychain name into hints
        hints.insert(AuthItemRef(AGENT_HINT_KEYCHAIN_PATH, AuthValueOverlay(database ? (uint32_t)strlen(database) : 0, const_cast<char*>(database))));
 
        // keychain name into hints
        hints.insert(AuthItemRef(AGENT_HINT_KEYCHAIN_PATH, AuthValueOverlay(database ? (uint32_t)strlen(database) : 0, const_cast<char*>(database))));
@@ -548,20 +553,29 @@ Reason QueryKeychainUse::queryUser (const char *database, const char *descriptio
                        passwordItem->getCssmData(data);
                }
                while ((reason = (const_cast<KeychainDatabase*>(mPassphraseCheck)->decode(data) ? SecurityAgent::noReason : SecurityAgent::invalidPassphrase)));
                        passwordItem->getCssmData(data);
                }
                while ((reason = (const_cast<KeychainDatabase*>(mPassphraseCheck)->decode(data) ? SecurityAgent::noReason : SecurityAgent::invalidPassphrase)));
+        
+        readChoice();
        }
        else
        {
        }
        else
        {
-               create("builtin", "confirm-access");
-        setInput(hints, context);
-               invoke();
+//        create("builtin", "confirm-access");
+//        setInput(hints, context);
+//        invoke();
+        
+        // This is a hack to support <rdar://problem/34677969>, 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;
 }
 
        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
 //
 // 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
index 1be58018b14138ddf4fd709e568e7167aa27ecbd..2217294c2000d34082aaed77854f2080e7f083cb 100644 (file)
@@ -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,
 {
     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);
     if (wrappingKey) {
         context.replace(CSSM_ATTRIBUTE_KEY, myKey(*wrappingKey).cssmKey());
                wrappingKey->validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context);
index da54bbe0b267a2c454517fd1784717a0b2fe5205..8ec656531e7aed7c9e88a2340bb9d09f3413b10c 100644 (file)
@@ -177,10 +177,18 @@ void Session::updateAudit() const
     mAudit = info;
 }
 
     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());
 {
     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);
     }
     if (keybagQuery.query() != SecurityAgent::noReason) {
         CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED);
     }
index 1c2e4da737870157ecc1ce0a609a829330d11040..a40069aee18c220894377147f3c28eb82c66c0cf 100644 (file)
@@ -112,7 +112,7 @@ protected:
        void kill();
 
 public:
        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();
     void changeKeyStorePassphrase();
     void resetKeyStorePassphrase(const CssmData &passphrase);
     service_context_t get_current_service_context();