Locksmith icon indicating copy to clipboard operation
Locksmith copied to clipboard

Enumerate all items stored in Keychain

Open kayvink opened this issue 10 years ago • 4 comments
trafficstars

It would be great to have a function that enumerates all items stored in the Keychain

kayvink avatar Aug 11 '15 09:08 kayvink

Would something like this work?

Create an allClasses array on SecurityClass:

public enum SecurityClass: Int {
    case GenericPassword, InternetPassword, Certificate, Key, Identity

    static let allClasses = [GenericPassword, InternetPassword, Certificate, Key, Identity]
}

Then add a public class function to iterate through each class and perform the request, calling the passed handler on success:

public class func each(userAccount: String, itemHandler : NSDictionary -> ()) {
    for securityClass in SecurityClass.allClasses {
        let request = LocksmithRequest(userAccount: userAccount)
        request.type = .Read
        request.securityClass = securityClass
        request.matchLimit = .Many

        let (result, error) = Locksmith.performRequest(request)

        if let result = result {
            itemHandler(result)
        }
    }
}

Usage would look something like this:

Locksmith.each("[email protected]") { result in
    // result is a non-Optional NSDictionary
    print(result)
}

Didn't test it or anything yet.

getaaron avatar Aug 11 '15 11:08 getaaron

Would it be possible to redefine userAccount as optional? I've never tried using the keychain without kSecAttrAccount.

getaaron avatar Aug 11 '15 11:08 getaaron

@kayvink definitely an interesting idea.

@getaaron love the look of that API—that use of trailing closures is super nice 👍

Going off the docs and this StackOverflow post, I think we could either a) make LocksmithRequests userAccount property optional, then make sure we set kSecMatchLimit to all on the request if it's nil; b) make this entirely its own method, and just translate the SO post to Swift. First option appeals to me more.

Also, I wonder what would happen if we set userAccount to "" and set the matchLimit to .Many (which we should rename to .All at some stage) in the current implementation.

Won't have time to play around with this until the weekend, but definitely something that'll be good to include—cheers for the suggestions!

matthewpalmer avatar Aug 11 '15 12:08 matthewpalmer

I'm trying to figure out if this feature is available, or if not, how I can re-create it. I can see where each() was merged into 1.2.2 but it appears to have been re-factored away or removed again since then.

Is there currently a solution or technique that can be used to return either the name or object for all accounts in the keychain?

eliburke avatar Nov 28 '16 18:11 eliburke