]> git.saurik.com Git - apple/security.git/blob - keychain/ckks/CKKSCurrentItemPointer.m
Security-59306.11.20.tar.gz
[apple/security.git] / keychain / ckks / CKKSCurrentItemPointer.m
1 /*
2 * Copyright (c) 2017 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #import "keychain/ckks/CKKSCurrentItemPointer.h"
25
26 #if OCTAGON
27
28 @implementation CKKSCurrentItemPointer
29
30 - (instancetype)initForIdentifier:(NSString*)identifier
31 currentItemUUID:(NSString*)currentItemUUID
32 state:(CKKSProcessedState*)state
33 zoneID:(CKRecordZoneID*)zoneID
34 encodedCKRecord: (NSData*) encodedrecord
35 {
36 if(self = [super initWithCKRecordType: SecCKRecordCurrentItemType encodedCKRecord:encodedrecord zoneID:zoneID]) {
37 _state = state;
38 _identifier = identifier;
39 _currentItemUUID = currentItemUUID;
40 }
41 return self;
42 }
43
44 - (NSString*)description {
45 return [NSString stringWithFormat:@"<CKKSCurrentItemPointer(%@) %@: %@>", self.zoneID.zoneName, self.identifier, self.currentItemUUID];
46 }
47
48 #pragma mark - CKKSCKRecordHolder methods
49
50 - (NSString*) CKRecordName {
51 return self.identifier;
52 }
53
54 - (CKRecord*)updateCKRecord: (CKRecord*) record zoneID: (CKRecordZoneID*) zoneID {
55 if(![record.recordType isEqualToString: SecCKRecordCurrentItemType]) {
56 @throw [NSException
57 exceptionWithName:@"WrongCKRecordTypeException"
58 reason:[NSString stringWithFormat: @"CKRecordType (%@) was not %@", record.recordType, SecCKRecordCurrentItemType]
59 userInfo:nil];
60 }
61
62 // The record name should already match identifier...
63 if(![record.recordID.recordName isEqualToString: self.identifier]) {
64 @throw [NSException
65 exceptionWithName:@"WrongCKRecordNameException"
66 reason:[NSString stringWithFormat: @"CKRecord name (%@) was not %@", record.recordID.recordName, self.identifier]
67 userInfo:nil];
68 }
69
70 // Set the parent reference
71 record[SecCKRecordItemRefKey] = [[CKReference alloc] initWithRecordID: [[CKRecordID alloc] initWithRecordName: self.currentItemUUID zoneID: zoneID]
72 action: CKReferenceActionNone];
73 return record;
74 }
75
76 - (bool)matchesCKRecord: (CKRecord*) record {
77 if(![record.recordType isEqualToString: SecCKRecordCurrentItemType]) {
78 return false;
79 }
80
81 if(![record.recordID.recordName isEqualToString: self.identifier]) {
82 return false;
83 }
84
85 if(![[record[SecCKRecordItemRefKey] recordID].recordName isEqualToString: self.currentItemUUID]) {
86 return false;
87 }
88
89 return true;
90 }
91
92 - (void)setFromCKRecord: (CKRecord*) record {
93 if(![record.recordType isEqualToString: SecCKRecordCurrentItemType]) {
94 @throw [NSException
95 exceptionWithName:@"WrongCKRecordTypeException"
96 reason:[NSString stringWithFormat: @"CKRecordType (%@) was not %@", record.recordType, SecCKRecordCurrentItemType]
97 userInfo:nil];
98 }
99
100 [self setStoredCKRecord:record];
101
102 self.identifier = (CKKSKeyClass*) record.recordID.recordName;
103 self.currentItemUUID = [record[SecCKRecordItemRefKey] recordID].recordName;
104 }
105
106 #pragma mark - Load from database
107
108 + (instancetype)fromDatabase:(NSString*)identifier state:(CKKSProcessedState*)state zoneID:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error {
109 return [self fromDatabaseWhere: @{@"identifier":identifier, @"state":state, @"ckzone":zoneID.zoneName} error: error];
110 }
111
112 + (instancetype)tryFromDatabase:(NSString*)identifier state:(CKKSProcessedState*)state zoneID:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error {
113 return [self tryFromDatabaseWhere: @{@"identifier":identifier, @"state":state, @"ckzone":zoneID.zoneName} error: error];
114 }
115
116 + (NSArray<CKKSCurrentItemPointer*>*)remoteItemPointers: (CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error {
117 return [self allWhere: @{@"state": SecCKKSProcessedStateRemote, @"ckzone":zoneID.zoneName} error:error];
118 }
119
120 + (NSArray<CKKSCurrentItemPointer*>*)allInZone:(CKRecordZoneID*)zoneID error:(NSError * __autoreleasing *)error {
121 return [self allWhere: @{@"ckzone":zoneID.zoneName} error:error];
122 }
123
124 + (bool)deleteAll:(CKRecordZoneID*)zoneID error:(NSError * __autoreleasing *)error {
125 bool ok = [CKKSSQLDatabaseObject deleteFromTable:[self sqlTable] where: @{@"ckzone":zoneID.zoneName} connection:nil error: error];
126
127 if(ok) {
128 secdebug("ckksitem", "Deleted all %@", self);
129 } else {
130 secdebug("ckksitem", "Couldn't delete all %@: %@", self, error ? *error : @"unknown");
131 }
132 return ok;
133 }
134
135 #pragma mark - CKKSSQLDatabaseObject methods
136
137 + (NSString*)sqlTable {
138 return @"currentitems";
139 }
140
141 + (NSArray<NSString*>*)sqlColumns {
142 return @[@"identifier", @"currentItemUUID", @"state", @"ckzone", @"ckrecord"];
143 }
144
145 - (NSDictionary<NSString*,NSString*>*) whereClauseToFindSelf {
146 return @{@"identifier": self.identifier, @"ckzone":self.zoneID.zoneName, @"state":self.state};
147 }
148
149 - (NSDictionary<NSString*,NSString*>*)sqlValues {
150 return @{@"identifier": self.identifier,
151 @"currentItemUUID": CKKSNilToNSNull(self.currentItemUUID),
152 @"state": CKKSNilToNSNull(self.state),
153 @"ckzone": CKKSNilToNSNull(self.zoneID.zoneName),
154 @"ckrecord": CKKSNilToNSNull([self.encodedCKRecord base64EncodedStringWithOptions:0]),
155 };
156 }
157
158 + (instancetype)fromDatabaseRow:(NSDictionary<NSString *, CKKSSQLResult*>*) row {
159 return [[CKKSCurrentItemPointer alloc] initForIdentifier:row[@"identifier"].asString
160 currentItemUUID:row[@"currentItemUUID"].asString
161 state:(CKKSProcessedState*)row[@"state"].asString
162 zoneID:[[CKRecordZoneID alloc] initWithZoneName:row[@"ckzone"].asString ownerName:CKCurrentUserDefaultName]
163 encodedCKRecord:row[@"ckrecord"].asBase64DecodedData];
164 }
165
166 @end
167
168 #endif // OCTAGON
169