2 * Copyright (c) 2018 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
27 func sanitizeForClientXPC() -> Error {
28 let nserror = self as NSError
30 // CoreData errors might have extra things in them that need removal.
31 if nserror.domain == NSCocoaErrorDomain {
32 return nserror.cleanAllButDescription()
35 // The docs for CKXPCSuitableError say it only returns nil if you pass it nil, but swift can't read those.
36 guard let ckCleanedError = CKXPCSuitableError(self) else {
37 return ContainerError.unknownCloudKitError
44 func cleanAllButDescription() -> NSError {
45 let userInfo: [String: AnyHashable]?
46 if let description = self.userInfo[NSLocalizedDescriptionKey] as? AnyHashable {
47 userInfo = [NSLocalizedDescriptionKey: description]
52 return NSError(domain: self.domain,
58 class Client: TrustedPeersHelperProtocol {
60 let endpoint: NSXPCListenerEndpoint?
61 let containerMap: ContainerMap
63 init(endpoint: NSXPCListenerEndpoint?, containerMap: ContainerMap) {
64 self.endpoint = endpoint
65 self.containerMap = containerMap
68 func ping(reply: @escaping (() -> Void)) {
72 func logComplete(function: String, container: ContainerName, error: Error?) {
73 if let error = error {
74 os_log("%{public}@ errored for %{public}@: %{public}@", log: tplogDebug, type: .default, function, container.description, error as CVarArg)
76 os_log("%{public}@ finished for %{public}@", log: tplogDebug, type: .default, function, container.description)
80 internal func getContainer(withContainer container: String, context: String) throws -> Container {
81 let containerName = ContainerName(container: container, context: context)
82 return try self.containerMap.findOrCreate(name: containerName)
85 func dump(withContainer container: String, context: String, reply: @escaping ([AnyHashable: Any]?, Error?) -> Void) {
87 let containerName = ContainerName(container: container, context: context)
88 os_log("Dumping for %{public}@", log: tplogDebug, type: .default, containerName.description)
89 let container = try self.containerMap.findOrCreate(name: containerName)
90 container.dump { result, error in
91 self.logComplete(function: "Dumping", container: container.name, error: error)
92 reply(result, error?.sanitizeForClientXPC())
95 os_log("Dumping failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
96 reply(nil, error.sanitizeForClientXPC())
100 func dumpEgoPeer(withContainer container: String,
102 reply: @escaping (String?, TPPeerPermanentInfo?, TPPeerStableInfo?, TPPeerDynamicInfo?, Error?) -> Void) {
104 let containerName = ContainerName(container: container, context: context)
105 os_log("Dumping peer for %{public}@", log: tplogDebug, type: .default, containerName.description)
106 let container = try self.containerMap.findOrCreate(name: containerName)
107 container.dumpEgoPeer { peerID, perm, stable, dyn, error in
108 self.logComplete(function: "Dumping peer", container: container.name, error: error)
109 reply(peerID, perm, stable, dyn, error?.sanitizeForClientXPC())
112 os_log("Dumping peer failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
113 reply(nil, nil, nil, nil, error.sanitizeForClientXPC())
117 func trustStatus(withContainer container: String, context: String, reply: @escaping (TrustedPeersHelperEgoPeerStatus, Error?) -> Void) {
119 let containerName = ContainerName(container: container, context: context)
120 let container = try self.containerMap.findOrCreate(name: containerName)
121 container.trustStatus { egoPeerStatus, error in
122 reply(egoPeerStatus, error?.sanitizeForClientXPC())
125 os_log("Trust status failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
126 reply(TrustedPeersHelperEgoPeerStatus(egoPeerID: nil,
127 status: TPPeerStatus.unknown,
128 viablePeerCountsByModelID: [:],
129 peerCountsByMachineID: [:],
132 error.sanitizeForClientXPC())
136 func fetchTrustState(withContainer container: String, context: String, reply: @escaping (TrustedPeersHelperPeerState?, [TrustedPeersHelperPeer]?, Error?) -> Void) {
138 let containerName = ContainerName(container: container, context: context)
139 os_log("Fetch Trust State for %{public}@", log: tplogDebug, type: .default, containerName.description)
140 let container = try self.containerMap.findOrCreate(name: containerName)
141 container.fetchTrustState { peerState, peerList, error in
142 reply(peerState, peerList, error?.sanitizeForClientXPC())
145 os_log("Fetch Trust State failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
146 reply(nil, nil, error.sanitizeForClientXPC())
150 func reset(withContainer container: String, context: String, resetReason: CuttlefishResetReason, reply: @escaping (Error?) -> Void) {
152 let containerName = ContainerName(container: container, context: context)
153 os_log("Resetting for %{public}@", log: tplogDebug, type: .default, containerName.description)
154 let container = try self.containerMap.findOrCreate(name: containerName)
155 container.reset(resetReason: resetReason) { error in
156 self.logComplete(function: "Resetting", container: container.name, error: error)
157 reply(error?.sanitizeForClientXPC()) }
159 os_log("Resetting failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
160 reply(error.sanitizeForClientXPC())
164 func localReset(withContainer container: String, context: String, reply: @escaping (Error?) -> Void) {
166 let containerName = ContainerName(container: container, context: context)
167 os_log("Performing local reset for %{public}@", log: tplogDebug, type: .default, containerName.description)
168 let container = try self.containerMap.findOrCreate(name: containerName)
169 container.localReset { error in
170 self.logComplete(function: "Local reset", container: container.name, error: error)
171 reply(error?.sanitizeForClientXPC())
174 os_log("Local reset failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
175 reply(error.sanitizeForClientXPC())
179 func setAllowedMachineIDsWithContainer(_ container: String,
181 allowedMachineIDs: Set<String>,
182 honorIDMSListChanges: Bool,
183 reply: @escaping (Bool, Error?) -> Void) {
185 let containerName = ContainerName(container: container, context: context)
186 os_log("Setting allowed machineIDs for %{public}@ to %{public}@", log: tplogDebug, type: .default, containerName.description, allowedMachineIDs)
187 let container = try self.containerMap.findOrCreate(name: containerName)
188 container.setAllowedMachineIDs(allowedMachineIDs, honorIDMSListChanges: honorIDMSListChanges) { differences, error in
189 self.logComplete(function: "Setting allowed machineIDs", container: container.name, error: error)
190 reply(differences, error?.sanitizeForClientXPC())
193 os_log("Setting allowed machineIDs failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
194 reply(false, error.sanitizeForClientXPC())
198 func addAllowedMachineIDs(withContainer container: String,
200 machineIDs: [String],
201 reply: @escaping (Error?) -> Void) {
203 let containerName = ContainerName(container: container, context: context)
204 os_log("Adding allowed machineIDs for %{public}@: %{public}@", log: tplogDebug, type: .default, containerName.description, machineIDs)
205 let container = try self.containerMap.findOrCreate(name: containerName)
206 container.addAllow(machineIDs) { error in
207 self.logComplete(function: "Adding allowed machineIDs", container: container.name, error: error)
208 reply(error?.sanitizeForClientXPC())
211 os_log("Adding allowed machineID failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
212 reply(error.sanitizeForClientXPC())
216 func removeAllowedMachineIDs(withContainer container: String,
218 machineIDs: [String],
219 reply: @escaping (Error?) -> Void) {
221 let containerName = ContainerName(container: container, context: context)
222 os_log("Removing allowed machineIDs for %{public}@: %{public}@", log: tplogDebug, type: .default, containerName.description, machineIDs)
223 let container = try self.containerMap.findOrCreate(name: containerName)
224 container.removeAllow(machineIDs) { error in
225 self.logComplete(function: "Removing allowed machineIDs", container: container.name, error: error)
226 reply(error?.sanitizeForClientXPC())
229 os_log("Removing allowed machineID failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
230 reply(error.sanitizeForClientXPC())
234 func fetchAllowedMachineIDs(withContainer container: String, context: String, reply: @escaping (Set<String>?, Error?) -> Void) {
236 let containerName = ContainerName(container: container, context: context)
237 os_log("Fetching allowed machineIDs for %{public}@", log: tplogDebug, type: .default, containerName.description)
238 let container = try self.containerMap.findOrCreate(name: containerName)
239 container.fetchAllowedMachineIDs { mids, error in
240 self.logComplete(function: "Fetched allowed machineIDs", container: container.name, error: error)
241 reply(mids, error?.sanitizeForClientXPC())
244 os_log("Fetching allowed machineIDs failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
245 reply(nil, error.sanitizeForClientXPC())
249 func fetchEgoEpoch(withContainer container: String, context: String, reply: @escaping (UInt64, Error?) -> Void) {
251 let containerName = ContainerName(container: container, context: context)
252 os_log("retrieving epoch for %{public}@", log: tplogDebug, type: .default, containerName.description)
253 let container = try self.containerMap.findOrCreate(name: containerName)
254 container.getEgoEpoch { epoch, error in
255 reply(epoch, error?.sanitizeForClientXPC())
258 os_log("Epoch retrieval failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
259 reply(0, error.sanitizeForClientXPC())
263 func prepare(withContainer container: String,
271 serialNumber: String?,
273 policyVersion: TPPolicyVersion?,
274 policySecrets: [String: Data]?,
275 syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus,
276 signingPrivKeyPersistentRef: Data?,
277 encPrivKeyPersistentRef: Data?,
278 reply: @escaping (String?, Data?, Data?, Data?, Data?, TPSyncingPolicy?, Error?) -> Void) {
280 let containerName = ContainerName(container: container, context: context)
281 os_log("Preparing new identity for %{public}@", log: tplogDebug, type: .default, containerName.description)
282 let container = try self.containerMap.findOrCreate(name: containerName)
283 container.prepare(epoch: epoch,
284 machineID: machineID,
285 bottleSalt: bottleSalt,
288 deviceName: deviceName,
289 serialNumber: serialNumber,
290 osVersion: osVersion,
291 policyVersion: policyVersion,
292 policySecrets: policySecrets,
293 syncUserControllableViews: syncUserControllableViews,
294 signingPrivateKeyPersistentRef: signingPrivKeyPersistentRef,
295 encryptionPrivateKeyPersistentRef: encPrivKeyPersistentRef) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, policy, error in
296 self.logComplete(function: "Prepare", container: container.name, error: error)
297 reply(peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, policy, error?.sanitizeForClientXPC())
300 os_log("Prepare failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
301 reply(nil, nil, nil, nil, nil, nil, error.sanitizeForClientXPC())
305 func establish(withContainer container: String,
307 ckksKeys: [CKKSKeychainBackedKeySet],
308 tlkShares: [CKKSTLKShare],
309 preapprovedKeys: [Data]?,
310 reply: @escaping (String?, [CKRecord]?, TPSyncingPolicy?, Error?) -> Void) {
312 let containerName = ContainerName(container: container, context: context)
313 os_log("Establishing %{public}@", log: tplogDebug, type: .default, containerName.description)
314 let container = try self.containerMap.findOrCreate(name: containerName)
315 container.establish(ckksKeys: ckksKeys,
316 tlkShares: tlkShares,
317 preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, policy, error in
318 self.logComplete(function: "Establishing", container: container.name, error: error)
319 reply(peerID, keyHierarchyRecords, policy, error?.sanitizeForClientXPC()) }
321 os_log("Establishing failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
322 reply(nil, nil, nil, error.sanitizeForClientXPC())
326 func vouch(withContainer container: String,
330 permanentInfoSig: Data,
333 ckksKeys: [CKKSKeychainBackedKeySet],
334 reply: @escaping (Data?, Data?, Error?) -> Void) {
336 let containerName = ContainerName(container: container, context: context)
337 os_log("Vouching %{public}@", log: tplogDebug, type: .default, containerName.description)
338 let container = try self.containerMap.findOrCreate(name: containerName)
339 container.vouch(peerID: peerID,
340 permanentInfo: permanentInfo,
341 permanentInfoSig: permanentInfoSig,
342 stableInfo: stableInfo,
343 stableInfoSig: stableInfoSig,
344 ckksKeys: ckksKeys) { voucher, voucherSig, error in
345 self.logComplete(function: "Vouching", container: container.name, error: error)
346 reply(voucher, voucherSig, error?.sanitizeForClientXPC()) }
348 os_log("Vouching failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
349 reply(nil, nil, error.sanitizeForClientXPC())
353 func preflightVouchWithBottle(withContainer container: String,
356 reply: @escaping (String?, TPSyncingPolicy?, Bool, Error?) -> Void) {
358 let containerName = ContainerName(container: container, context: context)
359 os_log("Preflight Vouch With Bottle %{public}@", log: tplogDebug, type: .default, containerName.description)
360 let container = try self.containerMap.findOrCreate(name: containerName)
361 container.preflightVouchWithBottle(bottleID: bottleID) { peerID, policy, refetched, error in
362 self.logComplete(function: "Preflight Vouch With Bottle", container: container.name, error: error)
363 reply(peerID, policy, refetched, error?.sanitizeForClientXPC()) }
365 os_log("Preflighting Vouch With Bottle failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
366 reply(nil, nil, false, error.sanitizeForClientXPC())
370 func vouchWithBottle(withContainer container: String,
375 tlkShares: [CKKSTLKShare],
376 reply: @escaping (Data?, Data?, Int64, Int64, Error?) -> Void) {
378 let containerName = ContainerName(container: container, context: context)
379 os_log("Vouching With Bottle %{public}@", log: tplogDebug, type: .default, containerName.description)
380 let container = try self.containerMap.findOrCreate(name: containerName)
381 container.vouchWithBottle(bottleID: bottleID, entropy: entropy, bottleSalt: bottleSalt, tlkShares: tlkShares) { voucher, voucherSig, uniqueTLKsRecovered, totalTLKSharesRecovered, error in
382 self.logComplete(function: "Vouching With Bottle", container: container.name, error: error)
383 reply(voucher, voucherSig, uniqueTLKsRecovered, totalTLKSharesRecovered, error?.sanitizeForClientXPC()) }
385 os_log("Vouching with Bottle failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
386 reply(nil, nil, 0, 0, error.sanitizeForClientXPC())
390 func preflightVouchWithRecoveryKey(withContainer container: String,
394 reply: @escaping (String?, TPSyncingPolicy?, Error?) -> Void) {
396 let containerName = ContainerName(container: container, context: context)
397 os_log("Preflight Vouch With RecoveryKey %{public}@", log: tplogDebug, type: .default, containerName.description)
398 let container = try self.containerMap.findOrCreate(name: containerName)
399 container.preflightVouchWithRecoveryKey(recoveryKey: recoveryKey, salt: salt) { rkID, policy, error in
400 self.logComplete(function: "Preflight Vouch With RecoveryKey", container: container.name, error: error)
401 reply(rkID, policy, error?.sanitizeForClientXPC()) }
403 os_log("Preflighting Vouch With RecoveryKey failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
404 reply(nil, nil, error.sanitizeForClientXPC())
408 func vouchWithRecoveryKey(withContainer container: String,
412 tlkShares: [CKKSTLKShare],
413 reply: @escaping (Data?, Data?, Error?) -> Void) {
415 let containerName = ContainerName(container: container, context: context)
416 os_log("Vouching With Recovery Key %{public}@", log: tplogDebug, type: .default, containerName.description)
417 let container = try self.containerMap.findOrCreate(name: containerName)
418 container.vouchWithRecoveryKey(recoveryKey: recoveryKey, salt: salt, tlkShares: tlkShares) { voucher, voucherSig, error in
419 self.logComplete(function: "Vouching With Recovery Key", container: container.name, error: error)
420 reply(voucher, voucherSig, error?.sanitizeForClientXPC()) }
422 os_log("Vouching with Recovery Key failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
423 reply(nil, nil, error.sanitizeForClientXPC())
427 func join(withContainer container: String,
431 ckksKeys: [CKKSKeychainBackedKeySet],
432 tlkShares: [CKKSTLKShare],
433 preapprovedKeys: [Data]?,
434 reply: @escaping (String?, [CKRecord]?, TPSyncingPolicy?, Error?) -> Void) {
436 let containerName = ContainerName(container: container, context: context)
437 os_log("Joining %{public}@", log: tplogDebug, type: .default, containerName.description)
438 let container = try self.containerMap.findOrCreate(name: containerName)
439 container.join(voucherData: voucherData,
440 voucherSig: voucherSig,
442 tlkShares: tlkShares,
443 preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, policy, error in
444 reply(peerID, keyHierarchyRecords, policy, error?.sanitizeForClientXPC())
447 os_log("Joining failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
448 reply(nil, nil, nil, error.sanitizeForClientXPC())
452 func preflightPreapprovedJoin(withContainer container: String,
454 preapprovedKeys: [Data]?,
455 reply: @escaping (Bool, Error?) -> Void) {
457 let containerName = ContainerName(container: container, context: context)
458 os_log("Attempting to preflight a preapproved join for %{public}@", log: tplogDebug, type: .default, containerName.description)
459 let container = try self.containerMap.findOrCreate(name: containerName)
460 container.preflightPreapprovedJoin(preapprovedKeys: preapprovedKeys) { success, error in reply(success, error?.sanitizeForClientXPC()) }
462 os_log("preflightPreapprovedJoin failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
463 reply(false, error.sanitizeForClientXPC())
467 func attemptPreapprovedJoin(withContainer container: String,
469 ckksKeys: [CKKSKeychainBackedKeySet],
470 tlkShares: [CKKSTLKShare],
471 preapprovedKeys: [Data]?,
472 reply: @escaping (String?, [CKRecord]?, TPSyncingPolicy?, Error?) -> Void) {
474 let containerName = ContainerName(container: container, context: context)
475 os_log("Attempting a preapproved join for %{public}@", log: tplogDebug, type: .default, containerName.description)
476 let container = try self.containerMap.findOrCreate(name: containerName)
477 container.preapprovedJoin(ckksKeys: ckksKeys,
478 tlkShares: tlkShares,
479 preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, policy, error in
480 reply(peerID, keyHierarchyRecords, policy, error?.sanitizeForClientXPC()) }
482 os_log("attemptPreapprovedJoin failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
483 reply(nil, nil, nil, error.sanitizeForClientXPC())
487 func update(withContainer container: String,
490 serialNumber: String?,
492 policyVersion: NSNumber?,
493 policySecrets: [String: Data]?,
494 syncUserControllableViews: NSNumber?,
495 reply: @escaping (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) -> Void) {
497 let containerName = ContainerName(container: container, context: context)
498 os_log("Updating %{public}@", log: tplogDebug, type: .default, containerName.description)
499 let container = try self.containerMap.findOrCreate(name: containerName)
501 let syncUserControllableSetting: TPPBPeerStableInfo_UserControllableViewStatus?
502 if let value = syncUserControllableViews?.int32Value {
504 case TPPBPeerStableInfo_UserControllableViewStatus.ENABLED.rawValue:
505 syncUserControllableSetting = .ENABLED
506 case TPPBPeerStableInfo_UserControllableViewStatus.DISABLED.rawValue:
507 syncUserControllableSetting = .DISABLED
508 case TPPBPeerStableInfo_UserControllableViewStatus.FOLLOWING.rawValue:
509 syncUserControllableSetting = .FOLLOWING
511 throw ContainerError.unknownSyncUserControllableViewsValue(value: value)
514 syncUserControllableSetting = nil
517 container.update(deviceName: deviceName,
518 serialNumber: serialNumber,
519 osVersion: osVersion,
520 policyVersion: policyVersion?.uint64Value,
521 policySecrets: policySecrets,
522 syncUserControllableViews: syncUserControllableSetting) { state, policy, error in reply(state, policy, error?.sanitizeForClientXPC()) }
524 os_log("update failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
525 reply(nil, nil, error.sanitizeForClientXPC())
529 func setPreapprovedKeysWithContainer(_ container: String,
531 preapprovedKeys: [Data],
532 reply: @escaping (TrustedPeersHelperPeerState?, Error?) -> Void) {
534 let containerName = ContainerName(container: container, context: context)
535 os_log("setPreapprovedKeysWithContainer %{public}@", log: tplogDebug, type: .default, containerName.description)
536 let container = try self.containerMap.findOrCreate(name: containerName)
537 container.set(preapprovedKeys: preapprovedKeys) { state, error in reply(state, error?.sanitizeForClientXPC()) }
539 os_log("setPreapprovedKeysWithContainer failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
540 reply(nil, error.sanitizeForClientXPC())
544 func updateTLKs(withContainer container: String,
546 ckksKeys: [CKKSKeychainBackedKeySet],
547 tlkShares: [CKKSTLKShare],
548 reply: @escaping ([CKRecord]?, Error?) -> Void) {
550 let containerName = ContainerName(container: container, context: context)
551 os_log("Updating TLKs for %{public}@", log: tplogDebug, type: .default, containerName.description)
552 let container = try self.containerMap.findOrCreate(name: containerName)
553 container.updateTLKs(ckksKeys: ckksKeys,
554 tlkShares: tlkShares) { records, error in
555 reply(records, error?.sanitizeForClientXPC())
558 os_log("updateTLKs failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
559 reply(nil, error.sanitizeForClientXPC())
563 func departByDistrustingSelf(withContainer container: String,
565 reply: @escaping (Error?) -> Void) {
567 let containerName = ContainerName(container: container, context: context)
568 os_log("Departing %{public}@", log: tplogDebug, type: .default, containerName.description)
569 let container = try self.containerMap.findOrCreate(name: containerName)
570 container.departByDistrustingSelf { error in
571 reply(error?.sanitizeForClientXPC())
574 os_log("departByDistrustingSelf failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
575 reply(error.sanitizeForClientXPC())
579 func distrustPeerIDs(withContainer container: String,
581 peerIDs: Set<String>,
582 reply: @escaping (Error?) -> Void) {
584 let containerName = ContainerName(container: container, context: context)
585 os_log("Distrusting %{public}@ in %{public}@", log: tplogDebug, type: .default, peerIDs, containerName.description)
586 let container = try self.containerMap.findOrCreate(name: containerName)
587 container.distrust(peerIDs: peerIDs) { error in
588 reply(error?.sanitizeForClientXPC())
591 os_log("distrustPeerIDs failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
592 reply(error.sanitizeForClientXPC())
596 func fetchViableBottles(withContainer container: String, context: String, reply: @escaping ([String]?, [String]?, Error?) -> Void) {
598 let containerName = ContainerName(container: container, context: context)
599 os_log("fetchViableBottles in %{public}@", log: tplogDebug, type: .default, containerName.description)
600 let container = try self.containerMap.findOrCreate(name: containerName)
601 container.fetchViableBottles { sortedBottleIDs, partialBottleIDs, error in
602 reply(sortedBottleIDs, partialBottleIDs, error?.sanitizeForClientXPC())
605 os_log("fetchViableBottles failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
606 reply(nil, nil, error.sanitizeForClientXPC())
610 func fetchViableEscrowRecords(withContainer container: String, context: String, forceFetch: Bool, reply: @escaping ([Data]?, Error?) -> Void) {
612 let containerName = ContainerName(container: container, context: context)
613 os_log("fetchViableEscrowRecords in %@", log: tplogDebug, type: .default, containerName.description)
614 let container = try self.containerMap.findOrCreate(name: containerName)
615 container.fetchEscrowRecords(forceFetch: forceFetch) { recordDatas, error in
616 reply(recordDatas, error?.sanitizeForClientXPC())
619 reply(nil, error.sanitizeForClientXPC())
623 func fetchEscrowContents(withContainer container: String, context: String, reply: @escaping (Data?, String?, Data?, Error?) -> Void) {
625 let containerName = ContainerName(container: container, context: context)
626 os_log("fetchEscrowContents in %{public}@", log: tplogDebug, type: .default, containerName.description)
627 let container = try self.containerMap.findOrCreate(name: containerName)
628 container.fetchEscrowContents { entropy, bottleID, signingPublicKey, error in
629 reply(entropy, bottleID, signingPublicKey, error?.sanitizeForClientXPC())
632 os_log("fetchEscrowContents failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
633 reply(nil, nil, nil, error.sanitizeForClientXPC())
637 func fetchCurrentPolicy(withContainer container: String,
639 modelIDOverride: String?,
640 reply: @escaping (TPSyncingPolicy?, TPPBPeerStableInfo_UserControllableViewStatus, Error?) -> Void) {
642 let containerName = ContainerName(container: container, context: context)
643 os_log("Fetching policy+views for %{public}@", log: tplogDebug, type: .default, containerName.description)
644 let container = try self.containerMap.findOrCreate(name: containerName)
645 container.fetchCurrentPolicy(modelIDOverride: modelIDOverride) { policy, peersOpinion, error in
646 reply(policy, peersOpinion, error?.sanitizeForClientXPC())
649 os_log("fetchCurrentPolicy failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
650 reply(nil, .UNKNOWN, error.sanitizeForClientXPC())
654 func fetchPolicyDocuments(withContainer container: String,
656 versions: Set<TPPolicyVersion>,
657 reply: @escaping ([TPPolicyVersion: Data]?, Error?) -> Void) {
659 let containerName = ContainerName(container: container, context: context)
660 os_log("Fetching policy documents %{public}@ with versions: %{public}@", log: tplogDebug, type: .default, containerName.description, versions)
661 let container = try self.containerMap.findOrCreate(name: containerName)
662 container.fetchPolicyDocuments(versions: versions) { entries, error in
663 reply(entries, error?.sanitizeForClientXPC())
666 os_log("fetchPolicyDocuments failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
667 reply(nil, error.sanitizeForClientXPC())
671 func validatePeers(withContainer container: String, context: String, reply: @escaping ([AnyHashable: Any]?, Error?) -> Void) {
673 let containerName = ContainerName(container: container, context: context)
674 os_log("ValidatePeers for %{public}@", log: tplogDebug, type: .default, containerName.description)
675 let container = try self.containerMap.findOrCreate(name: containerName)
676 let request = ValidatePeersRequest()
677 container.validatePeers(request: request) { result, error in
678 self.logComplete(function: "validatePeers", container: container.name, error: error)
679 reply(result, error?.sanitizeForClientXPC())
682 os_log("ValidatePeers failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
683 reply(nil, error.sanitizeForClientXPC())
687 func setRecoveryKeyWithContainer(_ container: String,
691 ckksKeys: [CKKSKeychainBackedKeySet],
692 reply: @escaping ([CKRecord]?, Error?) -> Void) {
694 let containerName = ContainerName(container: container, context: context)
695 os_log("SetRecoveryKey for %{public}@", log: tplogDebug, type: .default, containerName.description)
696 let container = try self.containerMap.findOrCreate(name: containerName)
697 container.setRecoveryKey(recoveryKey: recoveryKey, salt: salt, ckksKeys: ckksKeys) { records, error in
698 self.logComplete(function: "setRecoveryKey", container: container.name, error: error)
699 reply(records, error?.sanitizeForClientXPC())
702 os_log("SetRecoveryKey failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
703 reply(nil, error.sanitizeForClientXPC())
707 func reportHealth(withContainer container: String, context: String, stateMachineState: String, trustState: String, reply: @escaping (Error?) -> Void) {
709 let containerName = ContainerName(container: container, context: context)
710 os_log("ReportHealth for %{public}@", log: tplogDebug, type: .default, containerName.description)
711 let container = try self.containerMap.findOrCreate(name: containerName)
712 let request = ReportHealthRequest.with {
713 $0.stateMachineState = stateMachineState
715 container.reportHealth(request: request) { error in
716 self.logComplete(function: "reportHealth", container: container.name, error: error)
717 reply(error?.sanitizeForClientXPC())
720 os_log("ReportHealth failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
721 reply(error.sanitizeForClientXPC())
725 func pushHealthInquiry(withContainer container: String, context: String, reply: @escaping (Error?) -> Void) {
727 let containerName = ContainerName(container: container, context: context)
728 os_log("PushHealthInquiry for %{public}@", log: tplogDebug, type: .default, containerName.description)
729 let container = try self.containerMap.findOrCreate(name: containerName)
730 container.pushHealthInquiry { error in
731 self.logComplete(function: "pushHealthInquiry", container: container.name, error: error)
732 reply(error?.sanitizeForClientXPC())
735 os_log("PushHealthInquiry failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
736 reply(error.sanitizeForClientXPC())
740 func requestHealthCheck(withContainer container: String, context: String, requiresEscrowCheck: Bool, reply: @escaping (Bool, Bool, Bool, Bool, Error?) -> Void) {
742 let containerName = ContainerName(container: container, context: context)
743 os_log("Health Check! requiring escrow check? %d for %{public}@", log: tplogDebug, type: .default, requiresEscrowCheck, containerName.description)
744 let container = try self.containerMap.findOrCreate(name: containerName)
745 container.requestHealthCheck(requiresEscrowCheck: requiresEscrowCheck) { postRepair, postEscrow, postReset, leaveTrust, error in
746 reply(postRepair, postEscrow, postReset, leaveTrust, error?.sanitizeForClientXPC())
749 os_log("Health Check! failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
750 reply(false, false, false, false, error.sanitizeForClientXPC())
754 func getSupportAppInfo(withContainer container: String, context: String, reply: @escaping (Data?, Error?) -> Void) {
756 let containerName = ContainerName(container: container, context: context)
757 os_log("getSupportAppInfo for %{public}@", log: tplogDebug, type: .default, containerName.description)
758 let container = try self.containerMap.findOrCreate(name: containerName)
759 container.getSupportAppInfo { info, error in
760 reply(info, error?.sanitizeForClientXPC())
763 os_log("getSupportInfo failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
764 reply(nil, error.sanitizeForClientXPC())
767 func removeEscrowCache(withContainer container: String, context: String, reply: @escaping (Error?) -> Void) {
769 let containerName = ContainerName(container: container, context: context)
770 os_log("removeEscrowCache for %{public}@", log: tplogDebug, type: .default, containerName.description)
771 let container = try self.containerMap.findOrCreate(name: containerName)
772 container.removeEscrowCache { error in
773 reply(error?.sanitizeForClientXPC())
776 os_log("removeEscrowCache failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
777 reply(error.sanitizeForClientXPC())