VALSynchronizableValet.m 3.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //
  2. // VALSynchronizableValet.m
  3. // Valet
  4. //
  5. // Created by Dan Federman on 3/16/15.
  6. // Copyright 2015 Square, Inc.
  7. //
  8. // Licensed under the Apache License, Version 2.0 (the "License");
  9. // you may not use this file except in compliance with the License.
  10. // You may obtain a copy of the License at
  11. //
  12. //    http://www.apache.org/licenses/LICENSE-2.0
  13. //
  14. // Unless required by applicable law or agreed to in writing, software
  15. // distributed under the License is distributed on an "AS IS" BASIS,
  16. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. // See the License for the specific language governing permissions and
  18. // limitations under the License.
  19. //
  20. #import "VALSynchronizableValet.h"
  21. #import "VALValet_Protected.h"
  22. #import "ValetDefines.h"
  23. @implementation VALSynchronizableValet
  24. @synthesize baseQuery = _baseQuery;
  25. #pragma mark - Class Methods
  26. + (BOOL)supportsSynchronizableKeychainItems;
  27. {
  28. #pragma clang diagnostic push
  29. #pragma clang diagnostic ignored "-Wtautological-compare"
  30. #define SUPPORTS_SYNCHRONIZABLE_KEYCHAIN_MAC (TARGET_OS_MAC && __MAC_10_9)
  31. #define SUPPORTS_SYNCHRONIZABLE_KEYCHAIN_IOS (TARGET_OS_IPHONE && (__IPHONE_8_2 || (__IPHONE_7_0 && !TARGET_IPHONE_SIMULATOR)))
  32. #if SUPPORTS_SYNCHRONIZABLE_KEYCHAIN_MAC || SUPPORTS_SYNCHRONIZABLE_KEYCHAIN_IOS
  33. return (&kSecAttrSynchronizable != NULL && &kSecAttrSynchronizableAny != NULL);
  34. #else
  35. return NO;
  36. #endif
  37. #pragma clang diagnostic pop
  38. }
  39. #pragma mark - Private Class Methods
  40. + (void)_augmentBaseQuery:(nonnull NSMutableDictionary *)mutableBaseQuery;
  41. {
  42. #if SUPPORTS_SYNCHRONIZABLE_KEYCHAIN_MAC || SUPPORTS_SYNCHRONIZABLE_KEYCHAIN_IOS
  43. mutableBaseQuery[(__bridge id)kSecAttrSynchronizable] = @YES;
  44. #endif
  45. }
  46. #pragma mark - Initialization
  47. - (nullable instancetype)initWithIdentifier:(nonnull NSString *)identifier accessibility:(VALAccessibility)accessibility;
  48. {
  49. VALCheckCondition(accessibility == VALAccessibilityWhenUnlocked || accessibility == VALAccessibilityAfterFirstUnlock || accessibility == VALAccessibilityAlways, nil, @"Accessibility must not be scoped to this device");
  50. VALCheckCondition([[self class] supportsSynchronizableKeychainItems], nil, @"This device does not support synchronizing data to iCloud.");
  51. self = [super initWithIdentifier:identifier accessibility:accessibility];
  52. NSMutableDictionary *const baseQuery = [[self class] mutableBaseQueryWithIdentifier:identifier
  53. accessibility:accessibility
  54. initializer:_cmd];
  55. [[self class] _augmentBaseQuery:baseQuery];
  56. _baseQuery = baseQuery;
  57. return [[self class] sharedValetForValet:self];
  58. }
  59. - (nullable instancetype)initWithSharedAccessGroupIdentifier:(nonnull NSString *)sharedAccessGroupIdentifier accessibility:(VALAccessibility)accessibility;
  60. {
  61. VALCheckCondition(accessibility == VALAccessibilityWhenUnlocked || accessibility == VALAccessibilityAfterFirstUnlock || accessibility == VALAccessibilityAlways, nil, @"Accessibility must not be scoped to this device");
  62. VALCheckCondition([[self class] supportsSynchronizableKeychainItems], nil, @"This device does not support synchronizing data to iCloud.");
  63. self = [super initWithSharedAccessGroupIdentifier:sharedAccessGroupIdentifier accessibility:accessibility];
  64. NSMutableDictionary *const baseQuery = [[self class] mutableBaseQueryWithSharedAccessGroupIdentifier:sharedAccessGroupIdentifier
  65. accessibility:accessibility
  66. initializer:_cmd];
  67. [[self class] _augmentBaseQuery:baseQuery];
  68. _baseQuery = baseQuery;
  69. return [[self class] sharedValetForValet:self];
  70. }
  71. @end