diff --git a/core/systems/HandleSys.cpp b/core/systems/HandleSys.cpp index 7ef9cc1d..835bf3c9 100644 --- a/core/systems/HandleSys.cpp +++ b/core/systems/HandleSys.cpp @@ -283,6 +283,7 @@ HandleError HandleSystem::MakePrimHandle(HandleType_t type, pHandle->serial = m_HSerial; pHandle->owner = owner; pHandle->ch_next = 0; + pHandle->access_special = false; /* Create the hash value */ Handle_t hash = pHandle->serial; @@ -336,8 +337,25 @@ void HandleSystem::SetTypeSecurityOwner(HandleType_t type, IdentityToken_t *pTok m_Types[type].typeSec.ident = pToken; } -Handle_t HandleSystem::CreateHandleEx(HandleType_t type, void *object, IdentityToken_t *owner, IdentityToken_t *ident, HandleError *err, bool identity) +Handle_t HandleSystem::CreateHandleInt(HandleType_t type, + void *object, + const HandleSecurity *pSec, + HandleError *err, + const HandleAccess *pAccess, + bool identity) { + IdentityToken_t *ident; + IdentityToken_t *owner; + + if (pSec) + { + ident = pSec->pIdentity; + owner = pSec->pOwner; + } else { + ident = NULL; + owner = NULL; + } + if (!type || type >= HANDLESYS_TYPEARRAY_SIZE || m_Types[type].dispatch == NULL) @@ -376,15 +394,31 @@ Handle_t HandleSystem::CreateHandleEx(HandleType_t type, void *object, IdentityT return 0; } + if (pAccess) + { + pHandle->access_special = true; + pHandle->sec = *pAccess; + } + pHandle->object = object; pHandle->clone = 0; return handle; } +Handle_t HandleSystem::CreateHandleEx(HandleType_t type, void *object, const HandleSecurity *pSec, const HandleAccess *pAccess, HandleError *err) +{ + return CreateHandleInt(type, object, pSec, err, pAccess, false); +} + Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityToken_t *owner, IdentityToken_t *ident, HandleError *err) { - return CreateHandleEx(type, object, owner, ident, err, false); + HandleSecurity sec; + + sec.pIdentity = ident; + sec.pOwner = owner; + + return CreateHandleEx(type, object, &sec, NULL, err); } bool HandleSystem::TypeCheck(HandleType_t intype, HandleType_t outtype) @@ -447,7 +481,14 @@ HandleError HandleSystem::GetHandle(Handle_t handle, bool HandleSystem::CheckAccess(QHandle *pHandle, HandleAccessRight right, const HandleSecurity *pSecurity) { QHandleType *pType = &m_Types[pHandle->type]; - unsigned int access = pType->hndlSec.access[right]; + unsigned int access; + + if (pHandle->access_special) + { + access = pHandle->sec.access[right]; + } else { + access = pType->hndlSec.access[right]; + } /* Check if the type's identity matches */ if (access & HANDLE_RESTRICT_IDENTITY) @@ -487,6 +528,13 @@ HandleError HandleSystem::CloneHandle(QHandle *pHandle, unsigned int index, Hand return err; } + /* Assign permissions from parent */ + if (pHandle->access_special) + { + pNewHandle->access_special = true; + pNewHandle->sec = pHandle->sec; + } + pNewHandle->clone = index; pHandle->refcount++; diff --git a/core/systems/HandleSys.h b/core/systems/HandleSys.h index 97962562..0288abda 100644 --- a/core/systems/HandleSys.h +++ b/core/systems/HandleSys.h @@ -63,6 +63,8 @@ struct QHandle unsigned int refcount; /* Reference count for safe destruction */ unsigned int clone; /* If non-zero, this is our cloned parent index */ HandleSet set; /* Information about the handle's state */ + bool access_special; /* Whether or not access rules are special or type-derived */ + HandleAccess sec; /* Security rules */ /* The following variables are unrelated to the Handle array, and used * as an inlined chain of information */ unsigned int freeID; /* ID of a free handle in the free handle chain */ @@ -126,6 +128,12 @@ public: //IHandleSystem bool InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess); bool TypeCheck(HandleType_t intype, HandleType_t outtype); + + virtual Handle_t CreateHandleEx(HandleType_t type, + void *object, + const HandleSecurity *pSec, + const HandleAccess *pAccess, + HandleError *err); protected: /** * Decodes a handle with sanity and security checking. @@ -170,7 +178,7 @@ protected: HandleError FreeHandle(QHandle *pHandle, unsigned int index); void UnlinkHandleFromOwner(QHandle *pHandle, unsigned int index); HandleError CloneHandle(QHandle *pHandle, unsigned int index, Handle_t *newhandle, IdentityToken_t *newOwner); - Handle_t CreateHandleEx(HandleType_t type, void *object, IdentityToken_t *owner, IdentityToken_t *ident, HandleError *err, bool identity); + Handle_t CreateHandleInt(HandleType_t type, void *object, const HandleSecurity *pSec, HandleError *err, const HandleAccess *pAccess, bool identity); private: QHandle *m_Handles; QHandleType *m_Types; diff --git a/core/systems/ShareSys.cpp b/core/systems/ShareSys.cpp index 95e7184d..b8649cea 100644 --- a/core/systems/ShareSys.cpp +++ b/core/systems/ShareSys.cpp @@ -104,7 +104,11 @@ IdentityToken_t *ShareSystem::CreateIdentity(IdentityType_t type) /* :TODO: Cache? */ IdentityToken_t *pToken = new IdentityToken_t; - pToken->ident = g_HandleSys.CreateHandleEx(type, NULL, GetIdentRoot(), GetIdentRoot(), NULL, true); + + HandleSecurity sec; + sec.pOwner = sec.pIdentity = GetIdentRoot(); + + pToken->ident = g_HandleSys.CreateHandleInt(type, NULL, &sec, NULL, NULL, true); return pToken; } diff --git a/public/IHandleSys.h b/public/IHandleSys.h index 92cf5a72..a1dc7b6f 100644 --- a/public/IHandleSys.h +++ b/public/IHandleSys.h @@ -39,7 +39,7 @@ #include #define SMINTERFACE_HANDLESYSTEM_NAME "IHandleSys" -#define SMINTERFACE_HANDLESYSTEM_VERSION 1 +#define SMINTERFACE_HANDLESYSTEM_VERSION 2 /** Specifies no Identity */ #define DEFAULT_IDENTITY NULL @@ -303,6 +303,23 @@ namespace SourceMod * @return True on success, false if version is unsupported. */ virtual bool InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess) =0; + + /** + * @brief Creates a new handle. + * + * @param type Type to use on the handle. + * @param object Object to bind to the handle. + * @param pSec Security pointer; pOwner is written as the owner, + * pIdent is used as the parent identity for authorization. + * @param pAccess Access right descriptor for the Handle; NULL for type defaults. + * @param err Optional pointer to store an error code. + * @return A new Handle_t, or 0 on failure. + */ + virtual Handle_t CreateHandleEx(HandleType_t type, + void *object, + const HandleSecurity *pSec, + const HandleAccess *pAccess, + HandleError *err) =0; }; }