]> git.saurik.com Git - apple/security.git/blob - OSX/sec/ipc/server_endpoint.m
Security-59754.41.1.tar.gz
[apple/security.git] / OSX / sec / ipc / server_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 #include <xpc/private.h>
28 #include <xpc/xpc.h>
29
30 #include "ipc/securityd_client.h"
31 #include "ipc/server_security_helpers.h"
32 #include "ipc/server_entitlement_helpers.h"
33 #include "ipc/server_endpoint.h"
34
35 #include "keychain/securityd/SecItemServer.h"
36 #include <Security/SecEntitlements.h>
37
38 #pragma mark - Securityd Server
39
40 @implementation SecuritydXPCServer
41 @synthesize connection = _connection;
42
43 - (instancetype)initWithConnection:(NSXPCConnection *)connection
44 {
45 if ((self = [super init])) {
46 _connection = connection;
47
48 if (!fill_security_client(&self->_client, connection.effectiveUserIdentifier, connection.auditToken)) {
49 return nil;
50 }
51 }
52 return self;
53 }
54
55 - (instancetype)initWithSecurityClient:(SecurityClient*) existingClient
56 {
57 if(!existingClient) {
58 return nil;
59 }
60 if((self = [super init])) {
61 _connection = nil;
62
63 self->_client.task = CFRetainSafe(existingClient->task);
64 self->_client.accessGroups = CFRetainSafe(existingClient->accessGroups);
65 self->_client.allowSystemKeychain = existingClient->allowSystemKeychain;
66 self->_client.allowSyncBubbleKeychain = existingClient->allowSyncBubbleKeychain;
67 self->_client.isNetworkExtension = existingClient->isNetworkExtension;
68 self->_client.canAccessNetworkExtensionAccessGroups = existingClient->canAccessNetworkExtensionAccessGroups;
69 self->_client.uid = existingClient->uid;
70 self->_client.musr = CFRetainSafe(existingClient->musr);
71 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) && TARGET_HAS_KEYSTORE
72 self->_client.keybag = existingClient->keybag;
73 #endif
74 #if TARGET_OS_IPHONE
75 self->_client.inMultiUser = existingClient->inMultiUser;
76 self->_client.activeUser = existingClient->activeUser;
77 #endif
78 self->_client.applicationIdentifier = CFRetainSafe(existingClient->applicationIdentifier);
79 self->_client.isAppClip = existingClient->isAppClip;
80 }
81 return self;
82 }
83
84
85 - (bool)clientHasBooleanEntitlement: (NSString*) entitlement {
86 return SecTaskGetBooleanValueForEntitlement(self->_client.task, (__bridge CFStringRef) entitlement);
87 }
88
89 -(void)dealloc {
90 CFReleaseNull(self->_client.task);
91 CFReleaseNull(self->_client.accessGroups);
92 CFReleaseNull(self->_client.musr);
93 CFReleaseNull(self->_client.applicationIdentifier);
94 }
95 @end
96
97
98 // Class to use for local dispatching of securityd xpcs. Adds capability of fake entitlements, because you don't have a real task on the other end.
99 @interface LocalSecuritydXPCServer : SecuritydXPCServer
100 @property NSMutableDictionary<NSString*, id>* fakeEntitlements;
101 - (instancetype)initWithSecurityClient:(SecurityClient*) existingClient fakeEntitlements:(NSDictionary<NSString*, id>*)fakeEntitlements;
102 @end
103
104 @implementation LocalSecuritydXPCServer
105 - (instancetype)initWithSecurityClient:(SecurityClient*) existingClient fakeEntitlements:(NSDictionary<NSString*, id>*)fakeEntitlements {
106 if((self = [super initWithSecurityClient: existingClient])) {
107 _fakeEntitlements = [fakeEntitlements mutableCopy];
108 }
109 return self;
110 }
111
112 - (bool)clientHasBooleanEntitlement: (NSString*) entitlement {
113 if(self.fakeEntitlements) {
114 return [self.fakeEntitlements[entitlement] isEqual: @YES];
115 } else {
116 return false;
117 }
118 }
119 @end
120
121
122 #pragma mark - SecuritydXPCServerListener
123
124 // Responsible for bringing up new SecuritydXPCServer objects, and configuring them with their remote connection
125 @interface SecuritydXPCServerListener : NSObject <NSXPCListenerDelegate>
126 @property (retain,nonnull) NSXPCListener *listener;
127 @end
128
129 @implementation SecuritydXPCServerListener
130 -(instancetype)init
131 {
132 if((self = [super init])){
133 self.listener = [[NSXPCListener alloc] initWithMachServiceName:@(kSecuritydGeneralServiceName)];
134 self.listener.delegate = self;
135 [self.listener resume];
136 }
137 return self;
138 }
139
140 - (BOOL)listener:(__unused NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection
141 {
142 // Anyone is allowed to get a connection to securityd, except if you have kSecEntitlementKeychainDeny entitlement
143 // The SecuritydClient class _must_ check for required entitlements in each XPC handler.
144
145 if([newConnection valueForEntitlement: (__bridge NSString*) kSecEntitlementKeychainDeny]) {
146 return NO;
147 }
148
149 newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(SecuritydXPCProtocol)];
150 // Configure the interface on the server side, too
151 [SecuritydXPCClient configureSecuritydXPCProtocol: newConnection.exportedInterface];
152
153 newConnection.exportedObject = [[SecuritydXPCServer alloc] initWithConnection:newConnection];
154 [newConnection resume];
155
156 return YES;
157 }
158 @end
159
160 void
161 SecCreateSecuritydXPCServer(void)
162 {
163 static SecuritydXPCServerListener* listener = NULL;
164 static dispatch_once_t onceToken;
165 dispatch_once(&onceToken, ^{
166 @autoreleasepool {
167 listener = [[SecuritydXPCServerListener alloc] init];
168 }
169 });
170 }
171
172 id<SecuritydXPCProtocol> SecCreateLocalSecuritydXPCServer(void) {
173 // Create a fake securitydxpcserver using the access groups of securityd and some number of fake entitlements
174 SecurityClient* client = SecSecurityClientGet();
175
176 // We know that SecuritydXPCServerListener will comply with SecuritydXPCProtocol via category, so help the compiler out
177 return (id<SecuritydXPCProtocol>) [[LocalSecuritydXPCServer alloc] initWithSecurityClient: client fakeEntitlements: @{}];
178 }
179
180 CFTypeRef SecCreateLocalCFSecuritydXPCServer(void) {
181 return CFBridgingRetain(SecCreateLocalSecuritydXPCServer());
182 }
183
184 void SecResetLocalSecuritydXPCFakeEntitlements(void) {
185 if([(__bridge id) gSecurityd->secd_xpc_server isKindOfClass: [LocalSecuritydXPCServer class]]) {
186 LocalSecuritydXPCServer* server = (__bridge LocalSecuritydXPCServer*)gSecurityd->secd_xpc_server;
187 server.fakeEntitlements = [[NSMutableDictionary alloc] init];
188 }
189 }
190
191 void SecAddLocalSecuritydXPCFakeEntitlement(CFStringRef entitlement, CFTypeRef value) {
192 if([(__bridge id) gSecurityd->secd_xpc_server isKindOfClass: [LocalSecuritydXPCServer class]]) {
193 LocalSecuritydXPCServer* server = (__bridge LocalSecuritydXPCServer*)gSecurityd->secd_xpc_server;
194 server.fakeEntitlements[(__bridge NSString*)entitlement] = (__bridge id)value;
195 }
196 }