]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurityd/lib/sstransit.cpp
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurityd / lib / sstransit.cpp
1 /*
2 * Copyright (c) 2000-2004,2006,2011,2013-2014 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
25 //
26 // sstransit - Securityd client side transition support.
27 //
28 #include "sstransit.h"
29 #include <security_cdsa_client/cspclient.h>
30 #include <security_utilities/mach++.h>
31
32 namespace Security {
33 namespace SecurityServer {
34
35 using MachPlusPlus::check;
36 using MachPlusPlus::VMGuard;
37
38 //
39 // DataOutput helper.
40 // This happens "at the end" of a glue method, via the DataOutput destructor.
41 //
42 DataOutput::~DataOutput()
43 {
44 // @@@ Why are we setting up a VMGuard if mData is NULL?
45 VMGuard _(mData, mLength);
46 if (mData) // was assigned to; IPC returned OK
47 if (mTarget) { // output CssmData exists
48 if (mTarget->data()) { // caller provided buffer
49 if (mTarget->length() < mLength)
50 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
51 mTarget->length(mLength); // no allocation; shorten buffer
52 } else { // allocate buffer
53 *mTarget = CssmData(allocator.malloc(mLength), mLength);
54 }
55 memcpy(mTarget->data(), mData, mLength);
56 }
57 }
58
59
60 //
61 // Copy an AccessCredentials for shipment.
62 // In addition, scan the samples for "special" database locking samples
63 // and translate certain items for safe shipment. Note that this overwrites
64 // part of the CssmList value (CSPHandle -> SS/KeyHandle), but we do it on
65 // the COPY, so that's okay.
66 //
67 DatabaseAccessCredentials::DatabaseAccessCredentials(const AccessCredentials *creds, Allocator &alloc)
68 : Copier<AccessCredentials>(creds, alloc)
69 {
70 if (creds) {
71 for (uint32 n = 0; n < value()->samples().length(); n++) {
72 TypedList sample = value()->samples()[n];
73 sample.checkProper();
74 switch (sample.type()) {
75 case CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK:
76 sample.snip(); // skip sample type (snip() advances to next)
77 sample.checkProper();
78 if (sample.type() == CSSM_SAMPLE_TYPE_SYMMETRIC_KEY ||
79 sample.type() == CSSM_SAMPLE_TYPE_ASYMMETRIC_KEY) {
80 secinfo("SSclient", "key sample encountered");
81 // proper form is sample[1] = DATA:CSPHandle, sample[2] = DATA:CSSM_KEY,
82 // sample[3] = auxiliary data (not changed)
83 if (sample.length() != 4
84 || sample[1].type() != CSSM_LIST_ELEMENT_DATUM
85 || sample[2].type() != CSSM_LIST_ELEMENT_DATUM
86 || sample[3].type() != CSSM_LIST_ELEMENT_DATUM)
87 CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE);
88 mapKeySample(
89 sample[1].data(),
90 *sample[2].data().interpretedAs<CssmKey>(CSSM_ERRCODE_INVALID_SAMPLE_VALUE));
91 }
92 break;
93 case CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK:
94 sample.snip(); // skip sample type
95 sample.checkProper();
96 if (sample.type() == CSSM_SAMPLE_TYPE_SYMMETRIC_KEY ||
97 sample.type() == CSSM_SAMPLE_TYPE_ASYMMETRIC_KEY) {
98 secinfo("SSclient", "key sample encountered");
99 // proper form is sample[1] = DATA:CSPHandle, sample[2] = DATA:CSSM_KEY
100 if (sample.length() != 3
101 || sample[1].type() != CSSM_LIST_ELEMENT_DATUM
102 || sample[2].type() != CSSM_LIST_ELEMENT_DATUM)
103 CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE);
104 mapKeySample(
105 sample[1].data(),
106 *sample[2].data().interpretedAs<CssmKey>(CSSM_ERRCODE_INVALID_SAMPLE_VALUE));
107 }
108 break;
109 default:
110 break;
111 }
112 }
113 }
114 }
115
116 void DatabaseAccessCredentials::mapKeySample(CssmData &cspHandleData, CssmKey &key)
117 {
118 // We use a CSP passthrough to get the securityd key handle for a (reference) key.
119 // We try the passthrough on everyone, since there's multiple CSP/DL modules
120 // that play games with securityd, and we want to give everyone a chance to play.
121
122 // @@@ can't use CssmClient (it makes its own attachments)
123 CSSM_CC_HANDLE ctx;
124 CSSM_CSP_HANDLE &cspHandle = *cspHandleData.interpretedAs<CSSM_CSP_HANDLE>(CSSM_ERRCODE_INVALID_SAMPLE_VALUE);
125 CssmError::check(CSSM_CSP_CreatePassThroughContext(cspHandle, &key, &ctx));
126 KeyHandle ssKey;
127 CSSM_RETURN passthroughError =
128 CSSM_CSP_PassThrough(ctx, CSSM_APPLESCPDL_CSP_GET_KEYHANDLE, NULL, (void **)&ssKey);
129 CSSM_DeleteContext(ctx); // ignore error
130 switch (passthroughError) {
131 case CSSM_OK: // got the passthrough; rewrite the sample
132 assert(sizeof(CSSM_CSP_HANDLE) >= sizeof(KeyHandle)); // future insurance
133 cspHandle = ssKey;
134 cspHandleData.length(sizeof(KeyHandle));
135 secinfo("SSclient", "key sample mapped to key 0x%x", ssKey);
136 return;
137 case CSSMERR_CSP_INVALID_PASSTHROUGH_ID:
138 return; // CSP didn't understand the callback; leave the sample alone
139 default:
140 CssmError::throwMe(passthroughError); // error
141 }
142 }
143
144
145 //
146 // Inbound/outbound transit for the elaborate data-access attribute vectors
147 //
148 DataRetrieval::DataRetrieval(CssmDbRecordAttributeData *&attributes, Allocator &alloc)
149 : Copier<CssmDbRecordAttributeData>(attributes),
150 mAllocator(alloc), mAttributes(attributes), mAddr(NULL), mBase(NULL), mLength(0)
151 {
152 }
153
154 DataRetrieval::~DataRetrieval()
155 {
156 if (mAddr) {
157 relocate(mAddr, mBase);
158 if (mAttributes->size() != mAddr->size()) {
159 secemergency("~DataRetrieval: size mismatch, %u != %u", mAttributes->size(), mAddr->size());
160 abort();
161 }
162
163 // global (per-record) fields
164 mAttributes->recordType(mAddr->recordType());
165 mAttributes->semanticInformation(mAddr->semanticInformation());
166
167 // transfer data values (but not infos, which we keep in the original vector)
168 for (uint32 n = 0; n < mAttributes->size(); n++)
169 mAttributes->at(n).copyValues(mAddr->at(n), mAllocator);
170 }
171 }
172
173
174 } // namespace SecurityServer
175 } // end namespace Security