Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

obse.c File Reference

#include "obp.h"

Go to the source code of this file.

Functions

NTSTATUS NtSetSecurityObject (IN HANDLE Handle, IN SECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR SecurityDescriptor)
NTSTATUS ObSetSecurityObjectByPointer (IN PVOID Object, IN SECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR SecurityDescriptor)
NTSTATUS NtQuerySecurityObject (IN HANDLE Handle, IN SECURITY_INFORMATION SecurityInformation, OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Length, OUT PULONG LengthNeeded)
BOOLEAN ObCheckObjectAccess (IN PVOID Object, IN OUT PACCESS_STATE AccessState, IN BOOLEAN TypeMutexLocked, IN KPROCESSOR_MODE AccessMode, OUT PNTSTATUS AccessStatus)
BOOLEAN ObpCheckObjectReference (IN PVOID Object, IN OUT PACCESS_STATE AccessState, IN BOOLEAN TypeMutexLocked, IN KPROCESSOR_MODE AccessMode, OUT PNTSTATUS AccessStatus)
BOOLEAN ObpCheckTraverseAccess (IN PVOID DirectoryObject, IN ACCESS_MASK TraverseAccess, IN PACCESS_STATE AccessState OPTIONAL, IN BOOLEAN TypeMutexLocked, IN KPROCESSOR_MODE PreviousMode, OUT PNTSTATUS AccessStatus)
BOOLEAN ObCheckCreateObjectAccess (IN PVOID DirectoryObject, IN ACCESS_MASK CreateAccess, IN PACCESS_STATE AccessState, IN PUNICODE_STRING ComponentName, IN BOOLEAN TypeMutexLocked, IN KPROCESSOR_MODE PreviousMode, OUT PNTSTATUS AccessStatus)
NTSTATUS ObAssignObjectSecurityDescriptor (IN PVOID Object, IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL, IN POOL_TYPE PoolType)
NTSTATUS ObGetObjectSecurity (IN PVOID Object, OUT PSECURITY_DESCRIPTOR *SecurityDescriptor, OUT PBOOLEAN MemoryAllocated)
VOID ObReleaseObjectSecurity (IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN BOOLEAN MemoryAllocated)
NTSTATUS ObValidateSecurityQuota (IN PVOID Object, IN ULONG NewSize)
NTSTATUS ObAssignSecurity (IN PACCESS_STATE AccessState, IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL, IN PVOID Object, IN POBJECT_TYPE ObjectType)
NTSTATUS ObQuerySecurityDescriptorInfo (IN PSECURITY_INFORMATION SecurityInformation, OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN OUT PULONG Length, IN PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor)
NTSTATUS ObSetSecurityDescriptorInfo (IN PVOID Object, IN PSECURITY_INFORMATION SecurityInformation, IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, IN POOL_TYPE PoolType, IN PGENERIC_MAPPING GenericMapping)
NTSTATUS ObpValidateAccessMask (PACCESS_STATE AccessState)


Function Documentation

NTSTATUS NtQuerySecurityObject IN HANDLE  Handle,
IN SECURITY_INFORMATION  SecurityInformation,
OUT PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN ULONG  Length,
OUT PULONG  LengthNeeded
 

Definition at line 255 of file obse.c.

References EXCEPTION_EXECUTE_HANDLER, _OBJECT_TYPE_INITIALIZER::GenericMapping, Handle, KernelMode, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, OBJECT_TO_OBJECT_HEADER, ObReferenceObjectByHandle(), PAGED_CODE, _OBJECT_TYPE_INITIALIZER::PoolType, ProbeForWrite(), ProbeForWriteUlong, QuerySecurityDescriptor, _OBJECT_HEADER::SecurityDescriptor, _OBJECT_TYPE_INITIALIZER::SecurityProcedure, SeQuerySecurityAccessMask(), Status, _OBJECT_HEADER::Type, and _OBJECT_TYPE::TypeInfo.

Referenced by CmpCloneControlSet(), CmpCloneHwProfile(), CmpSaveBootControlSet(), Copy(), DumpSecurity(), and GetUserObjectSecurity().

00265 : 00266 00267 This routine is used to query the security descriptor for an 00268 object. 00269 00270 Arguments: 00271 00272 Handle - Supplies the handle for the object being investigated 00273 00274 SecurityInformation - Indicates the type of information we are 00275 interested in getting. e.g., owner, group, dacl, or sacl. 00276 00277 SecurityDescriptor - Supplies a pointer to where the information 00278 should be returned 00279 00280 Length - Supplies the size, in bytes, of the output buffer 00281 00282 LengthNeeded - Receives the length, in bytes, needed to store 00283 the output security descriptor 00284 00285 Return Value: 00286 00287 An appropriate NTSTATUS value 00288 00289 --*/ 00290 00291 { 00292 NTSTATUS Status; 00293 PVOID Object; 00294 ACCESS_MASK DesiredAccess; 00295 OBJECT_HANDLE_INFORMATION HandleInformation; 00296 KPROCESSOR_MODE RequestorMode; 00297 POBJECT_HEADER ObjectHeader; 00298 POBJECT_TYPE ObjectType; 00299 00300 PAGED_CODE(); 00301 00302 // 00303 // Probe output parameters 00304 // 00305 00306 RequestorMode = KeGetPreviousMode(); 00307 00308 if (RequestorMode != KernelMode) { 00309 00310 try { 00311 00312 ProbeForWriteUlong( LengthNeeded ); 00313 00314 ProbeForWrite( SecurityDescriptor, Length, sizeof(ULONG) ); 00315 00316 } except(EXCEPTION_EXECUTE_HANDLER) { 00317 00318 return GetExceptionCode(); 00319 } 00320 } 00321 00322 // 00323 // Establish the accesses needed to the object based upon the 00324 // security information being queried 00325 // 00326 00327 SeQuerySecurityAccessMask( SecurityInformation, &DesiredAccess ); 00328 00329 Status = ObReferenceObjectByHandle( Handle, 00330 DesiredAccess, 00331 NULL, 00332 RequestorMode, 00333 &Object, 00334 &HandleInformation ); 00335 00336 if (!NT_SUCCESS( Status )) { 00337 00338 return( Status ); 00339 } 00340 00341 // 00342 // Map the object body to an object header and the corresponding 00343 // object type 00344 // 00345 00346 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 00347 ObjectType = ObjectHeader->Type; 00348 00349 // 00350 // Invoke the object type's security callback routine to query 00351 // the object. This routine is assumed to have a try-except around 00352 // the setting of the output security descriptor 00353 // 00354 00355 Status = (ObjectType->TypeInfo.SecurityProcedure)( Object, 00356 QuerySecurityDescriptor, 00357 &SecurityInformation, 00358 SecurityDescriptor, 00359 &Length, 00360 &ObjectHeader->SecurityDescriptor, 00361 ObjectType->TypeInfo.PoolType, 00362 &ObjectType->TypeInfo.GenericMapping ); 00363 00364 // 00365 // Indicate the length needed for the security descriptor. This 00366 // will be set even if the callback failed so the caller will know 00367 // the number of bytes necessary 00368 // 00369 00370 try { 00371 00372 *LengthNeeded = Length; 00373 00374 } except(EXCEPTION_EXECUTE_HANDLER) { 00375 00376 ObDereferenceObject( Object ); 00377 00378 return(GetExceptionCode()); 00379 } 00380 00381 // 00382 // And return to our caller 00383 // 00384 00385 ObDereferenceObject( Object ); 00386 00387 return( Status ); 00388 }

NTSTATUS NtSetSecurityObject IN HANDLE  Handle,
IN SECURITY_INFORMATION  SecurityInformation,
IN PSECURITY_DESCRIPTOR  SecurityDescriptor
 

Definition at line 46 of file obse.c.

References ASSERT, FALSE, Handle, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), ObSetSecurityObjectByPointer(), PAGED_CODE, PagedPool, SeCaptureSecurityDescriptor(), SeReleaseSecurityDescriptor(), SeSetSecurityAccessMask(), Status, and TRUE.

Referenced by main(), and SetUserObjectSecurity().

00054 : 00055 00056 This routine is used to invoke an object's security routine. It 00057 is used to set the object's security state. 00058 00059 Arguments: 00060 00061 Handle - Supplies the handle for the object being modified 00062 00063 SecurityInformation - Indicates the type of information we are 00064 interested in setting. e.g., owner, group, dacl, or sacl. 00065 00066 SecurityDescriptor - Supplies the security descriptor for the 00067 object being modified. 00068 00069 Return Value: 00070 00071 An appropriate NTSTATUS value 00072 00073 --*/ 00074 00075 { 00076 NTSTATUS Status; 00077 PVOID Object; 00078 ACCESS_MASK DesiredAccess; 00079 OBJECT_HANDLE_INFORMATION HandleInformation; 00080 KPROCESSOR_MODE RequestorMode; 00081 SECURITY_DESCRIPTOR_RELATIVE *CapturedDescriptor; 00082 00083 PAGED_CODE(); 00084 00085 // 00086 // Make sure the passed security descriptor is really there. 00087 // SeCaptureSecurityDescriptor doesn't mind being passed a NULL 00088 // SecurityDescriptor, and will just return NULL back. 00089 // 00090 00091 if (!ARGUMENT_PRESENT( SecurityDescriptor )) { 00092 00093 return( STATUS_ACCESS_VIOLATION ); 00094 } 00095 00096 // 00097 // Establish the accesses needed to the object based upon the 00098 // security information being modified. 00099 // 00100 00101 SeSetSecurityAccessMask( SecurityInformation, &DesiredAccess ); 00102 00103 Status = ObReferenceObjectByHandle( Handle, 00104 DesiredAccess, 00105 NULL, 00106 RequestorMode = KeGetPreviousMode(), 00107 &Object, 00108 &HandleInformation ); 00109 00110 if (NT_SUCCESS( Status )) { 00111 00112 // 00113 // Probe and capture the input security descriptor, and return 00114 // right away if it is ill-formed. 00115 // 00116 // Because the security descriptor is always captured the returned 00117 // security descriptor is in self-relative format. 00118 // 00119 00120 Status = SeCaptureSecurityDescriptor( SecurityDescriptor, 00121 RequestorMode, 00122 PagedPool, 00123 TRUE, 00124 (PSECURITY_DESCRIPTOR *)&CapturedDescriptor ); 00125 00126 if (NT_SUCCESS( Status )) { 00127 00128 // 00129 // Now check for a valid combination of what the user wants to set 00130 // and what was supplied in the input security descriptor. If the 00131 // caller wants to set the owner then the owner field of the 00132 // security descriptor better not be null, likewise for the group 00133 // setting. If anything is missing we'll return and error. 00134 // 00135 00136 ASSERT(CapturedDescriptor->Control & SE_SELF_RELATIVE); 00137 00138 if (((SecurityInformation & OWNER_SECURITY_INFORMATION) && 00139 (CapturedDescriptor->Owner == 0)) 00140 00141 || 00142 00143 ((SecurityInformation & GROUP_SECURITY_INFORMATION) && 00144 (CapturedDescriptor->Group == 0))) { 00145 00146 SeReleaseSecurityDescriptor( (PSECURITY_DESCRIPTOR)CapturedDescriptor, 00147 RequestorMode, 00148 TRUE ); 00149 00150 ObDereferenceObject( Object ); 00151 00152 ASSERT(FALSE); 00153 return( STATUS_INVALID_SECURITY_DESCR ); 00154 } 00155 00156 Status = ObSetSecurityObjectByPointer( Object, 00157 SecurityInformation, 00158 CapturedDescriptor ); 00159 00160 SeReleaseSecurityDescriptor( (PSECURITY_DESCRIPTOR)CapturedDescriptor, 00161 RequestorMode, 00162 TRUE ); 00163 } 00164 00165 ObDereferenceObject( Object ); 00166 00167 } 00168 00169 return( Status ); 00170 }

NTSTATUS ObAssignObjectSecurityDescriptor IN PVOID  Object,
IN PSECURITY_DESCRIPTOR SecurityDescriptor  OPTIONAL,
IN POOL_TYPE  PoolType
 

Definition at line 1183 of file obse.c.

References NT_SUCCESS, NTSTATUS(), NULL, OBJECT_TO_OBJECT_HEADER, ObpLogSecurityDescriptor(), PAGED_CODE, and Status.

Referenced by CmpSecurityMethod(), SeDefaultObjectMethod(), SeMakeAnonymousLogonToken(), and SeMakeSystemToken().

01191 : 01192 01193 Takes a pointer to an object and sets the SecurityDescriptor field 01194 in the object's header. 01195 01196 Arguments: 01197 01198 Object - Supplies a pointer to the object 01199 01200 SecurityDescriptor - Supplies a pointer to the security descriptor 01201 to be assigned to the object. This pointer may be null if there 01202 is no security on the object. 01203 01204 PoolType - Supplies the type of pool memory used to allocate the 01205 security descriptor. This field is currently ignored. 01206 01207 Return Value: 01208 01209 An appropriate NTSTATUS value. 01210 01211 --*/ 01212 01213 { 01214 NTSTATUS Status; 01215 PSECURITY_DESCRIPTOR OutputSecurityDescriptor; 01216 01217 PAGED_CODE(); 01218 01219 // 01220 // If the security descriptor isn't supplied then we set the 01221 // object header's security descriptor to null and return 01222 // to our caller 01223 // 01224 01225 if (!ARGUMENT_PRESENT(SecurityDescriptor)) { 01226 01227 OBJECT_TO_OBJECT_HEADER( Object )->SecurityDescriptor = NULL; 01228 01229 return( STATUS_SUCCESS ); 01230 } 01231 01232 // 01233 // Log the new security descriptor into our security database and 01234 // get back the real security descriptor to use 01235 // 01236 01237 Status = ObpLogSecurityDescriptor( SecurityDescriptor, &OutputSecurityDescriptor ); 01238 01239 // 01240 // If we've been successful so far then set the object's 01241 // security descriptor to the newly allocated one. 01242 // 01243 01244 if (NT_SUCCESS(Status)) { 01245 01246 OBJECT_TO_OBJECT_HEADER( Object )->SecurityDescriptor = OutputSecurityDescriptor; 01247 } 01248 01249 // 01250 // And return to our caller 01251 // 01252 01253 return( Status ); 01254 }

NTSTATUS ObAssignSecurity IN PACCESS_STATE  AccessState,
IN PSECURITY_DESCRIPTOR ParentDescriptor  OPTIONAL,
IN PVOID  Object,
IN POBJECT_TYPE  ObjectType
 

Definition at line 1574 of file obse.c.

References AssignSecurityDescriptor, NT_SUCCESS, NTSTATUS(), NULL, ObpBeginTypeSpecificCallOut, ObpDirectoryObjectType, ObpEndTypeSpecificCallOut, PAGED_CODE, PagedPool, SeAssignSecurity(), SeDeassignSecurity(), and Status.

Referenced by ObInsertObject(), and xxxCreateDesktop2().

01583 : 01584 01585 This routine will assign a security descriptor to a newly created object. 01586 It assumes that the AccessState parameter contains a captured security 01587 descriptor. 01588 01589 Arguments: 01590 01591 AccessState - The AccessState containing the security information 01592 for this object creation. 01593 01594 ParentDescriptor - The security descriptor from the parent object, if 01595 available. 01596 01597 Object - A pointer to the object being created. 01598 01599 ObjectType - Supplies the type of object being created. 01600 01601 Return Value: 01602 01603 STATUS_SUCCESS - indicates the operation was successful. 01604 01605 STATUS_INVALID_OWNER - The owner SID provided as the owner of the 01606 target security descriptor is not one the caller is authorized 01607 to assign as the owner of an object. 01608 01609 STATUS_PRIVILEGE_NOT_HELD - The caller does not have the privilege 01610 necessary to explicitly assign the specified system ACL. 01611 SeSecurityPrivilege privilege is needed to explicitly assign 01612 system ACLs to objects. 01613 01614 --*/ 01615 01616 { 01617 PSECURITY_DESCRIPTOR NewDescriptor = NULL; 01618 NTSTATUS Status; 01619 KIRQL SaveIrql; 01620 01621 PAGED_CODE(); 01622 01623 // 01624 // SeAssignSecurity will construct the final version 01625 // of the security descriptor 01626 // 01627 01628 Status = SeAssignSecurity( ParentDescriptor, 01629 AccessState->SecurityDescriptor, 01630 &NewDescriptor, 01631 (BOOLEAN)(ObjectType == ObpDirectoryObjectType), 01632 &AccessState->SubjectSecurityContext, 01633 &ObjectType->TypeInfo.GenericMapping, 01634 PagedPool ); 01635 01636 if (!NT_SUCCESS( Status )) { 01637 01638 return( Status ); 01639 } 01640 01641 ObpBeginTypeSpecificCallOut( SaveIrql ); 01642 01643 // 01644 // Now invoke the security method callback to finish 01645 // the assignment. 01646 // 01647 01648 Status = (*ObjectType->TypeInfo.SecurityProcedure)( Object, 01649 AssignSecurityDescriptor, 01650 NULL, 01651 NewDescriptor, 01652 NULL, 01653 NULL, 01654 PagedPool, 01655 &ObjectType->TypeInfo.GenericMapping ); 01656 01657 ObpEndTypeSpecificCallOut( SaveIrql, "Security", ObjectType, Object ); 01658 01659 if (!NT_SUCCESS( Status )) { 01660 01661 // 01662 // The attempt to assign the security descriptor to the object 01663 // failed. Free the space used by the new security descriptor. 01664 // 01665 01666 SeDeassignSecurity( &NewDescriptor ); 01667 } 01668 01669 // 01670 // And return to our caller 01671 // 01672 01673 return( Status ); 01674 }

BOOLEAN ObCheckCreateObjectAccess IN PVOID  DirectoryObject,
IN ACCESS_MASK  CreateAccess,
IN PACCESS_STATE  AccessState,
IN PUNICODE_STRING  ComponentName,
IN BOOLEAN  TypeMutexLocked,
IN KPROCESSOR_MODE  PreviousMode,
OUT PNTSTATUS  AccessStatus
 

Definition at line 983 of file obse.c.

References FALSE, _OBJECT_TYPE_INITIALIZER::GenericMapping, NT_SUCCESS, NTSTATUS(), NULL, ObGetObjectSecurity(), OBJECT_TO_OBJECT_HEADER, ObpEnterObjectTypeMutex, ObpLeaveObjectTypeMutex, ObReleaseObjectSecurity(), PAGED_CODE, SeAccessCheck(), SeAppendPrivileges(), SeCreateObjectAuditAlarm(), SeFreePrivileges(), SeLockSubjectContext(), SeUnlockSubjectContext(), Status, TRUE, _OBJECT_HEADER::Type, and _OBJECT_TYPE::TypeInfo.

Referenced by ObpLookupObjectName(), and xxxCreateDesktop2().

00995 : 00996 00997 This routine checks to see if we are allowed to create an object in the 00998 given directory, and performs auditing as appropriate. 00999 01000 Arguments: 01001 01002 DirectoryObject - The directory object being examined. 01003 01004 CreateAccess - The access mask corresponding to create access for 01005 this directory type. 01006 01007 AccessState - Checks for traverse access will typically be incidental 01008 to some other access attempt. Information on the current state of 01009 that access attempt is required so that the constituent access 01010 attempts may be associated with each other in the audit log. 01011 01012 ComponentName - Pointer to a Unicode string containing the name of 01013 the object being created. 01014 01015 TypeMutexLocked - Indicates whether the type mutex for this object's 01016 type is locked. The type mutex is used to protect the object's 01017 security descriptor from being modified while it is being accessed. 01018 01019 PreviousMode - The previous processor mode. 01020 01021 AccessStatus - Pointer to a variable to return the status code of the 01022 access attempt. In the case of failure this status code must be 01023 propagated back to the user. 01024 01025 Return Value: 01026 01027 BOOLEAN - TRUE if access is allowed and FALSE otherwise. AccessStatus 01028 contains the status code to be passed back to the caller. It is not 01029 correct to simply pass back STATUS_ACCESS_DENIED, since this will have 01030 to change with the advent of mandatory access control. 01031 01032 --*/ 01033 01034 { 01035 BOOLEAN AccessAllowed; 01036 ACCESS_MASK GrantedAccess = 0; 01037 PSECURITY_DESCRIPTOR SecurityDescriptor; 01038 BOOLEAN MemoryAllocated; 01039 NTSTATUS Status; 01040 POBJECT_HEADER ObjectHeader; 01041 POBJECT_TYPE ObjectType; 01042 PPRIVILEGE_SET Privileges = NULL; 01043 BOOLEAN AuditPerformed = FALSE; 01044 01045 PAGED_CODE(); 01046 01047 // 01048 // Map the object body to its object header and corresponding 01049 // object type 01050 // 01051 01052 ObjectHeader = OBJECT_TO_OBJECT_HEADER( DirectoryObject ); 01053 ObjectType = ObjectHeader->Type; 01054 01055 // 01056 // If the caller didn't lock the object type down then 01057 // we'll do it now 01058 // 01059 01060 if (!TypeMutexLocked) { 01061 01062 ObpEnterObjectTypeMutex( ObjectType ); 01063 } 01064 01065 // 01066 // Obtain the object's security descriptor and make it was 01067 // successful 01068 // 01069 01070 Status = ObGetObjectSecurity( DirectoryObject, 01071 &SecurityDescriptor, 01072 &MemoryAllocated ); 01073 01074 if (!NT_SUCCESS( Status )) { 01075 01076 if (!TypeMutexLocked) { 01077 01078 ObpLeaveObjectTypeMutex( ObjectType ); 01079 } 01080 01081 *AccessStatus = Status; 01082 01083 return( FALSE ); 01084 } 01085 01086 // 01087 // lock the caller's tokens until after auditing has been 01088 // performed. 01089 // 01090 01091 SeLockSubjectContext( &AccessState->SubjectSecurityContext ); 01092 01093 // 01094 // if we have a security descriptor then do an access 01095 // check to see if access is allowed and set in the 01096 // privileges if necessary 01097 // 01098 01099 if (SecurityDescriptor != NULL) { 01100 01101 AccessAllowed = SeAccessCheck( SecurityDescriptor, 01102 &AccessState->SubjectSecurityContext, 01103 TRUE, // Tokens are locked 01104 CreateAccess, 01105 0, 01106 &Privileges, 01107 &ObjectType->TypeInfo.GenericMapping, 01108 PreviousMode, 01109 &GrantedAccess, 01110 AccessStatus ); 01111 01112 if (Privileges != NULL) { 01113 01114 Status = SeAppendPrivileges( AccessState, 01115 Privileges ); 01116 01117 SeFreePrivileges( Privileges ); 01118 } 01119 01120 // 01121 // This is wrong, but leave for reference. 01122 // 01123 // if (AccessAllowed) { 01124 // 01125 // AccessState->PreviouslyGrantedAccess |= GrantedAccess; 01126 // AccessState->RemainingDesiredAccess &= ~GrantedAccess; 01127 // } 01128 // 01129 01130 #if 0 01131 SeCreateObjectAuditAlarm( &AccessState->OperationID, 01132 DirectoryObject, 01133 ComponentName, 01134 SecurityDescriptor, 01135 &AccessState->SubjectSecurityContext, 01136 CreateAccess, 01137 AccessState->PrivilegesUsed, 01138 AccessAllowed, 01139 &AuditPerformed, 01140 PreviousMode ); 01141 01142 if ( AuditPerformed ) { 01143 01144 AccessState->AuditHandleCreation = TRUE; 01145 } 01146 #endif 01147 01148 } else { 01149 01150 // 01151 // At this point there is not a security descriptor 01152 // so we'll assume access is allowed 01153 // 01154 01155 AccessAllowed = TRUE; 01156 } 01157 01158 // 01159 // Free the caller's token and if the caller didn't have the 01160 // object type locked we need to free it. 01161 // 01162 01163 SeUnlockSubjectContext( &AccessState->SubjectSecurityContext ); 01164 01165 if (!TypeMutexLocked) { 01166 01167 ObpLeaveObjectTypeMutex( ObjectType ); 01168 } 01169 01170 // 01171 // Finally free the security descriptor 01172 // and return to our caller 01173 // 01174 01175 ObReleaseObjectSecurity( SecurityDescriptor, 01176 MemoryAllocated ); 01177 01178 return( AccessAllowed ); 01179 }

BOOLEAN ObCheckObjectAccess IN PVOID  Object,
IN OUT PACCESS_STATE  AccessState,
IN BOOLEAN  TypeMutexLocked,
IN KPROCESSOR_MODE  AccessMode,
OUT PNTSTATUS  AccessStatus
 

Definition at line 392 of file obse.c.

References FALSE, _OBJECT_TYPE_INITIALIZER::GenericMapping, _OBJECT_TYPE::Name, NT_SUCCESS, NTSTATUS(), NULL, ObGetObjectSecurity(), OBJECT_TO_OBJECT_HEADER, ObpEnterObjectTypeMutex, ObpLeaveObjectTypeMutex, ObReleaseObjectSecurity(), PAGED_CODE, SeAccessCheck(), SeAppendPrivileges(), SeFreePrivileges(), SeLockSubjectContext(), SeOpenObjectAuditAlarm(), SeUnlockSubjectContext(), Status, TRUE, _OBJECT_HEADER::Type, and _OBJECT_TYPE::TypeInfo.

Referenced by AccessCheckObject(), CmpDoOpen(), and ObpIncrementHandleCount().

00402 : 00403 00404 This routine performs access validation on the passed object. The 00405 remaining desired access mask is extracted from the AccessState 00406 parameter and passes to the appropriate security routine to perform the 00407 access check. 00408 00409 If the access attempt is successful, SeAccessCheck returns a mask 00410 containing the granted accesses. The bits in this mask are turned 00411 on in the PreviouslyGrantedAccess field of the AccessState, and 00412 are turned off in the RemainingDesiredAccess field. 00413 00414 Arguments: 00415 00416 Object - The object being examined. 00417 00418 AccessState - The ACCESS_STATE structure containing accumulated 00419 information about the current attempt to gain access to the object. 00420 00421 TypeMutexLocked - Indicates whether the type mutex for this object's 00422 type is locked. The type mutex is used to protect the object's 00423 security descriptor from being modified while it is being accessed. 00424 00425 AccessMode - The previous processor mode. 00426 00427 AccessStatus - Pointer to a variable to return the status code of the 00428 access attempt. In the case of failure this status code must be 00429 propagated back to the user. 00430 00431 00432 Return Value: 00433 00434 BOOLEAN - TRUE if access is allowed and FALSE otherwise 00435 00436 --*/ 00437 00438 { 00439 ACCESS_MASK GrantedAccess = 0; 00440 BOOLEAN AccessAllowed; 00441 BOOLEAN MemoryAllocated; 00442 NTSTATUS Status; 00443 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; 00444 POBJECT_HEADER ObjectHeader; 00445 POBJECT_TYPE ObjectType; 00446 PPRIVILEGE_SET Privileges = NULL; 00447 00448 PAGED_CODE(); 00449 00450 // 00451 // Map the object body to an object header and the 00452 // corresponding object type 00453 // 00454 00455 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 00456 ObjectType = ObjectHeader->Type; 00457 00458 // 00459 // If the caller does not have the object type locked 00460 // then lock it down 00461 // 00462 00463 if (!TypeMutexLocked) { 00464 00465 ObpEnterObjectTypeMutex( ObjectType ); 00466 } 00467 00468 // 00469 // Obtain the object's security descriptor 00470 // 00471 00472 Status = ObGetObjectSecurity( Object, 00473 &SecurityDescriptor, 00474 &MemoryAllocated ); 00475 00476 // 00477 // If we failed in getting the security descriptor then 00478 // put the object type lock back where it was and return 00479 // the error back to our caller 00480 // 00481 00482 if (!NT_SUCCESS( Status )) { 00483 00484 if (!TypeMutexLocked) { 00485 00486 ObpLeaveObjectTypeMutex( ObjectType ); 00487 } 00488 00489 *AccessStatus = Status; 00490 00491 return( FALSE ); 00492 00493 } else { 00494 00495 // 00496 // Otherwise we've been successful at getting the 00497 // object's security descriptor, but now make sure 00498 // it is not null. 00499 00500 if (SecurityDescriptor == NULL) { 00501 00502 if (!TypeMutexLocked) { 00503 00504 ObpLeaveObjectTypeMutex( ObjectType ); 00505 } 00506 00507 *AccessStatus = Status; 00508 00509 return(TRUE); 00510 } 00511 } 00512 00513 // 00514 // We have a non-null security descriptor so now 00515 // lock the caller's tokens until after auditing has been 00516 // performed. 00517 // 00518 00519 SeLockSubjectContext( &AccessState->SubjectSecurityContext ); 00520 00521 // 00522 // Do the access check, and if we have some privileges then 00523 // put those in the access state too. 00524 // 00525 00526 AccessAllowed = SeAccessCheck( SecurityDescriptor, 00527 &AccessState->SubjectSecurityContext, 00528 TRUE, // Tokens are locked 00529 AccessState->RemainingDesiredAccess, 00530 AccessState->PreviouslyGrantedAccess, 00531 &Privileges, 00532 &ObjectType->TypeInfo.GenericMapping, 00533 AccessMode, 00534 &GrantedAccess, 00535 AccessStatus ); 00536 00537 if (Privileges != NULL) { 00538 00539 Status = SeAppendPrivileges( AccessState, 00540 Privileges ); 00541 00542 SeFreePrivileges( Privileges ); 00543 } 00544 00545 // 00546 // If we were granted access then set that fact into 00547 // what we've been granted and remove it from what remains 00548 // to be granted. 00549 // 00550 00551 if (AccessAllowed) { 00552 00553 AccessState->PreviouslyGrantedAccess |= GrantedAccess; 00554 AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED); 00555 } 00556 00557 // 00558 // Audit the attempt to open the object, audit 00559 // the creation of its handle later. 00560 // 00561 // **** SecurityDescriptor cannot be null 00562 // 00563 00564 if ( SecurityDescriptor != NULL ) { 00565 00566 SeOpenObjectAuditAlarm( &ObjectType->Name, 00567 Object, 00568 NULL, // AbsoluteObjectName 00569 SecurityDescriptor, 00570 AccessState, 00571 FALSE, // ObjectCreated (FALSE, only open here) 00572 AccessAllowed, 00573 AccessMode, 00574 &AccessState->GenerateOnClose ); 00575 } 00576 00577 SeUnlockSubjectContext( &AccessState->SubjectSecurityContext ); 00578 00579 // 00580 // If the caller didn't lock the object type then we have to 00581 // remove our lock on it. 00582 // 00583 00584 if (!TypeMutexLocked) { 00585 00586 ObpLeaveObjectTypeMutex( ObjectType ); 00587 } 00588 00589 // 00590 // Free the security descriptor before returning to 00591 // our caller 00592 // 00593 00594 ObReleaseObjectSecurity( SecurityDescriptor, 00595 MemoryAllocated ); 00596 00597 return( AccessAllowed ); 00598 }

NTSTATUS ObGetObjectSecurity IN PVOID  Object,
OUT PSECURITY_DESCRIPTOR *  SecurityDescriptor,
OUT PBOOLEAN  MemoryAllocated
 

Definition at line 1258 of file obse.c.

References ExAllocatePoolWithTag, ExFreePool(), FALSE, _OBJECT_TYPE_INITIALIZER::GenericMapping, NT_SUCCESS, NTSTATUS(), NULL, OBJECT_TO_OBJECT_HEADER, ObpBeginTypeSpecificCallOut, ObpCentralizedSecurity, ObpEndTypeSpecificCallOut, ObpReferenceSecurityDescriptor(), PAGED_CODE, PagedPool, _OBJECT_TYPE_INITIALIZER::PoolType, QuerySecurityDescriptor, _OBJECT_HEADER::SecurityDescriptor, _OBJECT_TYPE_INITIALIZER::SecurityProcedure, Status, TRUE, _OBJECT_HEADER::Type, and _OBJECT_TYPE::TypeInfo.

Referenced by ObCheckCreateObjectAccess(), ObCheckObjectAccess(), ObInsertObject(), ObpCheckObjectReference(), ObpCheckTraverseAccess(), ObpProcessDosDeviceSymbolicLink(), PspCreateProcess(), PspCreateThread(), and PspSetPrimaryToken().

01266 : 01267 01268 Given an object, this routine will find its security descriptor. 01269 It will do this by calling the object's security method. 01270 01271 It is possible for an object not to have a security descriptor 01272 at all. Unnamed objects such as events that can only be referenced 01273 by a handle are an example of an object that does not have a 01274 security descriptor. 01275 01276 Arguments: 01277 01278 Object - Supplies the object body being queried. 01279 01280 SecurityDescriptor - Returns a pointer to the object's security 01281 descriptor. 01282 01283 MemoryAllocated - indicates whether we had to allocate pool 01284 memory to hold the security descriptor or not. This should 01285 be passed back into ObReleaseObjectSecurity. 01286 01287 Return Value: 01288 01289 STATUS_SUCCESS - The operation was successful. Note that the 01290 operation may be successful and still return a NULL security 01291 descriptor. 01292 01293 STATUS_INSUFFICIENT_RESOURCES - Insufficient memory was available 01294 to satisfy the request. 01295 01296 --*/ 01297 01298 { 01299 SECURITY_INFORMATION SecurityInformation; 01300 ULONG Length = 0; 01301 NTSTATUS Status; 01302 POBJECT_TYPE ObjectType; 01303 POBJECT_HEADER ObjectHeader; 01304 KIRQL SaveIrql; 01305 01306 PAGED_CODE(); 01307 01308 // 01309 // Map the object body to its object header and corresponding 01310 // object type 01311 // 01312 01313 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 01314 ObjectType = ObjectHeader->Type; 01315 01316 // 01317 // If the object is one that uses the default object method, 01318 // its security descriptor is contained in ob's security 01319 // descriptor cache. 01320 // 01321 // Reference it so that it doesn't go away out from under us. 01322 // 01323 01324 if (ObpCentralizedSecurity(ObjectType)) { 01325 01326 *SecurityDescriptor = ObpReferenceSecurityDescriptor( Object ); 01327 01328 *MemoryAllocated = FALSE; 01329 01330 return( STATUS_SUCCESS ); 01331 } 01332 01333 // 01334 // Request a complete security descriptor 01335 // 01336 01337 SecurityInformation = OWNER_SECURITY_INFORMATION | 01338 GROUP_SECURITY_INFORMATION | 01339 DACL_SECURITY_INFORMATION | 01340 SACL_SECURITY_INFORMATION; 01341 01342 // 01343 // Call the security method with Length = 0 to find out 01344 // how much memory we need to store the final result. 01345 // 01346 // Note that the ObjectsSecurityDescriptor parameter is NULL, 01347 // because we expect whoever is on the other end of this call 01348 // to find the security descriptor for us. We pass in a pool 01349 // type to keep the compiler happy, it will not be used for a 01350 // query operation. 01351 // 01352 01353 01354 ObpBeginTypeSpecificCallOut( SaveIrql ); 01355 01356 Status = (*ObjectType->TypeInfo.SecurityProcedure)( Object, 01357 QuerySecurityDescriptor, 01358 &SecurityInformation, 01359 *SecurityDescriptor, 01360 &Length, 01361 &ObjectHeader->SecurityDescriptor, // not used 01362 ObjectType->TypeInfo.PoolType, 01363 &ObjectType->TypeInfo.GenericMapping ); 01364 01365 ObpEndTypeSpecificCallOut( SaveIrql, "Security", ObjectType, Object ); 01366 01367 if (Status != STATUS_BUFFER_TOO_SMALL) { 01368 01369 return( Status ); 01370 } 01371 01372 // 01373 // Now that we know how large the security descriptor is we 01374 // can allocate space for it 01375 // 01376 01377 *SecurityDescriptor = ExAllocatePoolWithTag( PagedPool, Length, 'qSbO' ); 01378 01379 if (*SecurityDescriptor == NULL) { 01380 01381 return( STATUS_INSUFFICIENT_RESOURCES ); 01382 } 01383 01384 *MemoryAllocated = TRUE; 01385 01386 // 01387 // The security method will return an absolute format 01388 // security descriptor that just happens to be in a self 01389 // contained buffer (not to be confused with a self-relative 01390 // security descriptor). 01391 // 01392 01393 ObpBeginTypeSpecificCallOut( SaveIrql ); 01394 01395 Status = (*ObjectType->TypeInfo.SecurityProcedure)( Object, 01396 QuerySecurityDescriptor, 01397 &SecurityInformation, 01398 *SecurityDescriptor, 01399 &Length, 01400 &ObjectHeader->SecurityDescriptor, 01401 ObjectType->TypeInfo.PoolType, 01402 &ObjectType->TypeInfo.GenericMapping ); 01403 01404 ObpEndTypeSpecificCallOut( SaveIrql, "Security", ObjectType, Object ); 01405 01406 if (!NT_SUCCESS( Status )) { 01407 01408 ExFreePool( *SecurityDescriptor ); 01409 01410 *MemoryAllocated = FALSE; 01411 } 01412 01413 return( Status ); 01414 }

BOOLEAN ObpCheckObjectReference IN PVOID  Object,
IN OUT PACCESS_STATE  AccessState,
IN BOOLEAN  TypeMutexLocked,
IN KPROCESSOR_MODE  AccessMode,
OUT PNTSTATUS  AccessStatus
 

Definition at line 602 of file obse.c.

References FALSE, _OBJECT_TYPE_INITIALIZER::GenericMapping, NT_SUCCESS, NTSTATUS(), NULL, ObGetObjectSecurity(), OBJECT_TO_OBJECT_HEADER, ObpEnterObjectTypeMutex, ObpLeaveObjectTypeMutex, ObReleaseObjectSecurity(), PAGED_CODE, SeAccessCheck(), SeLockSubjectContext(), SeObjectReferenceAuditAlarm(), SeUnlockSubjectContext(), Status, TRUE, _OBJECT_HEADER::Type, and _OBJECT_TYPE::TypeInfo.

Referenced by ObReferenceObjectByName().

00612 : 00613 00614 The routine performs access validation on the passed object. The 00615 remaining desired access mask is extracted from the AccessState 00616 parameter and passes to the appropriate security routine to 00617 perform the access check. 00618 00619 If the access attempt is successful, SeAccessCheck returns a mask 00620 containing the granted accesses. The bits in this mask are turned 00621 on in the PreviouslyGrantedAccess field of the AccessState, and 00622 are turned off in the RemainingDesiredAccess field. 00623 00624 This routine differs from ObpCheckObjectAccess in that it calls 00625 a different audit routine. 00626 00627 Arguments: 00628 00629 Object - The object being examined. 00630 00631 AccessState - The ACCESS_STATE structure containing accumulated 00632 information about the current attempt to gain access to the object. 00633 00634 TypeMutexLocked - Indicates whether the type mutex for this object's 00635 type is locked. The type mutex is used to protect the object's 00636 security descriptor from being modified while it is being accessed. 00637 00638 AccessMode - The previous processor mode. 00639 00640 AccessStatus - Pointer to a variable to return the status code of the 00641 access attempt. In the case of failure this status code must be 00642 propagated back to the user. 00643 00644 00645 Return Value: 00646 00647 BOOLEAN - TRUE if access is allowed and FALSE otherwise 00648 00649 --*/ 00650 00651 { 00652 BOOLEAN AccessAllowed; 00653 ACCESS_MASK GrantedAccess = 0; 00654 BOOLEAN MemoryAllocated; 00655 PSECURITY_DESCRIPTOR SecurityDescriptor; 00656 NTSTATUS Status; 00657 POBJECT_HEADER ObjectHeader; 00658 POBJECT_TYPE ObjectType; 00659 PPRIVILEGE_SET Privileges = NULL; 00660 00661 PAGED_CODE(); 00662 00663 // 00664 // Map the object body to an object header and the 00665 // corresponding object type 00666 // 00667 00668 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 00669 ObjectType = ObjectHeader->Type; 00670 00671 // 00672 // If the caller does not have the object type locked 00673 // then lock it down 00674 // 00675 00676 if (!TypeMutexLocked) { 00677 00678 ObpEnterObjectTypeMutex( ObjectType ); 00679 } 00680 00681 // 00682 // Obtain the object's security descriptor 00683 // 00684 00685 Status = ObGetObjectSecurity( Object, 00686 &SecurityDescriptor, 00687 &MemoryAllocated ); 00688 00689 // 00690 // If we failed in getting the security descriptor then 00691 // put the object type lock back where it was and return 00692 // the error back to our caller 00693 // 00694 00695 if (!NT_SUCCESS( Status )) { 00696 00697 if (!TypeMutexLocked) { 00698 00699 ObpLeaveObjectTypeMutex( ObjectType ); 00700 } 00701 00702 *AccessStatus = Status; 00703 00704 return( FALSE ); 00705 } 00706 00707 // 00708 // Lock the caller's tokens until after auditing has been 00709 // performed. 00710 // 00711 00712 SeLockSubjectContext( &AccessState->SubjectSecurityContext ); 00713 00714 // 00715 // Do the access check, and if we have some privileges then 00716 // put those in the access state too. 00717 // 00718 00719 AccessAllowed = SeAccessCheck( SecurityDescriptor, 00720 &AccessState->SubjectSecurityContext, 00721 TRUE, // Tokens are locked 00722 AccessState->RemainingDesiredAccess, 00723 AccessState->PreviouslyGrantedAccess, 00724 &Privileges, 00725 &ObjectType->TypeInfo.GenericMapping, 00726 AccessMode, 00727 &GrantedAccess, 00728 AccessStatus ); 00729 00730 if (AccessAllowed) { 00731 00732 AccessState->PreviouslyGrantedAccess |= GrantedAccess; 00733 AccessState->RemainingDesiredAccess &= ~GrantedAccess; 00734 } 00735 00736 // 00737 // If we have a security descriptor then call the security routine 00738 // to audit this reference and then unlock the caller's token 00739 // 00740 00741 if ( SecurityDescriptor != NULL ) { 00742 00743 SeObjectReferenceAuditAlarm( &AccessState->OperationID, 00744 Object, 00745 SecurityDescriptor, 00746 &AccessState->SubjectSecurityContext, 00747 AccessState->RemainingDesiredAccess | AccessState->PreviouslyGrantedAccess, 00748 ((PAUX_ACCESS_DATA)(AccessState->AuxData))->PrivilegesUsed, 00749 AccessAllowed, 00750 AccessMode ); 00751 } 00752 00753 SeUnlockSubjectContext( &AccessState->SubjectSecurityContext ); 00754 00755 // 00756 // If the caller didn't have the object type locked then remove 00757 // our lock 00758 // 00759 00760 if (!TypeMutexLocked) { 00761 00762 ObpLeaveObjectTypeMutex( ObjectType ); 00763 } 00764 00765 // 00766 // Finally free the security descriptor 00767 // and return to our caller 00768 // 00769 00770 ObReleaseObjectSecurity( SecurityDescriptor, 00771 MemoryAllocated ); 00772 00773 return( AccessAllowed ); 00774 }

BOOLEAN ObpCheckTraverseAccess IN PVOID  DirectoryObject,
IN ACCESS_MASK  TraverseAccess,
IN PACCESS_STATE AccessState  OPTIONAL,
IN BOOLEAN  TypeMutexLocked,
IN KPROCESSOR_MODE  PreviousMode,
OUT PNTSTATUS  AccessStatus
 

Definition at line 778 of file obse.c.

References FALSE, _OBJECT_TYPE_INITIALIZER::GenericMapping, NT_SUCCESS, NTSTATUS(), NULL, ObGetObjectSecurity(), OBJECT_TO_OBJECT_HEADER, ObpEnterObjectTypeMutex, ObpLeaveObjectTypeMutex, ObReleaseObjectSecurity(), PAGED_CODE, SeAccessCheck(), SeAppendPrivileges(), SeFastTraverseCheck(), SeFreePrivileges(), SeLockSubjectContext(), SeUnlockSubjectContext(), Status, TOKEN_IS_RESTRICTED, TRUE, _OBJECT_HEADER::Type, and _OBJECT_TYPE::TypeInfo.

Referenced by ObpLookupObjectName().

00789 : 00790 00791 This routine checks for traverse access to the given directory object. 00792 00793 Note that the contents of the AccessState structure are not 00794 modified, since it is assumed that this access check is incidental 00795 to another access operation. 00796 00797 Arguments: 00798 00799 DirectoryObject - The object body of the object being examined. 00800 00801 TraverseAccess - The desired access to the object, most likely DIRECTORY 00802 TRAVERSE access. 00803 00804 AccessState - Checks for traverse access will typically be incidental 00805 to some other access attempt. Information on the current state of 00806 that access attempt is required so that the constituent access 00807 attempts may be associated with each other in the audit log. 00808 This is an OPTIONAL parameter, in which case the call will 00809 success ONLY if the Directory Object grants World traverse 00810 access rights. 00811 00812 TypeMutexLocked - Indicates whether the type mutex for this object's 00813 type is locked. The type mutex is used to protect the object's 00814 security descriptor from being modified while it is being accessed. 00815 00816 PreviousMode - The previous processor mode. 00817 00818 AccessStatus - Pointer to a variable to return the status code of the 00819 access attempt. In the case of failure this status code must be 00820 propagated back to the user. 00821 00822 Return Value: 00823 00824 BOOLEAN - TRUE if access is allowed and FALSE otherwise. AccessStatus 00825 contains the status code to be passed back to the caller. It is not 00826 correct to simply pass back STATUS_ACCESS_DENIED, since this will have 00827 to change with the advent of mandatory access control. 00828 00829 --*/ 00830 00831 { 00832 BOOLEAN AccessAllowed; 00833 ACCESS_MASK GrantedAccess = 0; 00834 PSECURITY_DESCRIPTOR SecurityDescriptor; 00835 BOOLEAN MemoryAllocated; 00836 NTSTATUS Status; 00837 POBJECT_HEADER ObjectHeader; 00838 POBJECT_TYPE ObjectType; 00839 BOOLEAN SubjectContextLocked = FALSE; 00840 PPRIVILEGE_SET Privileges = NULL; 00841 00842 PAGED_CODE(); 00843 00844 // 00845 // Map the object body to an object header and corresponding 00846 // object type 00847 // 00848 00849 ObjectHeader = OBJECT_TO_OBJECT_HEADER( DirectoryObject ); 00850 ObjectType = ObjectHeader->Type; 00851 00852 // 00853 // If the caller hasn't locked down the object type then 00854 // lock it down now 00855 // 00856 00857 if (!TypeMutexLocked) { 00858 00859 ObpEnterObjectTypeMutex( ObjectType ); 00860 } 00861 00862 // 00863 // Obtain the object's security descriptor and make it was 00864 // successful 00865 // 00866 00867 Status = ObGetObjectSecurity( DirectoryObject, 00868 &SecurityDescriptor, 00869 &MemoryAllocated ); 00870 00871 if (!NT_SUCCESS( Status )) { 00872 00873 if (!TypeMutexLocked) { 00874 00875 ObpLeaveObjectTypeMutex( ObjectType ); 00876 } 00877 00878 *AccessStatus = Status; 00879 00880 return( FALSE ); 00881 } 00882 00883 // 00884 // Check to see if WORLD has TRAVERSE access, by seeing if the 00885 // token is restricted or the fast traverse check fails meaning 00886 // that the world does not have traverse access 00887 // 00888 00889 if (((AccessState->Flags & TOKEN_IS_RESTRICTED) != 0) 00890 00891 || 00892 00893 (!SeFastTraverseCheck( SecurityDescriptor, 00894 DIRECTORY_TRAVERSE, 00895 PreviousMode ))) { 00896 00897 // 00898 // SeFastTraverseCheck could be modified to tell us that 00899 // no one has any access to this directory. However, 00900 // we're going to have to fail this entire call if 00901 // that is the case, so we really don't need to worry 00902 // all that much about making it blindingly fast. 00903 // 00904 00905 if (ARGUMENT_PRESENT( AccessState )) { 00906 00907 // 00908 // The world does not have traverse access and we have 00909 // the client's access state so lock down the client's 00910 // token and then do the access check, appending privileges 00911 // if present. The access check will give the answer 00912 // we return back to our caller 00913 // 00914 00915 SeLockSubjectContext( &AccessState->SubjectSecurityContext ); 00916 00917 SubjectContextLocked = TRUE; 00918 00919 AccessAllowed = SeAccessCheck( SecurityDescriptor, 00920 &AccessState->SubjectSecurityContext, 00921 TRUE, // Tokens are locked 00922 TraverseAccess, 00923 0, 00924 &Privileges, 00925 &ObjectType->TypeInfo.GenericMapping, 00926 PreviousMode, 00927 &GrantedAccess, 00928 AccessStatus ); 00929 00930 if (Privileges != NULL) { 00931 00932 Status = SeAppendPrivileges( AccessState, 00933 Privileges ); 00934 00935 SeFreePrivileges( Privileges ); 00936 } 00937 } 00938 00939 } else { 00940 00941 // 00942 // At this point the world has traverse access 00943 // 00944 00945 AccessAllowed = TRUE; 00946 } 00947 00948 // 00949 // If the client's token is locked then now we can unlock it 00950 // 00951 // **** this should be able to move up into the preceding clause 00952 // where it is locked 00953 // 00954 00955 if ( SubjectContextLocked ) { 00956 00957 SeUnlockSubjectContext( &AccessState->SubjectSecurityContext ); 00958 } 00959 00960 // 00961 // If the caller did not lock the object type then we 00962 // now need to unlock it 00963 // 00964 00965 if (!TypeMutexLocked) { 00966 00967 ObpLeaveObjectTypeMutex( ObjectType ); 00968 } 00969 00970 // 00971 // Finally free the security descriptor 00972 // and then return to our caller 00973 // 00974 00975 ObReleaseObjectSecurity( SecurityDescriptor, 00976 MemoryAllocated ); 00977 00978 return( AccessAllowed ); 00979 }

NTSTATUS ObpValidateAccessMask PACCESS_STATE  AccessState  ) 
 

Definition at line 1886 of file obse.c.

References NULL, PAGED_CODE, _ACCESS_STATE::PreviouslyGrantedAccess, _ACCESS_STATE::RemainingDesiredAccess, and _ACCESS_STATE::SecurityDescriptor.

Referenced by ObInsertObject(), and ObOpenObjectByName().

01892 : 01893 01894 Checks the desired access mask of a passed object against the 01895 passed security descriptor. 01896 01897 Arguments: 01898 01899 AccessState - A pointer to the AccessState for the pending operation. 01900 01901 Return Value: 01902 01903 Only returns STATUS_SUCCESS 01904 01905 --*/ 01906 01907 { 01908 SECURITY_DESCRIPTOR *SecurityDescriptor = AccessState->SecurityDescriptor; 01909 01910 PAGED_CODE(); 01911 01912 // 01913 // First make sure the access state has a security descriptor. If there 01914 // is one and it has a system acl and the previously granted access did 01915 // not include system security then add the fact that we want system 01916 // security to the remaining desired access state. 01917 // 01918 01919 if (SecurityDescriptor != NULL) { 01920 01921 if ( SecurityDescriptor->Control & SE_SACL_PRESENT ) { 01922 01923 if ( !(AccessState->PreviouslyGrantedAccess & ACCESS_SYSTEM_SECURITY)) { 01924 01925 AccessState->RemainingDesiredAccess |= ACCESS_SYSTEM_SECURITY; 01926 } 01927 } 01928 } 01929 01930 return( STATUS_SUCCESS ); 01931 }

NTSTATUS ObQuerySecurityDescriptorInfo IN PSECURITY_INFORMATION  SecurityInformation,
OUT PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN OUT PULONG  Length,
IN PSECURITY_DESCRIPTOR *  ObjectsSecurityDescriptor
 

Definition at line 1679 of file obse.c.

References NTSTATUS(), ObpAcquireDescriptorCacheReadLock(), ObpReleaseDescriptorCacheLock(), PAGED_CODE, SeQuerySecurityDescriptorInfo(), and Status.

Referenced by SeDefaultObjectMethod().

01687 : 01688 01689 This routine will extract the desired information from the 01690 passed security descriptor and return the information in 01691 the passed buffer as a security descriptor in self-relative 01692 format. 01693 01694 This routine assumes that all parameters are captured and 01695 safe to reference. 01696 01697 Arguments: 01698 01699 SecurityInformation - Specifies what information is being queried. 01700 01701 SecurityDescriptor - Supplies the buffer to output the requested 01702 information into. 01703 01704 This buffer has been probed only to the size indicated by 01705 the Length parameter. Since it still points into user space, 01706 it must always be accessed in a try clause. 01707 01708 Length - Supplies the address of a variable containing the length of 01709 the security descriptor buffer. Upon return this variable will 01710 contain the length needed to store the requested information. 01711 01712 ObjectsSecurityDescriptor - Supplies the address of a pointer to 01713 the objects security descriptor. The passed security descriptor 01714 must be in self-relative format. 01715 01716 Return Value: 01717 01718 NTSTATUS - STATUS_SUCCESS if successful and an appropriate error value 01719 otherwise 01720 01721 --*/ 01722 { 01723 NTSTATUS Status; 01724 01725 PAGED_CODE(); 01726 01727 // 01728 // Take the read lock on the security descriptor cache so we 01729 // don't collide with anyone who is modifying this security 01730 // descriptor (bug 347986). 01731 // 01732 01733 ObpAcquireDescriptorCacheReadLock(); 01734 01735 Status = SeQuerySecurityDescriptorInfo( SecurityInformation, 01736 SecurityDescriptor, 01737 Length, 01738 ObjectsSecurityDescriptor 01739 ); 01740 ObpReleaseDescriptorCacheLock(); 01741 01742 return( Status ); 01743 }

VOID ObReleaseObjectSecurity IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN BOOLEAN  MemoryAllocated
 

Definition at line 1418 of file obse.c.

References ExFreePool(), NULL, ObpDereferenceSecurityDescriptor(), and PAGED_CODE.

Referenced by ObCheckCreateObjectAccess(), ObCheckObjectAccess(), ObInsertObject(), ObpCheckObjectReference(), ObpCheckTraverseAccess(), ObpProcessDosDeviceSymbolicLink(), PspCreateProcess(), PspCreateThread(), and PspSetPrimaryToken().

01425 : 01426 01427 This function will free up any memory associated with a queried 01428 security descriptor. This undoes the function ObGetObjectSecurity 01429 01430 Arguments: 01431 01432 SecurityDescriptor - Supplies a pointer to the security descriptor 01433 to be freed. 01434 01435 MemoryAllocated - Supplies whether or not we should free the 01436 memory pointed to by SecurityDescriptor. 01437 01438 Return Value: 01439 01440 None. 01441 01442 --*/ 01443 01444 { 01445 PAGED_CODE(); 01446 01447 // 01448 // Check if there is a security descriptor to actually free 01449 // 01450 01451 if ( SecurityDescriptor != NULL ) { 01452 01453 // 01454 // If ObGetObjectSecurity allocated memory then we 01455 // need to free it. Otherwise what the earlier routine did 01456 // was reference the object to keep the security descriptor 01457 // to keep it from going away 01458 // 01459 01460 if (MemoryAllocated) { 01461 01462 ExFreePool( SecurityDescriptor ); 01463 01464 } else { 01465 01466 ObpDereferenceSecurityDescriptor( SecurityDescriptor ); 01467 } 01468 } 01469 }

NTSTATUS ObSetSecurityDescriptorInfo IN PVOID  Object,
IN PSECURITY_INFORMATION  SecurityInformation,
IN OUT PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN OUT PSECURITY_DESCRIPTOR *  ObjectsSecurityDescriptor,
IN POOL_TYPE  PoolType,
IN PGENERIC_MAPPING  GenericMapping
 

Definition at line 1748 of file obse.c.

References ExFreePool(), NT_SUCCESS, NTSTATUS(), OBJECT_TO_OBJECT_HEADER, ObpAcquireDescriptorCacheWriteLock(), ObpDereferenceSecurityDescriptor(), ObpDirectoryObjectType, ObpLogSecurityDescriptor(), ObpReleaseDescriptorCacheLock(), PAGED_CODE, SeFastTraverseCheck(), SeSetSecurityDescriptorInfo(), Status, and UserMode.

Referenced by SeDefaultObjectMethod(), and xxxCreateWindowStation().

01759 : 01760 01761 Sets the security descriptor on an already secure object. 01762 01763 Arguments: 01764 01765 Object - Pointer to the object being modified. 01766 01767 SecurityInformation - Describes which information in the SecurityDescriptor parameter 01768 is relevent. 01769 01770 SecurityDescriptor - Provides the new security information. 01771 01772 ObjectsSecurityDescriptor - Provides/returns the object's security descriptor. 01773 01774 PoolType - The pool the ObjectSecurityDescriptor is allocated from. 01775 01776 GenericMapping - Supplies the generic mapping for the object. 01777 01778 Return Value: 01779 01780 An appropriate status value 01781 01782 --*/ 01783 01784 { 01785 PSECURITY_DESCRIPTOR OldDescriptor; 01786 PSECURITY_DESCRIPTOR NewDescriptor; 01787 NTSTATUS Status; 01788 01789 PAGED_CODE(); 01790 01791 // 01792 // Check the rest of our input and call the default set security 01793 // method. Also make sure no one is modifying the security descriptor 01794 // while we're looking at it. 01795 // 01796 01797 ObpAcquireDescriptorCacheWriteLock(); 01798 01799 OldDescriptor = *ObjectsSecurityDescriptor; 01800 NewDescriptor = OldDescriptor; 01801 01802 Status = SeSetSecurityDescriptorInfo( Object, 01803 SecurityInformation, 01804 SecurityDescriptor, 01805 &NewDescriptor, 01806 PoolType, 01807 GenericMapping ); 01808 01809 // 01810 // Now if the object is an object directory object that 01811 // participated in snapped symbolic links. If so and the 01812 // new security on the object does NOT allow world traverse 01813 // access, then return an error, as it is too late to change 01814 // the security on the object directory at this point. 01815 // 01816 01817 if (NT_SUCCESS( Status ) 01818 01819 && 01820 01821 (OBJECT_TO_OBJECT_HEADER( Object )->Type == ObpDirectoryObjectType) 01822 01823 && 01824 01825 (((POBJECT_DIRECTORY)Object)->SymbolicLinkUsageCount != 0) 01826 01827 && 01828 01829 !SeFastTraverseCheck( NewDescriptor, DIRECTORY_TRAVERSE, UserMode )) { 01830 01831 KdPrint(( "OB: Failing attempt the remove world traverse access from object directory\n" )); 01832 01833 ExFreePool( NewDescriptor ); 01834 01835 Status = STATUS_INVALID_PARAMETER; 01836 } 01837 01838 // 01839 // If we successfully set the new security descriptor then we 01840 // need to log it in our database and get yet another pointer 01841 // to the finaly security descriptor 01842 // 01843 01844 if ( NT_SUCCESS( Status )) { 01845 01846 Status = ObpLogSecurityDescriptor( NewDescriptor, 01847 ObjectsSecurityDescriptor ); 01848 01849 ObpReleaseDescriptorCacheLock(); 01850 01851 if ( NT_SUCCESS( Status )) { 01852 01853 // 01854 // Dereference old SecurityDescriptor and insert new one 01855 // 01856 01857 ObpDereferenceSecurityDescriptor( OldDescriptor ); 01858 01859 } else { 01860 01861 // 01862 // We failed logging the new security descriptor. 01863 // Clean up and fail the entire operation. 01864 // 01865 01866 ExFreePool( NewDescriptor ); 01867 } 01868 } else { 01869 01870 // 01871 // Release the security descriptor lock 01872 // 01873 01874 ObpReleaseDescriptorCacheLock(); 01875 } 01876 01877 // 01878 // And return to our caller 01879 // 01880 01881 return( Status ); 01882 }

NTSTATUS ObSetSecurityObjectByPointer IN PVOID  Object,
IN SECURITY_INFORMATION  SecurityInformation,
IN PSECURITY_DESCRIPTOR  SecurityDescriptor
 

Definition at line 174 of file obse.c.

References ASSERT, _OBJECT_TYPE_INITIALIZER::GenericMapping, NTSTATUS(), NULL, OBJECT_TO_OBJECT_HEADER, PAGED_CODE, _OBJECT_TYPE_INITIALIZER::PoolType, _OBJECT_HEADER::SecurityDescriptor, _OBJECT_TYPE_INITIALIZER::SecurityProcedure, SetSecurityDescriptor, Status, _OBJECT_HEADER::Type, and _OBJECT_TYPE::TypeInfo.

Referenced by IopChangeDeviceObjectFromRegistryProperties(), IopSetSecurityObjectFromRegistry(), and NtSetSecurityObject().

00182 : 00183 00184 This routine is used to invoke an object's security routine. It 00185 is used to set the object's security state. 00186 00187 This routine is accessible only to the kernel and assumes that all 00188 necessary validation of parameters has been done by the caller. 00189 00190 Arguments: 00191 00192 Object - Supplies the pointer for the object being modified 00193 00194 SecurityInformation - Indicates the type of information we are 00195 interested in setting. e.g., owner, group, dacl, or sacl. 00196 00197 SecurityDescriptor - Supplies the security descriptor for the 00198 object being modified. 00199 00200 Return Value: 00201 00202 An appropriate NTSTATUS value 00203 00204 --*/ 00205 00206 { 00207 NTSTATUS Status; 00208 POBJECT_HEADER ObjectHeader; 00209 POBJECT_TYPE ObjectType; 00210 00211 PAGED_CODE(); 00212 00213 // DbgPrint("ObSetSecurityObjectByPointer called for object %#08lx with info " 00214 // "%x and descriptor %#08lx\n", 00215 // Object, SecurityInformation, SecurityDescriptor); 00216 00217 // 00218 // Map the object body to an object header and the corresponding 00219 // object type 00220 // 00221 00222 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 00223 ObjectType = ObjectHeader->Type; 00224 00225 // 00226 // Make sure the passed security descriptor is really there. 00227 // 00228 00229 ASSERT(ARGUMENT_PRESENT( SecurityDescriptor )); 00230 00231 // 00232 // Now invoke the security procedure call back to set the security 00233 // descriptor for the object 00234 // 00235 00236 Status = (ObjectType->TypeInfo.SecurityProcedure) 00237 ( Object, 00238 SetSecurityDescriptor, 00239 &SecurityInformation, 00240 SecurityDescriptor, 00241 NULL, 00242 &ObjectHeader->SecurityDescriptor, 00243 ObjectType->TypeInfo.PoolType, 00244 &ObjectType->TypeInfo.GenericMapping ); 00245 00246 00247 // DbgPrint("ObSetSecurityObjectByPointer: object security routine returned " 00248 // "%#08lx\n", Status); 00249 00250 return( Status ); 00251 }

NTSTATUS ObValidateSecurityQuota IN PVOID  Object,
IN ULONG  NewSize
 

Definition at line 1473 of file obse.c.

References _OBJECT_HEADER::Flags, NULL, OB_FLAG_DEFAULT_SECURITY_QUOTA, OBJECT_HEADER_TO_QUOTA_INFO, OBJECT_TO_OBJECT_HEADER, PAGED_CODE, SE_DEFAULT_SECURITY_QUOTA, and _OBJECT_HEADER_QUOTA_INFO::SecurityDescriptorCharge.

Referenced by RtlpSetSecurityObject().

01480 : 01481 01482 This routine will check to see if the new security information 01483 is larger than is allowed by the object's pre-allocated quota. 01484 01485 Arguments: 01486 01487 Object - Supplies a pointer to the object whose information is to be 01488 modified. 01489 01490 NewSize - Supplies the size of the proposed new security 01491 information. 01492 01493 Return Value: 01494 01495 STATUS_SUCCESS - New size is within alloted quota. 01496 01497 STATUS_QUOTA_EXCEEDED - The desired adjustment would have exceeded 01498 the permitted security quota for this object. 01499 01500 --*/ 01501 01502 { 01503 POBJECT_HEADER ObjectHeader; 01504 POBJECT_HEADER_QUOTA_INFO QuotaInfo; 01505 01506 PAGED_CODE(); 01507 01508 // 01509 // Map the object body to its object header and corresponding 01510 // quota information block 01511 // 01512 01513 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 01514 QuotaInfo = OBJECT_HEADER_TO_QUOTA_INFO( ObjectHeader ); 01515 01516 // 01517 // If there isn't any quota info and the new size is greater 01518 // then the default security quota then if the object uses 01519 // the default value then we've exceeded quota otherwise 01520 // let the caller get the quota 01521 // 01522 01523 if ((QuotaInfo == NULL) && (NewSize > SE_DEFAULT_SECURITY_QUOTA)) { 01524 01525 if (!(ObjectHeader->Flags & OB_FLAG_DEFAULT_SECURITY_QUOTA)) { 01526 01527 // 01528 // Should really charge quota here. 01529 // 01530 01531 return( STATUS_SUCCESS ); 01532 } 01533 01534 return( STATUS_QUOTA_EXCEEDED ); 01535 01536 // 01537 // If the quota is not null and the new size is greater than the 01538 // allowed quota charge then if the charge is zero we grant the 01539 // request otherwise we've exceeded quota. 01540 // 01541 // **** this logic seems wierd 01542 // 01543 01544 } else if ((QuotaInfo != NULL) && (NewSize > QuotaInfo->SecurityDescriptorCharge)) { 01545 01546 if (QuotaInfo->SecurityDescriptorCharge == 0) { 01547 01548 // 01549 // Should really charge quota here. 01550 // 01551 01552 // QuotaInfo->SecurityDescriptorCharge = SeComputeSecurityQuota( NewSize ); 01553 01554 return( STATUS_SUCCESS ); 01555 } 01556 01557 return( STATUS_QUOTA_EXCEEDED ); 01558 01559 // 01560 // Otherwise we have two cases. (1) there isn't any quota info but 01561 // the size is within limits or (2) there is a quota info block and 01562 // the size is within the specified security descriptor charge so 01563 // return success to our caller 01564 // 01565 01566 } else { 01567 01568 return( STATUS_SUCCESS ); 01569 } 01570 }


Generated on Sat May 15 19:44:59 2004 for test by doxygen 1.3.7