2 * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #include "secd_regressions.h"
27 #include <securityd/SecDbItem.h>
28 #include <utilities/array_size.h>
29 #include <utilities/SecCFWrappers.h>
30 #include <utilities/SecFileLocations.h>
31 #include <utilities/fileIo.h>
33 #include <securityd/SecItemServer.h>
35 #include <Security/SecBasePriv.h>
36 #include <Security/SecItemBackup.h>
38 #include <TargetConditionals.h>
39 #include <AssertMacros.h>
41 #import "SecBackupKeybagEntry.h"
45 <rdar://problem/30685971> Add test for keybag table add SPI
46 <rdar://problem/30412884> Create an SPI to add a keybag to the keychain database (Keybag Table)
48 // original secd_35_keychain_migrate_inet
50 sudo defaults write /Library/Preferences/com.apple.security V10SchemaUpgradeTest -bool true
51 sudo defaults read /Library/Preferences/com.apple.security V10SchemaUpgradeTest
58 #include "SecdTestKeychainUtilities.h"
60 static const bool kTestCustomKeybag = false;
61 static const bool kTestLocalKeybag = false;
63 void SecAccessGroupsSetCurrent(CFArrayRef accessGroups);
64 CFArrayRef SecAccessGroupsGetCurrent(void);
66 #define kSecdTestCreateCustomKeybagTestCount 6
67 #define kSecdTestLocalKeybagTestCount 1
68 #define kSecdTestKeybagtableTestCount 5
69 #define kSecdTestAddItemTestCount 2
71 #define DATA_ARG(x) (x) ? CFDataGetBytePtr((x)) : NULL, (x) ? (int)CFDataGetLength((x)) : 0
73 // copied from si-33-keychain-backup.c
74 static CFDataRef create_keybag(keybag_handle_t bag_type, CFDataRef password)
76 keybag_handle_t handle = bad_keybag_handle;
78 if (aks_create_bag(DATA_ARG(password), bag_type, &handle) == 0) {
81 if (aks_save_bag(handle, &keybag, &keybag_size) == 0) {
82 return CFDataCreate(kCFAllocatorDefault, keybag, keybag_size);
86 return CFDataCreate(kCFAllocatorDefault, NULL, 0);
89 static bool createCustomKeybag() {
91 keybag_handle_t keybag;
93 char *passcode="password";
94 int passcode_len=(int)strlen(passcode);
95 const bool kTestLockedKeybag = false;
97 ok(kIOReturnSuccess==aks_create_bag(passcode, passcode_len, kAppleKeyStoreDeviceBag, &keybag), "create keybag");
98 ok(kIOReturnSuccess==aks_get_lock_state(keybag, &state), "get keybag state");
99 ok(!(state&keybag_state_locked), "keybag unlocked");
100 SecItemServerSetKeychainKeybag(keybag);
102 if (kTestLockedKeybag) {
104 ok(kIOReturnSuccess==aks_lock_bag(keybag), "lock keybag");
105 ok(kIOReturnSuccess==aks_get_lock_state(keybag, &state), "get keybag state");
106 ok(state&keybag_state_locked, "keybag locked");
112 static int keychainTestEnvironment(const char *environmentName, dispatch_block_t do_in_reset, dispatch_block_t do_in_environment) {
116 CFArrayRef old_ag = SecAccessGroupsGetCurrent();
117 CFMutableArrayRef test_ag = CFArrayCreateMutableCopy(NULL, 0, old_ag);
118 CFArrayAppendValue(test_ag, CFSTR("test"));
119 SecAccessGroupsSetCurrent(test_ag);
121 secd_test_setup_temp_keychain(environmentName, do_in_reset);
122 bool haveCustomKeybag = kTestCustomKeybag && createCustomKeybag();
124 // Perform tasks in the test keychain environment
125 if (do_in_environment)
133 if (haveCustomKeybag)
134 SecItemServerResetKeychainKeybag();
136 // Reset server accessgroups
137 SecAccessGroupsSetCurrent(old_ag);
138 CFReleaseSafe(test_ag);
139 // Reset custom $HOME
140 SetCustomHomePath(NULL);
141 SecKeychainDbReset(NULL);
145 static int addOneItemTest(NSString *account) {
146 /* Creating a password */
147 const char *v_data = "test";
148 CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data));
150 NSDictionary *item = @{
151 (__bridge NSString *)kSecClass : (__bridge NSString *)kSecClassInternetPassword,
152 (__bridge NSString *)kSecAttrServer : @"members.spamcop.net",
153 (__bridge NSString *)kSecAttrAccount : account, // e.g. @"smith",
154 (__bridge NSString *)kSecAttrPort : @80,
155 (__bridge NSString *)kSecAttrProtocol : @"http",
156 (__bridge NSString *)kSecAttrAuthenticationType : @"dflt",
157 (__bridge NSString *)kSecValueData : (__bridge NSData *)pwdata
160 ok_status(SecItemAdd((CFDictionaryRef)item, NULL), "add internet password, while unlocked");
161 CFReleaseSafe(pwdata);
165 static int localKeybagTest() {
166 const char *pass = "sup3rsekretpassc0de";
167 CFDataRef password = CFDataCreate(NULL, (UInt8 *)pass, strlen(pass));
168 CFDataRef keybag = create_keybag(kAppleKeyStoreAsymmetricBackupBag, password);
170 CFReleaseNull(keybag);
171 CFReleaseNull(password);
175 static int test_keybagtable() {
176 CFErrorRef error = NULL;
177 const char *pass = "sup3rsekretpassc0de";
178 CFDataRef password = CFDataCreate(NULL, (UInt8 *)pass, strlen(pass));
179 CFDataRef identifier = NULL;
180 CFURLRef pathinfo = NULL;
182 ok(SecBackupKeybagAdd(password, &identifier, &pathinfo, &error));
183 CFReleaseNull(error);
185 NSDictionary *deleteQuery = @{(__bridge NSString *)kSecAttrPublicKeyHash:(__bridge NSData *)identifier};
186 ok(SecBackupKeybagDelete((__bridge CFDictionaryRef)deleteQuery, &error));
188 ok(SecBackupKeybagAdd(password, &identifier, &pathinfo, &error));
189 CFReleaseNull(error);
191 ok(SecBackupKeybagAdd(password, &identifier, &pathinfo, &error));
192 CFReleaseNull(error);
194 NSDictionary *deleteAllQuery = @{(id)kSecMatchLimit: (id)kSecMatchLimitAll};
195 ok(SecBackupKeybagDelete((__bridge CFDictionaryRef)deleteAllQuery, &error));
197 CFReleaseNull(identifier);
198 CFReleaseNull(pathinfo);
199 CFReleaseNull(password);
200 CFReleaseNull(error);
204 static void showHomeURL() {
206 CFURLRef homeURL = SecCopyHomeURL();
207 NSLog(@"Home URL for test : %@", homeURL);
208 CFReleaseSafe(homeURL);
212 int secd_230_keybagtable(int argc, char *const *argv)
214 int testcount = kSecdTestSetupTestCount + kSecdTestKeybagtableTestCount + kSecdTestAddItemTestCount;
215 if (kTestLocalKeybag)
216 testcount += kSecdTestLocalKeybagTestCount;
217 if (kTestCustomKeybag)
218 testcount += kSecdTestCreateCustomKeybagTestCount;
219 plan_tests(testcount);
221 dispatch_block_t run_tests = ^{
223 if (kTestLocalKeybag)
225 addOneItemTest(@"smith");
227 addOneItemTest(@"jones");
230 dispatch_block_t do_in_reset = NULL;
231 dispatch_block_t do_in_environment = run_tests;
233 keychainTestEnvironment("secd_230_keybagtable", do_in_reset, do_in_environment);
240 int secd_230_keybagtable(int argc, char *const *argv)
245 todo("Not yet working in simulator");
250 /* not implemented in simulator (no keybag) */