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