From 728e12e6816d6e1ff8ecf95bed1403e0f2fb9b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=A9=E8=BE=BA=E7=BE=85=E3=82=A8=E3=83=AB=E3=83=8D?= =?UTF-8?q?=E3=82=B9=E3=83=88?= Date: Wed, 23 Apr 2014 16:16:29 +0900 Subject: [PATCH] Update SSKeychain There was no reason to use an outdated version. * Updated the source files. * Updated podspec. Everything works. Closes #84. --- Evernote-SDK-iOS.podspec | 2 +- evernote-sdk-ios.xcodeproj/project.pbxproj | 8 + evernote-sdk-ios/3rdParty/SSKeychain/LICENSE | 2 +- .../3rdParty/SSKeychain/SSKeychain.h | 312 ++++-------------- .../3rdParty/SSKeychain/SSKeychain.m | 234 ++----------- .../3rdParty/SSKeychain/SSKeychainQuery.h | 133 ++++++++ .../3rdParty/SSKeychain/SSKeychainQuery.m | 282 ++++++++++++++++ 7 files changed, 516 insertions(+), 457 deletions(-) mode change 100755 => 100644 evernote-sdk-ios/3rdParty/SSKeychain/LICENSE create mode 100644 evernote-sdk-ios/3rdParty/SSKeychain/SSKeychainQuery.h create mode 100644 evernote-sdk-ios/3rdParty/SSKeychain/SSKeychainQuery.m diff --git a/Evernote-SDK-iOS.podspec b/Evernote-SDK-iOS.podspec index f52f88c..c6cdc08 100644 --- a/Evernote-SDK-iOS.podspec +++ b/Evernote-SDK-iOS.podspec @@ -15,5 +15,5 @@ Pod::Spec.new do |s| s.libraries = 'xml2' s.xcconfig = { 'HEADER_SEARCH_PATHS' => '"$(SDKROOT)/usr/include/libxml2"' } - s.dependency 'SSKeychain', '0.2.1' + s.dependency 'SSKeychain', '~> 1.2.2' end diff --git a/evernote-sdk-ios.xcodeproj/project.pbxproj b/evernote-sdk-ios.xcodeproj/project.pbxproj index b338de0..800dc6e 100755 --- a/evernote-sdk-ios.xcodeproj/project.pbxproj +++ b/evernote-sdk-ios.xcodeproj/project.pbxproj @@ -244,6 +244,8 @@ A9FDF718165C5C7200DC7E4B /* ENConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = A9FDF716165C5C7100DC7E4B /* ENConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; A9FDF719165C5C7200DC7E4B /* ENConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = A9FDF717165C5C7100DC7E4B /* ENConstants.m */; }; A9FDF71B165C5D0300DC7E4B /* ENConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = A9FDF717165C5C7100DC7E4B /* ENConstants.m */; }; + E55E707119079EAC008B1648 /* SSKeychainQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = E55E706F19079EAC008B1648 /* SSKeychainQuery.h */; }; + E55E707219079EAC008B1648 /* SSKeychainQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = E55E707019079EAC008B1648 /* SSKeychainQuery.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -463,6 +465,8 @@ A9D166C4169151D600043DA0 /* TObjective-C.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TObjective-C.h"; sourceTree = ""; }; A9FDF716165C5C7100DC7E4B /* ENConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ENConstants.h; sourceTree = ""; }; A9FDF717165C5C7100DC7E4B /* ENConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ENConstants.m; sourceTree = ""; }; + E55E706F19079EAC008B1648 /* SSKeychainQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSKeychainQuery.h; sourceTree = ""; }; + E55E707019079EAC008B1648 /* SSKeychainQuery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSKeychainQuery.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -795,6 +799,8 @@ 0BF0CF7E152E25E1003D6115 /* LICENSE */, 0BF0CF7F152E25E1003D6115 /* SSKeychain.h */, 0BF0CF80152E25E1003D6115 /* SSKeychain.m */, + E55E706F19079EAC008B1648 /* SSKeychainQuery.h */, + E55E707019079EAC008B1648 /* SSKeychainQuery.m */, ); path = SSKeychain; sourceTree = ""; @@ -988,6 +994,7 @@ 0B943F721525015500DB20A3 /* TProcessorFactory.h in Headers */, 0B943F731525015500DB20A3 /* THTTPClient.h in Headers */, A9BE47D7178200B400471BF7 /* ENEncryptedContentInfo.h in Headers */, + E55E707119079EAC008B1648 /* SSKeychainQuery.h in Headers */, A9BE47DA178200B400471BF7 /* ENMIMEUtils.h in Headers */, A9BE47DD178200B400471BF7 /* ENMLWriter.h in Headers */, A9BE47E0178200B400471BF7 /* ENXMLDTD.h in Headers */, @@ -1251,6 +1258,7 @@ A9BE47DB178200B400471BF7 /* ENMIMEUtils.m in Sources */, A9BE47DE178200B400471BF7 /* ENMLWriter.m in Sources */, A9BE47E1178200B400471BF7 /* ENXMLDTD.m in Sources */, + E55E707219079EAC008B1648 /* SSKeychainQuery.m in Sources */, A9BE47E5178200B400471BF7 /* ENXMLWriter.m in Sources */, A9BE47EE178200B400471BF7 /* NSRegularExpression+ENAGRegex.m in Sources */, A9BE47F1178200B400471BF7 /* NSString+EDAMAdditions.m in Sources */, diff --git a/evernote-sdk-ios/3rdParty/SSKeychain/LICENSE b/evernote-sdk-ios/3rdParty/SSKeychain/LICENSE old mode 100755 new mode 100644 index ab23a91..2ed16bd --- a/evernote-sdk-ios/3rdParty/SSKeychain/LICENSE +++ b/evernote-sdk-ios/3rdParty/SSKeychain/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2010-2011 Sam Soffes. +Copyright (c) 2010-2014 Sam Soffes, http://soff.es Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/evernote-sdk-ios/3rdParty/SSKeychain/SSKeychain.h b/evernote-sdk-ios/3rdParty/SSKeychain/SSKeychain.h index 0d27bd0..3fcb2de 100644 --- a/evernote-sdk-ios/3rdParty/SSKeychain/SSKeychain.h +++ b/evernote-sdk-ios/3rdParty/SSKeychain/SSKeychain.h @@ -1,50 +1,24 @@ // // SSKeychain.h -// SSToolkit +// SSKeychain // // Created by Sam Soffes on 5/19/10. -// Copyright (c) 2009-2011 Sam Soffes. All rights reserved. +// Copyright (c) 2010-2014 Sam Soffes. All rights reserved. // -#import -#import +#import "SSKeychainQuery.h" -/** Error codes that can be returned in NSError objects. */ -typedef enum { - /** No error. */ - SSKeychainErrorNone = noErr, - +/** + Error code specific to SSKeychain that can be returned in NSError objects. + For codes returned by the operating system, refer to SecBase.h for your + platform. + */ +typedef NS_ENUM(OSStatus, SSKeychainErrorCode) { /** Some of the arguments were invalid. */ SSKeychainErrorBadArguments = -1001, - - /** There was no password. */ - SSKeychainErrorNoPassword = -1002, - - /** One or more parameters passed internally were not valid. */ - SSKeychainErrorInvalidParameter = errSecParam, - - /** Failed to allocate memory. */ - SSKeychainErrorFailedToAllocated = errSecAllocate, - - /** No trust results are available. */ - SSKeychainErrorNotAvailable = errSecNotAvailable, - - /** Authorization/Authentication failed. */ - SSKeychainErrorAuthorizationFailed = errSecAuthFailed, - - /** The item already exists. */ - SSKeychainErrorDuplicatedItem = errSecDuplicateItem, - - /** The item cannot be found.*/ - SSKeychainErrorNotFound = errSecItemNotFound, - - /** Interaction with the Security Server is not allowed. */ - SSKeychainErrorInteractionNotAllowed = errSecInteractionNotAllowed, - - /** Unable to decode the provided data. */ - SSKeychainErrorFailedToDecode = errSecDecode -} SSKeychainErrorCode; +}; +/** SSKeychain error domain */ extern NSString *const kSSKeychainErrorDomain; /** Account name. */ @@ -52,7 +26,7 @@ extern NSString *const kSSKeychainAccountKey; /** Time the item was created. - + The value will be a string. */ extern NSString *const kSSKeychainCreatedAtKey; @@ -67,7 +41,7 @@ extern NSString *const kSSKeychainDescriptionKey; extern NSString *const kSSKeychainLabelKey; /** Time the item was last modified. - + The value will be a string. */ extern NSString *const kSSKeychainLastModifiedKey; @@ -78,277 +52,107 @@ extern NSString *const kSSKeychainWhereKey; /** Simple wrapper for accessing accounts, getting passwords, setting passwords, and deleting passwords using the system Keychain on Mac OS X and iOS. - + This was originally inspired by EMKeychain and SDKeychain (both of which are now gone). Thanks to the authors. SSKeychain has since switched to a simpler implementation that was abstracted from [SSToolkit](http://sstoolk.it). */ @interface SSKeychain : NSObject -///----------------------- -/// @name Getting Accounts -///----------------------- - -/** - Returns an array containing the Keychain's accounts, or `nil` if the Keychain has no accounts. - - See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the - dictionaries returned by this method. - - @return An array of dictionaries containing the Keychain's accounts, or `nil` if the Keychain doesn't have any - accounts. The order of the objects in the array isn't defined. - - @see allAccounts: - */ -+ (NSArray *)allAccounts; - -/** - Returns an array containing the Keychain's accounts, or `nil` if the Keychain doesn't have any - accounts. - - See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the - dictionaries returned by this method. - - @param error If accessing the accounts fails, upon return contains an error that describes the problem. - - @return An array of dictionaries containing the Keychain's accounts, or `nil` if the Keychain doesn't have any - accounts. The order of the objects in the array isn't defined. - - @see allAccounts - */ -+ (NSArray *)allAccounts:(NSError **)error; - -/** - Returns an array containing the Keychain's accounts for a given service, or `nil` if the Keychain doesn't have any - accounts for the given service. - - See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the - dictionaries returned by this method. - - @param serviceName The service for which to return the corresponding accounts. - - @return An array of dictionaries containing the Keychain's accountsfor a given `serviceName`, or `nil` if the Keychain - doesn't have any accounts for the given `serviceName`. The order of the objects in the array isn't defined. - - @see accountsForService:error: - */ -+ (NSArray *)accountsForService:(NSString *)serviceName; - -/** - Returns an array containing the Keychain's accounts for a given service, or `nil` if the Keychain doesn't have any - accounts for the given service. - - @param serviceName The service for which to return the corresponding accounts. - - @param error If accessing the accounts fails, upon return contains an error that describes the problem. - - @return An array of dictionaries containing the Keychain's accountsfor a given `serviceName`, or `nil` if the Keychain - doesn't have any accounts for the given `serviceName`. The order of the objects in the array isn't defined. - - @see accountsForService: - */ -+ (NSArray *)accountsForService:(NSString *)serviceName error:(NSError **)error; - - -///------------------------ -/// @name Getting Passwords -///------------------------ +#pragma mark - Classic methods /** Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't have a password for the given parameters. - - @param serviceName The service for which to return the corresponding password. - - @param account The account for which to return the corresponding password. - - @return Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't - have a password for the given parameters. - - @see passwordForService:account:error: - */ -+ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account; -/** - Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't have a - password for the given parameters. - @param serviceName The service for which to return the corresponding password. - - @param account The account for which to return the corresponding password. - - @param error If accessing the password fails, upon return contains an error that describes the problem. - - @return Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't - have a password for the given parameters. - - @see passwordForService:account: - */ -+ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; -/** - Returns the password data for a given account and service, or `nil` if the Keychain doesn't have data - for the given parameters. - - @param serviceName The service for which to return the corresponding password. - @param account The account for which to return the corresponding password. - - @param error If accessing the password fails, upon return contains an error that describes the problem. - - @return Returns a the password data for the given account and service, or `nil` if the Keychain doesn't - have data for the given parameters. - - @see passwordDataForService:account:error: - */ -+ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account; -/** - Returns the password data for a given account and service, or `nil` if the Keychain doesn't have data - for the given parameters. - - @param serviceName The service for which to return the corresponding password. - - @param account The account for which to return the corresponding password. - - @param error If accessing the password fails, upon return contains an error that describes the problem. - - @return Returns a the password data for the given account and service, or `nil` if the Keychain doesn't + @return Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't have a password for the given parameters. - - @see passwordDataForService:account: */ -+ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; - ++ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account; ++ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; -///------------------------- -/// @name Deleting Passwords -///------------------------- /** Deletes a password from the Keychain. - - @param serviceName The service for which to delete the corresponding password. - - @param account The account for which to delete the corresponding password. - - @return Returns `YES` on success, or `NO` on failure. - - @see deletePasswordForService:account:error: - */ -+ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account; -/** - Deletes a password from the Keychain. - @param serviceName The service for which to delete the corresponding password. - + @param account The account for which to delete the corresponding password. - - @param error If deleting the password fails, upon return contains an error that describes the problem. - + @return Returns `YES` on success, or `NO` on failure. - - @see deletePasswordForService:account: */ ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account; + (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; -///------------------------ -/// @name Setting Passwords -///------------------------ - /** Sets a password in the Keychain. - - @param password The password to store in the Keychain. - - @param serviceName The service for which to set the corresponding password. - - @param account The account for which to set the corresponding password. - - @return Returns `YES` on success, or `NO` on failure. - - @see setPassword:forService:account:error: - */ -+ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account; -/** - Sets a password in the Keychain. - @param password The password to store in the Keychain. - + @param serviceName The service for which to set the corresponding password. - + @param account The account for which to set the corresponding password. - - @param error If setting the password fails, upon return contains an error that describes the problem. - + @return Returns `YES` on success, or `NO` on failure. - - @see setPassword:forService:account: */ ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account; + (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; + /** - Sets arbirary data in the Keychain. - - @param password The data to store in the Keychain. - - @param serviceName The service for which to set the corresponding password. - - @param account The account for which to set the corresponding password. - - @param error If setting the password fails, upon return contains an error that describes the problem. - - @return Returns `YES` on success, or `NO` on failure. - - @see setPasswordData:forService:account:error: + Returns an array containing the Keychain's accounts, or `nil` if the Keychain has no accounts. + + See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the + dictionaries returned by this method. + + @return An array of dictionaries containing the Keychain's accounts, or `nil` if the Keychain doesn't have any + accounts. The order of the objects in the array isn't defined. */ -+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account; ++ (NSArray *)allAccounts; + /** - Sets arbirary data in the Keychain. - - @param password The data to store in the Keychain. - - @param serviceName The service for which to set the corresponding password. - - @param account The account for which to set the corresponding password. - - @param error If setting the password fails, upon return contains an error that describes the problem. - - @return Returns `YES` on success, or `NO` on failure. - - @see setPasswordData:forService:account: + Returns an array containing the Keychain's accounts for a given service, or `nil` if the Keychain doesn't have any + accounts for the given service. + + See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the + dictionaries returned by this method. + + @param serviceName The service for which to return the corresponding accounts. + + @return An array of dictionaries containing the Keychain's accountsfor a given `serviceName`, or `nil` if the Keychain + doesn't have any accounts for the given `serviceName`. The order of the objects in the array isn't defined. */ -+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; ++ (NSArray *)accountsForService:(NSString *)serviceName; -///-------------------- -/// @name Configuration -///-------------------- +#pragma mark - Configuration #if __IPHONE_4_0 && TARGET_OS_IPHONE /** Returns the accessibility type for all future passwords saved to the Keychain. - + @return Returns the accessibility type. - - The return value will be `NULL` or one of the "Keychain Item Accessibility Constants" used for determining when a - keychain item should be readable. - - @see accessibilityType + + The return value will be `NULL` or one of the "Keychain Item Accessibility + Constants" used for determining when a keychain item should be readable. + + @see setAccessibilityType */ + (CFTypeRef)accessibilityType; /** Sets the accessibility type for all future passwords saved to the Keychain. - - @param accessibilityType One of the "Keychain Item Accessibility Constants" used for determining when a keychain item - should be readable. - + + @param accessibilityType One of the "Keychain Item Accessibility Constants" + used for determining when a keychain item should be readable. + If the value is `NULL` (the default), the Keychain default will be used. - + @see accessibilityType */ + (void)setAccessibilityType:(CFTypeRef)accessibilityType; diff --git a/evernote-sdk-ios/3rdParty/SSKeychain/SSKeychain.m b/evernote-sdk-ios/3rdParty/SSKeychain/SSKeychain.m index b3a4712..36337ba 100644 --- a/evernote-sdk-ios/3rdParty/SSKeychain/SSKeychain.m +++ b/evernote-sdk-ios/3rdParty/SSKeychain/SSKeychain.m @@ -1,15 +1,14 @@ // // SSKeychain.m -// SSToolkit +// SSKeychain // // Created by Sam Soffes on 5/19/10. -// Copyright (c) 2009-2011 Sam Soffes. All rights reserved. +// Copyright (c) 2010-2014 Sam Soffes. All rights reserved. // #import "SSKeychain.h" NSString *const kSSKeychainErrorDomain = @"com.samsoffes.sskeychain"; - NSString *const kSSKeychainAccountKey = @"acct"; NSString *const kSSKeychainCreatedAtKey = @"cdat"; NSString *const kSSKeychainClassKey = @"labl"; @@ -18,203 +17,66 @@ NSString *const kSSKeychainLastModifiedKey = @"mdat"; NSString *const kSSKeychainWhereKey = @"svce"; -#if __IPHONE_4_0 && TARGET_OS_IPHONE -CFTypeRef SSKeychainAccessibilityType = NULL; +#if __IPHONE_4_0 && TARGET_OS_IPHONE + static CFTypeRef SSKeychainAccessibilityType = NULL; #endif -@interface SSKeychain () -+ (NSMutableDictionary *)_queryForService:(NSString *)service account:(NSString *)account; -@end - @implementation SSKeychain -#pragma mark - Getting Accounts - -+ (NSArray *)allAccounts { - return [self accountsForService:nil error:nil]; ++ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account { + return [self passwordForService:serviceName account:account error:nil]; } -+ (NSArray *)allAccounts:(NSError **)error { - return [self accountsForService:nil error:error]; ++ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError *__autoreleasing *)error { + SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; + query.service = serviceName; + query.account = account; + [query fetch:error]; + return query.password; } -+ (NSArray *)accountsForService:(NSString *)service { - return [self accountsForService:service error:nil]; ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account { + return [self deletePasswordForService:serviceName account:account error:nil]; } -+ (NSArray *)accountsForService:(NSString *)service error:(NSError **)error { - OSStatus status = SSKeychainErrorBadArguments; - NSMutableDictionary *query = [self _queryForService:service account:nil]; -#if __has_feature(objc_arc) - [query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnAttributes]; - [query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit]; -#else - [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes]; - [query setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit]; -#endif - - CFTypeRef result = NULL; -#if __has_feature(objc_arc) - status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); -#else - status = SecItemCopyMatching((CFDictionaryRef)query, &result); -#endif - if (status != noErr && error != NULL) { - *error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil]; - return nil; - } - -#if __has_feature(objc_arc) - return (__bridge_transfer NSArray *)result; -#else - return [(NSArray *)result autorelease]; -#endif ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError *__autoreleasing *)error { + SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; + query.service = serviceName; + query.account = account; + return [query deleteItem:error]; } -#pragma mark - Getting Passwords - -+ (NSString *)passwordForService:(NSString *)service account:(NSString *)account { - return [self passwordForService:service account:account error:nil]; ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account { + return [self setPassword:password forService:serviceName account:account error:nil]; } -+ (NSString *)passwordForService:(NSString *)service account:(NSString *)account error:(NSError **)error { - NSData *data = [self passwordDataForService:service account:account error:error]; - if (data.length > 0) { - NSString *string = [[NSString alloc] initWithData:(NSData *)data encoding:NSUTF8StringEncoding]; -#if !__has_feature(objc_arc) - [string autorelease]; -#endif - return string; - } - - return nil; ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError *__autoreleasing *)error { + SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; + query.service = serviceName; + query.account = account; + query.password = password; + return [query save:error]; } -+ (NSData *)passwordDataForService:(NSString *)service account:(NSString *)account { - return [self passwordDataForService:service account:account error:nil]; -} - - -+ (NSData *)passwordDataForService:(NSString *)service account:(NSString *)account error:(NSError **)error { - OSStatus status = SSKeychainErrorBadArguments; - if (!service || !account) { - if (error) { - *error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil]; - } - return nil; - } - - CFTypeRef result = NULL; - NSMutableDictionary *query = [self _queryForService:service account:account]; -#if __has_feature(objc_arc) - [query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData]; - [query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; - status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); -#else - [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; - [query setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; - status = SecItemCopyMatching((CFDictionaryRef)query, &result); -#endif - - if (status != noErr && error != NULL) { - *error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil]; - return nil; - } - -#if __has_feature(objc_arc) - return (__bridge_transfer NSData *)result; -#else - return [(NSData *)result autorelease]; -#endif -} - - -#pragma mark - Deleting Passwords - -+ (BOOL)deletePasswordForService:(NSString *)service account:(NSString *)account { - return [self deletePasswordForService:service account:account error:nil]; -} - - -+ (BOOL)deletePasswordForService:(NSString *)service account:(NSString *)account error:(NSError **)error { - OSStatus status = SSKeychainErrorBadArguments; - if (service && account) { - NSMutableDictionary *query = [self _queryForService:service account:account]; -#if __has_feature(objc_arc) - status = SecItemDelete((__bridge CFDictionaryRef)query); -#else - status = SecItemDelete((CFDictionaryRef)query); -#endif - } - if (status != noErr && error != NULL) { - *error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil]; - } - return (status == noErr); - -} - - -#pragma mark - Setting Passwords - -+ (BOOL)setPassword:(NSString *)password forService:(NSString *)service account:(NSString *)account { - return [self setPassword:password forService:service account:account error:nil]; -} - - -+ (BOOL)setPassword:(NSString *)password forService:(NSString *)service account:(NSString *)account error:(NSError **)error { - NSData *data = [password dataUsingEncoding:NSUTF8StringEncoding]; - return [self setPasswordData:data forService:service account:account error:error]; ++ (NSArray *)allAccounts { + return [self accountsForService:nil]; } -+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)service account:(NSString *)account { - return [self setPasswordData:password forService:service account:account error:nil]; ++ (NSArray *)accountsForService:(NSString *)serviceName { + SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; + query.service = serviceName; + return [query fetchAll:nil]; } -+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)service account:(NSString *)account error:(NSError **)error { - OSStatus status = SSKeychainErrorBadArguments; - if (password && service && account) { - [self deletePasswordForService:service account:account]; - NSMutableDictionary *query = [self _queryForService:service account:account]; -#if __has_feature(objc_arc) - [query setObject:password forKey:(__bridge id)kSecValueData]; -#else - [query setObject:password forKey:(id)kSecValueData]; -#endif - #if __IPHONE_4_0 && TARGET_OS_IPHONE - if (SSKeychainAccessibilityType) { -#if __has_feature(objc_arc) - [query setObject:(id)[self accessibilityType] forKey:(__bridge id)kSecAttrAccessible]; -#else - [query setObject:(id)[self accessibilityType] forKey:(id)kSecAttrAccessible]; -#endif - } -#endif - -#if __has_feature(objc_arc) - status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); -#else - status = SecItemAdd((CFDictionaryRef)query, NULL); -#endif - } - if (status != noErr && error != NULL) { - *error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil]; - } - return (status == noErr); -} - - -#pragma mark - Configuration - -#if __IPHONE_4_0 && TARGET_OS_IPHONE + (CFTypeRef)accessibilityType { return SSKeychainAccessibilityType; } @@ -229,34 +91,4 @@ + (void)setAccessibilityType:(CFTypeRef)accessibilityType { } #endif - -#pragma mark - Private - -+ (NSMutableDictionary *)_queryForService:(NSString *)service account:(NSString *)account { - NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:3]; -#if __has_feature(objc_arc) - [dictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; -#else - [dictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; -#endif - - if (service) { -#if __has_feature(objc_arc) - [dictionary setObject:service forKey:(__bridge id)kSecAttrService]; -#else - [dictionary setObject:service forKey:(id)kSecAttrService]; -#endif - } - - if (account) { -#if __has_feature(objc_arc) - [dictionary setObject:account forKey:(__bridge id)kSecAttrAccount]; -#else - [dictionary setObject:account forKey:(id)kSecAttrAccount]; -#endif - } - - return dictionary; -} - @end diff --git a/evernote-sdk-ios/3rdParty/SSKeychain/SSKeychainQuery.h b/evernote-sdk-ios/3rdParty/SSKeychain/SSKeychainQuery.h new file mode 100644 index 0000000..436e2fd --- /dev/null +++ b/evernote-sdk-ios/3rdParty/SSKeychain/SSKeychainQuery.h @@ -0,0 +1,133 @@ +// +// SSKeychainQuery.h +// SSKeychain +// +// Created by Caleb Davenport on 3/19/13. +// Copyright (c) 2013-2014 Sam Soffes. All rights reserved. +// + +#import +#import + +#if __IPHONE_7_0 || __MAC_10_9 + // Keychain synchronization available at compile time + #define SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE 1 +#endif + +#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE +typedef NS_ENUM(NSUInteger, SSKeychainQuerySynchronizationMode) { + SSKeychainQuerySynchronizationModeAny, + SSKeychainQuerySynchronizationModeNo, + SSKeychainQuerySynchronizationModeYes +}; +#endif + +/** + Simple interface for querying or modifying keychain items. + */ +@interface SSKeychainQuery : NSObject + +/** kSecAttrAccount */ +@property (nonatomic, copy) NSString *account; + +/** kSecAttrService */ +@property (nonatomic, copy) NSString *service; + +/** kSecAttrLabel */ +@property (nonatomic, copy) NSString *label; + +#if __IPHONE_3_0 && TARGET_OS_IPHONE +/** kSecAttrAccessGroup (only used on iOS) */ +@property (nonatomic, copy) NSString *accessGroup; +#endif + +#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE +/** kSecAttrSynchronizable */ +@property (nonatomic) SSKeychainQuerySynchronizationMode synchronizationMode; +#endif + +/** Root storage for password information */ +@property (nonatomic, copy) NSData *passwordData; + +/** + This property automatically transitions between an object and the value of + `passwordData` using NSKeyedArchiver and NSKeyedUnarchiver. + */ +@property (nonatomic, copy) id passwordObject; + +/** + Convenience accessor for setting and getting a password string. Passes through + to `passwordData` using UTF-8 string encoding. + */ +@property (nonatomic, copy) NSString *password; + + +///------------------------ +/// @name Saving & Deleting +///------------------------ + +/** + Save the receiver's attributes as a keychain item. Existing items with the + given account, service, and access group will first be deleted. + + @param error Populated should an error occur. + + @return `YES` if saving was successful, `NO` otherwise. + */ +- (BOOL)save:(NSError **)error; + +/** + Dete keychain items that match the given account, service, and access group. + + @param error Populated should an error occur. + + @return `YES` if saving was successful, `NO` otherwise. + */ +- (BOOL)deleteItem:(NSError **)error; + + +///--------------- +/// @name Fetching +///--------------- + +/** + Fetch all keychain items that match the given account, service, and access + group. The values of `password` and `passwordData` are ignored when fetching. + + @param error Populated should an error occur. + + @return An array of dictionaries that represent all matching keychain items or + `nil` should an error occur. + The order of the items is not determined. + */ +- (NSArray *)fetchAll:(NSError **)error; + +/** + Fetch the keychain item that matches the given account, service, and access + group. The `password` and `passwordData` properties will be populated unless + an error occurs. The values of `password` and `passwordData` are ignored when + fetching. + + @param error Populated should an error occur. + + @return `YES` if fetching was successful, `NO` otherwise. + */ +- (BOOL)fetch:(NSError **)error; + + +///----------------------------- +/// @name Synchronization Status +///----------------------------- + +#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE +/** + Returns a boolean indicating if keychain synchronization is available on the device at runtime. The #define + SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE is only for compile time. If you are checking for the presence of synchronization, + you should use this method. + + @return A value indicating if keychain synchronization is available + */ ++ (BOOL)isSynchronizationAvailable; +#endif + +@end diff --git a/evernote-sdk-ios/3rdParty/SSKeychain/SSKeychainQuery.m b/evernote-sdk-ios/3rdParty/SSKeychain/SSKeychainQuery.m new file mode 100644 index 0000000..b93c620 --- /dev/null +++ b/evernote-sdk-ios/3rdParty/SSKeychain/SSKeychainQuery.m @@ -0,0 +1,282 @@ +// +// SSKeychainQuery.m +// SSKeychain +// +// Created by Caleb Davenport on 3/19/13. +// Copyright (c) 2013-2014 Sam Soffes. All rights reserved. +// + +#import "SSKeychainQuery.h" +#import "SSKeychain.h" + +@implementation SSKeychainQuery + +@synthesize account = _account; +@synthesize service = _service; +@synthesize label = _label; +@synthesize passwordData = _passwordData; + +#if __IPHONE_3_0 && TARGET_OS_IPHONE +@synthesize accessGroup = _accessGroup; +#endif + +#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE +@synthesize synchronizationMode = _synchronizationMode; +#endif + +#pragma mark - Public + +- (BOOL)save:(NSError *__autoreleasing *)error { + OSStatus status = SSKeychainErrorBadArguments; + if (!self.service || !self.account || !self.passwordData) { + if (error) { + *error = [[self class] errorWithCode:status]; + } + return NO; + } + + [self deleteItem:nil]; + + NSMutableDictionary *query = [self query]; + [query setObject:self.passwordData forKey:(__bridge id)kSecValueData]; + if (self.label) { + [query setObject:self.label forKey:(__bridge id)kSecAttrLabel]; + } +#if __IPHONE_4_0 && TARGET_OS_IPHONE + CFTypeRef accessibilityType = [SSKeychain accessibilityType]; + if (accessibilityType) { + [query setObject:(__bridge id)accessibilityType forKey:(__bridge id)kSecAttrAccessible]; + } +#endif + status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); + + if (status != errSecSuccess && error != NULL) { + *error = [[self class] errorWithCode:status]; + } + + return (status == errSecSuccess); +} + + +- (BOOL)deleteItem:(NSError *__autoreleasing *)error { + OSStatus status = SSKeychainErrorBadArguments; + if (!self.service || !self.account) { + if (error) { + *error = [[self class] errorWithCode:status]; + } + return NO; + } + + NSMutableDictionary *query = [self query]; +#if TARGET_OS_IPHONE + status = SecItemDelete((__bridge CFDictionaryRef)query); +#else + CFTypeRef result = NULL; + [query setObject:@YES forKey:(__bridge id)kSecReturnRef]; + status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); + if (status == errSecSuccess) { + status = SecKeychainItemDelete((SecKeychainItemRef)result); + CFRelease(result); + } +#endif + + if (status != errSecSuccess && error != NULL) { + *error = [[self class] errorWithCode:status]; + } + + return (status == errSecSuccess); +} + + +- (NSArray *)fetchAll:(NSError *__autoreleasing *)error { + OSStatus status = SSKeychainErrorBadArguments; + NSMutableDictionary *query = [self query]; + [query setObject:@YES forKey:(__bridge id)kSecReturnAttributes]; + [query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit]; + + CFTypeRef result = NULL; + status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); + if (status != errSecSuccess && error != NULL) { + *error = [[self class] errorWithCode:status]; + return nil; + } + + return (__bridge_transfer NSArray *)result; +} + + +- (BOOL)fetch:(NSError *__autoreleasing *)error { + OSStatus status = SSKeychainErrorBadArguments; + if (!self.service || !self.account) { + if (error) { + *error = [[self class] errorWithCode:status]; + } + return NO; + } + + CFTypeRef result = NULL; + NSMutableDictionary *query = [self query]; + [query setObject:@YES forKey:(__bridge id)kSecReturnData]; + [query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; + status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); + + if (status != errSecSuccess && error != NULL) { + *error = [[self class] errorWithCode:status]; + return NO; + } + + self.passwordData = (__bridge_transfer NSData *)result; + return YES; +} + + +#pragma mark - Accessors + +- (void)setPasswordObject:(id)object { + self.passwordData = [NSKeyedArchiver archivedDataWithRootObject:object]; +} + + +- (id)passwordObject { + if ([self.passwordData length]) { + return [NSKeyedUnarchiver unarchiveObjectWithData:self.passwordData]; + } + return nil; +} + + +- (void)setPassword:(NSString *)password { + self.passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; +} + + +- (NSString *)password { + if ([self.passwordData length]) { + return [[NSString alloc] initWithData:self.passwordData encoding:NSUTF8StringEncoding]; + } + return nil; +} + + +#pragma mark - Synchronization Status + +#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE ++ (BOOL)isSynchronizationAvailable { +#if TARGET_OS_IPHONE + // Apple suggested way to check for 7.0 at runtime + // https://developer.apple.com/library/ios/documentation/userexperience/conceptual/transitionguide/SupportingEarlieriOS.html + return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1; +#else + return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_8_4; +#endif +} +#endif + + +#pragma mark - Private + +- (NSMutableDictionary *)query { + NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:3]; + [dictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; + + if (self.service) { + [dictionary setObject:self.service forKey:(__bridge id)kSecAttrService]; + } + + if (self.account) { + [dictionary setObject:self.account forKey:(__bridge id)kSecAttrAccount]; + } + +#if __IPHONE_3_0 && TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR + if (self.accessGroup) { + [dictionary setObject:self.accessGroup forKey:(__bridge id)kSecAttrAccessGroup]; + } +#endif + +#ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE + if ([[self class] isSynchronizationAvailable]) { + id value; + + switch (self.synchronizationMode) { + case SSKeychainQuerySynchronizationModeNo: { + value = @NO; + break; + } + case SSKeychainQuerySynchronizationModeYes: { + value = @YES; + break; + } + case SSKeychainQuerySynchronizationModeAny: { + value = (__bridge id)(kSecAttrSynchronizableAny); + break; + } + } + + [dictionary setObject:value forKey:(__bridge id)(kSecAttrSynchronizable)]; + } +#endif + + return dictionary; +} + + ++ (NSError *)errorWithCode:(OSStatus) code { + NSString *message = nil; + switch (code) { + case errSecSuccess: return nil; + case SSKeychainErrorBadArguments: message = NSLocalizedStringFromTable(@"SSKeychainErrorBadArguments", @"SSKeychain", nil); break; + +#if TARGET_OS_IPHONE + case errSecUnimplemented: { + message = NSLocalizedStringFromTable(@"errSecUnimplemented", @"SSKeychain", nil); + break; + } + case errSecParam: { + message = NSLocalizedStringFromTable(@"errSecParam", @"SSKeychain", nil); + break; + } + case errSecAllocate: { + message = NSLocalizedStringFromTable(@"errSecAllocate", @"SSKeychain", nil); + break; + } + case errSecNotAvailable: { + message = NSLocalizedStringFromTable(@"errSecNotAvailable", @"SSKeychain", nil); + break; + } + case errSecDuplicateItem: { + message = NSLocalizedStringFromTable(@"errSecDuplicateItem", @"SSKeychain", nil); + break; + } + case errSecItemNotFound: { + message = NSLocalizedStringFromTable(@"errSecItemNotFound", @"SSKeychain", nil); + break; + } + case errSecInteractionNotAllowed: { + message = NSLocalizedStringFromTable(@"errSecInteractionNotAllowed", @"SSKeychain", nil); + break; + } + case errSecDecode: { + message = NSLocalizedStringFromTable(@"errSecDecode", @"SSKeychain", nil); + break; + } + case errSecAuthFailed: { + message = NSLocalizedStringFromTable(@"errSecAuthFailed", @"SSKeychain", nil); + break; + } + default: { + message = NSLocalizedStringFromTable(@"errSecDefault", @"SSKeychain", nil); + } +#else + default: + message = (__bridge_transfer NSString *)SecCopyErrorMessageString(code, NULL); +#endif + } + + NSDictionary *userInfo = nil; + if (message) { + userInfo = @{ NSLocalizedDescriptionKey : message }; + } + return [NSError errorWithDomain:kSSKeychainErrorDomain code:code userInfo:userInfo]; +} + +@end