X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_cssm/lib/attachment.h diff --git a/Security/libsecurity_cssm/lib/attachment.h b/Security/libsecurity_cssm/lib/attachment.h new file mode 100644 index 00000000..a18d33e5 --- /dev/null +++ b/Security/libsecurity_cssm/lib/attachment.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2000-2001,2003-2004,2011-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// +// attachment - CSSM module attachment objects +// +#ifndef _H_ATTACHMENT +#define _H_ATTACHMENT + +#include "cssmint.h" +#include "module.h" +#include +#include + + +// +// This type represents a single Attachment of any kind. +// Attachments are formed by the CSSM_ModuleAttach call and represent a "session" +// between a caller client and a particular plugin module. Any number of attachments +// can exist for a particular caller and a particular module. +// Attachment is an abstract class. You must subclass it to implement a concrete +// type of plugin. For the standard ones, see the end of this header. +// Key recovery does not use Attachments. +// EMMs are not Attachments, but the plugins they manage are. +// And yes, an Attachment *is* a lock. The API transition layer functions need +// to lock Attachments from the "outside", so there's no point in being coy about it. +// Locking the Attachment is equivalent to locking all its members except for +// instance-constant ones. +// +class Attachment : public HandleObject, // has a handle + public CssmMemoryFunctionsAllocator, // is an allocator + public CountingMutex { // is a counting lock + NOCOPY(Attachment) +public: + Attachment(Module *theModule, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + const CSSM_API_MEMORY_FUNCS &memoryOps, + CSSM_ATTACH_FLAGS attachFlags, + CSSM_KEY_HIERARCHY keyHierarchy); + virtual ~Attachment(); + + Module &module; + + // feature inquiries. These features are constant for the life of the Attachment + const Guid &myGuid() const { return module.myGuid(); } + CSSM_SERVICE_TYPE subserviceType() const { return mSubserviceType; } + uint32 subserviceId() const { return mSubserviceId; } + const CSSM_VERSION &pluginVersion() const { return mVersion; } + CSSM_ATTACH_FLAGS attachFlags() const { return mAttachFlags; } + + bool isThreadSafe() const { return module.isThreadSafe(); } + + // service a symbol table inquiry against our attachment + virtual void resolveSymbols(CSSM_FUNC_NAME_ADDR *FunctionTable, + uint32 NumFunctions) = 0; + + // terminate the live attachment and prepare to die + void detach(bool isLocked); + + template friend Sub &enterAttachment(CSSM_HANDLE); + + // need to redefine lock/trylock to implement HandleObject protocol + void lock() { CountingMutex::lock(); } + bool tryLock() { return CountingMutex::tryLock(); } + +private: + bool mIsActive; // successfully attached to plugin + + uint32 mSubserviceId; // subservice ID in use + CSSM_SERVICE_TYPE mSubserviceType; // service type + + // how we were created + CSSM_VERSION mVersion; // plugin version requested + CSSM_ATTACH_FLAGS mAttachFlags; // attach flags requested + CSSM_KEY_HIERARCHY mKeyHierarchy; // key hierarchy verified + +protected: + CSSM_MODULE_FUNCS *spiFunctionTable; // entry table as returned by plugin on attach + +private: + CSSM_UPCALLS upcalls; // upcall functions for our module + + // upcall implementors - these are handed to the plugin in `upcalls' + static void *upcallMalloc(CSSM_HANDLE handle, size_t size); + static void upcallFree(CSSM_HANDLE handle, void *mem); + static void *upcallRealloc(CSSM_HANDLE handle, void *mem, size_t size); + static void *upcallCalloc(CSSM_HANDLE handle, size_t num, size_t size); + static CSSM_RETURN upcallCcToHandle(CSSM_CC_HANDLE handle, CSSM_MODULE_HANDLE *modHandle); + static CSSM_RETURN upcallGetModuleInfo(CSSM_MODULE_HANDLE Module, + CSSM_GUID_PTR Guid, + CSSM_VERSION_PTR Version, + uint32 *SubServiceId, + CSSM_SERVICE_TYPE *SubServiceType, + CSSM_ATTACH_FLAGS *AttachFlags, + CSSM_KEY_HIERARCHY *KeyHierarchy, + CSSM_API_MEMORY_FUNCS_PTR AttachedMemFuncs, + CSSM_FUNC_NAME_ADDR_PTR FunctionTable, + uint32 NumFunctions); +}; + +// this should be a member template, but egcs barfs on its invocation +// @@@ pass module code in to get better "invalid handle" diag? +// @@@ or use template specializations here? +template +inline AttachmentSubclass &enterAttachment(CSSM_HANDLE h) +{ + AttachmentSubclass &attachment = HandleObject::findAndLock(h, CSSMERR_CSSM_INVALID_ADDIN_HANDLE); + attachment.finishEnter(); + return attachment; +} + + +// +// For the standard attachment types, function dispatch to the plugin +// is done based on the CSSM_SPI_xxx_FUNCS structures describing the +// types and ordering of entry points. The StandardAttachment class +// implements this by holding a copy of these tables for the use of +// the transition layer. +// You are free to subclass from Attachment directly if that makes better +// sense to your kind of plugin. +// +template +class StandardAttachment : public Attachment { +public: + typedef map NameMap; + + StandardAttachment(Module *theModule, + const NameMap &names, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + const CSSM_API_MEMORY_FUNCS &memoryOps, + CSSM_ATTACH_FLAGS attachFlags, + CSSM_KEY_HIERARCHY keyHierarchy) + : Attachment(theModule, version, subserviceId, subserviceType, + memoryOps, attachFlags, keyHierarchy), + nameMap(names) + { + try { + if (spiFunctionTable->NumberOfServiceFuncs < + sizeof(FunctionTable) / sizeof(CSSM_PROC_ADDR)) + CssmError::throwMe(CSSMERR_CSSM_INVALID_ADDIN_FUNCTION_TABLE); + // tolerate a table that's TOO large - perhaps it's a newer version + // @@@ with the new spec, we could just store the pointer + memcpy(&downcalls, spiFunctionTable->ServiceFuncs, sizeof(downcalls)); + } catch (...) { + // we are attached to the plugin, so tell it the show is off + detach(false); + throw; + } + } + + void resolveSymbols(CSSM_FUNC_NAME_ADDR *inFunctionTable, + uint32 NumFunctions) + { + for (unsigned n = 0; n < NumFunctions; n++) { + NameMap::const_iterator it = nameMap.find(inFunctionTable[n].Name); + inFunctionTable[n].Address = + (it == nameMap.end()) ? NULL : downcallNumber(it->second); + } + } + + FunctionTable downcalls; + + CSSM_PROC_ADDR downcallNumber(uint32 index) const + { + assert(index < sizeof(downcalls) / sizeof(CSSM_PROC_ADDR)); + return reinterpret_cast(&downcalls)[index]; + } + +private: + const NameMap &nameMap; +}; + + +#endif //_H_ATTACHMENT