Calls to the the Keychain Services fail with errSecNotAvailable when executing a target using the command line tools and the iphone simulator is set to Hardware version 6.0 (10A403). If I change the simulator version to other previous version (4.3, 5.0, 5.1) and re-execute using the same command line script the calls succeed.
I'm running latest XCode 4.5 and the command line tools were downloaded from within XCode.
To reproduce this error just do the following:
Execute the OCUnit target in XCode and see the test pass with whatever Hardware Version is set in the iphone simulator (just change it between executions).
Execute the OCUnit target from the command line using:
xcodebuild -target TARGET_NAME_HERE -sdk iphonesimulator -configuration Release TEST_AFTER_BUILD=YES
with iphone simulator set to Hardware Version 6.0 and the test will fail. If you change the iphone simulator Hardware Version to 4.3, 5.0 or 5.1 and execute the command line script again the test will succeed.
Is this a command line tool problem? an iphone simulator problem? an OCUnit target running from the command line problem?
Who likes having unit tests that only pass when comets are aligned??
Any ideas?
Here is the code:
#define KEYCHAIN_ITEM_ATTRIBUTES (id)kSecClassGenericPassword, kSecClass, @"MyService", kSecAttrService, @"MyPassword", kSecAttrAccount
const NSString* MyPassword = @"blabla";
- (void)testExample
{
// remove previous keychain item
OSStatus status = SecItemDelete((CFTypeRef)[NSDictionary dictionaryWithObjectsAndKeys:KEYCHAIN_ITEM_ATTRIBUTES, nil]);
NSLog(@"SecItemDelete status:%ld",status);
NSParameterAssert(status == errSecSuccess || status == errSecItemNotFound);
// add keychain item with new value
NSData *data = [MyPassword dataUsingEncoding:NSUTF8StringEncoding];
status = SecItemAdd((CFTypeRef)[NSDictionary dictionaryWithObjectsAndKeys:KEYCHAIN_ITEM_ATTRIBUTES, data, kSecValueData, nil], NULL);
NSLog(@"SecItemAdd status:%ld",status);
NSParameterAssert(status == errSecSuccess);
// get password
status = SecItemCopyMatching((CFTypeRef)[NSDictionary dictionaryWithObjectsAndKeys:KEYCHAIN_ITEM_ATTRIBUTES,
kSecMatchLimitOne, kSecMatchLimit, kCFBooleanTrue, kSecReturnData, nil], (CFTypeRef *)&data);
NSLog(@"SecItemCopyMatching status:%ld",status);
NSParameterAssert(status == errSecSuccess);
if (status == errSecItemNotFound)
NSLog(@"SecItemCopyMatching status:%ld", status);
else
NSLog(@"SecItemCopyMatching result:%@",[[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]);
}
Regarding securityd daemon not being launched, I can check it IS being launched, using
launchctl list | grep securityd
after the simulator starts, and getting
- 0 com.apple.iPhoneSimulator:com.apple.securityd
I also tried stopping this securityd daemon and launch another manually... I looked at GTM's RunIPhoneUnitTest.sh script for a simple line I could use, but when I try this
launchctl submit -l ios6securityd -- /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.0.sdk/usr/libexec/securityd
gives me a -5 status code on that daemon.
I came across this because I was having trouble getting keychain access when trying to run my unit tests from the Xcode 4.5.1 UI. Luckily, the breakage is something I'm familiar with from CI builds with most previous Xcode versions as well, which is that the simulator's securityd isn't properly launched.
Try launching securityd first, and see if that helps:
#!/bin/bash
simulator_root=`xcodebuild -version -sdk iphonesimulator Path`
"${simulator_root}/usr/libexec/securityd"
That worked for me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With