1/* 2 * Copyright (c) 2000-2001,2008,2011-2012 Apple Inc. All Rights Reserved. 3 * 4 * The contents of this file constitute Original Code as defined in and are 5 * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 * You may not use this file except in compliance with the License. Please obtain 7 * a copy of the License at http://www.apple.com/publicsource and read it before 8 * using this file. 9 * 10 * This Original Code and all software distributed under the License are 11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 * specific language governing rights and limitations under the License. 16 */ 17 18 19// 20// SSCSPDLSession.cpp - Security Server CSP/DL session. 21// 22#include "SSCSPDLSession.h" 23 24#include "CSPDLPlugin.h" 25#include "SSKey.h" 26 27 28#ifndef SECURITYSERVER_ACL_EDITS 29 30#include <security_cdsa_client/aclclient.h> 31#include <security_keychain/Access.h> 32#include <security_keychain/TrustedApplication.h> 33#include <security_utilities/seccfobject.h> 34 35// 36// ClientSessionKey - Lightweight wrapper for a KeyHandle that is also an CssmClient::AclBearer 37// 38class ClientSessionKey: public CssmClient::AclBearer 39{ 40public: 41 ClientSessionKey(SecurityServer::ClientSession &clientSession, SecurityServer::KeyHandle keyHandle); 42 ~ClientSessionKey(); 43 44 // Acl manipulation 45 virtual void getAcl(AutoAclEntryInfoList &aclInfos, 46 const char *selectionTag = NULL) const; 47 virtual void changeAcl(const CSSM_ACL_EDIT &aclEdit, 48 const CSSM_ACCESS_CREDENTIALS *cred = NULL); 49 50 // Acl owner manipulation 51 virtual void getOwner(AutoAclOwnerPrototype &owner) const; 52 virtual void changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, 53 const CSSM_ACCESS_CREDENTIALS *cred = NULL); 54 55 56private: 57 SecurityServer::ClientSession &mClientSession; 58 SecurityServer::KeyHandle mKeyHandle; 59}; 60 61#endif //!SECURITYSERVER_ACL_EDITS 62 63 64using namespace SecurityServer; 65 66// 67// SSCSPDLSession -- Security Server CSP session 68// 69SSCSPDLSession::SSCSPDLSession() 70{ 71} 72 73 74// 75// Reference Key management 76// 77void 78SSCSPDLSession::makeReferenceKey(SSCSPSession &session, KeyHandle inKeyHandle, 79 CssmKey &outKey, SSDatabase &inSSDatabase, 80 uint32 inKeyAttr, const CssmData *inKeyLabel) 81{ 82 new SSKey(session, inKeyHandle, outKey, inSSDatabase, inKeyAttr, 83 inKeyLabel); 84} 85 86SSKey & 87SSCSPDLSession::lookupKey(const CssmKey &inKey) 88{ 89 /* for now we only allow ref keys */ 90 if(inKey.blobType() != CSSM_KEYBLOB_REFERENCE) { 91 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); 92 } 93 94 /* fetch key (this is just mapping the value in inKey.KeyData to an SSKey) */ 95 SSKey &theKey = find<SSKey>(inKey); 96 97 #ifdef someday 98 /* 99 * Make sure caller hasn't changed any crucial header fields. 100 * Some fields were changed by makeReferenceKey, so make a local copy.... 101 */ 102 CSSM_KEYHEADER localHdr = cssmKey.KeyHeader; 103 get binKey-like thing from SSKey, maybe SSKey should keep a copy of 104 hdr...but that's' not supersecure....; 105 106 localHdr.BlobType = binKey->mKeyHeader.BlobType; 107 localHdr.Format = binKey->mKeyHeader.Format; 108 if(memcmp(&localHdr, &binKey->mKeyHeader, sizeof(CSSM_KEYHEADER))) { 109 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); 110 } 111 #endif 112 return theKey; 113} 114 115// Notification we receive when the acl on a key has changed. We should write it back to disk if it's persistent. 116void 117SSCSPDLSession::didChangeKeyAcl(SecurityServer::ClientSession &clientSession, 118 KeyHandle keyHandle, CSSM_ACL_AUTHORIZATION_TAG tag) 119{ 120 SSKey *theKey = NULL; 121 122 { 123 // Lookup the SSKey for the KeyHandle 124 StLock<Mutex> _(mKeyMapLock); 125 KeyMap::const_iterator it; 126 KeyMap::const_iterator end = mKeyMap.end(); 127 for (it = mKeyMap.begin(); it != end; ++it) 128 { 129 SSKey *aKey = dynamic_cast<SSKey *>(it->second); 130 if (aKey->optionalKeyHandle() == keyHandle) 131 { 132 // Write the key to disk if it's persistent. 133 theKey = aKey; 134 break; 135 } 136 } 137 } 138 139 if (theKey) 140 { 141 theKey->didChangeAcl(); 142 } 143 else 144 { 145 // @@@ Should we really throw here or just continue without updating the ACL? In reality this should never happen, so let's at least log it and throw. 146 secdebug("keyacl", "SSCSPDLSession::didChangeKeyAcl() keyHandle: %lu not found in map", (unsigned long)keyHandle); 147 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); 148 } 149} 150 151void 152SSCSPDLSession::didChangeKeyAclCallback(void *context, SecurityServer::ClientSession &clientSession, 153 SecurityServer::KeyHandle key, CSSM_ACL_AUTHORIZATION_TAG tag) 154{ 155 reinterpret_cast<SSCSPDLSession *>(context)->didChangeKeyAcl(clientSession, key, tag); 156} 157 158#ifndef SECURITYSERVER_ACL_EDITS 159// 160// ClientSessionKey - Lightweight wrapper for a KeyHandle that is also an CssmClient::AclBearer 161// 162ClientSessionKey::ClientSessionKey(ClientSession &clientSession, SecurityServer::KeyHandle keyHandle) : 163 mClientSession(clientSession), 164 mKeyHandle(keyHandle) 165{ 166} 167 168ClientSessionKey::~ClientSessionKey() 169{ 170} 171 172void 173ClientSessionKey::getAcl(AutoAclEntryInfoList &aclInfos, 174 const char *selectionTag) const 175{ 176 secdebug("keyacl", "ClientSessionKey::getAcl() keyHandle: %u", mKeyHandle); 177 aclInfos.allocator(mClientSession.returnAllocator); 178 mClientSession.getKeyAcl(mKeyHandle, selectionTag, 179 *static_cast<uint32 *>(aclInfos), 180 *reinterpret_cast<AclEntryInfo **>(static_cast<CSSM_ACL_ENTRY_INFO_PTR *>(aclInfos))); 181} 182 183void 184ClientSessionKey::changeAcl(const CSSM_ACL_EDIT &aclEdit, 185 const CSSM_ACCESS_CREDENTIALS *cred) 186{ 187 secdebug("keyacl", "ClientSessionKey::changeAcl() keyHandle: %u", mKeyHandle); 188 mClientSession.changeKeyAcl(mKeyHandle, AccessCredentials::overlay(*cred), AclEdit::overlay(aclEdit)); 189} 190 191void 192ClientSessionKey::getOwner(AutoAclOwnerPrototype &owner) const 193{ 194 secdebug("keyacl", "ClientSessionKey::getOwner() keyHandle: %u", mKeyHandle); 195 owner.allocator(mClientSession.returnAllocator); 196 mClientSession.getKeyOwner(mKeyHandle, 197 *reinterpret_cast<AclOwnerPrototype *>(static_cast<CSSM_ACL_OWNER_PROTOTYPE *>(owner))); 198} 199 200void 201ClientSessionKey::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, 202 const CSSM_ACCESS_CREDENTIALS *cred) 203{ 204 secdebug("keyacl", "ClientSessionKey::changeOwner() keyHandle: %u", mKeyHandle); 205 mClientSession.changeKeyOwner(mKeyHandle, AccessCredentials::overlay(*cred), AclOwnerPrototype::overlay(newOwner)); 206} 207 208#endif // !SECURITYSERVER_ACL_EDITS 209