]> git.saurik.com Git - apple/security.git/blob - keychain/securityd/SecItemBackupServer.c
Security-59754.80.3.tar.gz
[apple/security.git] / keychain / securityd / SecItemBackupServer.c
1 /*
2 * Copyright (c) 2015 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 #include "keychain/securityd/SecItemBackupServer.h"
25 #include "keychain/securityd/SecItemServer.h"
26 #include "keychain/SecureObjectSync/SOSEnginePriv.h"
27 #include "keychain/SecureObjectSync/SOSPeer.h"
28 #include <Security/SecureObjectSync/SOSBackupSliceKeyBag.h>
29 #include <Security/SecureObjectSync/SOSViews.h>
30 #include <unistd.h>
31
32 #include "keychain/securityd/SecDbItem.h"
33 #include <utilities/der_plist.h>
34
35 static bool withDataSourceAndEngine(CFErrorRef *error, void (^action)(SOSDataSourceRef ds, SOSEngineRef engine)) {
36 bool ok = false;
37 SOSDataSourceFactoryRef dsf = SecItemDataSourceFactoryGetDefault();
38 SOSDataSourceRef ds = SOSDataSourceFactoryCreateDataSource(dsf, kSecAttrAccessibleWhenUnlocked, error);
39 if (ds) {
40 SOSEngineRef engine = SOSDataSourceGetSharedEngine(ds, error);
41 if (engine) {
42 action(ds, engine);
43 ok = true;
44 }
45 ok &= SOSDataSourceRelease(ds, error);
46 }
47 return ok;
48 }
49
50 int SecServerItemBackupHandoffFD(CFStringRef backupName, CFErrorRef *error) {
51 __block int fd = -1;
52 if (!withDataSourceAndEngine(error, ^(SOSDataSourceRef ds, SOSEngineRef engine) {
53 SOSEngineForPeerID(engine, backupName, error, ^(SOSTransactionRef txn, SOSPeerRef peer) {
54 fd = SOSPeerHandoffFD(peer, error);
55 });
56 }) && fd >= 0) {
57 close(fd);
58 fd = -1;
59 }
60 return fd;
61 }
62
63 bool SecServerItemBackupSetConfirmedManifest(CFStringRef backupName, CFDataRef keybagDigest, CFDataRef manifestData, CFErrorRef *error) {
64 __block bool ok = true;
65 ok &= withDataSourceAndEngine(error, ^(SOSDataSourceRef ds, SOSEngineRef engine) {
66 ok = SOSEngineSetPeerConfirmedManifest(engine, backupName, keybagDigest, manifestData, error);
67 });
68 return ok;
69 }
70
71 CFArrayRef SecServerItemBackupCopyNames(CFErrorRef *error) {
72 __block CFArrayRef names = NULL;
73 if (!withDataSourceAndEngine(error, ^(SOSDataSourceRef ds, SOSEngineRef engine) {
74 names = SOSEngineCopyBackupPeerNames(engine, error);
75 })) {
76 CFReleaseNull(names);
77 }
78 return names;
79 }
80
81 CFStringRef SecServerItemBackupEnsureCopyView(CFStringRef viewName, CFErrorRef *error) {
82 __block CFStringRef name = NULL;
83 if(!withDataSourceAndEngine(error, ^(SOSDataSourceRef ds, SOSEngineRef engine) {
84 name = SOSEngineEnsureCopyBackupPeerForView(engine, viewName, error);
85 })) {
86 CFReleaseNull(name);
87 }
88 return name;
89 }
90
91 // TODO Move to datasource and remove dsRestoreObject
92 static bool SOSDataSourceWithBackup(SOSDataSourceRef ds, CFDataRef backup, keybag_handle_t bag_handle, CFErrorRef *error, void(^with)(SOSObjectRef item)) {
93 __block bool ok = true;
94 CFPropertyListRef plist = CFPropertyListCreateWithDERData(kCFAllocatorDefault, backup, kCFPropertyListImmutable, NULL, error);
95 CFDictionaryRef bdict = asDictionary(plist, error);
96 ok = (bdict != NULL);
97 if (ok) CFDictionaryForEach(bdict, ^(const void *key, const void *value) {
98 CFStringRef className = asString(key, error);
99 if (className) {
100 const SecDbClass *cls = kc_class_with_name(className);
101 if (cls) {
102 CFArrayRef items = asArray(value, error);
103 CFDataRef edata;
104 if (items) CFArrayForEachC(items, edata) {
105 SOSObjectRef item = (SOSObjectRef)SecDbItemCreateWithEncryptedData(kCFAllocatorDefault, cls, edata, bag_handle, error);
106 if (item) {
107 with(item);
108 CFRelease(item);
109 } else {
110 ok = false;
111 }
112 } else {
113 ok = false;
114 }
115 } else {
116 ok &= SecError(errSecDecode, error, CFSTR("bad class %@ in backup"), className);
117 }
118 } else {
119 ok = false;
120 }
121 });
122 CFReleaseSafe(plist);
123 return ok;
124 }
125
126 bool SecServerItemBackupRestore(CFStringRef backupName, CFStringRef peerID, CFDataRef keybag, CFDataRef secret, CFDataRef backup, CFErrorRef *error) {
127 // TODO: Decrypt and merge items in backup to dataSource
128
129 __block bool ok = false; // return false if the bag_handle code fails.
130 CFDataRef aksKeybag = NULL;
131 CFMutableSetRef viewSet = NULL;
132 SOSBackupSliceKeyBagRef backupSliceKeyBag = NULL;
133 keybag_handle_t bag_handle = bad_keybag_handle;
134
135 require(asData(secret, error), xit);
136 require(backupSliceKeyBag = SOSBackupSliceKeyBagCreateFromData(kCFAllocatorDefault, keybag, error), xit);
137
138 if (peerID) {
139 bag_handle = SOSBSKBLoadAndUnlockWithPeerIDAndSecret(backupSliceKeyBag, peerID, secret, error);
140 } else {
141 if (SOSBSKBIsDirect(backupSliceKeyBag)) {
142 bag_handle = SOSBSKBLoadAndUnlockWithDirectSecret(backupSliceKeyBag, secret, error);
143 } else {
144 bag_handle = SOSBSKBLoadAndUnlockWithWrappingSecret(backupSliceKeyBag, secret, error);
145 }
146 }
147 require(bag_handle != bad_keybag_handle, xit);
148
149 // TODO: How do we know which views we are allow to restore
150 //viewSet = SOSAccountCopyRestorableViews();
151
152 ok = true; // Start from original code start point - otherwise begin in this nest of stuff
153 ok &= withDataSourceAndEngine(error, ^(SOSDataSourceRef ds, SOSEngineRef engine) {
154 ok &= SOSDataSourceWith(ds, error, ^(SOSTransactionRef txn, bool *commit) {
155 ok &= SOSDataSourceWithBackup(ds, backup, bag_handle, error, ^(SOSObjectRef item) {
156 //if (SOSDataSourceIsInViewSet(item, viewSet)) {
157 SOSObjectRef mergedItem = NULL;
158 if (SOSDataSourceMergeObject(ds, txn, item, &mergedItem, error)) {
159 // if mergedItem == item then it was restored otherwise it was rejected by the conflict resolver.
160 CFReleaseSafe(mergedItem);
161 }
162 //}
163 });
164 });
165 });
166
167 xit:
168 if (bag_handle != bad_keybag_handle)
169 ok &= ks_close_keybag(bag_handle, error);
170
171 CFReleaseSafe(backupSliceKeyBag);
172 CFReleaseSafe(aksKeybag);
173 CFReleaseSafe(viewSet);
174
175 return ok;
176 }
177
178
179
180