]> git.saurik.com Git - apple/security.git/blob - keychain/TrustedPeersHelper/Container_BottledPeers.swift
Security-59306.101.1.tar.gz
[apple/security.git] / keychain / TrustedPeersHelper / Container_BottledPeers.swift
1 import CoreData
2 import Foundation
3
4 extension Container {
5 func preflightVouchWithBottle(bottleID: String,
6 reply: @escaping (String?, Set<String>?, TPPolicy?, Error?) -> Void) {
7 self.semaphore.wait()
8 let reply: (String?, Set<String>?, TPPolicy?, Error?) -> Void = {
9 os_log("preflightVouchWithBottle complete: %{public}@",
10 log: tplogTrace, type: .info, traceError($3))
11 self.semaphore.signal()
12 reply($0, $1, $2, $3)
13 }
14
15 self.fetchAndPersistChangesIfNeeded { fetchError in
16 guard fetchError == nil else {
17 os_log("preflightVouchWithBottle unable to fetch current peers: %{public}@", log: tplogDebug, type: .default, (fetchError as CVarArg?) ?? "")
18 reply(nil, nil, nil, fetchError)
19 return
20 }
21
22 // Ensure we have all policy versions claimed by peers, including our sponsor
23 let allPolicyVersions = self.model.allPolicyVersions()
24 self.fetchPolicyDocumentsWithSemaphore(versions: allPolicyVersions) { _, fetchPolicyDocumentsError in
25 guard fetchPolicyDocumentsError == nil else {
26 os_log("preflightVouchWithBottle unable to fetch policy documents: %{public}@", log: tplogDebug, type: .default, (fetchPolicyDocumentsError as CVarArg?) ?? "no error")
27 reply(nil, nil, nil, fetchPolicyDocumentsError)
28 return
29 }
30
31 self.moc.performAndWait {
32 guard let egoPeerID = self.containerMO.egoPeerID,
33 let egoPermData = self.containerMO.egoPeerPermanentInfo,
34 let egoPermSig = self.containerMO.egoPeerPermanentInfoSig else {
35 os_log("fetchCurrentPolicy failed to find ego peer information", log: tplogDebug, type: .error)
36 reply(nil, nil, nil, ContainerError.noPreparedIdentity)
37 return
38 }
39
40 let keyFactory = TPECPublicKeyFactory()
41 guard let egoPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else {
42 os_log("fetchCurrentPolicy failed to create TPPeerPermanentInfo", log: tplogDebug, type: .error)
43 reply(nil, nil, nil, ContainerError.invalidPermanentInfoOrSig)
44 return
45 }
46
47 self.onqueueFindBottle(bottleID: bottleID) { bottleMO, error in
48 guard let bottleMO = bottleMO else {
49 os_log("preflightVouchWithBottle found no bottle: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "")
50 reply(nil, nil, nil, error)
51 return
52 }
53
54 guard let sponsorPeer = self.model.peer(withID: bottleMO.peerID ?? "") else {
55 os_log("preflightVouchWithBottle found no peer to match bottle", log: tplogDebug, type: .default)
56 reply(nil, nil, nil, ContainerError.sponsorNotRegistered(bottleMO.peerID ?? "no peer ID given"))
57 return
58 }
59
60 guard let sponsorPeerStableInfo = sponsorPeer.stableInfo else {
61 os_log("preflightVouchWithBottle sponsor peer has no stable info", log: tplogDebug, type: .default)
62 reply(nil, nil, nil, ContainerError.sponsorNotRegistered(bottleMO.peerID ?? "no peer ID given"))
63 return
64 }
65
66 do {
67 // We need to extract the syncing policy that the remote peer would have used (if they were the type of device that we are)
68 // So, figure out their policy version...
69 let (views, policy) = try self.policyAndViewsFor(permanentInfo: egoPermanentInfo, stableInfo: sponsorPeerStableInfo)
70
71 reply(bottleMO.peerID, views, policy, nil)
72 } catch {
73 os_log("preflightVouchWithBottle failed to fetch policy: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "")
74 reply(nil, nil, nil, error)
75 }
76 }
77 }
78 }
79 }
80 }
81 }