]> git.saurik.com Git - apple/security.git/blob - keychain/securityd/Regressions/secd-210-keyinterest.m
Security-59754.80.3.tar.gz
[apple/security.git] / keychain / securityd / Regressions / secd-210-keyinterest.m
1 //
2 // secd-210-keyinterest.m
3 // Security
4 //
5 // Created by Mitch Adler on 10/31/16.
6 //
7 //
8
9 #import <Foundation/Foundation.h>
10
11 #include "secd_regressions.h"
12
13 #import "CKDStore.h"
14 #import "CKDKVSProxy.h"
15 #import "CKDSimulatedStore.h"
16 #import "CKDSimulatedAccount.h"
17 #import "CKDAKSLockMonitor.h"
18 #include "SOSCloudKeychainConstants.h"
19 #include "SOSAccountTesting.h"
20
21
22 #if SOS_ENABLED
23
24 @interface CKDSimulatedLockMonitor : NSObject<CKDLockMonitor>
25
26 @property (readwrite) BOOL unlockedSinceBoot;
27 @property (readwrite) BOOL locked;
28
29 @property (weak) NSObject<CKDLockListener>* listener;
30
31 + (instancetype) monitor;
32
33 - (instancetype) init;
34
35 - (void) recheck;
36
37 - (void) notifyListener;
38 - (void) connectTo: (NSObject<CKDLockListener>*) listener;
39
40 - (void) lock;
41 - (void) unlock;
42
43 @end
44
45
46 @implementation CKDSimulatedLockMonitor
47
48 + (instancetype) monitor {
49 return [[CKDSimulatedLockMonitor alloc] init];
50 }
51
52 - (instancetype) init {
53 if ((self = [super init])) {
54 _locked = true;
55 _unlockedSinceBoot = false;
56 }
57
58 [self notifyListener];
59
60 return self;
61 }
62
63 - (void) recheck {
64 }
65
66 - (void) notifyListener {
67 // Take a strong reference:
68 __strong __typeof(self.listener) listener = self.listener;
69
70 if (listener) {
71 if (self.locked) {
72 [listener locked];
73 } else {
74 [listener unlocked];
75 }
76 }
77 }
78
79 - (void) connectTo: (NSObject<CKDLockListener>*) listener {
80 self.listener = listener;
81 [self notifyListener];
82 }
83
84 - (void) lock {
85 self.locked = true;
86 [self notifyListener];
87 }
88 - (void) unlock {
89 self.locked = false;
90 self.unlockedSinceBoot = true;
91 [self notifyListener];
92 }
93
94
95 @end
96
97 @interface UbiqitousKVSProxy (Testing)
98 - (void) flush;
99 @end
100
101 @implementation UbiqitousKVSProxy (Testing)
102 - (void) flush {
103 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
104
105 [self doAfterFlush:^{
106 dispatch_semaphore_signal(sema);
107 }];
108
109 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
110 }
111 @end
112
113 static void tests(void) {
114 CKDSimulatedStore* store = [CKDSimulatedStore simulatedInterface];
115 CKDSimulatedAccount* account = [[CKDSimulatedAccount alloc] init];
116 CKDSimulatedLockMonitor* monitor = [CKDSimulatedLockMonitor monitor];
117
118 NSString * testKey = @"TestKey";
119
120 UbiqitousKVSProxy * proxy = [UbiqitousKVSProxy withAccount:account
121 store:store
122 lockMonitor:monitor
123 persistence:[NSURL fileURLWithPath:@"/tmp/kvsPersistenceTestFile"]];
124
125 NSDictionary* interests = @{ [NSString stringWithUTF8String:kMessageKeyParameter]:@{ @"UnlockedKeys":@[ testKey ] } };
126 NSString* accountID = @"Account1";
127
128 dispatch_sync([proxy ckdkvsproxy_queue], ^{
129 [proxy registerKeys:interests forAccount:accountID];
130 });
131
132 is([[account extractKeyChanges] count], (NSUInteger)0, "No changes yet");
133
134 [store remoteSetObject:@1 forKey:testKey];
135 [proxy flush];
136
137 is([[account extractKeyChanges] count], (NSUInteger)0, "Still none while locked");
138
139 [monitor unlock];
140 [proxy flush];
141
142 is([[account extractKeyChanges] count], (NSUInteger)1, "Notified after unlock");
143
144 [monitor lock];
145 [monitor unlock];
146 [proxy flush];
147
148 is([[account extractKeyChanges] count], (NSUInteger)0, "lock unlock and nothing changes");
149
150 [store remoteSetObject:@2 forKey:testKey];
151 [proxy flush];
152
153 {
154 NSDictionary<NSString*, NSObject*> *changes = [account extractKeyChanges];
155 is([changes count], (NSUInteger)1, "lock, nothing changes");
156 is(changes[testKey], @2, "Sent second value");
157 }
158
159 [monitor lock];
160 [store remoteSetObject:@3 forKey:testKey];
161 [proxy flush];
162
163 is([[account extractKeyChanges] count], (NSUInteger)0, "Changes to Unlocked not when locked");
164
165 [monitor unlock];
166 [proxy flush];
167
168 {
169 NSDictionary<NSString*, NSObject*> *changes = [account extractKeyChanges];
170 is([changes count], (NSUInteger)1, "Change defered to after unlock");
171 is(changes[testKey], @3, "Correct value");
172 }
173
174 dispatch_sync([proxy ckdkvsproxy_queue], ^{
175 [proxy registerKeys:interests forAccount:accountID];
176 });
177 [proxy flush];
178
179 is([[account extractKeyChanges] count], (NSUInteger)0, "Same interests, no new data");
180
181 dispatch_sync([proxy ckdkvsproxy_queue], ^{
182 [proxy registerKeys:interests forAccount:@"different"];
183 });
184 [proxy flush];
185
186 {
187 NSDictionary<NSString*, NSObject*> *changes = [account extractKeyChanges];
188 is([changes count], (NSUInteger)1, "New account, same interests, new data");
189 is(changes[testKey], @3, "Latest value for new data");
190 }
191
192 }
193
194 #endif
195
196 int secd_210_keyinterest(int argc, char *const *argv)
197 {
198 #if SOS_ENABLED
199 plan_tests(12);
200 tests();
201 #else
202 plan_tests(0);
203 #endif
204 return 0;
205 }