1.1 --- a/core/systems/HandleSys.cpp Tue Jan 02 02:59:49 2007 +0000
1.2 +++ b/core/systems/HandleSys.cpp Thu Jan 04 02:08:27 2007 +0000
1.3 @@ -14,7 +14,7 @@
1.4
1.5 inline HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index)
1.6 {
1.7 - return g_HandleSys.GetHandle(token->ident, g_ShareSys.GetIdentRoot(), &ignore_handle, index, HandleAccess_Read);
1.8 + return g_HandleSys.GetHandle(token->ident, g_ShareSys.GetIdentRoot(), &ignore_handle, index);
1.9 }
1.10
1.11 HandleSystem::HandleSystem()
1.12 @@ -39,24 +39,39 @@
1.13 delete m_strtab;
1.14 }
1.15
1.16 -HandleType_t HandleSystem::CreateType(const char *name, IHandleTypeDispatch *dispatch)
1.17 -{
1.18 - return CreateTypeEx(name, dispatch, 0, NULL, NULL);
1.19 -}
1.20
1.21 -HandleType_t HandleSystem::CreateChildType(const char *name, HandleType_t parent, IHandleTypeDispatch *dispatch)
1.22 -{
1.23 - return CreateTypeEx(name, dispatch, parent, NULL, NULL);
1.24 -}
1.25 -
1.26 -HandleType_t HandleSystem::CreateTypeEx(const char *name,
1.27 - IHandleTypeDispatch *dispatch,
1.28 - HandleType_t parent,
1.29 - const HandleSecurity *security,
1.30 - IdentityToken_t *ident)
1.31 +HandleType_t HandleSystem::CreateType(const char *name,
1.32 + IHandleTypeDispatch *dispatch,
1.33 + HandleType_t parent,
1.34 + const TypeAccess *typeAccess,
1.35 + const HandleAccess *hndlAccess,
1.36 + IdentityToken_t *ident,
1.37 + HandleError *err)
1.38 {
1.39 if (!dispatch)
1.40 {
1.41 + if (err)
1.42 + {
1.43 + *err = HandleError_Parameter;
1.44 + }
1.45 + return 0;
1.46 + }
1.47 +
1.48 + if (typeAccess && typeAccess->hsVersion > SMINTERFACE_HANDLESYSTEM_VERSION)
1.49 + {
1.50 + if (err)
1.51 + {
1.52 + *err = HandleError_Version;
1.53 + }
1.54 + return 0;
1.55 + }
1.56 +
1.57 + if (hndlAccess && hndlAccess->hsVersion > SMINTERFACE_HANDLESYSTEM_VERSION)
1.58 + {
1.59 + if (err)
1.60 + {
1.61 + *err = HandleError_Version;
1.62 + }
1.63 return 0;
1.64 }
1.65
1.66 @@ -67,34 +82,44 @@
1.67 isChild = true;
1.68 if (parent & HANDLESYS_SUBTYPE_MASK)
1.69 {
1.70 + if (err)
1.71 + {
1.72 + *err = HandleError_NoInherit;
1.73 + }
1.74 return 0;
1.75 }
1.76 if (parent >= HANDLESYS_TYPEARRAY_SIZE
1.77 - || m_Types[parent].dispatch == NULL
1.78 - || (m_Types[parent].sec.access[HandleAccess_Inherit] == false
1.79 - && m_Types[parent].sec.owner != ident))
1.80 + || m_Types[parent].dispatch == NULL)
1.81 {
1.82 + if (err)
1.83 + {
1.84 + *err = HandleError_Parameter;
1.85 + }
1.86 + return 0;
1.87 + }
1.88 + if (m_Types[parent].typeSec.access[HTypeAccess_Inherit] == false
1.89 + && (m_Types[parent].typeSec.ident != ident))
1.90 + {
1.91 + if (err)
1.92 + {
1.93 + *err = HandleError_Access;
1.94 + }
1.95 return 0;
1.96 }
1.97 }
1.98
1.99 - if (!security)
1.100 + if (name && name[0] != '\0')
1.101 {
1.102 - if (isChild)
1.103 + if (sm_trie_retrieve(m_TypeLookup, name, NULL))
1.104 {
1.105 - security = &m_Types[parent].sec;
1.106 - } else {
1.107 - static HandleSecurity def_h;
1.108 - security = &def_h;
1.109 + if (err)
1.110 + {
1.111 + *err = HandleError_Parameter;
1.112 + }
1.113 + return 0;
1.114 }
1.115 }
1.116
1.117 - if (security->access[HandleAccess_Create]
1.118 - && sm_trie_retrieve(m_TypeLookup, name, NULL))
1.119 - {
1.120 - return 0;
1.121 - }
1.122 -
1.123 unsigned int index;
1.124
1.125 if (isChild)
1.126 @@ -102,6 +127,10 @@
1.127 QHandleType *pParent = &m_Types[parent];
1.128 if (pParent->children >= HANDLESYS_MAX_SUBTYPES)
1.129 {
1.130 + if (err)
1.131 + {
1.132 + *err = HandleError_Limit;
1.133 + }
1.134 return 0;
1.135 }
1.136 index = 0;
1.137 @@ -115,6 +144,10 @@
1.138 }
1.139 if (!index)
1.140 {
1.141 + if (err)
1.142 + {
1.143 + *err = HandleError_Limit;
1.144 + }
1.145 return 0;
1.146 }
1.147 pParent->children++;
1.148 @@ -124,6 +157,10 @@
1.149 /* Reserve another index */
1.150 if (m_TypeTail >= HANDLESYS_TYPEARRAY_SIZE)
1.151 {
1.152 + if (err)
1.153 + {
1.154 + *err = HandleError_Limit;
1.155 + }
1.156 return 0;
1.157 } else {
1.158 m_TypeTail += (HANDLESYS_MAX_SUBTYPES + 1);
1.159 @@ -145,9 +182,24 @@
1.160 } else {
1.161 pType->nameIdx = -1;
1.162 }
1.163 - pType->sec = *security;
1.164 +
1.165 pType->opened = 0;
1.166
1.167 + if (typeAccess)
1.168 + {
1.169 + pType->typeSec = *typeAccess;
1.170 + } else {
1.171 + InitAccessDefaults(&pType->typeSec, NULL);
1.172 + pType->typeSec.ident = ident;
1.173 + }
1.174 +
1.175 + if (hndlAccess)
1.176 + {
1.177 + pType->hndlSec = *hndlAccess;
1.178 + } else {
1.179 + InitAccessDefaults(NULL, &pType->hndlSec);
1.180 + }
1.181 +
1.182 if (!isChild)
1.183 {
1.184 pType->children = 0;
1.185 @@ -264,33 +316,46 @@
1.186 return;
1.187 }
1.188
1.189 - m_Types[type].sec.owner = pToken;
1.190 + m_Types[type].typeSec.ident = pToken;
1.191 }
1.192
1.193 -Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityToken_t *source, IdentityToken_t *ident)
1.194 +Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityToken_t *owner, IdentityToken_t *ident, HandleError *err)
1.195 {
1.196 if (!type
1.197 || type >= HANDLESYS_TYPEARRAY_SIZE
1.198 || m_Types[type].dispatch == NULL)
1.199 {
1.200 + if (err)
1.201 + {
1.202 + *err = HandleError_Parameter;
1.203 + }
1.204 return 0;
1.205 }
1.206
1.207 - /* Check the security of this handle */
1.208 + /* Check to see if we're allowed to create this handle type */
1.209 QHandleType *pType = &m_Types[type];
1.210 - if (!pType->sec.access[HandleAccess_Create]
1.211 - && pType->sec.owner != ident)
1.212 + if (!pType->typeSec.access[HTypeAccess_Create]
1.213 + && (!pType->typeSec.ident
1.214 + || pType->typeSec.ident != ident))
1.215 {
1.216 + if (err)
1.217 + {
1.218 + *err = HandleError_Access;
1.219 + }
1.220 return 0;
1.221 }
1.222
1.223 unsigned int index;
1.224 Handle_t handle;
1.225 QHandle *pHandle;
1.226 - HandleError err;
1.227 + HandleError _err;
1.228
1.229 - if ((err=MakePrimHandle(type, &pHandle, &index, &handle, source)) != HandleError_None)
1.230 + if ((_err=MakePrimHandle(type, &pHandle, &index, &handle, owner)) != HandleError_None)
1.231 {
1.232 + if (err)
1.233 + {
1.234 + *err = _err;
1.235 + }
1.236 return 0;
1.237 }
1.238
1.239 @@ -300,16 +365,6 @@
1.240 return handle;
1.241 }
1.242
1.243 -Handle_t HandleSystem::CreateScriptHandle(HandleType_t type,
1.244 - void *object,
1.245 - IPluginContext *pContext,
1.246 - IdentityToken_t *ident)
1.247 -{
1.248 - IPlugin *pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
1.249 -
1.250 - return CreateHandle(type, object, pPlugin->GetIdentity(), ident);
1.251 -}
1.252 -
1.253 bool HandleSystem::TypeCheck(HandleType_t intype, HandleType_t outtype)
1.254 {
1.255 /* Check the type inheritance */
1.256 @@ -334,7 +389,6 @@
1.257 IdentityToken_t *ident,
1.258 QHandle **in_pHandle,
1.259 unsigned int *in_index,
1.260 - HandleAccessRight access,
1.261 bool ignoreFree)
1.262 {
1.263 unsigned int serial = (handle >> 16);
1.264 @@ -348,11 +402,6 @@
1.265 QHandle *pHandle = &m_Handles[index];
1.266 QHandleType *pType = &m_Types[pHandle->type];
1.267
1.268 - if ((access != HandleAccess_TOTAL)
1.269 - && (!pType->sec.access[access] && pType->sec.owner != ident))
1.270 - {
1.271 - return HandleError_Access;
1.272 - }
1.273 if (!pHandle->set
1.274 || (pHandle->set == HandleSet_Freed && !ignoreFree))
1.275 {
1.276 @@ -374,13 +423,44 @@
1.277 return HandleError_None;
1.278 }
1.279
1.280 -HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *out_newhandle, IdentityToken_t *source, IdentityToken_t *ident)
1.281 +bool HandleSystem::CheckAccess(QHandle *pHandle, HandleAccessRight right, const HandleSecurity *pSecurity)
1.282 +{
1.283 + QHandleType *pType = &m_Types[pHandle->type];
1.284 + unsigned int access = pType->hndlSec.access[right];
1.285 +
1.286 + /* Check if the type's identity matches */
1.287 + if (access & HANDLE_RESTRICT_IDENTITY)
1.288 + {
1.289 + IdentityToken_t *owner = pType->typeSec.ident;
1.290 + if (!owner
1.291 + || (!pSecurity || pSecurity->pIdentity != owner))
1.292 + {
1.293 + return false;
1.294 + }
1.295 + }
1.296 +
1.297 + /* Check if the owner is allowed */
1.298 + if (access & HANDLE_RESTRICT_OWNER)
1.299 + {
1.300 + IdentityToken_t *owner = pHandle->owner;
1.301 + if (owner
1.302 + && (!pSecurity || pSecurity->pOwner != owner))
1.303 + {
1.304 + return false;
1.305 + }
1.306 + }
1.307 +
1.308 + return true;
1.309 +}
1.310 +
1.311 +HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *newhandle, IdentityToken_t *newOwner, const HandleSecurity *pSecurity)
1.312 {
1.313 HandleError err;
1.314 QHandle *pHandle;
1.315 unsigned int index;
1.316 + IdentityToken_t *ident = pSecurity ? pSecurity->pIdentity : NULL;
1.317
1.318 - if ((err=GetHandle(handle, ident, &pHandle, &index, HandleAccess_Clone)) != HandleError_None)
1.319 + if ((err=GetHandle(handle, ident, &pHandle, &index)) != HandleError_None)
1.320 {
1.321 return err;
1.322 }
1.323 @@ -391,49 +471,49 @@
1.324 return HandleError_Identity;
1.325 }
1.326
1.327 - QHandleType *pType = &m_Types[pHandle->type];
1.328 + /* Check if the handle can be cloned */
1.329 + if (!CheckAccess(pHandle, HandleAccess_Clone, pSecurity))
1.330 + {
1.331 + return HandleError_Access;
1.332 + }
1.333
1.334 /* Get a new Handle ID */
1.335 unsigned int new_index;
1.336 QHandle *pNewHandle;
1.337 Handle_t new_handle;
1.338
1.339 - if ((err=MakePrimHandle(pHandle->type, &pNewHandle, &new_index, &new_handle, source)) != HandleError_None)
1.340 + if ((err=MakePrimHandle(pHandle->type, &pNewHandle, &new_index, &new_handle, newOwner)) != HandleError_None)
1.341 {
1.342 return err;
1.343 }
1.344
1.345 - pNewHandle->clone = handle;
1.346 + pNewHandle->clone = index;
1.347 pHandle->refcount++;
1.348
1.349 - if (out_newhandle)
1.350 - {
1.351 - *out_newhandle = new_handle;
1.352 - }
1.353 + *newhandle = new_handle;
1.354
1.355 return HandleError_None;
1.356 }
1.357
1.358 -HandleError HandleSystem::FreeHandle(Handle_t handle, IdentityToken_t *pOwner, IdentityToken_t *ident)
1.359 +HandleError HandleSystem::FreeHandle(Handle_t handle, const HandleSecurity *pSecurity)
1.360 {
1.361 unsigned int index;
1.362 QHandle *pHandle;
1.363 HandleError err;
1.364 + IdentityToken_t *ident = pSecurity ? pSecurity->pIdentity : NULL;
1.365
1.366 - if ((err=GetHandle(handle, ident, &pHandle, &index, HandleAccess_IdentDelete)) != HandleError_None)
1.367 + if ((err=GetHandle(handle, ident, &pHandle, &index)) != HandleError_None)
1.368 {
1.369 return err;
1.370 }
1.371
1.372 - QHandleType *pType = &m_Types[pHandle->type];
1.373 -
1.374 - if (pType->sec.access[HandleAccess_OwnerDelete] == false
1.375 - && pHandle->owner
1.376 - && pHandle->owner != pOwner)
1.377 + if (!CheckAccess(pHandle, HandleAccess_Delete, pSecurity))
1.378 {
1.379 return HandleError_Access;
1.380 }
1.381
1.382 + QHandleType *pType = &m_Types[pHandle->type];
1.383 +
1.384 bool dofree = false;
1.385 if (pHandle->clone)
1.386 {
1.387 @@ -441,9 +521,10 @@
1.388 QHandle *pMaster;
1.389 unsigned int master;
1.390
1.391 - /* This call should not return an error, it'd be a corruption sign */
1.392 - err = GetHandle(pHandle->clone, ident, &pMaster, &master, HandleAccess_IdentDelete, true);
1.393 - assert(err == HandleError_None);
1.394 + /* Note that if we ever have per-handle security, we would need to re-check
1.395 + * the access on this Handle. */
1.396 + master = pHandle->clone;
1.397 + pMaster = &m_Handles[master];
1.398
1.399 /* Release the clone now */
1.400 ReleasePrimHandle(index);
1.401 @@ -471,20 +552,23 @@
1.402 return HandleError_None;
1.403 }
1.404
1.405 -HandleError HandleSystem::ReadHandle(Handle_t handle,
1.406 - HandleType_t type,
1.407 - IdentityToken_t *ident,
1.408 - void **object)
1.409 +HandleError HandleSystem::ReadHandle(Handle_t handle, HandleType_t type, const HandleSecurity *pSecurity, void **object)
1.410 {
1.411 unsigned int index;
1.412 QHandle *pHandle;
1.413 HandleError err;
1.414 + IdentityToken_t *ident = pSecurity ? pSecurity->pIdentity : NULL;
1.415
1.416 - if ((err=GetHandle(handle, ident, &pHandle, &index, HandleAccess_Read)) != HandleError_None)
1.417 + if ((err=GetHandle(handle, ident, &pHandle, &index)) != HandleError_None)
1.418 {
1.419 return err;
1.420 }
1.421
1.422 + if (!CheckAccess(pHandle, HandleAccess_Read, pSecurity))
1.423 + {
1.424 + return HandleError_Access;
1.425 + }
1.426 +
1.427 /* Check the type inheritance */
1.428 if (pHandle->type & HANDLESYS_SUBTYPE_MASK)
1.429 {
1.430 @@ -505,8 +589,7 @@
1.431 /* if we're a clone, the rules change - object is ONLY in our reference */
1.432 if (pHandle->clone)
1.433 {
1.434 - /* :TODO: optimize this */
1.435 - return ReadHandle(pHandle->clone, pHandle->type, ident, object);
1.436 + pHandle = &m_Handles[pHandle->clone];
1.437 }
1.438 *object = pHandle->object;
1.439 }
1.440 @@ -579,7 +662,8 @@
1.441
1.442 QHandleType *pType = &m_Types[type];
1.443
1.444 - if (pType->sec.owner && pType->sec.owner != ident)
1.445 + if (pType->typeSec.ident
1.446 + && pType->typeSec.ident != ident)
1.447 {
1.448 return false;
1.449 }
1.450 @@ -598,7 +682,7 @@
1.451 childType = &m_Types[type + i];
1.452 if (childType->dispatch)
1.453 {
1.454 - RemoveType(type + i, childType->sec.owner);
1.455 + RemoveType(type + i, childType->typeSec.ident);
1.456 }
1.457 }
1.458 /* Link us into the free chain */
1.459 @@ -658,10 +742,38 @@
1.460 QHandle *pHandle;
1.461 unsigned int index;
1.462
1.463 - if (GetHandle(handle, g_ShareSys.GetIdentRoot(), &pHandle, &index, HandleAccess_Read) != HandleError_None)
1.464 + if (GetHandle(handle, g_ShareSys.GetIdentRoot(), &pHandle, &index) != HandleError_None)
1.465 {
1.466 return;
1.467 }
1.468
1.469 pHandle->set = HandleSet_Identity;
1.470 }
1.471 +
1.472 +bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess)
1.473 +{
1.474 + if (pTypeAccess)
1.475 + {
1.476 + if (pTypeAccess->hsVersion > SMINTERFACE_HANDLESYSTEM_VERSION)
1.477 + {
1.478 + return false;
1.479 + }
1.480 + pTypeAccess->access[HTypeAccess_Create] = false;
1.481 + pTypeAccess->access[HTypeAccess_Inherit] = false;
1.482 + pTypeAccess->ident = NULL;
1.483 + }
1.484 +
1.485 + if (pHandleAccess)
1.486 + {
1.487 + if (pHandleAccess->hsVersion > SMINTERFACE_HANDLESYSTEM_VERSION)
1.488 + {
1.489 + return false;
1.490 + }
1.491 +
1.492 + pHandleAccess->access[HandleAccess_Clone] = 0;
1.493 + pHandleAccess->access[HandleAccess_Delete] = HANDLE_RESTRICT_OWNER;
1.494 + pHandleAccess->access[HandleAccess_Read] = HANDLE_RESTRICT_IDENTITY;
1.495 + }
1.496 +
1.497 + return true;
1.498 +}