]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSControlServer.m
6412bad32f36cf7855021f7a1216c2c45b1a10c8
[apple/security.git] / keychain / SecureObjectSync / SOSControlServer.m
1 #import <Foundation/Foundation.h>
2 #import <Foundation/NSXPCConnection_Private.h>
3 #import <Security/SecEntitlements.h>
4 #import <ipc/securityd_client.h>
5 #import "SOSAccount.h"
6 #import "SOSControlHelper.h"
7 #import "SOSControlServer.h"
8
9 @interface SOSControlServer : NSObject <NSXPCListenerDelegate>
10 @end
11
12 @interface SOSClient ()
13 @property (strong) SOSAccount * account;
14 - (instancetype)initSOSClientWithAccount:(SOSAccount *)account;
15 - (bool)checkEntitlement:(NSString *)entitlement;
16 @end
17
18 @interface SOSClientRemote : SOSClient
19 @property (weak) NSXPCConnection * connection;
20 - (instancetype)initSOSConnectionWithConnection:(NSXPCConnection *)connection account:(SOSAccount *)account;
21 @end
22
23 @implementation SOSControlServer
24
25 - (BOOL)listener:(__unused NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection
26 {
27 NSNumber *num = [newConnection valueForEntitlement:(__bridge NSString *)kSecEntitlementKeychainCloudCircle];
28 if (![num isKindOfClass:[NSNumber class]] || ![num boolValue]) {
29 secerror("sos: Client pid: %d doesn't have entitlement: %@",
30 [newConnection processIdentifier], kSecEntitlementKeychainCloudCircle);
31 return NO;
32 }
33
34 SOSClientRemote *sosClient = [[SOSClientRemote alloc] initSOSConnectionWithConnection:newConnection account:(__bridge SOSAccount *)SOSKeychainAccountGetSharedAccount()];
35
36 newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(SOSControlProtocol)];
37 _SOSControlSetupInterface(newConnection.exportedInterface);
38 newConnection.exportedObject = sosClient;
39
40 [newConnection resume];
41
42 return YES;
43 }
44
45 - (SOSClient *)internalSOSClient
46 {
47 return [[SOSClient alloc] initSOSClientWithAccount:(__bridge SOSAccount *)SOSKeychainAccountGetSharedAccount()];
48 }
49
50 @end
51
52 @implementation SOSClient
53
54 @synthesize account = _account;
55
56 - (instancetype)initSOSClientWithAccount:(SOSAccount *)account
57 {
58 if ((self = [super init])) {
59 _account = account;
60 }
61 return self;
62 }
63
64 - (bool)checkEntitlement:(NSString *)entitlement
65 {
66 return true;
67 }
68
69 - (void)userPublicKey:(void ((^))(BOOL trusted, NSData *spki, NSError *error))reply
70 {
71 [self.account userPublicKey:reply];
72 }
73
74 - (void)kvsPerformanceCounters:(void(^)(NSDictionary <NSString *, NSNumber *> *))reply
75 {
76 [self.account kvsPerformanceCounters:reply];
77 }
78
79 - (void)rateLimitingPerformanceCounters:(void(^)(NSDictionary <NSString *, NSString *> *))reply
80 {
81 [self.account rateLimitingPerformanceCounters:reply];
82 }
83
84 - (void)stashedCredentialPublicKey:(void(^)(NSData *, NSError *error))reply
85 {
86 [self.account stashedCredentialPublicKey:reply];
87 }
88
89 - (void)assertStashedAccountCredential:(void(^)(BOOL result, NSError *error))reply
90 {
91 [self.account assertStashedAccountCredential:reply];
92 }
93
94 - (void)validatedStashedAccountCredential:(void(^)(NSData *credential, NSError *error))complete
95 {
96 [self.account validatedStashedAccountCredential:complete];
97 }
98
99 - (void)stashAccountCredential:(NSData *)credential complete:(void(^)(bool success, NSError *error))complete
100 {
101 [self.account stashAccountCredential:credential complete:complete];
102 }
103
104 - (void)myPeerInfo:(void (^)(NSData *, NSError *))complete
105 {
106 [self.account myPeerInfo:complete];
107 }
108
109 - (void)circleHash:(void (^)(NSString *, NSError *))complete
110 {
111 [self.account circleHash:complete];
112 }
113
114
115 - (void)circleJoiningBlob:(NSData *)applicant complete:(void (^)(NSData *blob, NSError *))complete
116 {
117 [self.account circleJoiningBlob:applicant complete:complete];
118 }
119
120 - (void)joinCircleWithBlob:(NSData *)blob version:(PiggyBackProtocolVersion)version complete:(void (^)(bool success, NSError *))complete
121 {
122 [self.account joinCircleWithBlob:blob version:version complete:complete];
123 }
124
125 - (void)initialSyncCredentials:(uint32_t)flags complete:(void (^)(NSArray *, NSError *))complete
126 {
127 if (![self checkEntitlement:(__bridge NSString *)kSecEntitlementKeychainInitialSync]) {
128 complete(@[], [NSError errorWithDomain:(__bridge NSString *)kSOSErrorDomain code:kSOSEntitlementMissing userInfo:NULL]);
129 return;
130 }
131
132 [self.account initialSyncCredentials:flags complete:complete];
133 }
134
135 - (void)importInitialSyncCredentials:(NSArray *)items complete:(void (^)(bool success, NSError *))complete
136 {
137 if (![self checkEntitlement:(__bridge NSString *)kSecEntitlementKeychainInitialSync]) {
138 complete(false, [NSError errorWithDomain:(__bridge NSString *)kSOSErrorDomain code:kSOSEntitlementMissing userInfo:NULL]);
139 return;
140 }
141
142 [self.account importInitialSyncCredentials:items complete:complete];
143 }
144
145 - (void)triggerSync:(NSArray <NSString *> *)peers complete:(void(^)(bool success, NSError *))complete
146 {
147 if (![self checkEntitlement:(__bridge NSString *)kSecEntitlementKeychainCloudCircle]) {
148 complete(false, [NSError errorWithDomain:(__bridge NSString *)kSOSErrorDomain code:kSOSEntitlementMissing userInfo:NULL]);
149 return;
150 }
151
152 [self.account triggerSync:peers complete:complete];
153 }
154
155 - (void)getWatchdogParameters:(void (^)(NSDictionary* parameters, NSError* error))complete
156 {
157 [self.account getWatchdogParameters:complete];
158 }
159
160 - (void)setWatchdogParmeters:(NSDictionary*)parameters complete:(void (^)(NSError* error))complete
161 {
162 [self.account setWatchdogParmeters:parameters complete:complete];
163 }
164
165 - (void) ghostBust:(SOSAccountGhostBustingOptions)options complete: (void(^)(bool ghostBusted, NSError *error))complete {
166 [self.account ghostBust:options complete:complete];
167 }
168
169 - (void)ghostBustTriggerTimed:(SOSAccountGhostBustingOptions)options complete: (void(^)(bool ghostBusted, NSError *error))complete {
170 [self.account ghostBustTriggerTimed:options complete:complete];
171 }
172
173 - (void) ghostBustPeriodic:(SOSAccountGhostBustingOptions)options complete: (void(^)(bool busted, NSError *error))complete {
174 [self.account ghostBustPeriodic:options complete:complete];
175 }
176
177 - (void) ghostBustInfo: (void(^)(NSData *json, NSError *error))complete {
178 [self.account ghostBustInfo:complete];
179 }
180
181 @end
182
183 @implementation SOSClientRemote
184
185 - (instancetype)initSOSConnectionWithConnection:(NSXPCConnection *)connection account:(SOSAccount *)account
186 {
187 self = [super initSOSClientWithAccount:account];
188 if (self) {
189 self.connection = connection;
190 }
191 return self;
192 }
193
194 - (bool)checkEntitlement:(NSString *)entitlement
195 {
196 NSXPCConnection *strongConnection = _connection;
197
198 NSNumber *num = [strongConnection valueForEntitlement:entitlement];
199 if (![num isKindOfClass:[NSNumber class]] || ![num boolValue]) {
200 secerror("sos: Client pid: %d doesn't have entitlement: %@",
201 [strongConnection processIdentifier], entitlement);
202 return false;
203 }
204 return true;
205 }
206 @end
207
208 static SOSControlServer *sosServer;
209
210 void
211 SOSControlServerInitialize(void)
212 {
213 static dispatch_once_t once;
214 static NSXPCListener *listener;
215
216 dispatch_once(&once, ^{
217 @autoreleasepool {
218 sosServer = [SOSControlServer new];
219
220 listener = [[NSXPCListener alloc] initWithMachServiceName:@(kSecuritydSOSServiceName)];
221 listener.delegate = sosServer;
222 [listener resume];
223 }
224 });
225 }
226
227 SOSClient *
228 SOSControlServerInternalClient(void)
229 {
230 SOSControlServerInitialize();
231 return [sosServer internalSOSClient];
232 }