]> git.saurik.com Git - apple/security.git/blob - keychain/securityd/SecItemBackupServer.c
Security-59306.41.2.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 // TODO Move to datasource and remove dsRestoreObject
82 static bool SOSDataSourceWithBackup(SOSDataSourceRef ds, CFDataRef backup, keybag_handle_t bag_handle, CFErrorRef *error, void(^with)(SOSObjectRef item)) {
83 __block bool ok = true;
84 CFPropertyListRef plist = CFPropertyListCreateWithDERData(kCFAllocatorDefault, backup, kCFPropertyListImmutable, NULL, error);
85 CFDictionaryRef bdict = asDictionary(plist, error);
86 ok = (bdict != NULL);
87 if (ok) CFDictionaryForEach(bdict, ^(const void *key, const void *value) {
88 CFStringRef className = asString(key, error);
89 if (className) {
90 const SecDbClass *cls = kc_class_with_name(className);
91 if (cls) {
92 CFArrayRef items = asArray(value, error);
93 CFDataRef edata;
94 if (items) CFArrayForEachC(items, edata) {
95 SOSObjectRef item = (SOSObjectRef)SecDbItemCreateWithEncryptedData(kCFAllocatorDefault, cls, edata, bag_handle, error);
96 if (item) {
97 with(item);
98 CFRelease(item);
99 } else {
100 ok = false;
101 }
102 } else {
103 ok = false;
104 }
105 } else {
106 ok &= SecError(errSecDecode, error, CFSTR("bad class %@ in backup"), className);
107 }
108 } else {
109 ok = false;
110 }
111 });
112 CFReleaseSafe(plist);
113 return ok;
114 }
115
116 bool SecServerItemBackupRestore(CFStringRef backupName, CFStringRef peerID, CFDataRef keybag, CFDataRef secret, CFDataRef backup, CFErrorRef *error) {
117 // TODO: Decrypt and merge items in backup to dataSource
118
119 __block bool ok = false; // return false if the bag_handle code fails.
120 CFDataRef aksKeybag = NULL;
121 CFMutableSetRef viewSet = NULL;
122 SOSBackupSliceKeyBagRef backupSliceKeyBag = NULL;
123 keybag_handle_t bag_handle = bad_keybag_handle;
124
125 require(asData(secret, error), xit);
126 require(backupSliceKeyBag = SOSBackupSliceKeyBagCreateFromData(kCFAllocatorDefault, keybag, error), xit);
127
128 if (peerID) {
129 bag_handle = SOSBSKBLoadAndUnlockWithPeerIDAndSecret(backupSliceKeyBag, peerID, secret, error);
130 } else {
131 if (SOSBSKBIsDirect(backupSliceKeyBag)) {
132 bag_handle = SOSBSKBLoadAndUnlockWithDirectSecret(backupSliceKeyBag, secret, error);
133 } else {
134 bag_handle = SOSBSKBLoadAndUnlockWithWrappingSecret(backupSliceKeyBag, secret, error);
135 }
136 }
137 require(bag_handle != bad_keybag_handle, xit);
138
139 // TODO: How do we know which views we are allow to restore
140 //viewSet = SOSAccountCopyRestorableViews();
141
142 ok = true; // Start from original code start point - otherwise begin in this nest of stuff
143 ok &= withDataSourceAndEngine(error, ^(SOSDataSourceRef ds, SOSEngineRef engine) {
144 ok &= SOSDataSourceWith(ds, error, ^(SOSTransactionRef txn, bool *commit) {
145 ok &= SOSDataSourceWithBackup(ds, backup, bag_handle, error, ^(SOSObjectRef item) {
146 //if (SOSDataSourceIsInViewSet(item, viewSet)) {
147 SOSObjectRef mergedItem = NULL;
148 if (SOSDataSourceMergeObject(ds, txn, item, &mergedItem, error)) {
149 // if mergedItem == item then it was restored otherwise it was rejected by the conflict resolver.
150 CFReleaseSafe(mergedItem);
151 }
152 //}
153 });
154 });
155 });
156
157 xit:
158 if (bag_handle != bad_keybag_handle)
159 ok &= ks_close_keybag(bag_handle, error);
160
161 CFReleaseSafe(backupSliceKeyBag);
162 CFReleaseSafe(aksKeybag);
163 CFReleaseSafe(viewSet);
164
165 return ok;
166 }
167
168
169
170