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