]> git.saurik.com Git - apple/security.git/blob - keychain/ot/OctagonControlServer.m
Security-59754.41.1.tar.gz
[apple/security.git] / keychain / ot / OctagonControlServer.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 <objc/runtime.h>
26 #import <Foundation/NSXPCConnection_Private.h>
27
28 #import <utilities/debugging.h>
29 #import <Security/SecEntitlements.h>
30 #import "keychain/ot/OctagonControlServer.h"
31 #import "keychain/ot/OTManager.h"
32 #import "keychain/ot/OT.h"
33 #import "keychain/ot/OTConstants.h"
34 #import "keychain/categories/NSError+UsefulConstructors.h"
35
36 #if OCTAGON
37 @interface OctagonXPCEntitlementChecker ()
38 @property OTManager* manager;
39 @property id<OctagonEntitlementBearerProtocol> entitlementBearer;
40 - (instancetype)initWithManager:(OTManager*)manager
41 entitlementBearer:(id<OctagonEntitlementBearerProtocol>)bearer;
42 @end
43
44 @implementation OctagonXPCEntitlementChecker
45
46 - (instancetype)initWithManager:(OTManager*)manager entitlementBearer:(id<OctagonEntitlementBearerProtocol>)bearer
47 {
48 // NSProxy does not implement init, so don't call super init
49 _manager = manager;
50 _entitlementBearer = bearer;
51 return self;
52 }
53
54 - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
55 {
56 return [self.manager methodSignatureForSelector:selector];
57 }
58
59 - (void)forwardInvocation:(NSInvocation *)invocation
60 {
61 if(sel_isEqual(invocation.selector, @selector(fetchEscrowContents:contextID:reply:))) {
62 if(![self.entitlementBearer valueForEntitlement:kSecEntitlementPrivateOctagonEscrow]) {
63 secerror("Client %@ does not have entitlement %@, rejecting rpc", self.entitlementBearer, kSecEntitlementPrivateOctagonEscrow);
64 [invocation setSelector:@selector(failFetchEscrowContents:contextID:reply:)];
65 [invocation invokeWithTarget:self];
66 return;
67 }
68 }
69 [invocation invokeWithTarget:self.manager];
70 }
71
72 - (void)failFetchEscrowContents:(NSString*)containerName
73 contextID:(NSString *)contextID
74 reply:(void (^)(NSData* _Nullable entropy,
75 NSString* _Nullable bottleID,
76 NSData* _Nullable signingPublicKey,
77 NSError* _Nullable error))reply
78 {
79 reply(nil, nil, nil, [NSError errorWithDomain:NSOSStatusErrorDomain
80 code:errSecMissingEntitlement
81 description:[NSString stringWithFormat: @"Missing entitlement '%@'", kSecEntitlementPrivateOctagonEscrow]]);
82 }
83
84 + (BOOL)conformsToProtocol:(Protocol *)protocol {
85 return [[OTManager class] conformsToProtocol:protocol];
86 }
87
88 // Launder a OctagonXPCEntitlementChecker into something that type-safely implements the protocol we're interested in
89 + (id<OTControlProtocol>)createWithManager:(OTManager*)manager
90 entitlementBearer:(id<OctagonEntitlementBearerProtocol>)bearer
91 {
92 return (id<OTControlProtocol>) [[OctagonXPCEntitlementChecker alloc] initWithManager:manager entitlementBearer:bearer];
93 }
94 @end
95 #endif // OCTAGON
96
97 @interface OctagonControlServer : NSObject <NSXPCListenerDelegate>
98 @end
99
100 @implementation OctagonControlServer
101
102 - (BOOL)listener:(__unused NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection
103 {
104 #if OCTAGON
105 NSNumber *num = [newConnection valueForEntitlement:kSecEntitlementPrivateOctagon];
106 if (![num isKindOfClass:[NSNumber class]] || ![num boolValue]) {
107 secerror("octagon: Client pid: %d doesn't have entitlement: %@",
108 [newConnection processIdentifier], kSecEntitlementPrivateOctagon);
109 return NO;
110 }
111 // In the future, we should consider vending a proxy object that can return a nicer error.
112 if (!OctagonIsEnabled()) {
113 secerror("Octagon: Client pid: %d attempted to use Octagon, but Octagon is not enabled.",
114 newConnection.processIdentifier);
115 return NO;
116 }
117
118 secinfo("octagon", "received connection from client pid %d", [newConnection processIdentifier]);
119 newConnection.exportedInterface = OTSetupControlProtocol([NSXPCInterface interfaceWithProtocol:@protocol(OTControlProtocol)]);
120 newConnection.exportedObject = [OctagonXPCEntitlementChecker createWithManager:[OTManager manager] entitlementBearer:newConnection];
121
122 [newConnection resume];
123
124 return YES;
125 #else // OCTAGON
126 secerror("octagon does not exist on this platform");
127 return NO;
128 #endif // OCTAGON
129 }
130 @end
131
132 void
133 OctagonControlServerInitialize(void)
134 {
135 static dispatch_once_t once;
136 static OctagonControlServer *server;
137 static NSXPCListener *listener;
138
139 dispatch_once(&once, ^{
140 @autoreleasepool {
141 server = [OctagonControlServer new];
142
143 listener = [[NSXPCListener alloc] initWithMachServiceName:@(kSecuritydOctagonServiceName)];
144 listener.delegate = server;
145 [listener resume];
146 }
147 });
148 }