Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Perform class check on kSecAttrAccount keychain value during migration #114

Merged
merged 1 commit into from Aug 14, 2017
Merged

Perform class check on kSecAttrAccount keychain value during migration #114

merged 1 commit into from Aug 14, 2017

Conversation

kgleong
Copy link
Contributor

@kgleong kgleong commented Aug 12, 2017

@@ -974,7 +974,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Xcode wouldn't build unless this was > 8.0

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be a breaking change, requiring a major version bump. Let's revert this part of the change since it'll affect people using us in submodules?

Copy link
Collaborator

@dfed dfed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to revert the breaking change and bump a bugfix version in the podspec before this can be merged. Good fix & test though! Appreciate the change :)

@@ -974,7 +974,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be a breaking change, requiring a major version bump. Let's revert this part of the change since it'll affect people using us in submodules?

@kgleong
Copy link
Contributor Author

kgleong commented Aug 12, 2017

@dfed that makes sense. I've removed the deployment target change

@dfed
Copy link
Collaborator

dfed commented Aug 12, 2017

Looks like CI is failing

/Users/travis/build/square/Valet/ValetTests/ValetTests.m:684: error: -[KeychainTests test_migrateObjectsMatchingQueryRemoveOnCompletion_withExistingAccountNameNSDataKeychainEntry_doesNotRaiseException] : ((error) == nil) failed: "Error Domain=VALMigrationErrorDomain Code=4 "(null)""

Possible that CI is running against a different SDK that didn't have this issue?

@kgleong
Copy link
Contributor Author

kgleong commented Aug 12, 2017

ah, looks like the mac test failed. apparently adding an NSData entry for kSecAttrAccount is discarded by OSX but not iOS. Seems like an Apple inconsistency that they enforce it on OSX but not iOS, though perhaps it's due to backwards compat issues.

when inspecting the keychain during migration in OSX:

(lldb) po keychainEntry
{
    cdat = "2017-08-12 11:37:39 +0000";
    class = genp;
    labl = "Keychain_With_Account_Name_As_NSData";
    mdat = "2017-08-12 11:37:39 +0000";
    svce = "Keychain_With_Account_Name_As_NSData";
    "v_Data" = <666f6f>;
    "v_PersistentRef" = <...>;
}

in iOS:

(lldb) po keychainEntry
{
    acct = <666f6f>;
    agrp = "9XUJ7M53NG.com.squareup.Valet-iOS-Test-Host-App";
    cdat = "2017-08-12 11:35:45 +0000";
    mdat = "2017-08-12 11:35:45 +0000";
    musr = <>;
    pdmn = ak;
    svce = "Keychain_With_Account_Name_As_NSData";
    sync = 0;
    tomb = 0;
    "v_Data" = <666f6f>;
    "v_PersistentRef" = <67656e70 00000000 00000325>;
}

for (VALValet *const additionalValet in self.additionalValets) {
[additionalValet removeAllObjects];
}

for (NSDictionary *keychainEntry in self.manualKeychainEntries) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems much simpler to do this than some of the other workarounds to reset the keychain:

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like a reasonable solution! Since this cleanup is needed for only one test may be best to keep the cleanup localized to that test. I'm a big fan of putting the cleanup at the top of the test, so if tearDown is aborted the next run of the test still succeeds.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, what about a finally block? I didn't know this existed and it does the same thing i wanted to get out of tearDown(): something that is ensured to run regardless of whether an exception is thrown and execution stops.

NSDictionary *keychainEntry = <..>

@try {
.. all the code
}
@finally {
  SecItemDelete(keychainEntry);
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm throwing straw men out there now (but I have been bit by these in the past): finally won't prevent against

  • Hitting cmd+. in the middle of the test
  • Another test polluting the keychain

Normally I don't protect against these kinds of issues in my tests. But since keychain is both persistent and a black box I like to control for as many factors as I can in each test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah gotcha. thanks for all the tips and the open source search terms

@dfed
Copy link
Collaborator

dfed commented Aug 12, 2017

Really good find re Mac/iOS not having the same implementation here. Not surprising at all – there are lovely subtle differences between the two implementations... keychain on iOS and Mac have entirely different implementations under then hood (the code is open source). Thank you again for the fix! Last thing before we get an approval is making the test more resilient to a rerun after failing halfway through the prior run. Almost there!

(Keychain is always more complex than it looks. Always. 😅)

@kgleong
Copy link
Contributor Author

kgleong commented Aug 13, 2017

where does one find the open source code? i remember @EricMuller22 entering some magical google search term...

@dfed
Copy link
Collaborator

dfed commented Aug 13, 2017

I tend to google "Apple open source secitem" 🙂

Here's some of it: https://opensource.apple.com/source/Security/Security-55471/sec/Security/SecItem.c

…ncheck.

* #113
* `(migrateObjectsMatchingQuery: removeOnCompletion:)` assumes that data in `kSecAttrAccount` is a NSString.
* This can cause a crash if the value in kSecAttrAccount is an NSData object, for example.
@kgleong
Copy link
Contributor Author

kgleong commented Aug 13, 2017

@dfed I placed the SecItemDelete back in its previous place (as early as possible in the test)

@dfed
Copy link
Collaborator

dfed commented Aug 13, 2017

@EricMuller22 want to merge/release? I'll get to it tomorrow if not.

@EricMuller22
Copy link
Collaborator

LGTM, I'll let you handle merge/release though @dfed, going to be in meetings all day 😞

@kgleong
Copy link
Contributor Author

kgleong commented Dec 2, 2017

Posted this SO question https://stackoverflow.com/questions/47602876 to see if anyone knows why OSX and iOS handle NSData objects in kSecAttrAccount differently. fyi @EricMuller22 @dfed

@kgleong kgleong deleted the kgleong/class-check branch December 2, 2017 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants