]>
Commit | Line | Data |
---|---|---|
6b200bc3 A |
1 | // |
2 | // CKDAKSLockMonitor.m | |
3 | // Security | |
4 | // | |
5 | // Created by Mitch Adler on 11/2/16. | |
6 | // | |
7 | // | |
8 | ||
9 | #import <Foundation/Foundation.h> | |
10 | ||
11 | #import "CKDAKSLockMonitor.h" | |
12 | ||
13 | #include <utilities/SecCFRelease.h> | |
14 | #include <utilities/SecAKSWrappers.h> | |
15 | #include <utilities/debugging.h> | |
16 | ||
866f8763 | 17 | #include <notify.h> |
6b200bc3 A |
18 | |
19 | @interface CKDAKSLockMonitor () | |
20 | ||
21 | @property XPCNotificationDispatcher* dispatcher; | |
22 | @property XPCNotificationBlock notificationBlock; | |
866f8763 | 23 | @property dispatch_queue_t queue; |
6b200bc3 A |
24 | |
25 | @end | |
26 | ||
27 | @implementation CKDAKSLockMonitor | |
28 | ||
29 | + (instancetype) monitor { | |
30 | return [[CKDAKSLockMonitor alloc] init]; | |
31 | } | |
32 | ||
33 | - (instancetype)init { | |
34 | self = [super init]; | |
35 | ||
36 | if (self) { | |
37 | XPCNotificationDispatcher* dispatcher = [XPCNotificationDispatcher dispatcher]; | |
38 | ||
866f8763 A |
39 | _queue = dispatch_queue_create("CKDAKSLockMonitor", NULL); |
40 | _locked = true; | |
41 | _unlockedSinceBoot = false; | |
6b200bc3 | 42 | |
866f8763 A |
43 | /* also use dispatch to make sure */ |
44 | int token = 0; | |
45 | __weak typeof(self) weakSelf = self; | |
46 | notify_register_dispatch(kUserKeybagStateChangeNotification, &token, _queue, ^(int t) { | |
47 | [weakSelf _onqueueRecheck]; | |
48 | }); | |
6b200bc3 A |
49 | |
50 | [self recheck]; | |
866f8763 A |
51 | |
52 | [dispatcher addListener: self]; | |
6b200bc3 A |
53 | } |
54 | ||
55 | return self; | |
56 | } | |
57 | ||
58 | - (void) handleNotification:(const char *)name { | |
866f8763 | 59 | if (strcmp(name, kUserKeybagStateChangeNotification) == 0 || strcmp(name, "com.apple.mobile.keybagd.lock_status") == 0) { |
6b200bc3 A |
60 | [self recheck]; |
61 | } | |
62 | } | |
63 | ||
64 | - (void) notifyListener { | |
866f8763 A |
65 | // Take a strong reference: |
66 | __strong __typeof(self.listener) listener = self.listener; | |
67 | ||
68 | if (listener) { | |
6b200bc3 | 69 | if (self.locked) { |
866f8763 | 70 | [listener locked]; |
6b200bc3 | 71 | } else { |
866f8763 | 72 | [listener unlocked]; |
6b200bc3 A |
73 | } |
74 | } | |
75 | } | |
76 | ||
77 | - (void)connectTo: (NSObject<CKDLockListener>*) listener { | |
866f8763 | 78 | _listener = listener; |
6b200bc3 A |
79 | [self notifyListener]; |
80 | } | |
81 | ||
82 | - (void) recheck { | |
866f8763 A |
83 | dispatch_async(_queue, ^{ |
84 | [self _onqueueRecheck]; | |
85 | }); | |
86 | } | |
87 | ||
88 | - (void) _onqueueRecheck { | |
6b200bc3 A |
89 | CFErrorRef aksError = NULL; |
90 | bool locked = true; // Assume locked if we get an error | |
91 | ||
92 | if (!SecAKSGetIsLocked(&locked, &aksError)) { | |
93 | secerror("%@ Got error querying lock state: %@", self, aksError); | |
94 | CFReleaseSafe(aksError); | |
95 | } | |
96 | ||
97 | BOOL previousLocked = self.locked; | |
866f8763 | 98 | _locked = locked; |
6b200bc3 A |
99 | |
100 | if (!self.locked) { | |
866f8763 | 101 | _unlockedSinceBoot = true; |
6b200bc3 A |
102 | } |
103 | ||
104 | if (previousLocked != self.locked) { | |
105 | // recheck might get called from ckdkvsproxy_queue (see 30510390) | |
106 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ | |
107 | [self notifyListener]; | |
108 | }); | |
109 | } | |
110 | } | |
111 | ||
112 | @end |