]> git.saurik.com Git - apple/security.git/blob - keychain/securityd/Regressions/secd-200-logstate.m
Security-59754.80.3.tar.gz
[apple/security.git] / keychain / securityd / Regressions / secd-200-logstate.m
1 /*
2 * Copyright (c) 2013-2016 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 //
24 // secd-200-logstate.c
25 // sec
26 //
27
28 #include <stdio.h>
29
30
31
32
33 #include <Security/SecBase.h>
34 #include <Security/SecItem.h>
35
36 #include <CoreFoundation/CFDictionary.h>
37
38 #include "keychain/SecureObjectSync/SOSAccount.h"
39 #include <Security/SecureObjectSync/SOSCloudCircle.h>
40 #include "keychain/SecureObjectSync/SOSInternal.h"
41 #include "keychain/SecureObjectSync/SOSUserKeygen.h"
42 #include "keychain/SecureObjectSync/SOSTransport.h"
43
44 #include <stdlib.h>
45 #include <unistd.h>
46
47 #include "secd_regressions.h"
48 #include "SOSTestDataSource.h"
49
50 #include "SOSRegressionUtilities.h"
51 #include <utilities/SecCFWrappers.h>
52 #include <Security/SecKeyPriv.h>
53
54 #include "keychain/securityd/SOSCloudCircleServer.h"
55
56 #include "SOSAccountTesting.h"
57
58 #include "SecdTestKeychainUtilities.h"
59 #if SOS_ENABLED
60
61 #define HOW_MANY_MINIONS 4
62
63 static bool SOSArrayForEachAccount(CFArrayRef accounts, bool (^operation)(SOSAccount* account)) {
64 __block bool retval = true;
65 CFArrayForEach(accounts, ^(const void *value) {
66 SOSAccount* account = (__bridge SOSAccount*) value;
67 retval &= operation(account);
68 });
69 return retval;
70 }
71
72
73 static inline void FeedChangesToMasterMinions(CFMutableDictionaryRef changes, SOSAccount* master_account, CFArrayRef minion_accounts) {
74 FeedChangesTo(changes, master_account);
75 SOSArrayForEachAccount(minion_accounts, ^bool(SOSAccount* account) {
76 FeedChangesTo(changes, account);
77 return true;
78 });
79 FeedChangesTo(changes, master_account);
80
81 }
82
83
84 static inline bool ProcessChangesOnceMasterMinions(CFMutableDictionaryRef changes, SOSAccount* master_account, CFArrayRef minion_accounts) {
85 bool result = FillAllChanges(changes);
86 FeedChangesToMasterMinions(changes, master_account, minion_accounts);
87 return result;
88 }
89
90 static inline int ProcessChangesForMasterAndMinions(CFMutableDictionaryRef changes, SOSAccount* master_account, CFArrayRef minion_accounts) {
91 int result = 0;
92 bool new_data = false;
93 do {
94 new_data = ProcessChangesOnceMasterMinions(changes, master_account, minion_accounts);
95 ++result;
96 } while (new_data);
97 return result;
98 }
99
100 static bool MakeTheBigCircle(CFMutableDictionaryRef changes, SOSAccount* master_account, CFArrayRef minion_accounts, CFErrorRef *error) {
101 bool retval = SOSAccountResetToOffering_wTxn(master_account, error);
102 if(!retval)
103 return retval;
104 ProcessChangesForMasterAndMinions(changes, master_account, minion_accounts);
105 retval = SOSArrayForEachAccount(minion_accounts, ^bool(SOSAccount* account) {
106 bool localret = SOSAccountJoinCircles_wTxn(account, error);
107 ProcessChangesForMasterAndMinions(changes, master_account, minion_accounts);
108 return localret;
109 });
110 require_quiet(retval, errOut);
111 CFArrayRef applicants = SOSAccountCopyApplicants(master_account, error);
112 retval = SOSAccountAcceptApplicants(master_account , applicants, error);
113 CFReleaseNull(applicants);
114 ProcessChangesForMasterAndMinions(changes, master_account, minion_accounts);
115 errOut:
116 return retval;
117 }
118
119
120 static CFArrayRef CreateManyAccountsForLocalChanges(CFStringRef namefmt, CFStringRef data_source_name, size_t howmany)
121 CF_FORMAT_FUNCTION(1, 0);
122
123 static CFArrayRef CreateManyAccountsForLocalChanges(CFStringRef name, CFStringRef data_source_name, size_t howmany) {
124 CFMutableArrayRef accounts = CFArrayCreateMutable(kCFAllocatorDefault, howmany, &kCFTypeArrayCallBacks);
125
126 for(size_t i = 0; i < howmany; i++) {
127 CFStringRef tmpname = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@%ld"), name, (long)i);
128 SOSAccount* tmp = CreateAccountForLocalChanges(tmpname, CFSTR("TestSource"));
129 CFArraySetValueAtIndex(accounts, i, (__bridge const void *)(tmp));
130 CFReleaseNull(tmpname);
131 }
132 return accounts;
133 }
134
135 static bool AssertAllCredentialsAndUpdate(CFMutableDictionaryRef changes, SOSAccount* master_account, CFArrayRef minion_accounts, CFStringRef user_account, CFDataRef user_password, CFErrorRef *error) {
136 __block bool retval = SOSAccountAssertUserCredentialsAndUpdate(master_account, user_account, user_password, error);
137 ProcessChangesForMasterAndMinions(changes, master_account, minion_accounts);
138 retval &= SOSArrayForEachAccount(minion_accounts, ^bool(SOSAccount* account) {
139 CFReleaseNull(*error);
140 return SOSAccountAssertUserCredentialsAndUpdate(account, user_account, user_password, error);
141 });
142 CFReleaseNull(*error);
143
144 return retval;
145 }
146
147 static void timeval_delta(struct timeval *delta, struct timeval *start, struct timeval *end) {
148 if(end->tv_usec >= start->tv_usec) {
149 delta->tv_usec = end->tv_usec - start->tv_usec;
150 } else {
151 end->tv_sec--;
152 end->tv_usec += 1000000;
153 delta->tv_usec = end->tv_usec - start->tv_usec;
154 }
155 delta->tv_sec = end->tv_sec - start->tv_sec;
156 }
157
158 static void reportTime(int peers, void(^action)(void)) {
159 struct rusage start_rusage;
160 struct rusage end_rusage;
161 struct timeval delta_utime;
162 struct timeval delta_stime;
163
164 getrusage(RUSAGE_SELF, &start_rusage);
165 action();
166 getrusage(RUSAGE_SELF, &end_rusage);
167 timeval_delta(&delta_utime, &start_rusage.ru_utime, &end_rusage.ru_utime);
168 timeval_delta(&delta_stime, &start_rusage.ru_stime, &end_rusage.ru_stime);
169
170 diag("AccountLogState for %d peers: %ld.%06d user %ld.%06d system", peers,
171 delta_utime.tv_sec, delta_utime.tv_usec,
172 delta_stime.tv_sec, delta_stime.tv_usec);
173 }
174
175 static void tests(void)
176 {
177 NSError* ns_error = nil;
178 CFErrorRef error = NULL;
179 CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10);
180 CFStringRef cfaccount = CFSTR("test@test.org");
181
182 CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
183
184 SOSAccount* master_account = CreateAccountForLocalChanges(CFSTR("master"), CFSTR("TestSource"));
185 CFArrayRef minion_accounts = CreateManyAccountsForLocalChanges(CFSTR("minion"), CFSTR("TestSource"), HOW_MANY_MINIONS);
186
187 ok(AssertAllCredentialsAndUpdate(changes, master_account, minion_accounts, cfaccount, cfpassword, &error), "Credential setting (%@)", error);
188 CFReleaseNull(cfpassword);
189
190 secLogEnable();
191 reportTime(1, ^{
192 SOSAccountLogState(master_account);
193 });
194 secLogDisable();
195
196 ok(MakeTheBigCircle(changes, master_account, minion_accounts, &error), "Get Everyone into the circle %@", error);
197
198 diag("WHAT?");
199 secLogEnable();
200 reportTime(HOW_MANY_MINIONS+1, ^{
201 SOSAccountLogState(master_account);
202 });
203 SOSAccountLogViewState(master_account);
204 secLogDisable();
205
206 NSData* acctData = [master_account encodedData:&ns_error];
207 diag("Account DER Size is %lu for %d peers", (unsigned long)[acctData length], HOW_MANY_MINIONS+1);
208 ns_error = nil;
209
210 SOSAccountTrustClassic* trust = master_account.trust;
211 CFDataRef circleData = SOSCircleCopyEncodedData(trust.trustedCircle, kCFAllocatorDefault, &error);
212 diag("Circle DER Size is %ld for %d peers", CFDataGetLength(circleData), HOW_MANY_MINIONS+1);
213 CFReleaseNull(circleData);
214 CFReleaseNull(error);
215
216 CFDataRef peerData = SOSPeerInfoCopyEncodedData(master_account.peerInfo, kCFAllocatorDefault, &error);
217 diag("Peer DER Size is %ld", CFDataGetLength(peerData));
218 CFReleaseNull(peerData);
219 CFReleaseNull(error);
220
221 CFReleaseNull(error);
222 CFReleaseNull(minion_accounts);
223
224 SOSTestCleanup();
225
226 }
227 #endif
228
229 int secd_200_logstate(int argc, char *const *argv)
230 {
231 #if SOS_ENABLED
232 plan_tests(((HOW_MANY_MINIONS+1)*10 + 1));
233 secd_test_setup_temp_keychain(__FUNCTION__, NULL);
234 tests();
235 #else
236 plan_tests(0);
237 #endif
238 return 0;
239 }