]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/Regressions/secd-210-keyinterest.m
a3d9989b4bccbc3e60e51500bfc57d03a692a2bf
[apple/security.git] / OSX / sec / SOSCircle / Regressions / secd-210-keyinterest.m
1 //
2 // sc-160-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 if (self.listener) {
66 if (self.locked) {
67 [self.listener locked];
68 } else {
69 [self.listener unlocked];
70 }
71 }
72 }
73
74 - (void) connectTo: (NSObject<CKDLockListener>*) listener {
75 self.listener = listener;
76 [self notifyListener];
77 }
78
79 - (void) lock {
80 self.locked = true;
81 [self notifyListener];
82 }
83 - (void) unlock {
84 self.locked = false;
85 self.unlockedSinceBoot = true;
86 [self notifyListener];
87 }
88
89
90 @end
91
92 @interface UbiqitousKVSProxy (Testing)
93 - (void) flush;
94 @end
95
96 @implementation UbiqitousKVSProxy (Testing)
97 - (void) flush {
98 dispatch_semaphore_t sema = dispatch_semaphore_create(0);
99
100 [self doAfterFlush:^{
101 dispatch_semaphore_signal(sema);
102 }];
103
104 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
105 }
106 @end
107
108 static void tests(void) {
109 CKDSimulatedStore* store = [CKDSimulatedStore simulatedInterface];
110 CKDSimulatedAccount* account = [[CKDSimulatedAccount alloc] init];
111 CKDSimulatedLockMonitor* monitor = [CKDSimulatedLockMonitor monitor];
112
113 NSString * testKey = @"TestKey";
114
115 UbiqitousKVSProxy * proxy = [UbiqitousKVSProxy withAccount:account
116 store:store
117 lockMonitor:monitor
118 persistence:[NSURL fileURLWithPath:@"/tmp/kvsPersistenceTestFile"]];
119
120 NSDictionary* interests = @{ [NSString stringWithUTF8String:kMessageKeyParameter]:@{ @"UnlockedKeys":@[ testKey ] } };
121 NSString* accountID = @"Account1";
122
123 dispatch_sync([proxy ckdkvsproxy_queue], ^{
124 [proxy registerKeys:interests forAccount:accountID];
125 });
126
127 is([[account extractKeyChanges] count], (NSUInteger)0, "No changes yet");
128
129 [store remoteSetObject:@1 forKey:testKey];
130 [proxy flush];
131
132 is([[account extractKeyChanges] count], (NSUInteger)0, "Still none while locked");
133
134 [monitor unlock];
135 [proxy flush];
136
137 is([[account extractKeyChanges] count], (NSUInteger)1, "Notified after unlock");
138
139 [monitor lock];
140 [monitor unlock];
141 [proxy flush];
142
143 is([[account extractKeyChanges] count], (NSUInteger)0, "lock unlock and nothing changes");
144
145 [store remoteSetObject:@2 forKey:testKey];
146 [proxy flush];
147
148 {
149 NSDictionary<NSString*, NSObject*> *changes = [account extractKeyChanges];
150 is([changes count], (NSUInteger)1, "lock, nothing changes");
151 is(changes[testKey], @2, "Sent second value");
152 }
153
154 [monitor lock];
155 [store remoteSetObject:@3 forKey:testKey];
156 [proxy flush];
157
158 is([[account extractKeyChanges] count], (NSUInteger)0, "Changes to Unlocked not when locked");
159
160 [monitor unlock];
161 [proxy flush];
162
163 {
164 NSDictionary<NSString*, NSObject*> *changes = [account extractKeyChanges];
165 is([changes count], (NSUInteger)1, "Change defered to after unlock");
166 is(changes[testKey], @3, "Correct value");
167 }
168
169 dispatch_sync([proxy ckdkvsproxy_queue], ^{
170 [proxy registerKeys:interests forAccount:accountID];
171 });
172 [proxy flush];
173
174 is([[account extractKeyChanges] count], (NSUInteger)0, "Same interests, no new data");
175
176 dispatch_sync([proxy ckdkvsproxy_queue], ^{
177 [proxy registerKeys:interests forAccount:@"different"];
178 });
179 [proxy flush];
180
181 {
182 NSDictionary<NSString*, NSObject*> *changes = [account extractKeyChanges];
183 is([changes count], (NSUInteger)1, "New account, same interests, new data");
184 is(changes[testKey], @3, "Latest value for new data");
185 }
186
187 }
188
189
190 int secd_210_keyinterest(int argc, char *const *argv)
191 {
192 plan_tests(12);
193
194 tests();
195
196 return 0;
197 }