1// 2// secd-59-account-cleanup.c 3// sec 4// 5// Created by Mitch Adler on 6/18/13. 6// 7// 8 9 10 11#include <Security/SecBase.h> 12#include <Security/SecItem.h> 13 14#include <CoreFoundation/CFDictionary.h> 15 16#include <SecureObjectSync/SOSAccount.h> 17#include <SecureObjectSync/SOSCloudCircle.h> 18#include <SecureObjectSync/SOSInternal.h> 19#include <SecureObjectSync/SOSUserKeygen.h> 20 21#include <stdlib.h> 22#include <unistd.h> 23 24#include "secd_regressions.h" 25#include "SOSTestDataSource.h" 26 27#include "SOSRegressionUtilities.h" 28#include <utilities/SecCFWrappers.h> 29#include <Security/SecKeyPriv.h> 30 31#include <securityd/SOSCloudCircleServer.h> 32 33#include "SOSAccountTesting.h" 34 35 36static int kTestTestCount = 93; 37 38static void tests(void) 39{ 40 CFErrorRef error = NULL; 41 CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); 42 CFStringRef cfaccount = CFSTR("test@test.org"); 43 CFStringRef circle_name = CFSTR("TestSource"); 44 45 CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); 46 47 SOSAccountRef alice_account = CreateAccountForLocalChanges(changes, CFSTR("Alice"), circle_name); 48 SOSAccountRef bob_account = CreateAccountForLocalChanges(changes, CFSTR("Bob"), circle_name); 49 SOSAccountRef carole_account = CreateAccountForLocalChanges(changes, CFSTR("Carole"), circle_name); 50 51 ok(SOSAccountAssertUserCredentials(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); 52 53 // Bob wins writing at this point, feed the changes back to alice. 54 55 FeedChangesToMulti(changes, alice_account, carole_account, NULL); 56 57 ok(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); 58 CFReleaseNull(error); 59 60 ok(SOSAccountAssertUserCredentials(carole_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); 61 CFReleaseNull(error); 62 ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); 63 CFReleaseNull(error); 64 65 FeedChangesTo(changes, bob_account); 66 67 ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); 68 CFReleaseNull(error); 69 70 FeedChangesTo(changes, alice_account); 71 72 { 73 CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); 74 75 ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); 76 ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Alice accepts (%@)", error); 77 CFReleaseNull(error); 78 CFReleaseNull(applicants); 79 } 80 81 82 FeedChangesTo(changes, bob_account); // Bob sees he's accepted 83 84 FeedChangesTo(changes, alice_account); // Alice sees bob-concurring 85 86 ok(CFDictionaryGetCount(changes) == 0, "We converged. (%@)", changes); 87 88 accounts_agree("bob&alice pair", bob_account, alice_account); 89 90 CFArrayRef peers = SOSAccountCopyPeers(alice_account, &error); 91 ok(peers && CFArrayGetCount(peers) == 2, "See two peers %@ (%@)", peers, error); 92 CFReleaseNull(peers); 93 94 SOSFullPeerInfoRef fpiAlice = SOSAccountGetMyFullPeerInCircleNamed(alice_account, circle_name, NULL); 95 CFStringRef alice_id = CFStringCreateCopy(NULL, SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(fpiAlice))); 96 97 ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); 98 CFReleaseNull(error); 99 CFReleaseNull(cfpassword); 100 101 FeedChangesTo(changes, bob_account); // Bob sees alice bail. 102 103 is(CFDictionaryGetCountOfValue(changes, kCFNull),2, "2 Keys Nulled Out"); 104 105 CFDictionaryForEach(changes, ^(const void *key, const void *value) { 106 if(isNull(value)) { 107 CFStringRef circle_name = NULL, from_name = NULL, to_name = NULL; 108 SOSKVSKeyType keytype = SOSKVSKeyGetKeyTypeAndParse(key, &circle_name, &from_name, &to_name); 109 is(keytype, kMessageKey, "Expect only a message key"); 110 bool testcmp = CFEqualSafe(alice_id, from_name) || CFEqualSafe(alice_id, to_name); 111 ok(testcmp, "Alice is from_name(%@) or to_name(%@)", from_name, to_name); 112 CFReleaseNull(circle_name); 113 CFReleaseNull(from_name); 114 CFReleaseNull(to_name); 115 } 116 }); 117 118 FeedChangesToMulti(changes, alice_account, carole_account, NULL); 119 120 accounts_agree("Alice bails", bob_account, alice_account); 121 accounts_agree("Alice bails", bob_account, carole_account); 122 123 SOSAccountCleanupRetirementTickets(bob_account, 0, &error); 124 is(CFDictionaryGetCountOfValue(changes, kCFNull),0, "0 Keys Nulled Out"); 125 126 ok(SOSAccountJoinCircles(carole_account, &error), "Carole Applies (%@)", error); 127 CFReleaseNull(error); 128 129 FeedChangesTo(changes, bob_account); 130 131 { 132 CFArrayRef applicants = SOSAccountCopyApplicants(bob_account, &error); 133 134 ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); 135 ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts Carole (%@)", error); 136 CFReleaseNull(error); 137 CFReleaseNull(applicants); 138 } 139 140 // Bob should not yet cleanup Alice's retirment here on his own since it hasn't been long enough 141 // by default. 142 is(CFDictionaryGetCountOfValue(changes, kCFNull),0, "0 Keys Nulled Out"); 143 144 FeedChangesTo(changes, carole_account); // Carole sees he's accepted 145 FeedChangesTo(changes, bob_account); // Bob sees she's all happy. 146 147 accounts_agree("Carole joins", bob_account, carole_account); 148 149 SOSAccountCleanupRetirementTickets(bob_account, 0, &error); 150 151 is(countPeers(bob_account), 2, "Active peers after forced cleanup"); 152 is(countActivePeers(bob_account), 3, "Inactive peers after forced cleanup"); 153 154 is(CFDictionaryGetCountOfValue(changes, kCFNull), 1, "1 Keys Nulled Out"); 155 156 CFDictionaryForEach(changes, ^(const void *key, const void *value) { 157 if(isNull(value)) { 158 CFStringRef circle_name = NULL, retiree = NULL; 159 SOSKVSKeyType keytype = SOSKVSKeyGetKeyTypeAndParse(key, &circle_name, &retiree, NULL); 160 is(keytype, kRetirementKey, "Expect only a retirement key"); 161 ok(CFEqualSafe(alice_id, retiree), "Alice (%@) is retiree (%@)", alice_id, retiree); 162 CFReleaseNull(circle_name); 163 CFReleaseNull(retiree); 164 } 165 }); 166 167 CFReleaseNull(alice_id); 168 CFReleaseNull(carole_account); 169 CFReleaseNull(bob_account); 170 CFReleaseNull(alice_account); 171} 172 173int secd_59_account_cleanup(int argc, char *const *argv) 174{ 175 plan_tests(kTestTestCount); 176 177 tests(); 178 179 return 0; 180} 181