]> git.saurik.com Git - apple/security.git/blob - keychain/ckks/tests/CKKSLoggerTests.m
Security-58286.1.32.tar.gz
[apple/security.git] / keychain / ckks / tests / CKKSLoggerTests.m
1 /*
2 * Copyright (c) 2017 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #import "CKKSTests.h"
25 #import "keychain/ckks/CKKSAnalyticsLogger.h"
26 #import <Security/SFSQLite.h>
27 #import <Foundation/Foundation.h>
28 #import <XCTest/XCTest.h>
29
30 static NSString* tablePath = nil;
31
32 @interface SQLiteTests : XCTestCase
33 @end
34
35 @implementation SQLiteTests
36
37 + (void)setUp
38 {
39 [super setUp];
40
41 tablePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"test_table.db"];
42 }
43
44 - (void)setUp
45 {
46 [super setUp];
47
48 [[NSFileManager defaultManager] removeItemAtPath:tablePath error:nil];
49 }
50
51 - (void)tearDown
52 {
53 [[NSFileManager defaultManager] removeItemAtPath:tablePath error:nil];
54
55 [super tearDown];
56 }
57
58 - (void)testCreateLoggingDatabase
59 {
60 NSString* schema = @"CREATE table test (test_column INTEGER);";
61 SFSQLite* sqlTable = [[SFSQLite alloc] initWithPath:tablePath schema:schema];
62 XCTAssertTrue([sqlTable openWithError:nil]);
63 XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:tablePath]);
64 [sqlTable close];
65 }
66
67 - (void)testInsertAndDelete
68 {
69 NSString* schema = @"CREATE table test (test_column INTEGER);";
70 SFSQLite* sqlTable = [[SFSQLite alloc] initWithPath:tablePath schema:schema];
71 XCTAssertTrue([sqlTable openWithError:nil]);
72
73 [sqlTable insertOrReplaceInto:@"test" values:@{@"test_column" : @(1)}];
74 [sqlTable insertOrReplaceInto:@"test" values:@{@"test_column" : @(2)}];
75 [sqlTable insertOrReplaceInto:@"test" values:@{@"test_column" : @(3)}];
76 XCTAssertTrue([[sqlTable selectAllFrom:@"test" where:nil bindings:nil] count] == 3);
77
78 [sqlTable deleteFrom:@"test" where:@"test_column = ?" bindings:@[@3]];
79 XCTAssertTrue([[sqlTable selectAllFrom:@"test" where:nil bindings:nil] count] == 2);
80
81 [sqlTable executeSQL:@"delete from test"];
82 XCTAssertTrue([[sqlTable selectAllFrom:@"test" where:nil bindings:nil] count] == 0);
83 }
84
85 @end
86
87 @interface CKKSAnalyticsLoggerTests : CloudKitKeychainSyncingTestsBase
88 @end
89
90 @implementation CKKSAnalyticsLoggerTests
91
92 - (void)testLoggingJSONGenerated
93 {
94 [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test.
95
96 // We expect a single record to be uploaded.
97 [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID];
98
99 [self startCKKSSubsystem];
100
101 [self addGenericPassword: @"data" account: @"account-delete-me"];
102
103 OCMVerifyAllWithDelay(self.mockDatabase, 8);
104
105 NSError* error = nil;
106 NSData* json = [[CKKSAnalyticsLogger logger] getLoggingJSONWithError:&error];
107 XCTAssertNotNil(json, @"failed to generate logging json");
108 XCTAssertNil(error, @"encourntered error getting logging json: %@", error);
109
110 NSDictionary* dictionary = [NSJSONSerialization JSONObjectWithData:json options:0 error:&error];
111 XCTAssertNotNil(dictionary, @"failed to generate dictionary from json data");
112 XCTAssertNil(error, @"encountered error deserializing json: %@", error);
113 XCTAssertTrue([dictionary isKindOfClass:[NSDictionary class]], @"did not get the class we expected from json deserialization");
114 }
115
116 - (void)testSplunkDefaultTopicNameExists
117 {
118 CKKSAnalyticsLogger* logger = [CKKSAnalyticsLogger logger];
119 dispatch_sync(logger.splunkLoggingQueue, ^{
120 XCTAssertNotNil(logger.splunkTopicName);
121 });
122 }
123
124 - (void)testSplunkDefaultBagURLExists
125 {
126 CKKSAnalyticsLogger* logger = [CKKSAnalyticsLogger logger];
127 dispatch_sync(logger.splunkLoggingQueue, ^{
128 XCTAssertNotNil(logger.splunkBagURL);
129 });
130 }
131
132 // <rdar://problem/32983193> test_KeychainCKKS | CKKSTests failed: "Failed subtests: -[CloudKitKeychainSyncingTests testSplunkUploadURLExists]" [j71ap][CoreOSTigris15Z240][bats-e-27-204-1]
133 #if 0
134 - (void)testSplunkUploadURLExists
135 {
136 CKKSAnalyticsLogger* logger = [CKKSAnalyticsLogger logger];
137 dispatch_sync(logger.splunkLoggingQueue, ^{
138 logger.ignoreServerDisablingMessages = YES;
139 XCTAssertNotNil(logger.splunkUploadURL);
140 });
141 }
142 #endif
143
144 - (void)testLastSuccessfulSyncDate
145 {
146 [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test.
147 [self startCKKSSubsystem];
148 CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85"];
149 [self.keychainZone addToZone: ckr];
150
151 // Trigger a notification (with hilariously fake data)
152 [self.keychainView notifyZoneChange:nil];
153
154 [[[self.keychainView waitForFetchAndIncomingQueueProcessing] completionHandlerDidRunCondition] wait:4 * NSEC_PER_SEC];
155
156 NSDate* syncDate = [[CKKSAnalyticsLogger logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassC inView:self.keychainView];
157 XCTAssertNotNil(syncDate, "Failed to get a last successful sync date");
158 NSDate* nowDate = [NSDate dateWithTimeIntervalSinceNow:0];
159 NSTimeInterval timeIntervalSinceSyncDate = [nowDate timeIntervalSinceDate:syncDate];
160 XCTAssertTrue(timeIntervalSinceSyncDate >= 0.0 && timeIntervalSinceSyncDate <= 15.0, "Last sync date does not look like a reasonable one");
161 }
162
163 - (void)testExtraValuesToUploadToServer
164 {
165 [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test.
166 [self startCKKSSubsystem];
167 CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85"];
168 [self.keychainZone addToZone: ckr];
169
170 // Trigger a notification (with hilariously fake data)
171 [self.keychainView notifyZoneChange:nil];
172
173 [[[self.keychainView waitForFetchAndIncomingQueueProcessing] completionHandlerDidRunCondition] wait:4 * NSEC_PER_SEC];
174
175 NSDictionary* extraValues = [[CKKSAnalyticsLogger logger] extraValuesToUploadToServer];
176 XCTAssertTrue([extraValues[@"keychain-TLKs"] boolValue]);
177 XCTAssertTrue([extraValues[@"keychain-inSyncA"] boolValue]);
178 XCTAssertTrue([extraValues[@"keychain-inSyncC"] boolValue]);
179 XCTAssertTrue([extraValues[@"keychain-IQNOE"] boolValue]);
180 XCTAssertTrue([extraValues[@"keychain-OQNOE"] boolValue]);
181 XCTAssertTrue([extraValues[@"keychain-inSync"] boolValue]);
182 }
183
184 - (void)testNilEventDoesNotCrashTheSystem
185 {
186 CKKSAnalyticsLogger* logger = [CKKSAnalyticsLogger logger];
187 [logger logSuccessForEventNamed:nil];
188
189 NSData* json = nil;
190 NSError* error = nil;
191 XCTAssertNoThrow(json = [logger getLoggingJSONWithError:&error]);
192 XCTAssertNotNil(json, @"Failed to get JSON after logging nil event");
193 XCTAssertNil(error, @"Got error when grabbing JSON after logging nil event: %@", error);
194 }
195
196 - (void)testRaceToCreateLoggers
197 {
198 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
199 for (NSInteger i = 0; i < 5; i++) {
200 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
201 CKKSAnalyticsLogger* logger = [CKKSAnalyticsLogger logger];
202 [logger logSuccessForEvent:(CKKSAnalyticsFailableEvent*)@"test_event" inView:self.keychainView];
203 dispatch_semaphore_signal(semaphore);
204 });
205 }
206
207 for (NSInteger i = 0; i < 5; i++) {
208 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
209 }
210 }
211
212 - (void)testSysdiagnoseDump
213 {
214 [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test.
215 [self startCKKSSubsystem];
216 CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85"];
217 [self.keychainZone addToZone: ckr];
218
219 // Trigger a notification (with hilariously fake data)
220 [self.keychainView notifyZoneChange:nil];
221
222 [self.keychainView waitForFetchAndIncomingQueueProcessing];
223
224 NSError* error = nil;
225 NSString* sysdiagnose = [[CKKSAnalyticsLogger logger] getSysdiagnoseDumpWithError:&error];
226 XCTAssertNil(error, @"encountered an error grabbing CKKS analytics sysdiagnose: %@", error);
227 XCTAssertTrue(sysdiagnose.length > 0, @"failed to get a sysdiagnose from CKKS analytics");
228 }
229
230 @end