--- /dev/null
+//
+// SOSRingV0.c
+// sec
+//
+// Created by Richard Murphy on 3/5/15.
+//
+//
+
+#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"
+
+// MARK: V0 Ring Ops - same operation as V0 Circles
+
+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);// Maybe we need a retired peerID list?
+ 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
+};