static void tests(void) { SecKeyRef publicKey = NULL; CFErrorRef error = NULL; SOSCircleRef circle = SOSCircleCreate(NULL, CFSTR("Test Circle"), &error); CFStringRef circle_key = SOSCircleKeyCreateWithCircle(circle, NULL); CFStringRef circle_name = NULL; ok(circle_key, "Circle key created"); is(SOSKVSKeyGetKeyType(circle_key), kCircleKey, "Is circle key"); is(SOSKVSKeyGetKeyTypeAndParse(circle_key, &circle_name, NULL, NULL, NULL, NULL, NULL), kCircleKey, "Is circle key, extract name"); ok(circle_name, "Circle name extracted"); ok(CFEqualSafe(circle_name, SOSCircleGetName(circle)), "Circle name matches '%@' '%@'", circle_name, SOSCircleGetName(circle)); CFReleaseNull(circle_name); CFReleaseNull(circle_key); SOSPeerInfoRef pi = SOSCreatePeerInfoFromName(CFSTR("Test Peer"), &publicKey, &error); CFStringRef other_peer_id = CFSTR("OTHER PEER"); CFStringRef messageKey = SOSMessageKeyCreateWithCircleAndPeerNames(circle, SOSPeerInfoGetPeerID(pi), other_peer_id); ok(messageKey, "Getting message key '%@'", messageKey); CFStringRef message_circle_name = NULL; CFStringRef message_from_peer_id = NULL; CFStringRef message_to_peer_id = NULL; CFStringRef message_ring = NULL; CFStringRef message_peer_info = NULL; CFStringRef message_backup = NULL; is(SOSKVSKeyGetKeyType(messageKey), kMessageKey, "Is message key"); is(SOSKVSKeyGetKeyTypeAndParse(messageKey, &message_circle_name, &message_peer_info, &message_ring, &message_backup, &message_from_peer_id, &message_to_peer_id), kMessageKey, "Is message key, extract parts"); ok(CFEqualSafe(SOSCircleGetName(circle), message_circle_name), "circle key matches in message (%@ v %@)",SOSCircleGetName(circle), message_circle_name); ok(CFEqualSafe(SOSPeerInfoGetPeerID(pi), message_from_peer_id), "from peer set correctly (%@ v %@)", SOSPeerInfoGetPeerID(pi), message_from_peer_id); ok(CFEqualSafe(other_peer_id, message_to_peer_id), "to peer set correctly (%@ v %@)", other_peer_id, message_to_peer_id); CFStringRef retirementKey = SOSRetirementKeyCreateWithCircleAndPeer(circle, SOSPeerInfoGetPeerID(pi)); CFStringRef retirement_circle_name = NULL; CFStringRef retirement_peer_id = NULL; is(SOSKVSKeyGetKeyType(retirementKey), kRetirementKey, "Is retirement key"); is(SOSKVSKeyGetKeyTypeAndParse(retirementKey, &retirement_circle_name, NULL, NULL, NULL, &retirement_peer_id, NULL), kRetirementKey, "Is retirement key, extract parts"); CFReleaseSafe(retirementKey); ok(CFEqualSafe(SOSCircleGetName(circle), retirement_circle_name), "circle key matches in retirement (%@ v %@)", SOSCircleGetName(circle), retirement_circle_name); ok(CFEqualSafe(SOSPeerInfoGetPeerID(pi), retirement_peer_id), "retirement peer set correctly (%@ v %@)", SOSPeerInfoGetPeerID(pi), retirement_peer_id); CFReleaseNull(publicKey); CFReleaseNull(circle); CFReleaseNull(error); CFReleaseNull(pi); CFReleaseNull(messageKey); CFReleaseNull(message_circle_name); CFReleaseNull(message_from_peer_id); CFReleaseNull(message_to_peer_id); CFReleaseNull(retirement_circle_name); CFReleaseNull(retirement_peer_id); }
static void tests(void) { CFErrorRef error = NULL; CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); CFDataRef cfwrong_password = CFDataCreate(NULL, (uint8_t *) "NotFooFooFoo", 10); CFStringRef cfaccount = CFSTR("*****@*****.**"); CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); SOSAccountRef alice_account = CreateAccountForLocalChanges(CFSTR("Alice"), CFSTR("TestSource")); SOSAccountRef bob_account = CreateAccountForLocalChanges(CFSTR("Bob"), CFSTR("TestSource")); SOSAccountRef carol_account = CreateAccountForLocalChanges(CFSTR("Carol"), CFSTR("TestSource")); ok(SOSAccountAssertUserCredentialsAndUpdate(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); // Bob wins writing at this point, feed the changes back to alice. is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 1, "updates"); ok(SOSAccountAssertUserCredentialsAndUpdate(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); CFReleaseNull(error); ok(SOSAccountTryUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential trying (%@)", error); CFReleaseNull(error); ok(!SOSAccountTryUserCredentials(alice_account, cfaccount, cfwrong_password, &error), "Credential failing (%@)", error); CFReleaseNull(cfwrong_password); is(error ? CFErrorGetCode(error) : 0, kSOSErrorWrongPassword, "Expected SOSErrorWrongPassword"); CFReleaseNull(error); ok(SOSAccountResetToOffering_wTxn(alice_account, &error), "Reset to offering (%@)", error); CFReleaseNull(error); is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); ok(SOSAccountJoinCircles_wTxn(bob_account, &error), "Bob Applies (%@)", error); CFReleaseNull(error); is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); { CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Alice accepts (%@)", error); CFReleaseNull(error); CFReleaseNull(applicants); } is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 3, "updates"); accounts_agree("bob&alice pair", bob_account, alice_account); CFArrayRef peers = SOSAccountCopyPeers(alice_account, &error); ok(peers && CFArrayGetCount(peers) == 2, "See two peers %@ (%@)", peers, error); CFReleaseNull(peers); //bob now goes def while Alice does some stuff. ok(SOSAccountLeaveCircle(alice_account, &error), "ALICE LEAVES THE CIRCLE (%@)", error); ok(SOSAccountResetToOffering_wTxn(alice_account, &error), "Alice resets to offering again (%@)", error); is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); accounts_agree("bob&alice pair", bob_account, alice_account); is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 1, "updates"); ok(SOSAccountAssertUserCredentialsAndUpdate(carol_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); SOSAccountSetUserPublicTrustedForTesting(carol_account); ok(SOSAccountResetToOffering_wTxn(carol_account, &error), "Carol is going to push a reset to offering (%@)", error); int64_t valuePtr = 0; CFNumberRef gencount = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &valuePtr); SOSCircleSetGeneration(carol_account->trusted_circle, gencount); SecKeyRef user_privkey = SOSUserKeygen(cfpassword, carol_account->user_key_parameters, &error); CFNumberRef genCountTest = SOSCircleGetGeneration(carol_account->trusted_circle); CFIndex testPtr; CFNumberGetValue(genCountTest, kCFNumberCFIndexType, &testPtr); ok(testPtr== 0); SOSCircleSignOldStyleResetToOfferingCircle(carol_account->trusted_circle, carol_account->my_identity, user_privkey, &error); SOSTransportCircleTestRemovePendingChange(carol_account->circle_transport, SOSCircleGetName(carol_account->trusted_circle), NULL); CFDataRef circle_data = SOSCircleCopyEncodedData(carol_account->trusted_circle, kCFAllocatorDefault, &error); if (circle_data) { SOSTransportCirclePostCircle(carol_account->circle_transport, SOSCircleGetName(carol_account->trusted_circle), circle_data, &error); } genCountTest = SOSCircleGetGeneration(carol_account->trusted_circle); CFNumberGetValue(genCountTest, kCFNumberCFIndexType, &testPtr); ok(testPtr== 0); ok(SOSAccountAssertUserCredentialsAndUpdate(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); ok(SOSAccountAssertUserCredentialsAndUpdate(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); SOSAccountSetUserPublicTrustedForTesting(alice_account); SOSAccountSetUserPublicTrustedForTesting(bob_account); is(ProcessChangesUntilNoChange(changes, carol_account, alice_account, bob_account, NULL), 2, "updates"); ok(kSOSCCNotInCircle == SOSAccountGetCircleStatus(alice_account, &error), "alice is not in the account (%@)", error); ok(kSOSCCNotInCircle == SOSAccountGetCircleStatus(bob_account, &error), "bob is not in the account (%@)", error); ok(kSOSCCInCircle == SOSAccountGetCircleStatus(carol_account, &error), "carol is in the account (%@)", error); CFReleaseNull(gencount); CFReleaseNull(bob_account); CFReleaseNull(alice_account); CFReleaseNull(cfpassword); SOSTestCleanup(); }
SOSAccountRef SOSAccountCreateFromDER_V1(CFAllocatorRef allocator, SOSDataSourceFactoryRef factory, CFErrorRef* error, const uint8_t** der_p, const uint8_t *der_end) { SOSAccountRef account = NULL; const uint8_t *sequence_end; *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); { CFDictionaryRef decoded_gestalt = NULL; *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, *der_p, der_end); if (*der_p == 0) return NULL; account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory); CFReleaseNull(decoded_gestalt); } CFArrayRef array = NULL; *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); if (*der_p != sequence_end) *der_p = NULL; __block bool success = true; require_quiet(array && *der_p, fail); CFArrayForEach(array, ^(const void *value) { if (success) { if (isString(value)) { CFDictionaryAddValue(account->circles, value, kCFNull); } else { CFDataRef circleData = NULL; CFDataRef fullPeerInfoData = NULL; if (isData(value)) { circleData = (CFDataRef) value; } else if (isArray(value)) { CFArrayRef pair = (CFArrayRef) value; CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { circleData = (CFDataRef) circleObject; fullPeerInfoData = (CFDataRef) fullPeerInfoObject; } } if (circleData) { SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); require_action_quiet(circle, fail, success = false); CFStringRef circleName = SOSCircleGetName(circle); CFDictionaryAddValue(account->circles, circleName, circle); if (fullPeerInfoData) { SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); require_action_quiet(full_peer, fail, success = false); CFDictionaryAddValue(account->circle_identities, circleName, full_peer); CFReleaseNull(full_peer); } fail: CFReleaseNull(circle); } } } });
bool SOSAccountIsMyPeerActiveInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) { SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, SOSCircleGetName(circle), NULL); if(!fpi) return false; return SOSCircleHasActivePeer(circle, SOSFullPeerInfoGetPeerInfo(fpi), error); }
SOSPeerInfoRef SOSAccountGetMyPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) { SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, SOSCircleGetName(circle), error); return fpi ? SOSFullPeerInfoGetPeerInfo(fpi) : NULL; }
bool SOSAccountDestroyCirclePeerInfo(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) { return SOSAccountDestroyCirclePeerInfoNamed(account, SOSCircleGetName(circle), error); }