client_endpoint.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 #import <Foundation/Foundation.h> 25 #import <Foundation/NSXPCConnection.h> 26 #import <Foundation/NSXPCConnection_Private.h> 27 #import <objc/runtime.h> 28 #import <utilities/debugging.h> 29 #import <Security/SecXPCHelper.h> 30 31 #include <ipc/securityd_client.h> 32 33 @implementation SecuritydXPCClient 34 @synthesize connection = _connection; 35 36 - (instancetype) init 37 { 38 if ((self = [super init])) { 39 NSXPCInterface *interface = [NSXPCInterface interfaceWithProtocol:@protocol(SecuritydXPCProtocol)]; 40 41 self.connection = [[NSXPCConnection alloc] initWithMachServiceName:@(kSecuritydGeneralServiceName) options:0]; 42 if (self.connection == NULL) { 43 return NULL; 44 } 45 46 self.connection.remoteObjectInterface = interface; 47 [SecuritydXPCClient configureSecuritydXPCProtocol: self.connection.remoteObjectInterface]; 48 49 [self.connection resume]; 50 } 51 52 return self; 53 } 54 55 +(void)configureSecuritydXPCProtocol: (NSXPCInterface*) interface { 56 NSXPCInterface *rpcCallbackInterface = [NSXPCInterface interfaceWithProtocol: @protocol(SecuritydXPCCallbackProtocol)]; 57 [interface setInterface:rpcCallbackInterface 58 forSelector:@selector(SecItemAddAndNotifyOnSync:syncCallback:complete:) 59 argumentIndex:1 60 ofReply:0]; 61 62 #if OCTAGON 63 NSSet<Class> *errClasses = [SecXPCHelper safeErrorClasses]; 64 65 @try { 66 [rpcCallbackInterface setClasses:errClasses forSelector:@selector(callCallback:error:) argumentIndex:1 ofReply:NO]; 67 68 [interface setClasses:errClasses forSelector:@selector(SecItemAddAndNotifyOnSync: 69 syncCallback: 70 complete:) argumentIndex:2 ofReply:YES]; 71 [interface setClasses:errClasses forSelector:@selector(secItemSetCurrentItemAcrossAllDevices: 72 newCurrentItemHash: 73 accessGroup: 74 identifier: 75 viewHint: 76 oldCurrentItemReference: 77 oldCurrentItemHash: 78 complete:) argumentIndex:0 ofReply:YES]; 79 [interface setClasses:errClasses forSelector:@selector(secItemFetchCurrentItemAcrossAllDevices: 80 identifier: 81 viewHint: 82 fetchCloudValue: 83 complete:) argumentIndex:1 ofReply:YES]; 84 [interface setClasses:errClasses forSelector:@selector(secItemDigest: 85 accessGroup: 86 complete:) argumentIndex:1 ofReply:YES]; 87 [interface setClasses:errClasses forSelector:@selector(secKeychainDeleteMultiuser:complete:) argumentIndex:1 ofReply:YES]; 88 [interface setClasses:errClasses forSelector:@selector(secItemVerifyBackupIntegrity:completion:) argumentIndex:1 ofReply:YES]; 89 90 } 91 @catch(NSException* e) { 92 secerror("Could not configure SecuritydXPCProtocol: %@", e); 93 @throw e; 94 } 95 #endif // OCTAGON 96 } 97 @end 98 99 @implementation SecuritydXPCCallback 100 @synthesize callback = _callback; 101 102 -(instancetype)initWithCallback: (SecBoolNSErrorCallback) callback { 103 if((self = [super init])) { 104 _callback = callback; 105 } 106 return self; 107 } 108 109 - (void)callCallback: (bool) result error:(NSError*) error { 110 self.callback(result, error); 111 } 112 @end 113 114 id<SecuritydXPCProtocol> SecuritydXPCProxyObject(bool synchronous, void (^rpcErrorHandler)(NSError *)) 115 { 116 if (gSecurityd && gSecurityd->secd_xpc_server) { 117 return (__bridge id<SecuritydXPCProtocol>)gSecurityd->secd_xpc_server; 118 } 119 120 static SecuritydXPCClient* rpc; 121 static dispatch_once_t onceToken; 122 123 dispatch_once(&onceToken, ^{ 124 rpc = [[SecuritydXPCClient alloc] init]; 125 }); 126 127 if (rpc == NULL) { 128 rpcErrorHandler([NSError errorWithDomain:@"securityd" code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Could not create SecuritydXPCClient" }]); 129 return NULL; 130 } else { 131 if (synchronous) { 132 return [rpc.connection synchronousRemoteObjectProxyWithErrorHandler:rpcErrorHandler]; 133 } else { 134 return [rpc.connection remoteObjectProxyWithErrorHandler:rpcErrorHandler]; 135 } 136 } 137 } 138