#include "SOSRingV0.h"
#include <AssertMacros.h>
#include <Security/SecureObjectSync/SOSInternal.h>
#include <Security/SecureObjectSync/SOSPeerInfoInternal.h>
#include <Security/SecureObjectSync/SOSPeerInfoCollections.h>
#include <Security/SecureObjectSync/SOSCircle.h>
#include <Security/SecFramework.h>
#include <Security/SecKey.h>
#include <Security/SecKeyPriv.h>
#include <CoreFoundation/CoreFoundation.h>
#include <utilities/SecCFWrappers.h>
#include <stdlib.h>
#include <assert.h>
#include "SOSRingUtils.h"
#include "SOSRingTypes.h"
static SOSRingRef SOSRingCreate_V0(CFStringRef name, CFStringRef myPeerID, CFErrorRef *error) {
SOSRingRef retval = NULL;
retval = SOSRingCreate_Internal(name, 0, error);
if(!retval) return NULL;
SOSRingSetLastModifier(retval, myPeerID);
return retval;
}
static bool SOSRingResetToEmpty_V0(SOSRingRef ring, CFStringRef myPeerID, CFErrorRef *error) {
return SOSRingResetToEmpty_Internal(ring, error) && SOSRingSetLastModifier(ring, myPeerID);
}
static bool SOSRingResetToOffering_V0(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(requestor));
SecKeyRef priv = SOSFullPeerInfoCopyDeviceKey(requestor, error);
bool retval = priv && myPeerID &&
SOSRingResetToEmpty_Internal(ring, error) &&
SOSRingAddPeerID(ring, myPeerID) &&
SOSRingSetLastModifier(ring, myPeerID) &&
SOSRingGenerationSign_Internal(ring, user_privkey, error);
SOSRingConcordanceSign_Internal(ring, priv, error);
CFReleaseNull(priv);
return retval;
}
static SOSRingStatus SOSRingDeviceIsInRing_V0(SOSRingRef ring, CFStringRef peerID) {
if(SOSRingHasPeerID(ring, peerID)) return kSOSRingMember;
if(SOSRingHasApplicant(ring, peerID)) return kSOSRingApplicant;
if(SOSRingHasRejection(ring, peerID)) return kSOSRingReject;
return kSOSRingNotInRing;
}
static bool SOSRingApply_V0(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
bool retval = false;
CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(requestor));
if(SOSRingDeviceIsInRing_V0(ring, myPeerID) == kSOSRingReject) SOSRingRemoveRejection(ring, myPeerID);
require_action_quiet(SOSRingDeviceIsInRing_V0(ring, myPeerID) == kSOSRingNotInRing, errOut, secnotice("ring", "Already associated with ring"));
retval = myPeerID &&
SOSRingAddApplicant(ring, myPeerID) &&
SOSRingSetLastModifier(ring, myPeerID);
errOut:
return retval;
}
static bool SOSRingWithdraw_V0(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(requestor));
SOSRingSetLastModifier(ring, myPeerID);
if(SOSRingHasPeerID(ring, myPeerID)) {
SOSRingRemovePeerID(ring, myPeerID); SecKeyRef priv = SOSFullPeerInfoCopyDeviceKey(requestor, error);
SOSRingGenerationSign_Internal(ring, priv, error);
if(user_privkey) SOSRingGenerationSign_Internal(ring, user_privkey, error);
CFReleaseNull(priv);
} else if(SOSRingHasApplicant(ring, myPeerID)) {
SOSRingRemoveApplicant(ring, myPeerID);
} else if(SOSRingHasRejection(ring, myPeerID)) {
SOSRingRemoveRejection(ring, myPeerID);
} else {
SOSCreateError(kSOSErrorPeerNotFound, CFSTR("Not associated with Ring"), NULL, error);
return false;
}
return true;
}
static bool SOSRingGenerationSign_V0(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(requestor));
SecKeyRef priv = SOSFullPeerInfoCopyDeviceKey(requestor, error);
bool retval = priv && myPeerID &&
SOSRingSetLastModifier(ring, myPeerID) &&
SOSRingGenerationSign_Internal(ring, priv, error);
if(user_privkey) SOSRingGenerationSign_Internal(ring, user_privkey, error);
CFReleaseNull(priv);
return retval;
}
static bool SOSRingConcordanceSign_V0(SOSRingRef ring, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(requestor));
SecKeyRef priv = SOSFullPeerInfoCopyDeviceKey(requestor, error);
bool retval = priv && myPeerID &&
SOSRingSetLastModifier(ring, myPeerID) &&
SOSRingConcordanceSign_Internal(ring, priv, error);
CFReleaseNull(priv);
return retval;
}
__unused static bool SOSRingSetPayload_V0(SOSRingRef ring, SecKeyRef user_privkey, CFDataRef payload, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(requestor));
SecKeyRef priv = SOSFullPeerInfoCopyDeviceKey(requestor, error);
bool retval = priv && myPeerID &&
SOSRingSetLastModifier(ring, myPeerID) &&
SOSRingSetPayload_Internal(ring, payload) &&
SOSRingGenerationSign_Internal(ring, priv, error);
if(user_privkey) SOSRingConcordanceSign_Internal(ring, user_privkey, error);
CFReleaseNull(priv);
return retval;
}
__unused static CFDataRef SOSRingGetPayload_V0(SOSRingRef ring, CFErrorRef *error) {
return SOSRingGetPayload_Internal(ring);
}
ringFuncStruct basic = {
"V0",
1,
SOSRingCreate_V0,
SOSRingResetToEmpty_V0,
SOSRingResetToOffering_V0,
SOSRingDeviceIsInRing_V0,
SOSRingApply_V0,
SOSRingWithdraw_V0,
SOSRingGenerationSign_V0,
SOSRingConcordanceSign_V0,
SOSRingUserKeyConcordanceTrust,
NULL,
NULL
};