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