2 * Copyright (c) 2017 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 #import <Foundation/NSXPCConnection_Private.h>
29 #import <Security/SecItemPriv.h>
31 #import "keychain/ckks/CKKSControl.h"
32 #import "keychain/ckks/CKKSControlProtocol.h"
33 #import "keychain/ckks/CKKSControlServer.h"
35 #include <security_utilities/debugging.h>
37 @interface CKKSControl ()
38 @property (readwrite,assign) BOOL synchronous;
39 @property xpc_endpoint_t endpoint;
40 @property NSXPCConnection *connection;
43 @implementation CKKSControl
45 - (instancetype)initWithConnection:(NSXPCConnection*)connection {
46 if(self = [super init]) {
47 _connection = connection;
52 - (id<CKKSControlProtocol>)objectProxyWithErrorHandler:(void(^)(NSError * _Nonnull error))failureHandler
54 if (self.synchronous) {
55 return [self.connection synchronousRemoteObjectProxyWithErrorHandler:failureHandler];
57 return [self.connection remoteObjectProxyWithErrorHandler:failureHandler];
61 - (void)rpcStatus:(NSString*)viewName reply:(void(^)(NSArray<NSDictionary*>* result, NSError* error)) reply {
62 [[self objectProxyWithErrorHandler: ^(NSError* error) {
65 }] rpcStatus:viewName reply:^(NSArray<NSDictionary*>* result, NSError* error){
70 - (void)rpcFastStatus:(NSString*)viewName reply:(void(^)(NSArray<NSDictionary*>* result, NSError* error)) reply {
71 [[self objectProxyWithErrorHandler: ^(NSError* error) {
74 }] rpcFastStatus:viewName reply:^(NSArray<NSDictionary*>* result, NSError* error){
80 - (void)rpcResetLocal:(NSString*)viewName reply:(void(^)(NSError* error))reply {
81 [[self objectProxyWithErrorHandler:^(NSError* error) {
83 }] rpcResetLocal:viewName reply:^(NSError* error){
88 - (void)rpcResetCloudKit:(NSString*)viewName reason:(NSString *)reason reply:(void(^)(NSError* error))reply {
89 [[self objectProxyWithErrorHandler:^(NSError* error) {
91 }] rpcResetCloudKit:viewName reason:reason reply:^(NSError* error){
97 - (void)rpcResync:(NSString*)viewName reply:(void(^)(NSError* error))reply {
98 [[self objectProxyWithErrorHandler:^(NSError* error) {
100 }] rpcResync:viewName reply:^(NSError* error){
104 - (void)rpcFetchAndProcessChanges:(NSString*)viewName reply:(void(^)(NSError* error))reply {
105 [[self objectProxyWithErrorHandler:^(NSError* error) {
107 }] rpcFetchAndProcessChanges:viewName reply:^(NSError* error){
111 - (void)rpcFetchAndProcessClassAChanges:(NSString*)viewName reply:(void(^)(NSError* error))reply {
112 [[self objectProxyWithErrorHandler:^(NSError* error) {
114 }] rpcFetchAndProcessClassAChanges:viewName reply:^(NSError* error){
118 - (void)rpcPushOutgoingChanges:(NSString*)viewName reply:(void(^)(NSError* error))reply {
119 [[self objectProxyWithErrorHandler:^(NSError* error) {
121 }] rpcPushOutgoingChanges:viewName reply:^(NSError* error){
126 - (void)rpcCKMetric:(NSString *)eventName attributes:(NSDictionary *)attributes reply:(void(^)(NSError* error))reply {
127 [[self objectProxyWithErrorHandler:^(NSError* error) {
129 }] rpcCKMetric:eventName attributes:attributes reply:^(NSError* error){
134 - (void)rpcPerformanceCounters:(void(^)(NSDictionary <NSString *,NSNumber *> *,NSError*))reply {
135 [[self objectProxyWithErrorHandler: ^(NSError* error) {
137 }] performanceCounters:^(NSDictionary <NSString *, NSNumber *> *counters){
138 reply(counters, nil);
142 - (void)rpcGetCKDeviceIDWithReply:(void (^)(NSString *))reply {
143 [[self objectProxyWithErrorHandler:^(NSError * _Nonnull error) {
145 }] rpcGetCKDeviceIDWithReply:^(NSString *ckdeviceID) {
150 - (void)rpcTLKMissing:(NSString*)viewName reply:(void(^)(bool missing))reply {
151 [self rpcFastStatus:viewName reply:^(NSArray<NSDictionary*>* results, NSError* blockError) {
152 bool missing = false;
154 for(NSDictionary* result in results) {
155 NSString* name = result[@"view"];
156 NSString* keystate = result[@"keystate"];
158 if([name isEqualToString:@"global"]) {
159 // this is global status; no view implicated
163 if ([keystate isEqualToString:@"waitfortlk"] || [keystate isEqualToString:@"error"]) {
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;
178 CKKSKnownBadState response = CKKSKnownStatePossiblyGood;
180 for(NSDictionary* result in results) {
181 NSString* name = result[@"view"];
182 NSString* keystate = result[@"keystate"];
184 if([name isEqualToString:@"global"]) {
185 // this is global status; no view implicated
189 if ([keystate isEqualToString:@"waitfortlk"] || [keystate isEqualToString:@"error"]) {
192 if ([keystate isEqualToString:@"waitforunlock"]) {
193 waitForUnlock = true;
196 if([keystate isEqualToString:@"waitfortlkcreation"] ||
197 [keystate isEqualToString:@"waitfortlkupload"]) {
198 waitForOctagon = true;
202 response = (tlkMissing ? CKKSKnownStateTLKsMissing :
203 (waitForUnlock ? CKKSKnownStateWaitForUnlock :
204 (waitForOctagon ? CKKSKnownStateWaitForOctagon :
205 CKKSKnownStatePossiblyGood)));
211 + (CKKSControl*)controlObject:(NSError* __autoreleasing *)error {
212 return [CKKSControl CKKSControlObject:NO error:error];
215 + (CKKSControl*)CKKSControlObject:(BOOL)synchronous error:(NSError* __autoreleasing *)error {
217 NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:@(kSecuritydCKKSServiceName) options:0];
219 if (connection == nil) {
221 *error = [NSError errorWithDomain:@"securityd" code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Couldn't create connection (no reason given)"}];
226 NSXPCInterface *interface = CKKSSetupControlProtocol([NSXPCInterface interfaceWithProtocol:@protocol(CKKSControlProtocol)]);
227 connection.remoteObjectInterface = interface;
230 CKKSControl* c = [[CKKSControl alloc] initWithConnection:connection];
231 c.synchronous = synchronous;