5 // Created by Richard Murphy on 3/3/15.
9 #include "SOSRingBackup.h"
11 #include <AssertMacros.h>
13 #include <Security/SecureObjectSync/SOSInternal.h>
14 #include <Security/SecureObjectSync/SOSPeerInfoInternal.h>
15 #include <Security/SecureObjectSync/SOSPeerInfoCollections.h>
16 #include <Security/SecureObjectSync/SOSCircle.h>
17 #include <Security/SecureObjectSync/SOSViews.h>
18 #include <Security/SecFramework.h>
20 #include <Security/SecKey.h>
21 #include <Security/SecKeyPriv.h>
22 #include <CoreFoundation/CoreFoundation.h>
24 #include <utilities/SecCFWrappers.h>
29 #include "SOSRingUtils.h"
30 #include "SOSRingTypes.h"
31 #include "SOSRingBasic.h"
33 // MARK: Backup Ring Ops
35 static SOSRingRef
SOSRingCreate_Backup(CFStringRef name
, CFStringRef myPeerID
, CFErrorRef
*error
) {
36 return SOSRingCreate_ForType(name
, kSOSRingBackup
, myPeerID
, error
);
40 // Make sure all the peers in the ring have access to the ring views
41 static bool SOSBackupRingPeersInViews(CFSetRef peers
, SOSRingRef ring
) {
42 CFSetRef ringViews
= SOSBackupRingGetViews(ring
, NULL
);
43 if(!ringViews
) return false;
44 __block
bool retval
= true;
45 SOSRingForEachPeerID(ring
, ^(CFStringRef peerID
) {
46 SOSPeerInfoRef peerInfo
= SOSPeerInfoSetFindByID(peers
, peerID
);
48 CFSetForEach(ringViews
, ^(const void *value
) {
49 if(!SOSPeerInfoIsViewPermitted(peerInfo
, (CFStringRef
) value
)) retval
= false;
58 // Make sure that the ring includes me if I'm enabled for its view.
59 static SOSConcordanceStatus
SOSBackupRingEvaluateMyInclusion(SOSRingRef ring
, SOSFullPeerInfoRef me
) {
60 bool shouldBeInRing
= false;
61 bool amInThisRing
= false;
64 SOSPeerInfoRef pi
= SOSFullPeerInfoGetPeerInfo(me
);
65 CFStringRef peerID
= SOSPeerInfoGetPeerID(pi
);
66 CFSetRef ringViews
= SOSRingGetBackupViewset_Internal(ring
);
67 CFSetRef piViews
= SOSPeerInfoGetPermittedViews(pi
);
68 shouldBeInRing
= CFSetIsSubset(ringViews
, piViews
);
69 amInThisRing
= SOSRingHasPeerWithID(ring
, peerID
, NULL
);
72 if(shouldBeInRing
&& !amInThisRing
) return kSOSConcordanceMissingMe
;
73 if(!shouldBeInRing
&& amInThisRing
) return kSOSConcordanceImNotWorthy
;
74 return kSOSConcordanceTrusted
;
77 static SOSConcordanceStatus
SOSRingPeerKeyConcordanceTrust_Backup(SOSFullPeerInfoRef me
, CFSetRef peers
, SOSRingRef knownRing
, SOSRingRef proposedRing
,
78 __unused SecKeyRef knownPubkey
, SecKeyRef userPubkey
,
79 CFStringRef excludePeerID
, CFErrorRef
*error
) {
80 if(userPubkey
== NULL
) {
81 SOSCreateError(kSOSErrorPublicKeyAbsent
, CFSTR("Concordance with no public key - need to validate application"), NULL
, error
);
82 return kSOSConcordanceNoUserKey
;
85 if(SOSRingIsOlderGeneration(proposedRing
, knownRing
)) {
86 SOSCreateError(kSOSErrorReplay
, CFSTR("Bad generation"), NULL
, error
);
87 return kSOSConcordanceGenOld
;
91 if (SOSRingIsEmpty_Internal(proposedRing
)) {
92 return kSOSConcordanceTrusted
;
95 SOSConcordanceStatus localstatus
= SOSBackupRingEvaluateMyInclusion(proposedRing
, me
);
96 if(localstatus
== kSOSConcordanceMissingMe
) {
97 SOSCreateError(kSOSErrorReplay
, CFSTR("Improper exclusion of this peer"), NULL
, error
);
101 if(localstatus
== kSOSConcordanceImNotWorthy
) {
102 SOSCreateError(kSOSErrorReplay
, CFSTR("Improper inclusion of this peer"), NULL
, error
);
106 if(!SOSBackupRingPeersInViews(peers
, proposedRing
)) {
107 return kSOSConcordanceInvalidMembership
;
110 return GetSignersStatus_Transitive(peers
, knownRing
, proposedRing
, userPubkey
, excludePeerID
, error
);
113 bool SOSBackupRingSetViews(SOSRingRef ring
, SOSFullPeerInfoRef requestor
, CFSetRef viewSet
, CFErrorRef
*error
) {
114 CFStringRef myPeerID
= SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(requestor
));
115 SecKeyRef priv
= SOSFullPeerInfoCopyDeviceKey(requestor
, error
);
116 bool retval
= priv
&& myPeerID
&&
117 SOSRingSetLastModifier(ring
, myPeerID
) &&
118 SOSRingSetBackupViewset_Internal(ring
, viewSet
) &&
119 SOSRingGenerationSign_Internal(ring
, priv
, error
);
124 CFSetRef
SOSBackupRingGetViews(SOSRingRef ring
, CFErrorRef
*error
) {
125 return SOSRingGetBackupViewset_Internal(ring
);
128 ringFuncStruct backup
= {
131 SOSRingCreate_Backup
,
132 SOSRingResetToEmpty_Basic
,
133 SOSRingResetToOffering_Basic
,
134 SOSRingDeviceIsInRing_Basic
,
136 SOSRingWithdraw_Basic
,
137 SOSRingGenerationSign_Basic
,
138 SOSRingConcordanceSign_Basic
,
139 SOSRingPeerKeyConcordanceTrust_Backup
,
142 SOSRingSetPayload_Basic
,
143 SOSRingGetPayload_Basic
,