]> git.saurik.com Git - apple/security.git/blob - keychain/ckks/CKKSControl.m
Security-59306.80.4.tar.gz
[apple/security.git] / keychain / ckks / CKKSControl.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 #if __OBJC2__
25
26 #import <Foundation/NSXPCConnection_Private.h>
27 #import <xpc/xpc.h>
28
29 #import <Security/SecItemPriv.h>
30
31 #import "keychain/ckks/CKKSControl.h"
32 #import "keychain/ckks/CKKSControlProtocol.h"
33 #import "keychain/ckks/CKKSControlServer.h"
34
35 #include <security_utilities/debugging.h>
36
37 @interface CKKSControl ()
38 @property (readwrite,assign) BOOL synchronous;
39 @property xpc_endpoint_t endpoint;
40 @property NSXPCConnection *connection;
41 @end
42
43 @implementation CKKSControl
44
45 - (instancetype)initWithConnection:(NSXPCConnection*)connection {
46 if(self = [super init]) {
47 _connection = connection;
48 }
49 return self;
50 }
51
52 - (id<CKKSControlProtocol>)objectProxyWithErrorHandler:(void(^)(NSError * _Nonnull error))failureHandler
53 {
54 if (self.synchronous) {
55 return [self.connection synchronousRemoteObjectProxyWithErrorHandler:failureHandler];
56 } else {
57 return [self.connection remoteObjectProxyWithErrorHandler:failureHandler];
58 }
59 }
60
61 - (void)rpcStatus:(NSString*)viewName reply:(void(^)(NSArray<NSDictionary*>* result, NSError* error)) reply {
62 [[self objectProxyWithErrorHandler: ^(NSError* error) {
63 reply(nil, error);
64
65 }] rpcStatus:viewName reply:^(NSArray<NSDictionary*>* result, NSError* error){
66 reply(result, error);
67 }];
68 }
69
70 - (void)rpcFastStatus:(NSString*)viewName reply:(void(^)(NSArray<NSDictionary*>* result, NSError* error)) reply {
71 [[self objectProxyWithErrorHandler: ^(NSError* error) {
72 reply(nil, error);
73
74 }] rpcFastStatus:viewName reply:^(NSArray<NSDictionary*>* result, NSError* error){
75 reply(result, error);
76 }];
77 }
78
79
80 - (void)rpcResetLocal:(NSString*)viewName reply:(void(^)(NSError* error))reply {
81 [[self objectProxyWithErrorHandler:^(NSError* error) {
82 reply(error);
83 }] rpcResetLocal:viewName reply:^(NSError* error){
84 reply(error);
85 }];
86 }
87
88 - (void)rpcResetCloudKit:(NSString*)viewName reason:(NSString *)reason reply:(void(^)(NSError* error))reply {
89 [[self objectProxyWithErrorHandler:^(NSError* error) {
90 reply(error);
91 }] rpcResetCloudKit:viewName reason:reason reply:^(NSError* error){
92 reply(error);
93 }];
94 }
95
96
97 - (void)rpcResync:(NSString*)viewName reply:(void(^)(NSError* error))reply {
98 [[self objectProxyWithErrorHandler:^(NSError* error) {
99 reply(error);
100 }] rpcResync:viewName reply:^(NSError* error){
101 reply(error);
102 }];
103 }
104 - (void)rpcFetchAndProcessChanges:(NSString*)viewName reply:(void(^)(NSError* error))reply {
105 [[self objectProxyWithErrorHandler:^(NSError* error) {
106 reply(error);
107 }] rpcFetchAndProcessChanges:viewName reply:^(NSError* error){
108 reply(error);
109 }];
110 }
111 - (void)rpcFetchAndProcessClassAChanges:(NSString*)viewName reply:(void(^)(NSError* error))reply {
112 [[self objectProxyWithErrorHandler:^(NSError* error) {
113 reply(error);
114 }] rpcFetchAndProcessClassAChanges:viewName reply:^(NSError* error){
115 reply(error);
116 }];
117 }
118 - (void)rpcPushOutgoingChanges:(NSString*)viewName reply:(void(^)(NSError* error))reply {
119 [[self objectProxyWithErrorHandler:^(NSError* error) {
120 reply(error);
121 }] rpcPushOutgoingChanges:viewName reply:^(NSError* error){
122 reply(error);
123 }];
124 }
125
126 - (void)rpcCKMetric:(NSString *)eventName attributes:(NSDictionary *)attributes reply:(void(^)(NSError* error))reply {
127 [[self objectProxyWithErrorHandler:^(NSError* error) {
128 reply(error);
129 }] rpcCKMetric:eventName attributes:attributes reply:^(NSError* error){
130 reply(error);
131 }];
132 }
133
134 - (void)rpcPerformanceCounters:(void(^)(NSDictionary <NSString *,NSNumber *> *,NSError*))reply {
135 [[self objectProxyWithErrorHandler: ^(NSError* error) {
136 reply(nil, error);
137 }] performanceCounters:^(NSDictionary <NSString *, NSNumber *> *counters){
138 reply(counters, nil);
139 }];
140 }
141
142 - (void)rpcGetCKDeviceIDWithReply:(void (^)(NSString *))reply {
143 [[self objectProxyWithErrorHandler:^(NSError * _Nonnull error) {
144 reply(nil);
145 }] rpcGetCKDeviceIDWithReply:^(NSString *ckdeviceID) {
146 reply(ckdeviceID);
147 }];
148 }
149
150 - (void)rpcTLKMissing:(NSString*)viewName reply:(void(^)(bool missing))reply {
151 [self rpcFastStatus:viewName reply:^(NSArray<NSDictionary*>* results, NSError* blockError) {
152 bool missing = false;
153
154 for(NSDictionary* result in results) {
155 NSString* name = result[@"view"];
156 NSString* keystate = result[@"keystate"];
157
158 if([name isEqualToString:@"global"]) {
159 // this is global status; no view implicated
160 continue;
161 }
162
163 if ([keystate isEqualToString:@"waitfortlk"] || [keystate isEqualToString:@"error"]) {
164 missing = true;
165 }
166 }
167
168 reply(missing);
169 }];
170 }
171
172 - (void)rpcKnownBadState:(NSString* _Nullable)viewName reply:(void (^)(CKKSKnownBadState))reply {
173 [self rpcFastStatus:viewName reply:^(NSArray<NSDictionary*>* results, NSError* blockError) {
174 bool tlkMissing = false;
175 bool waitForUnlock = false;
176 bool waitForOctagon = false;
177
178 CKKSKnownBadState response = CKKSKnownStatePossiblyGood;
179
180 for(NSDictionary* result in results) {
181 NSString* name = result[@"view"];
182 NSString* keystate = result[@"keystate"];
183
184 if([name isEqualToString:@"global"]) {
185 // this is global status; no view implicated
186 continue;
187 }
188
189 if ([keystate isEqualToString:@"waitfortlk"] || [keystate isEqualToString:@"error"]) {
190 tlkMissing = true;
191 }
192 if ([keystate isEqualToString:@"waitforunlock"]) {
193 waitForUnlock = true;
194 }
195
196 if([keystate isEqualToString:@"waitfortlkcreation"] ||
197 [keystate isEqualToString:@"waitfortlkupload"]) {
198 waitForOctagon = true;
199 }
200 }
201
202 response = (tlkMissing ? CKKSKnownStateTLKsMissing :
203 (waitForUnlock ? CKKSKnownStateWaitForUnlock :
204 (waitForOctagon ? CKKSKnownStateWaitForOctagon :
205 CKKSKnownStatePossiblyGood)));
206
207 reply(response);
208 }];
209 }
210
211 + (CKKSControl*)controlObject:(NSError* __autoreleasing *)error {
212 return [CKKSControl CKKSControlObject:NO error:error];
213 }
214
215 + (CKKSControl*)CKKSControlObject:(BOOL)synchronous error:(NSError* __autoreleasing *)error {
216
217 NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:@(kSecuritydCKKSServiceName) options:0];
218
219 if (connection == nil) {
220 if(error) {
221 *error = [NSError errorWithDomain:@"securityd" code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Couldn't create connection (no reason given)"}];
222 }
223 return nil;
224 }
225
226 NSXPCInterface *interface = CKKSSetupControlProtocol([NSXPCInterface interfaceWithProtocol:@protocol(CKKSControlProtocol)]);
227 connection.remoteObjectInterface = interface;
228 [connection resume];
229
230 CKKSControl* c = [[CKKSControl alloc] initWithConnection:connection];
231 c.synchronous = synchronous;
232 return c;
233 }
234
235 @end
236
237 #endif // __OBJC2__