X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/bac41a7b9a0a9254fa30f8bb6e6038ab71a483e2..2b1671fa2b47dc427293e35029f0c21900e0bd45:/AppleCSPDL/SSCSPDLSession.cpp diff --git a/AppleCSPDL/SSCSPDLSession.cpp b/AppleCSPDL/SSCSPDLSession.cpp index 7a2bae58..23d66f76 100644 --- a/AppleCSPDL/SSCSPDLSession.cpp +++ b/AppleCSPDL/SSCSPDLSession.cpp @@ -24,14 +24,48 @@ #include "CSPDLPlugin.h" #include "SSKey.h" + +#ifndef SECURITYSERVER_ACL_EDITS + +#include <Security/aclclient.h> +#include <Security/Access.h> +#include <Security/TrustedApplication.h> + +// +// ClientSessionKey - Lightweight wrapper for a KeyHandle that is also an CssmClient::AclBearer +// +class ClientSessionKey: public CssmClient::AclBearer +{ +public: + ClientSessionKey(SecurityServer::ClientSession &clientSession, SecurityServer::KeyHandle keyHandle); + ~ClientSessionKey(); + + // Acl manipulation + virtual void getAcl(AutoAclEntryInfoList &aclInfos, + const char *selectionTag = NULL) const; + virtual void changeAcl(const CSSM_ACL_EDIT &aclEdit, + const CSSM_ACCESS_CREDENTIALS *cred = NULL); + + // Acl owner manipulation + virtual void getOwner(AutoAclOwnerPrototype &owner) const; + virtual void changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, + const CSSM_ACCESS_CREDENTIALS *cred = NULL); + + +private: + SecurityServer::ClientSession &mClientSession; + SecurityServer::KeyHandle mKeyHandle; +}; + +#endif //!SECURITYSERVER_ACL_EDITS + + using namespace SecurityServer; // // SSCSPDLSession -- Security Server CSP session // SSCSPDLSession::SSCSPDLSession() -// @@@ FIXME allocators needs to change. -: mClientSession(CssmAllocator::standard(), CssmAllocator::standard()) { } @@ -51,12 +85,135 @@ SSCSPDLSession::makeReferenceKey(SSCSPSession &session, KeyHandle inKeyHandle, SSKey & SSCSPDLSession::lookupKey(const CssmKey &inKey) { - if (inKey.blobType() == CSSM_KEYBLOB_REFERENCE) - return find<SSKey>(inKey); - else if (inKey.blobType() == CSSM_KEYBLOB_RAW) + /* for now we only allow ref keys */ + if(inKey.blobType() != CSSM_KEYBLOB_REFERENCE) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + + /* fetch key (this is just mapping the value in inKey.KeyData to an SSKey) */ + SSKey &theKey = find<SSKey>(inKey); + + #ifdef someday + /* + * Make sure caller hasn't changed any crucial header fields. + * Some fields were changed by makeReferenceKey, so make a local copy.... + */ + CSSM_KEYHEADER localHdr = cssmKey.KeyHeader; + get binKey-like thing from SSKey, maybe SSKey should keep a copy of + hdr...but that's' not supersecure....; + + localHdr.BlobType = binKey->mKeyHeader.BlobType; + localHdr.Format = binKey->mKeyHeader.Format; + if(memcmp(&localHdr, &binKey->mKeyHeader, sizeof(CSSM_KEYHEADER))) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + } + #endif + return theKey; +} + +// Notification we receive when the acl on a key has changed. We should write it back to disk if it's persistant. +void +SSCSPDLSession::didChangeKeyAcl(SecurityServer::ClientSession &clientSession, + KeyHandle keyHandle, CSSM_ACL_AUTHORIZATION_TAG tag) +{ +#ifndef SECURITYSERVER_ACL_EDITS + { + // The user checked to don't ask again checkbox in the rogue app alert. Let's edit the ACL for this key and add the calling application (ourself) to it. + secdebug("keyacl", "SSCSPDLSession::didChangeKeyAcl(keyHandle: %lu tag: %lu)", keyHandle, tag); + ClientSessionKey csKey(clientSession, keyHandle); // the underlying key + KeychainCore::SecPointer<KeychainCore::Access> access = new KeychainCore::Access(csKey); // extract access rights + KeychainCore::SecPointer<KeychainCore::TrustedApplication> thisApp = new KeychainCore::TrustedApplication; + access->addApplicationToRight(tag, thisApp.get()); // add this app + access->setAccess(csKey, true); // commit + } +#endif // !SECURITYSERVER_ACL_EDITS + + SSKey *theKey = NULL; + { - // @@@ How can we deal with this? + // Lookup the SSKey for the KeyHandle + StLock<Mutex> _(mKeyMapLock); + KeyMap::const_iterator it; + KeyMap::const_iterator end = mKeyMap.end(); + for (it = mKeyMap.begin(); it != end; ++it) + { + SSKey *aKey = dynamic_cast<SSKey *>(it->second); + if (aKey->optionalKeyHandle() == keyHandle) + { + // Write the key to disk if it's persistant. + theKey = aKey; + break; + } + } } - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + if (theKey) + { + theKey->didChangeAcl(); + } + else + { + // @@@ 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. + secdebug("keyacl", "SSCSPDLSession::didChangeKeyAcl() keyHandle: %lu not found in map", keyHandle); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + } } + +void +SSCSPDLSession::didChangeKeyAclCallback(void *context, SecurityServer::ClientSession &clientSession, + SecurityServer::KeyHandle key, CSSM_ACL_AUTHORIZATION_TAG tag) +{ + reinterpret_cast<SSCSPDLSession *>(context)->didChangeKeyAcl(clientSession, key, tag); +} + +#ifndef SECURITYSERVER_ACL_EDITS +// +// ClientSessionKey - Lightweight wrapper for a KeyHandle that is also an CssmClient::AclBearer +// +ClientSessionKey::ClientSessionKey(ClientSession &clientSession, SecurityServer::KeyHandle keyHandle) : + mClientSession(clientSession), + mKeyHandle(keyHandle) +{ +} + +ClientSessionKey::~ClientSessionKey() +{ +} + +void +ClientSessionKey::getAcl(AutoAclEntryInfoList &aclInfos, + const char *selectionTag) const +{ + secdebug("keyacl", "ClientSessionKey::getAcl() keyHandle: %lu", mKeyHandle); + aclInfos.allocator(mClientSession.returnAllocator); + mClientSession.getKeyAcl(mKeyHandle, selectionTag, + *static_cast<uint32 *>(aclInfos), + *reinterpret_cast<AclEntryInfo **>(static_cast<CSSM_ACL_ENTRY_INFO_PTR *>(aclInfos))); +} + +void +ClientSessionKey::changeAcl(const CSSM_ACL_EDIT &aclEdit, + const CSSM_ACCESS_CREDENTIALS *cred) +{ + secdebug("keyacl", "ClientSessionKey::changeAcl() keyHandle: %lu", mKeyHandle); + mClientSession.changeKeyAcl(mKeyHandle, AccessCredentials::overlay(*cred), AclEdit::overlay(aclEdit)); +} + +void +ClientSessionKey::getOwner(AutoAclOwnerPrototype &owner) const +{ + secdebug("keyacl", "ClientSessionKey::getOwner() keyHandle: %lu", mKeyHandle); + owner.allocator(mClientSession.returnAllocator); + mClientSession.getKeyOwner(mKeyHandle, + *reinterpret_cast<AclOwnerPrototype *>(static_cast<CSSM_ACL_OWNER_PROTOTYPE *>(owner))); +} + +void +ClientSessionKey::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, + const CSSM_ACCESS_CREDENTIALS *cred) +{ + secdebug("keyacl", "ClientSessionKey::changeOwner() keyHandle: %lu", mKeyHandle); + mClientSession.changeKeyOwner(mKeyHandle, AccessCredentials::overlay(*cred), AclOwnerPrototype::overlay(newOwner)); +} + +#endif // !SECURITYSERVER_ACL_EDITS