2 * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 // sstransit - Securityd client side transition support.
28 #include "sstransit.h"
29 #include <security_cdsa_client/cspclient.h>
30 #include <security_utilities/mach++.h>
31 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
34 namespace SecurityServer
{
36 using MachPlusPlus::check
;
37 using MachPlusPlus::VMGuard
;
41 // This happens "at the end" of a glue method, via the DataOutput destructor.
43 DataOutput::~DataOutput()
45 // @@@ Why are we setting up a VMGuard if mData is NULL?
46 VMGuard
_(mData
, mLength
);
47 if (mData
) // was assigned to; IPC returned OK
48 if (mTarget
) { // output CssmData exists
49 if (mTarget
->data()) { // caller provided buffer
50 if (mTarget
->length() < mLength
)
51 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR
);
52 mTarget
->length(mLength
); // no allocation; shorten buffer
53 } else { // allocate buffer
54 *mTarget
= CssmData(allocator
.malloc(mLength
), mLength
);
56 memcpy(mTarget
->data(), mData
, mLength
);
62 // Copy an AccessCredentials for shipment.
63 // In addition, scan the samples for "special" database locking samples
64 // and translate certain items for safe shipment. Note that this overwrites
65 // part of the CssmList value (CSPHandle -> SS/KeyHandle), but we do it on
66 // the COPY, so that's okay.
68 DatabaseAccessCredentials::DatabaseAccessCredentials(const AccessCredentials
*creds
, Allocator
&alloc
)
69 : Copier
<AccessCredentials
>(creds
, alloc
)
72 for (uint32 n
= 0; n
< value()->samples().length(); n
++) {
73 TypedList sample
= value()->samples()[n
];
75 switch (sample
.type()) {
76 case CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK
:
77 sample
.snip(); // skip sample type (snip() advances to next)
79 if (sample
.type() == CSSM_SAMPLE_TYPE_SYMMETRIC_KEY
||
80 sample
.type() == CSSM_SAMPLE_TYPE_ASYMMETRIC_KEY
) {
81 secdebug("SSclient", "key sample encountered");
82 // proper form is sample[1] = DATA:CSPHandle, sample[2] = DATA:CSSM_KEY,
83 // sample[3] = auxiliary data (not changed)
84 if (sample
.length() != 4
85 || sample
[1].type() != CSSM_LIST_ELEMENT_DATUM
86 || sample
[2].type() != CSSM_LIST_ELEMENT_DATUM
87 || sample
[3].type() != CSSM_LIST_ELEMENT_DATUM
)
88 CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE
);
91 *sample
[2].data().interpretedAs
<CssmKey
>(CSSM_ERRCODE_INVALID_SAMPLE_VALUE
));
94 case CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK
:
95 sample
.snip(); // skip sample type
97 if (sample
.type() == CSSM_SAMPLE_TYPE_SYMMETRIC_KEY
||
98 sample
.type() == CSSM_SAMPLE_TYPE_ASYMMETRIC_KEY
) {
99 secdebug("SSclient", "key sample encountered");
100 // proper form is sample[1] = DATA:CSPHandle, sample[2] = DATA:CSSM_KEY
101 if (sample
.length() != 3
102 || sample
[1].type() != CSSM_LIST_ELEMENT_DATUM
103 || sample
[2].type() != CSSM_LIST_ELEMENT_DATUM
)
104 CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE
);
107 *sample
[2].data().interpretedAs
<CssmKey
>(CSSM_ERRCODE_INVALID_SAMPLE_VALUE
));
117 void DatabaseAccessCredentials::mapKeySample(CssmData
&cspHandleData
, CssmKey
&key
)
119 // We use a CSP passthrough to get the securityd key handle for a (reference) key.
120 // We try the passthrough on everyone, since there's multiple CSP/DL modules
121 // that play games with securityd, and we want to give everyone a chance to play.
123 // @@@ can't use CssmClient (it makes its own attachments)
125 CSSM_CSP_HANDLE
&cspHandle
= *cspHandleData
.interpretedAs
<CSSM_CSP_HANDLE
>(CSSM_ERRCODE_INVALID_SAMPLE_VALUE
);
126 CssmError::check(CSSM_CSP_CreatePassThroughContext(cspHandle
, &key
, &ctx
));
128 CSSM_RETURN passthroughError
=
129 CSSM_CSP_PassThrough(ctx
, CSSM_APPLESCPDL_CSP_GET_KEYHANDLE
, NULL
, (void **)&ssKey
);
130 CSSM_DeleteContext(ctx
); // ignore error
131 switch (passthroughError
) {
132 case CSSM_OK
: // got the passthrough; rewrite the sample
133 assert(sizeof(CSSM_CSP_HANDLE
) >= sizeof(KeyHandle
)); // future insurance
135 cspHandleData
.length(sizeof(KeyHandle
));
136 secdebug("SSclient", "key sample mapped to key 0x%x", ssKey
);
138 case CSSMERR_CSP_INVALID_PASSTHROUGH_ID
:
139 return; // CSP didn't understand the callback; leave the sample alone
141 CssmError::throwMe(passthroughError
); // error
147 // Inbound/outbound transit for the elaborate data-access attribute vectors
149 DataRetrieval::DataRetrieval(CssmDbRecordAttributeData
*&attributes
, Allocator
&alloc
)
150 : Copier
<CssmDbRecordAttributeData
>(attributes
),
151 mAllocator(alloc
), mAttributes(attributes
), mAddr(NULL
), mBase(NULL
), mLength(0)
155 DataRetrieval::~DataRetrieval()
158 relocate(mAddr
, mBase
);
159 assert(mAttributes
->size() == mAddr
->size());
161 // global (per-record) fields
162 mAttributes
->recordType(mAddr
->recordType());
163 mAttributes
->semanticInformation(mAddr
->semanticInformation());
165 // transfer data values (but not infos, which we keep in the original vector)
166 for (uint32 n
= 0; n
< mAttributes
->size(); n
++)
167 mAttributes
->at(n
).copyValues(mAddr
->at(n
), mAllocator
);
172 } // namespace SecurityServer
173 } // end namespace Security