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 32namespace Security { 33namespace SecurityServer { 34 35using MachPlusPlus::check; 36using MachPlusPlus::VMGuard; 37 38// 39// DataOutput helper. 40// This happens "at the end" of a glue method, via the DataOutput destructor. 41// 42DataOutput::~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// 67DatabaseAccessCredentials::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 secdebug("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 secdebug("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 116void 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 secdebug("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// 148DataRetrieval::DataRetrieval(CssmDbRecordAttributeData *&attributes, Allocator &alloc) 149 : Copier<CssmDbRecordAttributeData>(attributes), 150 mAllocator(alloc), mAttributes(attributes), mAddr(NULL), mBase(NULL), mLength(0) 151{ 152} 153 154DataRetrieval::~DataRetrieval() 155{ 156 if (mAddr) { 157 relocate(mAddr, mBase); 158 assert(mAttributes->size() == mAddr->size()); 159 160 // global (per-record) fields 161 mAttributes->recordType(mAddr->recordType()); 162 mAttributes->semanticInformation(mAddr->semanticInformation()); 163 164 // transfer data values (but not infos, which we keep in the original vector) 165 for (uint32 n = 0; n < mAttributes->size(); n++) 166 mAttributes->at(n).copyValues(mAddr->at(n), mAllocator); 167 } 168} 169 170 171} // namespace SecurityServer 172} // end namespace Security 173