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

accessck.c File Reference

#include "tokenp.h"
#include <sertlp.h>

Go to the source code of this file.

Enumerations

enum  ACCESS_MASK_FIELD_TO_UPDATE { UpdateRemaining, UpdateCurrentGranted, UpdateCurrentDenied }

Functions

VOID SepUpdateParentTypeList (IN PIOBJECT_TYPE_LIST ObjectTypeList, IN ULONG ObjectTypeListLength, IN ULONG StartIndex)
VOID SepAddAccessTypeList (IN PIOBJECT_TYPE_LIST ObjectTypeList, IN ULONG ObjectTypeListLength, IN ULONG StartIndex, IN ACCESS_MASK AccessMask, IN ACCESS_MASK_FIELD_TO_UPDATE FieldToUpdate)
NTSTATUS SeAccessCheckByType (IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSID PrincipalSelfSid, IN HANDLE ClientToken, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE_LIST ObjectTypeList OPTIONAL, IN ULONG ObjectTypeListLength, IN PGENERIC_MAPPING GenericMapping, OUT PPRIVILEGE_SET PrivilegeSet, IN OUT PULONG PrivilegeSetLength, OUT PACCESS_MASK GrantedAccess, OUT PNTSTATUS AccessStatus, IN BOOLEAN ReturnResultList)
VOID SepMaximumAccessCheck (IN PTOKEN EToken, IN PTOKEN PrimaryToken, IN PACL Dacl, IN PSID PrincipalSelfSid, IN ULONG LocalTypeListLength, IN PIOBJECT_TYPE_LIST LocalTypeList, IN ULONG ObjectTypeListLength, IN BOOLEAN Restricted)
VOID SepNormalAccessCheck (IN ACCESS_MASK Remaining, IN PTOKEN EToken, IN PTOKEN PrimaryToken, IN PACL Dacl, IN PSID PrincipalSelfSid, IN ULONG LocalTypeListLength, IN PIOBJECT_TYPE_LIST LocalTypeList, IN ULONG ObjectTypeListLength, IN BOOLEAN Restricted)
BOOLEAN SepSidInTokenEx (IN PACCESS_TOKEN AToken, IN PSID PrincipalSelfSid, IN PSID Sid, IN BOOLEAN DenyAce, IN BOOLEAN Restricted)
NTSTATUS SeCaptureObjectTypeList (IN POBJECT_TYPE_LIST ObjectTypeList OPTIONAL, IN ULONG ObjectTypeListLength, IN KPROCESSOR_MODE RequestorMode, OUT PIOBJECT_TYPE_LIST *CapturedObjectTypeList)
VOID SeFreeCapturedObjectTypeList (IN PVOID ObjectTypeList)
BOOLEAN SepObjectInTypeList (IN GUID *ObjectType, IN PIOBJECT_TYPE_LIST ObjectTypeList, IN ULONG ObjectTypeListLength, OUT PULONG ReturnedIndex)
BOOLEAN SepSidInToken (IN PACCESS_TOKEN AToken, IN PSID PrincipalSelfSid, IN PSID Sid, IN BOOLEAN DenyAce)
VOID SepAccessCheck (IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSID PrincipalSelfSid, IN PTOKEN PrimaryToken, IN PTOKEN ClientToken OPTIONAL, IN ACCESS_MASK DesiredAccess, IN PIOBJECT_TYPE_LIST ObjectTypeList OPTIONAL, IN ULONG ObjectTypeListLength, IN PGENERIC_MAPPING GenericMapping, IN ACCESS_MASK PreviouslyGrantedAccess, IN KPROCESSOR_MODE PreviousMode, OUT PACCESS_MASK GrantedAccess, OUT PPRIVILEGE_SET *Privileges OPTIONAL, OUT PNTSTATUS AccessStatus, IN BOOLEAN ReturnResultList, OUT PBOOLEAN ReturnSomeAccessGranted, OUT PBOOLEAN ReturnSomeAccessDenied)
NTSTATUS NtAccessCheck (IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN HANDLE ClientToken, IN ACCESS_MASK DesiredAccess, IN PGENERIC_MAPPING GenericMapping, OUT PPRIVILEGE_SET PrivilegeSet, IN OUT PULONG PrivilegeSetLength, OUT PACCESS_MASK GrantedAccess, OUT PNTSTATUS AccessStatus)
NTSTATUS NtAccessCheckByType (IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSID PrincipalSelfSid, IN HANDLE ClientToken, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE_LIST ObjectTypeList OPTIONAL, IN ULONG ObjectTypeListLength, IN PGENERIC_MAPPING GenericMapping, OUT PPRIVILEGE_SET PrivilegeSet, IN OUT PULONG PrivilegeSetLength, OUT PACCESS_MASK GrantedAccess, OUT PNTSTATUS AccessStatus)
NTSTATUS NtAccessCheckByTypeResultList (IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSID PrincipalSelfSid, IN HANDLE ClientToken, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE_LIST ObjectTypeList OPTIONAL, IN ULONG ObjectTypeListLength, IN PGENERIC_MAPPING GenericMapping, OUT PPRIVILEGE_SET PrivilegeSet, IN OUT PULONG PrivilegeSetLength, OUT PACCESS_MASK GrantedAccess, OUT PNTSTATUS AccessStatus)
VOID SeFreePrivileges (IN PPRIVILEGE_SET Privileges)
BOOLEAN SeAccessCheck (IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, IN BOOLEAN SubjectContextLocked, IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK PreviouslyGrantedAccess, OUT PPRIVILEGE_SET *Privileges OPTIONAL, IN PGENERIC_MAPPING GenericMapping, IN KPROCESSOR_MODE AccessMode, OUT PACCESS_MASK GrantedAccess, OUT PNTSTATUS AccessStatus)
BOOLEAN SeProxyAccessCheck (IN PUNICODE_STRING Volume, IN PUNICODE_STRING RelativePath, IN BOOLEAN ContainerObject, IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, IN BOOLEAN SubjectContextLocked, IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK PreviouslyGrantedAccess, OUT PPRIVILEGE_SET *Privileges OPTIONAL, IN PGENERIC_MAPPING GenericMapping, IN KPROCESSOR_MODE AccessMode, OUT PACCESS_MASK GrantedAccess, OUT PNTSTATUS AccessStatus)
NTSTATUS SePrivilegePolicyCheck (IN OUT PACCESS_MASK RemainingDesiredAccess, IN OUT PACCESS_MASK PreviouslyGrantedAccess, IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext OPTIONAL, IN PACCESS_TOKEN ExplicitToken OPTIONAL, OUT PPRIVILEGE_SET *PrivilegeSet, IN KPROCESSOR_MODE PreviousMode)
BOOLEAN SepTokenIsOwner (IN PACCESS_TOKEN EffectiveToken, IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN BOOLEAN TokenLocked)
BOOLEAN SeFastTraverseCheck (PSECURITY_DESCRIPTOR SecurityDescriptor, ACCESS_MASK TraverseAccess, KPROCESSOR_MODE AccessMode)


Enumeration Type Documentation

enum ACCESS_MASK_FIELD_TO_UPDATE
 

Enumeration values:
UpdateRemaining 
UpdateCurrentGranted 
UpdateCurrentDenied 

Definition at line 55 of file accessck.c.


Function Documentation

NTSTATUS NtAccessCheck IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN HANDLE  ClientToken,
IN ACCESS_MASK  DesiredAccess,
IN PGENERIC_MAPPING  GenericMapping,
OUT PPRIVILEGE_SET  PrivilegeSet,
IN OUT PULONG  PrivilegeSetLength,
OUT PACCESS_MASK  GrantedAccess,
OUT PNTSTATUS  AccessStatus
 

Definition at line 2413 of file accessck.c.

References ClientToken, FALSE, NULL, PAGED_CODE, and SeAccessCheckByType().

Referenced by CreateDAclToken(), and TestAccessCheck().

02427 : 02428 02429 See module abstract. 02430 02431 Arguments: 02432 02433 SecurityDescriptor - Supplies the security descriptor protecting the object 02434 being accessed 02435 02436 ClientToken - Supplies the handle of the user's token. 02437 02438 DesiredAccess - Supplies the desired access mask. 02439 02440 GenericMapping - Supplies the generic mapping associated with this 02441 object type. 02442 02443 PrivilegeSet - A pointer to a buffer that upon return will contain 02444 any privileges that were used to perform the access validation. 02445 If no privileges were used, the buffer will contain a privilege 02446 set consisting of zero privileges. 02447 02448 PrivilegeSetLength - The size of the PrivilegeSet buffer in bytes. 02449 02450 GrantedAccess - Returns an access mask describing the granted access. 02451 02452 AccessStatus - Status value that may be returned indicating the 02453 reason why access was denied. Routines should avoid hardcoding a 02454 return value of STATUS_ACCESS_DENIED so that a different value can 02455 be returned when mandatory access control is implemented. 02456 02457 Return Value: 02458 02459 STATUS_SUCCESS - The attempt proceeded normally. This does not 02460 mean access was granted, rather that the parameters were 02461 correct. 02462 02463 STATUS_GENERIC_NOT_MAPPED - The DesiredAccess mask contained 02464 an unmapped generic access. 02465 02466 STATUS_BUFFER_TOO_SMALL - The passed buffer was not large enough 02467 to contain the information being returned. 02468 02469 STATUS_NO_IMPERSONTAION_TOKEN - The passed Token was not an impersonation 02470 token. 02471 02472 --*/ 02473 02474 { 02475 02476 PAGED_CODE(); 02477 02478 return SeAccessCheckByType ( 02479 SecurityDescriptor, 02480 NULL, // No Principal Self sid 02481 ClientToken, 02482 DesiredAccess, 02483 NULL, // No ObjectType List 02484 0, // No ObjectType List 02485 GenericMapping, 02486 PrivilegeSet, 02487 PrivilegeSetLength, 02488 GrantedAccess, 02489 AccessStatus, 02490 FALSE ); // Return a single GrantedAccess and AccessStatus 02491 02492 02493 }

NTSTATUS NtAccessCheckByType IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN PSID  PrincipalSelfSid,
IN HANDLE  ClientToken,
IN ACCESS_MASK  DesiredAccess,
IN POBJECT_TYPE_LIST ObjectTypeList  OPTIONAL,
IN ULONG  ObjectTypeListLength,
IN PGENERIC_MAPPING  GenericMapping,
OUT PPRIVILEGE_SET  PrivilegeSet,
IN OUT PULONG  PrivilegeSetLength,
OUT PACCESS_MASK  GrantedAccess,
OUT PNTSTATUS  AccessStatus
 

Definition at line 2501 of file accessck.c.

References ClientToken, FALSE, PAGED_CODE, and SeAccessCheckByType().

02518 : 02519 02520 See module abstract. 02521 02522 Arguments: 02523 02524 SecurityDescriptor - Supplies the security descriptor protecting the object 02525 being accessed 02526 02527 PrincipalSelfSid - If the object being access checked is an object which 02528 represents a principal (e.g., a user object), this parameter should 02529 be the SID of the object. Any ACE containing the constant 02530 PRINCIPAL_SELF_SID is replaced by this SID. 02531 02532 The parameter should be NULL if the object does not represent a principal. 02533 02534 ClientToken - Supplies the handle of the user's token. 02535 02536 DesiredAccess - Supplies the desired access mask. 02537 02538 ObjectTypeList - Supplies a list of GUIDs representing the object (and 02539 sub-objects) being accessed. If no list is present, AccessCheckByType 02540 behaves identically to AccessCheck. 02541 02542 ObjectTypeListLength - Specifies the number of elements in the ObjectTypeList. 02543 02544 GenericMapping - Supplies the generic mapping associated with this 02545 object type. 02546 02547 PrivilegeSet - A pointer to a buffer that upon return will contain 02548 any privileges that were used to perform the access validation. 02549 If no privileges were used, the buffer will contain a privilege 02550 set consisting of zero privileges. 02551 02552 PrivilegeSetLength - The size of the PrivilegeSet buffer in bytes. 02553 02554 GrantedAccess - Returns an access mask describing the granted access. 02555 02556 AccessStatus - Status value that may be returned indicating the 02557 reason why access was denied. Routines should avoid hardcoding a 02558 return value of STATUS_ACCESS_DENIED so that a different value can 02559 be returned when mandatory access control is implemented. 02560 02561 Return Value: 02562 02563 STATUS_SUCCESS - The attempt proceeded normally. This does not 02564 mean access was granted, rather that the parameters were 02565 correct. 02566 02567 STATUS_GENERIC_NOT_MAPPED - The DesiredAccess mask contained 02568 an unmapped generic access. 02569 02570 STATUS_BUFFER_TOO_SMALL - The passed buffer was not large enough 02571 to contain the information being returned. 02572 02573 STATUS_NO_IMPERSONTAION_TOKEN - The passed Token was not an impersonation 02574 token. 02575 02576 --*/ 02577 02578 { 02579 02580 PAGED_CODE(); 02581 02582 return SeAccessCheckByType ( 02583 SecurityDescriptor, 02584 PrincipalSelfSid, 02585 ClientToken, 02586 DesiredAccess, 02587 ObjectTypeList, 02588 ObjectTypeListLength, 02589 GenericMapping, 02590 PrivilegeSet, 02591 PrivilegeSetLength, 02592 GrantedAccess, 02593 AccessStatus, 02594 FALSE ); // Return a single GrantedAccess and AccessStatus 02595 }

NTSTATUS NtAccessCheckByTypeResultList IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN PSID  PrincipalSelfSid,
IN HANDLE  ClientToken,
IN ACCESS_MASK  DesiredAccess,
IN POBJECT_TYPE_LIST ObjectTypeList  OPTIONAL,
IN ULONG  ObjectTypeListLength,
IN PGENERIC_MAPPING  GenericMapping,
OUT PPRIVILEGE_SET  PrivilegeSet,
IN OUT PULONG  PrivilegeSetLength,
OUT PACCESS_MASK  GrantedAccess,
OUT PNTSTATUS  AccessStatus
 

Definition at line 2602 of file accessck.c.

References ClientToken, PAGED_CODE, SeAccessCheckByType(), and TRUE.

02619 : 02620 02621 See module abstract. 02622 02623 Arguments: 02624 02625 SecurityDescriptor - Supplies the security descriptor protecting the object 02626 being accessed 02627 02628 PrincipalSelfSid - If the object being access checked is an object which 02629 represents a principal (e.g., a user object), this parameter should 02630 be the SID of the object. Any ACE containing the constant 02631 PRINCIPAL_SELF_SID is replaced by this SID. 02632 02633 The parameter should be NULL if the object does not represent a principal. 02634 02635 ClientToken - Supplies the handle of the user's token. 02636 02637 DesiredAccess - Supplies the desired access mask. 02638 02639 ObjectTypeList - Supplies a list of GUIDs representing the object (and 02640 sub-objects) being accessed. If no list is present, AccessCheckByType 02641 behaves identically to AccessCheck. 02642 02643 ObjectTypeListLength - Specifies the number of elements in the ObjectTypeList. 02644 02645 GenericMapping - Supplies the generic mapping associated with this 02646 object type. 02647 02648 PrivilegeSet - A pointer to a buffer that upon return will contain 02649 any privileges that were used to perform the access validation. 02650 If no privileges were used, the buffer will contain a privilege 02651 set consisting of zero privileges. 02652 02653 PrivilegeSetLength - The size of the PrivilegeSet buffer in bytes. 02654 02655 GrantedAccess - Returns an access mask describing the granted access. 02656 02657 AccessStatus - Status value that may be returned indicating the 02658 reason why access was denied. Routines should avoid hardcoding a 02659 return value of STATUS_ACCESS_DENIED so that a different value can 02660 be returned when mandatory access control is implemented. 02661 02662 Return Value: 02663 02664 STATUS_SUCCESS - The attempt proceeded normally. This does not 02665 mean access was granted, rather that the parameters were 02666 correct. 02667 02668 STATUS_GENERIC_NOT_MAPPED - The DesiredAccess mask contained 02669 an unmapped generic access. 02670 02671 STATUS_BUFFER_TOO_SMALL - The passed buffer was not large enough 02672 to contain the information being returned. 02673 02674 STATUS_NO_IMPERSONTAION_TOKEN - The passed Token was not an impersonation 02675 token. 02676 02677 --*/ 02678 02679 { 02680 02681 PAGED_CODE(); 02682 02683 return SeAccessCheckByType ( 02684 SecurityDescriptor, 02685 PrincipalSelfSid, 02686 ClientToken, 02687 DesiredAccess, 02688 ObjectTypeList, 02689 ObjectTypeListLength, 02690 GenericMapping, 02691 PrivilegeSet, 02692 PrivilegeSetLength, 02693 GrantedAccess, 02694 AccessStatus, 02695 TRUE ); // Return an array of GrantedAccess and AccessStatus 02696 }

BOOLEAN SeAccessCheck IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN PSECURITY_SUBJECT_CONTEXT  SubjectSecurityContext,
IN BOOLEAN  SubjectContextLocked,
IN ACCESS_MASK  DesiredAccess,
IN ACCESS_MASK  PreviouslyGrantedAccess,
OUT PPRIVILEGE_SET *Privileges  OPTIONAL,
IN PGENERIC_MAPPING  GenericMapping,
IN KPROCESSOR_MODE  AccessMode,
OUT PACCESS_MASK  GrantedAccess,
OUT PNTSTATUS  AccessStatus
 

Definition at line 3323 of file accessck.c.

References DbgPrint, EffectiveToken, FALSE, KernelMode, NULL, PAGED_CODE, PSECURITY_SUBJECT_CONTEXT, SeAssertMappedCanonicalAccess, SeLockSubjectContext(), SepAccessCheck(), SepDumpSecurityDescriptor(), SepDumpTokenInfo(), SepTokenIsOwner(), SeUnlockSubjectContext(), and TRUE.

Referenced by CmpCheckCreateAccess(), CmpCheckNotifyAccess(), IopParseDevice(), ObCheckCreateObjectAccess(), ObCheckObjectAccess(), ObpCheckObjectReference(), ObpCheckTraverseAccess(), PspCreateProcess(), PspCreateThread(), PspSetPrimaryToken(), SeProxyAccessCheck(), and TestAccessCheck().

03338 : 03339 03340 See module abstract 03341 03342 This routine MAY perform tests for the following 03343 privileges: 03344 03345 SeTakeOwnershipPrivilege 03346 SeSecurityPrivilege 03347 03348 depending upon the accesses being requested. 03349 03350 This routine may also check to see if the subject is the owner 03351 of the object (to grant WRITE_DAC access). 03352 03353 Arguments: 03354 03355 SecurityDescriptor - Supplies the security descriptor protecting the 03356 object being accessed 03357 03358 SubjectSecurityContext - A pointer to the subject's captured security 03359 context 03360 03361 SubjectContextLocked - Supplies a flag indiciating whether or not 03362 the user's subject context is locked, so that it does not have 03363 to be locked again. 03364 03365 DesiredAccess - Supplies the access mask that the user is attempting to 03366 acquire 03367 03368 PreviouslyGrantedAccess - Supplies any accesses that the user has 03369 already been granted, for example, as a result of holding a 03370 privilege. 03371 03372 Privileges - Supplies a pointer in which will be returned a privilege 03373 set indicating any privileges that were used as part of the 03374 access validation. 03375 03376 GenericMapping - Supplies the generic mapping associated with this 03377 object type. 03378 03379 AccessMode - Supplies the access mode to be used in the check 03380 03381 GrantedAccess - Pointer to a returned access mask indicatating the 03382 granted access 03383 03384 AccessStatus - Status value that may be returned indicating the 03385 reason why access was denied. Routines should avoid hardcoding a 03386 return value of STATUS_ACCESS_DENIED so that a different value can 03387 be returned when mandatory access control is implemented. 03388 03389 03390 Return Value: 03391 03392 BOOLEAN - TRUE if access is allowed and FALSE otherwise 03393 03394 --*/ 03395 03396 { 03397 BOOLEAN Success; 03398 03399 PAGED_CODE(); 03400 03401 if (AccessMode == KernelMode) { 03402 03403 if (DesiredAccess & MAXIMUM_ALLOWED) { 03404 03405 // 03406 // Give him: 03407 // GenericAll 03408 // Anything else he asked for 03409 // 03410 03411 *GrantedAccess = GenericMapping->GenericAll; 03412 *GrantedAccess |= (DesiredAccess & ~MAXIMUM_ALLOWED); 03413 *GrantedAccess |= PreviouslyGrantedAccess; 03414 03415 } else { 03416 03417 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess; 03418 } 03419 *AccessStatus = STATUS_SUCCESS; 03420 return(TRUE); 03421 } 03422 03423 // 03424 // If the object doesn't have a security descriptor (and it's supposed 03425 // to), return access denied. 03426 // 03427 03428 if ( SecurityDescriptor == NULL) { 03429 03430 *AccessStatus = STATUS_ACCESS_DENIED; 03431 return( FALSE ); 03432 03433 } 03434 03435 // 03436 // If we're impersonating a client, we have to be at impersonation level 03437 // of SecurityImpersonation or above. 03438 // 03439 03440 if ( (SubjectSecurityContext->ClientToken != NULL) && 03441 (SubjectSecurityContext->ImpersonationLevel < SecurityImpersonation) 03442 ) { 03443 *AccessStatus = STATUS_BAD_IMPERSONATION_LEVEL; 03444 return( FALSE ); 03445 } 03446 03447 if ( DesiredAccess == 0 ) { 03448 03449 if ( PreviouslyGrantedAccess == 0 ) { 03450 *AccessStatus = STATUS_ACCESS_DENIED; 03451 return( FALSE ); 03452 } 03453 03454 *GrantedAccess = PreviouslyGrantedAccess; 03455 *AccessStatus = STATUS_SUCCESS; 03456 *Privileges = NULL; 03457 return( TRUE ); 03458 03459 } 03460 03461 SeAssertMappedCanonicalAccess( DesiredAccess ); 03462 03463 03464 // 03465 // If the caller did not lock the subject context for us, 03466 // lock it here to keep lower level routines from having 03467 // to lock it. 03468 // 03469 03470 if ( !SubjectContextLocked ) { 03471 SeLockSubjectContext( SubjectSecurityContext ); 03472 } 03473 03474 // 03475 // If the user in the token is the owner of the object, we 03476 // must automatically grant ReadControl and WriteDac access 03477 // if desired. If the DesiredAccess mask is empty after 03478 // these bits are turned off, we don't have to do any more 03479 // access checking (ref section 4, DSA ACL Arch) 03480 // 03481 03482 if ( DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED) ) { 03483 03484 if ( SepTokenIsOwner( 03485 EffectiveToken( SubjectSecurityContext ), 03486 SecurityDescriptor, 03487 TRUE 03488 ) ) { 03489 03490 if ( DesiredAccess & MAXIMUM_ALLOWED ) { 03491 03492 PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL); 03493 03494 } else { 03495 03496 PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL)); 03497 } 03498 03499 DesiredAccess &= ~(WRITE_DAC | READ_CONTROL); 03500 } 03501 } 03502 03503 if (DesiredAccess == 0) { 03504 03505 if ( !SubjectContextLocked ) { 03506 SeUnlockSubjectContext( SubjectSecurityContext ); 03507 } 03508 03509 *GrantedAccess = PreviouslyGrantedAccess; 03510 *AccessStatus = STATUS_SUCCESS; 03511 return( TRUE ); 03512 03513 } else { 03514 03515 SepAccessCheck( 03516 SecurityDescriptor, 03517 NULL, // No PrincipalSelfSid 03518 SubjectSecurityContext->PrimaryToken, 03519 SubjectSecurityContext->ClientToken, 03520 DesiredAccess, 03521 NULL, // No object type list 03522 0, // No object type list 03523 GenericMapping, 03524 PreviouslyGrantedAccess, 03525 AccessMode, 03526 GrantedAccess, 03527 Privileges, 03528 AccessStatus, 03529 FALSE, // Don't return a list 03530 &Success, 03531 NULL 03532 ); 03533 #if DBG 03534 if (!Success && SepShowAccessFail) { 03535 DbgPrint("SE: Access check failed, DesiredAccess = 0x%x\n", 03536 DesiredAccess); 03537 SepDumpSD = TRUE; 03538 SepDumpSecurityDescriptor( 03539 SecurityDescriptor, 03540 "Input to SeAccessCheck\n" 03541 ); 03542 SepDumpSD = FALSE; 03543 SepDumpToken = TRUE; 03544 SepDumpTokenInfo( EffectiveToken( SubjectSecurityContext ) ); 03545 SepDumpToken = FALSE; 03546 } 03547 #endif 03548 03549 // 03550 // If we locked it in this routine, unlock it before we 03551 // leave. 03552 // 03553 03554 if ( !SubjectContextLocked ) { 03555 SeUnlockSubjectContext( SubjectSecurityContext ); 03556 } 03557 03558 return( Success ); 03559 } 03560 }

NTSTATUS SeAccessCheckByType IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN PSID  PrincipalSelfSid,
IN HANDLE  ClientToken,
IN ACCESS_MASK  DesiredAccess,
IN POBJECT_TYPE_LIST ObjectTypeList  OPTIONAL,
IN ULONG  ObjectTypeListLength,
IN PGENERIC_MAPPING  GenericMapping,
OUT PPRIVILEGE_SET  PrivilegeSet,
IN OUT PULONG  PrivilegeSetLength,
OUT PACCESS_MASK  GrantedAccess,
OUT PNTSTATUS  AccessStatus,
IN BOOLEAN  ReturnResultList
 

Definition at line 2704 of file accessck.c.

References ASSERT, ClientToken, ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), FALSE, IsValidElementCount, KernelMode, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, PagedPool, _SECURITY_SUBJECT_CONTEXT::PrimaryToken, ProbeAndReadUlong, ProbeForRead, ProbeForWrite(), ProbeForWriteUlong, PTOKEN, SeCaptureObjectTypeList(), SeCaptureSecurityDescriptor(), SeCaptureSid(), SeCaptureSubjectContext(), SECURITY_SUBJECT_CONTEXT, SeFreeCapturedObjectTypeList(), SeFreePrivileges(), SepAccessCheck(), SepAcquireTokenReadLock, SepPrivilegeSetSize, SepReleaseTokenReadLock, SePrivilegePolicyCheck(), SepTokenIsOwner(), SepTokenObjectType, SeReleaseSecurityDescriptor(), SeReleaseSid(), SeReleaseSubjectContext(), Status, Token, and TRUE.

Referenced by NtAccessCheck(), NtAccessCheckByType(), and NtAccessCheckByTypeResultList().

02722 : 02723 02724 See module abstract. 02725 02726 Arguments: 02727 02728 SecurityDescriptor - Supplies the security descriptor protecting the object 02729 being accessed 02730 02731 PrincipalSelfSid - If the object being access checked is an object which 02732 represents a principal (e.g., a user object), this parameter should 02733 be the SID of the object. Any ACE containing the constant 02734 PRINCIPAL_SELF_SID is replaced by this SID. 02735 02736 The parameter should be NULL if the object does not represent a principal. 02737 02738 ClientToken - Supplies the handle of the user's token. 02739 02740 DesiredAccess - Supplies the desired access mask. 02741 02742 ObjectTypeList - Supplies a list of GUIDs representing the object (and 02743 sub-objects) being accessed. If no list is present, AccessCheckByType 02744 behaves identically to AccessCheck. 02745 02746 ObjectTypeListLength - Specifies the number of elements in the ObjectTypeList. 02747 02748 GenericMapping - Supplies the generic mapping associated with this 02749 object type. 02750 02751 PrivilegeSet - A pointer to a buffer that upon return will contain 02752 any privileges that were used to perform the access validation. 02753 If no privileges were used, the buffer will contain a privilege 02754 set consisting of zero privileges. 02755 02756 PrivilegeSetLength - The size of the PrivilegeSet buffer in bytes. 02757 02758 GrantedAccess - Returns an access mask describing the granted access. 02759 02760 AccessStatus - Status value that may be returned indicating the 02761 reason why access was denied. Routines should avoid hardcoding a 02762 return value of STATUS_ACCESS_DENIED so that a different value can 02763 be returned when mandatory access control is implemented. 02764 02765 ReturnResultList - If true, GrantedAccess and AccessStatus are actually 02766 arrays of entries ObjectTypeListLength elements long. 02767 02768 Return Value: 02769 02770 STATUS_SUCCESS - The attempt proceeded normally. This does not 02771 mean access was granted, rather that the parameters were 02772 correct. 02773 02774 STATUS_GENERIC_NOT_MAPPED - The DesiredAccess mask contained 02775 an unmapped generic access. 02776 02777 STATUS_BUFFER_TOO_SMALL - The passed buffer was not large enough 02778 to contain the information being returned. 02779 02780 STATUS_NO_IMPERSONTAION_TOKEN - The passed Token was not an impersonation 02781 token. 02782 02783 --*/ 02784 02785 { 02786 ACCESS_MASK LocalGrantedAccess; 02787 PACCESS_MASK LocalGrantedAccessPointer = NULL; 02788 NTSTATUS LocalAccessStatus; 02789 PNTSTATUS LocalAccessStatusPointer = NULL; 02790 KPROCESSOR_MODE PreviousMode; 02791 NTSTATUS Status = STATUS_SUCCESS; 02792 PTOKEN Token = NULL; 02793 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL; 02794 PSID CapturedPrincipalSelfSid = NULL; 02795 ACCESS_MASK PreviouslyGrantedAccess = 0; 02796 GENERIC_MAPPING LocalGenericMapping; 02797 PIOBJECT_TYPE_LIST LocalObjectTypeList = NULL; 02798 PPRIVILEGE_SET Privileges = NULL; 02799 SECURITY_SUBJECT_CONTEXT SubjectContext; 02800 ULONG LocalPrivilegeSetLength; 02801 ULONG ResultListIndex; 02802 02803 PAGED_CODE(); 02804 02805 PreviousMode = KeGetPreviousMode(); 02806 02807 if (PreviousMode == KernelMode) { 02808 ASSERT( !ReturnResultList ); 02809 *AccessStatus = STATUS_SUCCESS; 02810 *GrantedAccess = DesiredAccess; 02811 return(STATUS_SUCCESS); 02812 } 02813 02814 try { 02815 02816 if ( ReturnResultList ) { 02817 02818 if ( ObjectTypeListLength == 0 ) { 02819 Status = STATUS_INVALID_PARAMETER; 02820 leave ; 02821 } 02822 02823 if ( !IsValidElementCount( ObjectTypeListLength, OBJECT_TYPE_LIST ) ) 02824 { 02825 Status = STATUS_INVALID_PARAMETER ; 02826 02827 leave ; 02828 } 02829 02830 ProbeForWrite( 02831 AccessStatus, 02832 sizeof(NTSTATUS) * ObjectTypeListLength, 02833 sizeof(ULONG) 02834 ); 02835 02836 ProbeForWrite( 02837 GrantedAccess, 02838 sizeof(ACCESS_MASK) * ObjectTypeListLength, 02839 sizeof(ULONG) 02840 ); 02841 02842 } else { 02843 ProbeForWriteUlong((PULONG)AccessStatus); 02844 ProbeForWriteUlong((PULONG)GrantedAccess); 02845 } 02846 02847 LocalPrivilegeSetLength = ProbeAndReadUlong( PrivilegeSetLength ); 02848 ProbeForWriteUlong( 02849 PrivilegeSetLength 02850 ); 02851 02852 ProbeForWrite( 02853 PrivilegeSet, 02854 LocalPrivilegeSetLength, 02855 sizeof(ULONG) 02856 ); 02857 02858 ProbeForRead( 02859 GenericMapping, 02860 sizeof(GENERIC_MAPPING), 02861 sizeof(ULONG) 02862 ); 02863 02864 LocalGenericMapping = *GenericMapping; 02865 02866 } except (EXCEPTION_EXECUTE_HANDLER) { 02867 Status = GetExceptionCode(); 02868 } 02869 if (!NT_SUCCESS( Status ) ) { 02870 return( Status ); 02871 } 02872 02873 if (DesiredAccess & 02874 ( GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL )) { 02875 02876 02877 Status = STATUS_GENERIC_NOT_MAPPED; 02878 goto Cleanup; 02879 } 02880 02881 // 02882 // Obtain a pointer to the passed token 02883 // 02884 02885 Status = ObReferenceObjectByHandle( 02886 ClientToken, // Handle 02887 (ACCESS_MASK)TOKEN_QUERY, // DesiredAccess 02888 SepTokenObjectType, // ObjectType 02889 PreviousMode, // AccessMode 02890 (PVOID *)&Token, // Object 02891 0 // GrantedAccess 02892 ); 02893 02894 if (!NT_SUCCESS(Status)) { 02895 Token = NULL; 02896 goto Cleanup; 02897 } 02898 02899 // 02900 // It must be an impersonation token, and at impersonation 02901 // level of Identification or above. 02902 // 02903 02904 if (Token->TokenType != TokenImpersonation) { 02905 Status = STATUS_NO_IMPERSONATION_TOKEN; 02906 goto Cleanup; 02907 } 02908 02909 if ( Token->ImpersonationLevel < SecurityIdentification ) { 02910 Status = STATUS_BAD_IMPERSONATION_LEVEL; 02911 goto Cleanup; 02912 } 02913 02914 // 02915 // Capture any Object type list 02916 // 02917 02918 Status = SeCaptureObjectTypeList( ObjectTypeList, 02919 ObjectTypeListLength, 02920 PreviousMode, 02921 &LocalObjectTypeList ); 02922 02923 if (!NT_SUCCESS(Status)) { 02924 goto Cleanup; 02925 } 02926 02927 // 02928 // Compare the DesiredAccess with the privileges in the 02929 // passed token, and see if we can either satisfy the requested 02930 // access with a privilege, or bomb out immediately because 02931 // we don't have a privilege we need. 02932 // 02933 02934 Status = SePrivilegePolicyCheck( 02935 &DesiredAccess, 02936 &PreviouslyGrantedAccess, 02937 NULL, 02938 (PACCESS_TOKEN)Token, 02939 &Privileges, 02940 PreviousMode 02941 ); 02942 02943 if (!NT_SUCCESS( Status )) { 02944 02945 try { 02946 02947 if ( ReturnResultList ) { 02948 for ( ResultListIndex=0; ResultListIndex<ObjectTypeListLength; ResultListIndex++ ) { 02949 AccessStatus[ResultListIndex] = Status; 02950 GrantedAccess[ResultListIndex] = 0; 02951 } 02952 02953 } else { 02954 *AccessStatus = Status; 02955 *GrantedAccess = 0; 02956 } 02957 02958 Status = STATUS_SUCCESS; 02959 02960 } except(EXCEPTION_EXECUTE_HANDLER) { 02961 02962 Status = GetExceptionCode(); 02963 } 02964 02965 goto Cleanup; 02966 } 02967 02968 // 02969 // Make sure the passed privileges buffer is large enough for 02970 // whatever we have to put into it. 02971 // 02972 02973 if (Privileges != NULL) { 02974 02975 if ( ((ULONG)SepPrivilegeSetSize( Privileges )) > LocalPrivilegeSetLength ) { 02976 02977 try { 02978 02979 *PrivilegeSetLength = SepPrivilegeSetSize( Privileges ); 02980 Status = STATUS_BUFFER_TOO_SMALL; 02981 02982 } except ( EXCEPTION_EXECUTE_HANDLER ) { 02983 02984 Status = GetExceptionCode(); 02985 } 02986 02987 SeFreePrivileges( Privileges ); 02988 02989 goto Cleanup; 02990 02991 } else { 02992 02993 try { 02994 02995 RtlCopyMemory( 02996 PrivilegeSet, 02997 Privileges, 02998 SepPrivilegeSetSize( Privileges ) 02999 ); 03000 03001 } except ( EXCEPTION_EXECUTE_HANDLER ) { 03002 03003 SeFreePrivileges( Privileges ); 03004 Status = GetExceptionCode(); 03005 goto Cleanup; 03006 } 03007 03008 } 03009 SeFreePrivileges( Privileges ); 03010 03011 } else { 03012 03013 // 03014 // No privileges were used, construct an empty privilege set 03015 // 03016 03017 if ( LocalPrivilegeSetLength < sizeof(PRIVILEGE_SET) ) { 03018 03019 try { 03020 03021 *PrivilegeSetLength = sizeof(PRIVILEGE_SET); 03022 Status = STATUS_BUFFER_TOO_SMALL; 03023 03024 } except ( EXCEPTION_EXECUTE_HANDLER ) { 03025 03026 Status = GetExceptionCode(); 03027 } 03028 03029 goto Cleanup; 03030 } 03031 03032 try { 03033 03034 PrivilegeSet->PrivilegeCount = 0; 03035 PrivilegeSet->Control = 0; 03036 03037 } except ( EXCEPTION_EXECUTE_HANDLER ) { 03038 03039 Status = GetExceptionCode(); 03040 goto Cleanup; 03041 03042 } 03043 03044 } 03045 03046 // 03047 // Capture the PrincipalSelfSid. 03048 // 03049 03050 if ( PrincipalSelfSid != NULL ) { 03051 Status = SeCaptureSid( 03052 PrincipalSelfSid, 03053 PreviousMode, 03054 NULL, 0, 03055 PagedPool, 03056 TRUE, 03057 &CapturedPrincipalSelfSid ); 03058 03059 if (!NT_SUCCESS(Status)) { 03060 CapturedPrincipalSelfSid = NULL; 03061 goto Cleanup; 03062 } 03063 } 03064 03065 03066 // 03067 // Capture the passed security descriptor. 03068 // 03069 // SeCaptureSecurityDescriptor probes the input security descriptor, 03070 // so we don't have to 03071 // 03072 03073 Status = SeCaptureSecurityDescriptor ( 03074 SecurityDescriptor, 03075 PreviousMode, 03076 PagedPool, 03077 FALSE, 03078 &CapturedSecurityDescriptor 03079 ); 03080 03081 if (!NT_SUCCESS(Status)) { 03082 goto Cleanup; 03083 } 03084 03085 03086 // 03087 // If there's no security descriptor, then we've been 03088 // called without all the parameters we need. 03089 // Return invalid security descriptor. 03090 // 03091 03092 if ( CapturedSecurityDescriptor == NULL ) { 03093 Status = STATUS_INVALID_SECURITY_DESCR; 03094 goto Cleanup; 03095 } 03096 03097 // 03098 // A valid security descriptor must have an owner and a group 03099 // 03100 03101 if ( RtlpOwnerAddrSecurityDescriptor( 03102 (PISECURITY_DESCRIPTOR)CapturedSecurityDescriptor 03103 ) == NULL || 03104 RtlpGroupAddrSecurityDescriptor( 03105 (PISECURITY_DESCRIPTOR)CapturedSecurityDescriptor 03106 ) == NULL ) { 03107 03108 SeReleaseSecurityDescriptor ( 03109 CapturedSecurityDescriptor, 03110 PreviousMode, 03111 FALSE 03112 ); 03113 03114 Status = STATUS_INVALID_SECURITY_DESCR; 03115 goto Cleanup; 03116 } 03117 03118 03119 SeCaptureSubjectContext( &SubjectContext ); 03120 03121 SepAcquireTokenReadLock( Token ); 03122 03123 // 03124 // If the user in the token is the owner of the object, we 03125 // must automatically grant ReadControl and WriteDac access 03126 // if desired. If the DesiredAccess mask is empty after 03127 // these bits are turned off, we don't have to do any more 03128 // access checking (ref section 4, DSA ACL Arch) 03129 // 03130 03131 03132 if ( DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED) ) { 03133 03134 if (SepTokenIsOwner( Token, CapturedSecurityDescriptor, TRUE )) { 03135 03136 if ( DesiredAccess & MAXIMUM_ALLOWED ) { 03137 03138 PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL); 03139 03140 } else { 03141 03142 PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL)); 03143 } 03144 03145 DesiredAccess &= ~(WRITE_DAC | READ_CONTROL); 03146 } 03147 03148 } 03149 03150 if (DesiredAccess == 0) { 03151 03152 try { 03153 03154 03155 if ( ReturnResultList ) { 03156 for ( ResultListIndex=0; ResultListIndex<ObjectTypeListLength; ResultListIndex++ ) { 03157 AccessStatus[ResultListIndex] = STATUS_SUCCESS; 03158 GrantedAccess[ResultListIndex] = PreviouslyGrantedAccess; 03159 } 03160 03161 } else { 03162 *AccessStatus = STATUS_SUCCESS; 03163 *GrantedAccess = PreviouslyGrantedAccess; 03164 } 03165 Status = STATUS_SUCCESS; 03166 03167 } except (EXCEPTION_EXECUTE_HANDLER) { 03168 03169 Status = GetExceptionCode(); 03170 03171 } 03172 03173 SepReleaseTokenReadLock( Token ); 03174 03175 SeReleaseSubjectContext( &SubjectContext ); 03176 03177 SeReleaseSecurityDescriptor ( 03178 CapturedSecurityDescriptor, 03179 PreviousMode, 03180 FALSE 03181 ); 03182 03183 goto Cleanup; 03184 03185 } 03186 03187 03188 // 03189 // Finally, handle the case where we actually have to check the DACL. 03190 // 03191 03192 if ( ReturnResultList ) { 03193 LocalGrantedAccessPointer = 03194 ExAllocatePoolWithTag( PagedPool, (sizeof(ACCESS_MASK)+sizeof(NTSTATUS)) * ObjectTypeListLength, 'aGeS' ); 03195 03196 if (LocalGrantedAccessPointer == NULL) { 03197 03198 SepReleaseTokenReadLock( Token ); 03199 03200 SeReleaseSubjectContext( &SubjectContext ); 03201 03202 SeReleaseSecurityDescriptor ( 03203 CapturedSecurityDescriptor, 03204 PreviousMode, 03205 FALSE 03206 ); 03207 03208 Status = STATUS_INSUFFICIENT_RESOURCES; 03209 goto Cleanup; 03210 } 03211 LocalAccessStatusPointer = (PNTSTATUS)(LocalGrantedAccessPointer + ObjectTypeListLength); 03212 } else { 03213 LocalGrantedAccessPointer = &LocalGrantedAccess; 03214 LocalAccessStatusPointer = &LocalAccessStatus; 03215 } 03216 03217 SepAccessCheck ( 03218 CapturedSecurityDescriptor, 03219 CapturedPrincipalSelfSid, 03220 SubjectContext.PrimaryToken, 03221 Token, 03222 DesiredAccess, 03223 LocalObjectTypeList, 03224 ObjectTypeListLength, 03225 &LocalGenericMapping, 03226 PreviouslyGrantedAccess, 03227 PreviousMode, 03228 LocalGrantedAccessPointer, 03229 NULL, 03230 LocalAccessStatusPointer, 03231 ReturnResultList, 03232 NULL, 03233 NULL ); 03234 03235 SepReleaseTokenReadLock( Token ); 03236 03237 SeReleaseSubjectContext( &SubjectContext ); 03238 03239 SeReleaseSecurityDescriptor ( 03240 CapturedSecurityDescriptor, 03241 PreviousMode, 03242 FALSE 03243 ); 03244 03245 try { 03246 03247 if ( ReturnResultList ) { 03248 for ( ResultListIndex=0; ResultListIndex<ObjectTypeListLength; ResultListIndex++ ) { 03249 AccessStatus[ResultListIndex] = LocalAccessStatusPointer[ResultListIndex]; 03250 GrantedAccess[ResultListIndex] = LocalGrantedAccessPointer[ResultListIndex]; 03251 } 03252 03253 } else { 03254 *AccessStatus = *LocalAccessStatusPointer; 03255 *GrantedAccess = *LocalGrantedAccessPointer; 03256 } 03257 03258 Status = STATUS_SUCCESS; 03259 03260 } except (EXCEPTION_EXECUTE_HANDLER) { 03261 Status = GetExceptionCode(); 03262 } 03263 03264 if ( ReturnResultList ) { 03265 if ( LocalGrantedAccessPointer != NULL ) { 03266 ExFreePool( LocalGrantedAccessPointer ); 03267 } 03268 } 03269 03270 03271 // 03272 // Free locally used resources. 03273 // 03274 Cleanup: 03275 03276 if ( Token != NULL ) { 03277 ObDereferenceObject( Token ); 03278 } 03279 03280 if ( LocalObjectTypeList != NULL ) { 03281 SeFreeCapturedObjectTypeList( LocalObjectTypeList ); 03282 } 03283 03284 if (CapturedPrincipalSelfSid != NULL) { 03285 SeReleaseSid( CapturedPrincipalSelfSid, PreviousMode, TRUE); 03286 } 03287 03288 return Status; 03289 }

NTSTATUS SeCaptureObjectTypeList IN POBJECT_TYPE_LIST ObjectTypeList  OPTIONAL,
IN ULONG  ObjectTypeListLength,
IN KPROCESSOR_MODE  RequestorMode,
OUT PIOBJECT_TYPE_LIST CapturedObjectTypeList
 

Definition at line 144 of file accessck.c.

References _IOBJECT_TYPE_LIST::CurrentDenied, _IOBJECT_TYPE_LIST::CurrentGranted, ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), _IOBJECT_TYPE_LIST::Flags, IOBJECT_TYPE_LIST, IsValidElementCount, _IOBJECT_TYPE_LIST::Level, NTSTATUS(), NULL, _IOBJECT_TYPE_LIST::ObjectType, PAGED_CODE, PagedPool, _IOBJECT_TYPE_LIST::ParentIndex, ProbeForRead, _IOBJECT_TYPE_LIST::Remaining, Status, UserMode, and USHORT.

Referenced by SeAccessCheckByType(), and SepAccessCheckAndAuditAlarm().

00152 : 00153 00154 This routine probes and captures a copy of any object type list 00155 that might have been provided via the ObjectTypeList argument. 00156 00157 The object type list is converted to the internal form that explicitly 00158 specifies the hierarchical relationship between the entries. 00159 00160 The object typs list is validated to ensure a valid hierarchical 00161 relationship is represented. 00162 00163 Arguments: 00164 00165 ObjectTypeList - The object type list from which the type list 00166 information is to be retrieved. 00167 00168 ObjectTypeListLength - Number of elements in ObjectTypeList 00169 00170 RequestorMode - Indicates the processor mode by which the access 00171 is being requested. 00172 00173 CapturedObjectTypeList - Receives the captured type list which 00174 must be freed using SeFreeCapturedObjectTypeList(). 00175 00176 Return Value: 00177 00178 STATUS_SUCCESS indicates no exceptions were encountered. 00179 00180 Any access violations encountered will be returned. 00181 00182 --*/ 00183 00184 { 00185 NTSTATUS Status = STATUS_SUCCESS; 00186 ULONG i; 00187 PIOBJECT_TYPE_LIST LocalTypeList = NULL; 00188 00189 ULONG Levels[ACCESS_MAX_LEVEL+1]; 00190 00191 PAGED_CODE(); 00192 00193 // 00194 // Set default return 00195 // 00196 00197 *CapturedObjectTypeList = NULL; 00198 00199 if (RequestorMode != UserMode) { 00200 return STATUS_NOT_IMPLEMENTED; 00201 } 00202 00203 try { 00204 00205 if ( ObjectTypeListLength == 0 ) { 00206 00207 // Drop through 00208 00209 } else if ( !ARGUMENT_PRESENT(ObjectTypeList) ) { 00210 00211 Status = STATUS_INVALID_PARAMETER; 00212 00213 } else { 00214 00215 if ( !IsValidElementCount( ObjectTypeListLength, IOBJECT_TYPE_LIST ) ) 00216 { 00217 Status = STATUS_INVALID_PARAMETER ; 00218 00219 // 00220 // No more to do, get out of the try statement: 00221 // 00222 00223 leave ; 00224 } 00225 00226 ProbeForRead( ObjectTypeList, 00227 sizeof(OBJECT_TYPE_LIST) * ObjectTypeListLength, 00228 sizeof(ULONG) 00229 ); 00230 00231 // 00232 // Allocate a buffer to copy into. 00233 // 00234 00235 LocalTypeList = ExAllocatePoolWithTag( PagedPool, sizeof(IOBJECT_TYPE_LIST) * ObjectTypeListLength, 'tOeS' ); 00236 00237 if ( LocalTypeList == NULL ) { 00238 Status = STATUS_INSUFFICIENT_RESOURCES; 00239 00240 // 00241 // Copy the callers structure to the local structure. 00242 // 00243 00244 } else { 00245 GUID * CapturedObjectType; 00246 for ( i=0; i<ObjectTypeListLength; i++ ) { 00247 USHORT CurrentLevel; 00248 00249 // 00250 // Limit ourselves 00251 // 00252 CurrentLevel = ObjectTypeList[i].Level; 00253 if ( CurrentLevel > ACCESS_MAX_LEVEL ) { 00254 Status = STATUS_INVALID_PARAMETER; 00255 break; 00256 } 00257 00258 // 00259 // Copy data the caller passed in 00260 // 00261 LocalTypeList[i].Level = CurrentLevel; 00262 LocalTypeList[i].Flags = 0; 00263 CapturedObjectType = ObjectTypeList[i].ObjectType; 00264 ProbeForRead( 00265 CapturedObjectType, 00266 sizeof(GUID), 00267 sizeof(ULONG) 00268 ); 00269 LocalTypeList[i].ObjectType = *CapturedObjectType; 00270 LocalTypeList[i].Remaining = 0; 00271 LocalTypeList[i].CurrentGranted = 0; 00272 LocalTypeList[i].CurrentDenied = 0; 00273 00274 // 00275 // Ensure that the level number is consistent with the 00276 // level number of the previous entry. 00277 // 00278 00279 if ( i == 0 ) { 00280 if ( CurrentLevel != 0 ) { 00281 Status = STATUS_INVALID_PARAMETER; 00282 break; 00283 } 00284 00285 } else { 00286 00287 // 00288 // The previous entry is either: 00289 // my immediate parent, 00290 // my sibling, or 00291 // the child (or grandchild, etc.) of my sibling. 00292 // 00293 if ( CurrentLevel > LocalTypeList[i-1].Level + 1 ) { 00294 Status = STATUS_INVALID_PARAMETER; 00295 break; 00296 } 00297 00298 // 00299 // Don't support two roots. 00300 // 00301 if ( CurrentLevel == 0 ) { 00302 Status = STATUS_INVALID_PARAMETER; 00303 break; 00304 } 00305 00306 } 00307 00308 // 00309 // If the above rules are maintained, 00310 // then my parent object is the last object seen that 00311 // has a level one less than mine. 00312 // 00313 00314 if ( CurrentLevel == 0 ) { 00315 LocalTypeList[i].ParentIndex = -1; 00316 } else { 00317 LocalTypeList[i].ParentIndex = Levels[CurrentLevel-1]; 00318 } 00319 00320 // 00321 // Save this obect as the last object seen at this level. 00322 // 00323 00324 Levels[CurrentLevel] = i; 00325 00326 } 00327 00328 } 00329 00330 } // end_if 00331 00332 } except(EXCEPTION_EXECUTE_HANDLER) { 00333 00334 00335 // 00336 // If we captured any proxy data, we need to free it now. 00337 // 00338 00339 if ( LocalTypeList != NULL ) { 00340 ExFreePool( LocalTypeList ); 00341 LocalTypeList = NULL; 00342 } 00343 00344 Status = GetExceptionCode(); 00345 } // end_try 00346 00347 *CapturedObjectTypeList = LocalTypeList; 00348 return Status; 00349 }

BOOLEAN SeFastTraverseCheck PSECURITY_DESCRIPTOR  SecurityDescriptor,
ACCESS_MASK  TraverseAccess,
KPROCESSOR_MODE  AccessMode
 

Definition at line 3871 of file accessck.c.

References Dacl, FALSE, FirstAce, KernelMode, NextAce, NULL, PAGED_CODE, RtlEqualSid(), SeWorldSid, and TRUE.

Referenced by IopParseDevice(), ObpCheckTraverseAccess(), ObpProcessDosDeviceSymbolicLink(), and ObSetSecurityDescriptorInfo().

03878 : 03879 03880 This routine will examine the DACL of the passed Security Descriptor 03881 to see if WORLD has Traverse access. If so, no further access checking 03882 is necessary. 03883 03884 Note that the SubjectContext for the client process does not have 03885 to be locked to make this call, since it does not examine any data 03886 structures in the Token. 03887 03888 Arguments: 03889 03890 SecurityDescriptor - The Security Descriptor protecting the container 03891 object being traversed. 03892 03893 TraverseAccess - Access mask describing Traverse access for this 03894 object type. 03895 03896 AccessMode - Supplies the access mode to be used in the check 03897 03898 03899 Return Value: 03900 03901 TRUE - WORLD has Traverse access to this container. FALSE 03902 otherwise. 03903 03904 --*/ 03905 03906 { 03907 PACL Dacl; 03908 ULONG i; 03909 PVOID Ace; 03910 ULONG AceCount; 03911 03912 PAGED_CODE(); 03913 03914 if ( AccessMode == KernelMode ) { 03915 return( TRUE ); 03916 } 03917 03918 if (SecurityDescriptor == NULL) { 03919 return( FALSE ); 03920 } 03921 03922 // 03923 // See if there is a valid DACL in the passed Security Descriptor. 03924 // No DACL, no security, all is granted. 03925 // 03926 03927 Dacl = RtlpDaclAddrSecurityDescriptor( (PISECURITY_DESCRIPTOR)SecurityDescriptor ); 03928 03929 // 03930 // If the SE_DACL_PRESENT bit is not set, the object has no 03931 // security, so all accesses are granted. 03932 // 03933 // Also grant all access if the Dacl is NULL. 03934 // 03935 03936 if ( !RtlpAreControlBitsSet( 03937 (PISECURITY_DESCRIPTOR)SecurityDescriptor, SE_DACL_PRESENT 03938 ) 03939 || (Dacl == NULL)) { 03940 03941 return(TRUE); 03942 } 03943 03944 // 03945 // There is security on this object. If the DACL is empty, 03946 // deny all access immediately 03947 // 03948 03949 if ((AceCount = Dacl->AceCount) == 0) { 03950 03951 return( FALSE ); 03952 } 03953 03954 // 03955 // There's stuff in the DACL, walk down the list and see 03956 // if WORLD has been granted TraverseAccess 03957 // 03958 03959 for ( i = 0, Ace = FirstAce( Dacl ) ; 03960 i < AceCount ; 03961 i++, Ace = NextAce( Ace ) 03962 ) { 03963 03964 if ( !(((PACE_HEADER)Ace)->AceFlags & INHERIT_ONLY_ACE)) { 03965 03966 if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_ACE_TYPE) ) { 03967 03968 if ( (TraverseAccess & ((PACCESS_ALLOWED_ACE)Ace)->Mask) ) { 03969 03970 if ( RtlEqualSid( SeWorldSid, &((PACCESS_ALLOWED_ACE)Ace)->SidStart ) ) { 03971 03972 return( TRUE ); 03973 } 03974 } 03975 03976 } else { 03977 03978 if ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_ACE_TYPE) ) { 03979 03980 if ( (TraverseAccess & ((PACCESS_DENIED_ACE)Ace)->Mask) ) { 03981 03982 if ( RtlEqualSid( SeWorldSid, &((PACCESS_DENIED_ACE)Ace)->SidStart ) ) { 03983 03984 return( FALSE ); 03985 } 03986 } 03987 } 03988 } 03989 } 03990 } 03991 03992 return( FALSE ); 03993 } }

VOID SeFreeCapturedObjectTypeList IN PVOID  ObjectTypeList  ) 
 

Definition at line 353 of file accessck.c.

References ExFreePool(), NULL, and PAGED_CODE.

Referenced by SeAccessCheckByType(), and SepAccessCheckAndAuditAlarm().

00359 : 00360 00361 This routine frees the data associated with a captured ObjectTypeList 00362 structure. 00363 00364 Arguments: 00365 00366 ObjectTypeList - Points to a captured object type list structure. 00367 00368 Return Value: 00369 00370 None. 00371 00372 --*/ 00373 00374 { 00375 PAGED_CODE(); 00376 00377 if ( ObjectTypeList != NULL ) { 00378 ExFreePool( ObjectTypeList ); 00379 } 00380 00381 return; 00382 }

VOID SeFreePrivileges IN PPRIVILEGE_SET  Privileges  ) 
 

Definition at line 3294 of file accessck.c.

References ExFreePool(), and PAGED_CODE.

Referenced by IopParseDevice(), ObCheckCreateObjectAccess(), ObCheckObjectAccess(), ObpCheckTraverseAccess(), and SeAccessCheckByType().

03300 : 03301 03302 This routine frees a privilege set returned by SeAccessCheck. 03303 03304 Arguments: 03305 03306 Privileges - Supplies a pointer to the privilege set to be freed. 03307 03308 Return Value: 03309 03310 None. 03311 03312 --*/ 03313 03314 { 03315 PAGED_CODE(); 03316 03317 ExFreePool( Privileges ); 03318 }

VOID SepAccessCheck IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN PSID  PrincipalSelfSid,
IN PTOKEN  PrimaryToken,
IN PTOKEN ClientToken  OPTIONAL,
IN ACCESS_MASK  DesiredAccess,
IN PIOBJECT_TYPE_LIST ObjectTypeList  OPTIONAL,
IN ULONG  ObjectTypeListLength,
IN PGENERIC_MAPPING  GenericMapping,
IN ACCESS_MASK  PreviouslyGrantedAccess,
IN KPROCESSOR_MODE  PreviousMode,
OUT PACCESS_MASK  GrantedAccess,
OUT PPRIVILEGE_SET *Privileges  OPTIONAL,
OUT PNTSTATUS  AccessStatus,
IN BOOLEAN  ReturnResultList,
OUT PBOOLEAN  ReturnSomeAccessGranted,
OUT PBOOLEAN  ReturnSomeAccessDenied
 

Definition at line 1564 of file accessck.c.

References ASSERT, ClientToken, _IOBJECT_TYPE_LIST::CurrentGranted, Dacl, FALSE, FirstAce, Index, NextAce, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PrimaryToken, PTOKEN, _IOBJECT_TYPE_LIST::Remaining, SeAssertMappedCanonicalAccess, SepAddAccessTypeList(), SepAssemblePrivileges(), SepDumpSecurityDescriptor(), SepDumpTokenInfo(), SepMaximumAccessCheck(), SepNormalAccessCheck(), SepObjectInTypeList(), SepSidInToken(), SepSinglePrivilegeCheck(), SeSecurityPrivilege, SeTakeOwnershipPrivilege, SeTokenIsRestricted(), Status, TRUE, and UpdateRemaining.

Referenced by SeAccessCheck(), SeAccessCheckByType(), and SepAccessCheckAndAuditAlarm().

01585 : 01586 01587 Worker routine for SeAccessCheck and NtAccessCheck. We actually do the 01588 access checking here. 01589 01590 Whether or not we actually evaluate the DACL is based on the following 01591 interaction between the SE_DACL_PRESENT bit in the security descriptor 01592 and the value of the DACL pointer itself. 01593 01594 01595 SE_DACL_PRESENT 01596 01597 SET CLEAR 01598 01599 +-------------+-------------+ 01600 | | | 01601 NULL | GRANT | GRANT | 01602 | ALL | ALL | 01603 DACL | | | 01604 Pointer +-------------+-------------+ 01605 | | | 01606 !NULL | EVALUATE | GRANT | 01607 | ACL | ALL | 01608 | | | 01609 +-------------+-------------+ 01610 01611 Arguments: 01612 01613 SecurityDescriptor - Pointer to the security descriptor from the object 01614 being accessed. 01615 01616 PrincipalSelfSid - If the object being access checked is an object which 01617 represents a principal (e.g., a user object), this parameter should 01618 be the SID of the object. Any ACE containing the constant 01619 PRINCIPAL_SELF_SID is replaced by this SID. 01620 01621 The parameter should be NULL if the object does not represent a principal. 01622 01623 Token - Pointer to user's token object. 01624 01625 TokenLocked - Boolean describing whether or not there is a read lock 01626 on the token. 01627 01628 DesiredAccess - Access mask describing the user's desired access to the 01629 object. This mask is assumed not to contain generic access types. 01630 01631 ObjectTypeList - Supplies a list of GUIDs representing the object (and 01632 sub-objects) being accessed. If no list is present, AccessCheckByType 01633 behaves identically to AccessCheck. 01634 01635 ObjectTypeListLength - Specifies the number of elements in the ObjectTypeList. 01636 01637 GenericMapping - Supplies a pointer to the generic mapping associated 01638 with this object type. 01639 01640 PreviouslyGrantedAccess - Access mask indicating any access' that have 01641 already been granted by higher level routines 01642 01643 PrivilgedAccessMask - Mask describing access types that may not be 01644 granted without a privilege. 01645 01646 GrantedAccess - Returns an access mask describing all granted access', 01647 or NULL. 01648 01649 Privileges - Optionally supplies a pointer in which will be returned 01650 any privileges that were used for the access. If this is null, 01651 it will be assumed that privilege checks have been done already. 01652 01653 AccessStatus - Returns STATUS_SUCCESS or other error code to be 01654 propogated back to the caller 01655 01656 ReturnResultList - If true, GrantedAccess and AccessStatus is actually 01657 an array of entries ObjectTypeListLength elements long. 01658 01659 ReturnSomeAccessGranted - Returns a value of TRUE to indicate that some access' 01660 were granted, FALSE otherwise. 01661 01662 ReturnSomeAccessDenied - Returns a value of FALSE if some of the requested 01663 access was not granted. This will alway be an inverse of SomeAccessGranted 01664 unless ReturnResultList is TRUE. In that case, 01665 01666 Return Value: 01667 01668 A value of TRUE indicates that some access' were granted, FALSE 01669 otherwise. 01670 01671 --*/ 01672 { 01673 NTSTATUS Status; 01674 ACCESS_MASK Remaining; 01675 01676 01677 PACL Dacl; 01678 01679 PVOID Ace; 01680 ULONG AceCount; 01681 01682 ULONG i; 01683 ULONG j; 01684 ULONG Index; 01685 ULONG PrivilegeCount = 0; 01686 BOOLEAN Success = FALSE; 01687 BOOLEAN SystemSecurity = FALSE; 01688 BOOLEAN WriteOwner = FALSE; 01689 PTOKEN EToken; 01690 01691 IOBJECT_TYPE_LIST FixedTypeList; 01692 PIOBJECT_TYPE_LIST LocalTypeList; 01693 ULONG LocalTypeListLength; 01694 ULONG ResultListIndex; 01695 01696 PAGED_CODE(); 01697 01698 #if DBG 01699 01700 SepDumpSecurityDescriptor( 01701 SecurityDescriptor, 01702 "Input to SeAccessCheck\n" 01703 ); 01704 01705 if (ARGUMENT_PRESENT( ClientToken )) { 01706 SepDumpTokenInfo( ClientToken ); 01707 } 01708 01709 SepDumpTokenInfo( PrimaryToken ); 01710 01711 #endif 01712 01713 01714 EToken = ARGUMENT_PRESENT( ClientToken ) ? ClientToken : PrimaryToken; 01715 01716 // 01717 // Assert that there are no generic accesses in the DesiredAccess 01718 // 01719 01720 SeAssertMappedCanonicalAccess( DesiredAccess ); 01721 01722 Remaining = DesiredAccess; 01723 01724 01725 // 01726 // Check for ACCESS_SYSTEM_SECURITY here, 01727 // fail if he's asking for it and doesn't have 01728 // the privilege. 01729 // 01730 01731 if ( Remaining & ACCESS_SYSTEM_SECURITY ) { 01732 01733 // 01734 // Bugcheck if we weren't given a pointer to return privileges 01735 // into. Our caller was supposed to have taken care of this 01736 // in that case. 01737 // 01738 01739 ASSERT( ARGUMENT_PRESENT( Privileges )); 01740 01741 Success = SepSinglePrivilegeCheck ( 01742 SeSecurityPrivilege, 01743 EToken, 01744 PreviousMode 01745 ); 01746 01747 if (!Success) { 01748 PreviouslyGrantedAccess = 0; 01749 Status = STATUS_PRIVILEGE_NOT_HELD; 01750 goto ReturnOneStatus; 01751 } 01752 01753 // 01754 // Success, remove ACCESS_SYSTEM_SECURITY from remaining, add it 01755 // to PreviouslyGrantedAccess 01756 // 01757 01758 Remaining &= ~ACCESS_SYSTEM_SECURITY; 01759 PreviouslyGrantedAccess |= ACCESS_SYSTEM_SECURITY; 01760 01761 PrivilegeCount++; 01762 SystemSecurity = TRUE; 01763 01764 if ( Remaining == 0 ) { 01765 Status = STATUS_SUCCESS; 01766 goto ReturnOneStatus; 01767 } 01768 01769 } 01770 01771 01772 // 01773 // Get pointer to client SID's 01774 // 01775 01776 Dacl = RtlpDaclAddrSecurityDescriptor( (PISECURITY_DESCRIPTOR)SecurityDescriptor ); 01777 01778 // 01779 // If the SE_DACL_PRESENT bit is not set, the object has no 01780 // security, so all accesses are granted. If he's asking for 01781 // MAXIMUM_ALLOWED, return the GENERIC_ALL field from the generic 01782 // mapping. 01783 // 01784 // Also grant all access if the Dacl is NULL. 01785 // 01786 01787 if ( !RtlpAreControlBitsSet( 01788 (PISECURITY_DESCRIPTOR)SecurityDescriptor, 01789 SE_DACL_PRESENT) || (Dacl == NULL)) { 01790 01791 01792 // 01793 // Restricted tokens treat a NULL dacl the same as a DACL with no 01794 // ACEs. 01795 // 01796 #ifdef SECURE_NULL_DACLS 01797 if (SeTokenIsRestricted( EToken )) { 01798 // 01799 // We know that Remaining != 0 here, because we 01800 // know it was non-zero coming into this routine, 01801 // and we've checked it against 0 every time we've 01802 // cleared a bit. 01803 // 01804 01805 ASSERT( Remaining != 0 ); 01806 01807 // 01808 // There are ungranted accesses. Since there is 01809 // nothing in the DACL, they will not be granted. 01810 // If, however, the only ungranted access at this 01811 // point is MAXIMUM_ALLOWED, and something has been 01812 // granted in the PreviouslyGranted mask, return 01813 // what has been granted. 01814 // 01815 01816 if ( (Remaining == MAXIMUM_ALLOWED) && (PreviouslyGrantedAccess != (ACCESS_MASK)0) ) { 01817 Status = STATUS_SUCCESS; 01818 goto ReturnOneStatus; 01819 01820 } else { 01821 PreviouslyGrantedAccess = 0; 01822 Status = STATUS_ACCESS_DENIED; 01823 goto ReturnOneStatus; 01824 } 01825 } 01826 #endif //SECURE_NULL_DACLS 01827 if (DesiredAccess & MAXIMUM_ALLOWED) { 01828 01829 // 01830 // Give him: 01831 // GenericAll 01832 // Anything else he asked for 01833 // 01834 01835 PreviouslyGrantedAccess = 01836 GenericMapping->GenericAll | 01837 (DesiredAccess | PreviouslyGrantedAccess) & ~MAXIMUM_ALLOWED; 01838 01839 } else { 01840 01841 PreviouslyGrantedAccess |= DesiredAccess; 01842 } 01843 01844 Status = STATUS_SUCCESS; 01845 goto ReturnOneStatus; 01846 } 01847 01848 // 01849 // There is security on this object. Check to see 01850 // if he's asking for WRITE_OWNER, and perform the 01851 // privilege check if so. 01852 // 01853 01854 if ( (Remaining & WRITE_OWNER) && ARGUMENT_PRESENT( Privileges ) ) { 01855 01856 Success = SepSinglePrivilegeCheck ( 01857 SeTakeOwnershipPrivilege, 01858 EToken, 01859 PreviousMode 01860 ); 01861 01862 if (Success) { 01863 01864 // 01865 // Success, remove WRITE_OWNER from remaining, add it 01866 // to PreviouslyGrantedAccess 01867 // 01868 01869 Remaining &= ~WRITE_OWNER; 01870 PreviouslyGrantedAccess |= WRITE_OWNER; 01871 01872 PrivilegeCount++; 01873 WriteOwner = TRUE; 01874 01875 if ( Remaining == 0 ) { 01876 Status = STATUS_SUCCESS; 01877 goto ReturnOneStatus; 01878 } 01879 } 01880 } 01881 01882 01883 // 01884 // If the DACL is empty, 01885 // deny all access immediately. 01886 // 01887 01888 if ((AceCount = Dacl->AceCount) == 0) { 01889 01890 // 01891 // We know that Remaining != 0 here, because we 01892 // know it was non-zero coming into this routine, 01893 // and we've checked it against 0 every time we've 01894 // cleared a bit. 01895 // 01896 01897 ASSERT( Remaining != 0 ); 01898 01899 // 01900 // There are ungranted accesses. Since there is 01901 // nothing in the DACL, they will not be granted. 01902 // If, however, the only ungranted access at this 01903 // point is MAXIMUM_ALLOWED, and something has been 01904 // granted in the PreviouslyGranted mask, return 01905 // what has been granted. 01906 // 01907 01908 if ( (Remaining == MAXIMUM_ALLOWED) && (PreviouslyGrantedAccess != (ACCESS_MASK)0) ) { 01909 Status = STATUS_SUCCESS; 01910 goto ReturnOneStatus; 01911 01912 } else { 01913 PreviouslyGrantedAccess = 0; 01914 Status = STATUS_ACCESS_DENIED; 01915 goto ReturnOneStatus; 01916 } 01917 } 01918 01919 // 01920 // Fake out a top level ObjectType list if none is passed by the caller. 01921 // 01922 01923 if ( ObjectTypeListLength == 0 ) { 01924 LocalTypeList = &FixedTypeList; 01925 LocalTypeListLength = 1; 01926 RtlZeroMemory( &FixedTypeList, sizeof(FixedTypeList) ); 01927 FixedTypeList.ParentIndex = -1; 01928 } else { 01929 LocalTypeList = ObjectTypeList; 01930 LocalTypeListLength = ObjectTypeListLength; 01931 } 01932 01933 // 01934 // If the caller wants the MAXIMUM_ALLOWED or the caller wants the 01935 // results on all objects and subobjects, use a slower algorithm 01936 // that traverses all the ACEs. 01937 // 01938 01939 if ( (DesiredAccess & MAXIMUM_ALLOWED) != 0 || 01940 ReturnResultList ) { 01941 01942 // 01943 // Do the normal maximum-allowed access check 01944 // 01945 01946 SepMaximumAccessCheck( 01947 EToken, 01948 PrimaryToken, 01949 Dacl, 01950 PrincipalSelfSid, 01951 LocalTypeListLength, 01952 LocalTypeList, 01953 ObjectTypeListLength, 01954 FALSE 01955 ); 01956 01957 // 01958 // If this is a restricted token, do the additional access check 01959 // 01960 01961 if (SeTokenIsRestricted( EToken ) ) { 01962 SepMaximumAccessCheck( 01963 EToken, 01964 PrimaryToken, 01965 Dacl, 01966 PrincipalSelfSid, 01967 LocalTypeListLength, 01968 LocalTypeList, 01969 ObjectTypeListLength, 01970 TRUE 01971 ); 01972 } 01973 01974 01975 // 01976 // If the caller wants to know the individual results of each sub-object, 01977 // sub-object, 01978 // break it down for him. 01979 // 01980 01981 if ( ReturnResultList ) { 01982 ACCESS_MASK GrantedAccessMask; 01983 ACCESS_MASK RequiredAccessMask; 01984 BOOLEAN SomeAccessGranted = FALSE; 01985 BOOLEAN SomeAccessDenied = FALSE; 01986 01987 // 01988 // Compute mask of Granted access bits to tell the caller about. 01989 // If he asked for MAXIMUM_ALLOWED, 01990 // tell him everything, 01991 // otherwise 01992 // tell him what he asked about. 01993 // 01994 01995 if (DesiredAccess & MAXIMUM_ALLOWED) { 01996 GrantedAccessMask = (ACCESS_MASK) ~MAXIMUM_ALLOWED; 01997 RequiredAccessMask = (DesiredAccess | PreviouslyGrantedAccess) & ~MAXIMUM_ALLOWED; 01998 } else { 01999 GrantedAccessMask = DesiredAccess | PreviouslyGrantedAccess; 02000 RequiredAccessMask = DesiredAccess | PreviouslyGrantedAccess; 02001 } 02002 02003 02004 02005 02006 // 02007 // Loop computing the access granted to each object and sub-object. 02008 // 02009 for ( ResultListIndex=0; 02010 ResultListIndex<LocalTypeListLength; 02011 ResultListIndex++ ) { 02012 02013 // 02014 // Return the subset of the access granted that the caller 02015 // expressed interest in. 02016 // 02017 02018 GrantedAccess[ResultListIndex] = 02019 (LocalTypeList[ResultListIndex].CurrentGranted | 02020 PreviouslyGrantedAccess ) & 02021 GrantedAccessMask; 02022 02023 // 02024 // If absolutely no access was granted, 02025 // indicate so. 02026 // 02027 if ( GrantedAccess[ResultListIndex] == 0 ) { 02028 AccessStatus[ResultListIndex] = STATUS_ACCESS_DENIED; 02029 SomeAccessDenied = TRUE; 02030 } else { 02031 02032 // 02033 // If some requested access is still missing, 02034 // the bottom line is that access is denied. 02035 // 02036 // Note, that ByTypeResultList actually returns the 02037 // partially granted access mask even though the caller 02038 // really has no access to the object. 02039 // 02040 02041 if ( ((~GrantedAccess[ResultListIndex]) & RequiredAccessMask ) != 0 ) { 02042 AccessStatus[ResultListIndex] = STATUS_ACCESS_DENIED; 02043 SomeAccessDenied = TRUE; 02044 } else { 02045 AccessStatus[ResultListIndex] = STATUS_SUCCESS; 02046 SomeAccessGranted = TRUE; 02047 } 02048 } 02049 } 02050 02051 if ( SomeAccessGranted && PrivilegeCount != 0 ) { 02052 02053 SepAssemblePrivileges( 02054 PrivilegeCount, 02055 SystemSecurity, 02056 WriteOwner, 02057 Privileges 02058 ); 02059 } 02060 02061 if ( ARGUMENT_PRESENT(ReturnSomeAccessGranted)) { 02062 *ReturnSomeAccessGranted = SomeAccessGranted; 02063 } 02064 if ( ARGUMENT_PRESENT(ReturnSomeAccessDenied)) { 02065 *ReturnSomeAccessDenied = SomeAccessDenied; 02066 } 02067 return; 02068 02069 // 02070 // If the caller is only interested in the access to the object itself, 02071 // just summarize. 02072 // 02073 02074 } else { 02075 02076 // 02077 // Turn off the MAXIMUM_ALLOWED bit and whatever we found that 02078 // he was granted. If the user passed in extra bits in addition 02079 // to MAXIMUM_ALLOWED, make sure that he was granted those access 02080 // types. If not, he didn't get what he wanted, so return failure. 02081 // 02082 02083 Remaining &= ~(MAXIMUM_ALLOWED | LocalTypeList->CurrentGranted); 02084 02085 if (Remaining != 0) { 02086 02087 Status = STATUS_ACCESS_DENIED; 02088 PreviouslyGrantedAccess = 0; 02089 goto ReturnOneStatus; 02090 02091 } 02092 02093 02094 02095 PreviouslyGrantedAccess |= LocalTypeList->CurrentGranted; 02096 Status = STATUS_SUCCESS; 02097 goto ReturnOneStatus; 02098 02099 } 02100 02101 } // if MAXIMUM_ALLOWED... 02102 02103 02104 #ifdef notdef 02105 // 02106 // The remaining bits are "remaining" at all levels 02107 02108 for ( j=0; j<LocalTypeListLength; j++ ) { 02109 LocalTypeList[j].Remaining = Remaining; 02110 } 02111 02112 // 02113 // Process the DACL handling individual access bits. 02114 // 02115 02116 for ( i = 0, Ace = FirstAce( Dacl ) ; 02117 ( i < AceCount ) && ( LocalTypeList->Remaining != 0 ) ; 02118 i++, Ace = NextAce( Ace ) ) { 02119 02120 if ( !(((PACE_HEADER)Ace)->AceFlags & INHERIT_ONLY_ACE)) { 02121 02122 // 02123 // Handle an Access Allowed ACE 02124 // 02125 02126 if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_ACE_TYPE) ) { 02127 02128 if ( SepSidInToken( EToken, PrincipalSelfSid, &((PACCESS_ALLOWED_ACE)Ace)->SidStart, FALSE ) ) { 02129 02130 // Optimize 'normal' case 02131 if ( LocalTypeListLength == 1 ) { 02132 LocalTypeList->Remaining &= ~((PACCESS_ALLOWED_ACE)Ace)->Mask; 02133 } else { 02134 // 02135 // The zeroeth object type represents the object itself. 02136 // 02137 SepAddAccessTypeList( 02138 LocalTypeList, // List to modify 02139 LocalTypeListLength, // Length of list 02140 0, // Element to update 02141 ((PACCESS_ALLOWED_ACE)Ace)->Mask, // Access Granted 02142 UpdateRemaining ); 02143 } 02144 02145 } 02146 02147 02148 // 02149 // Handle an object specific Access Allowed ACE 02150 // 02151 } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE) ) { 02152 GUID *ObjectTypeInAce; 02153 02154 // 02155 // If no object type is in the ACE, 02156 // treat this as an ACCESS_ALLOWED_ACE. 02157 // 02158 02159 ObjectTypeInAce = RtlObjectAceObjectType(Ace); 02160 02161 if ( ObjectTypeInAce == NULL ) { 02162 02163 if ( SepSidInToken( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), FALSE ) ) { 02164 02165 // Optimize 'normal' case 02166 if ( LocalTypeListLength == 1 ) { 02167 LocalTypeList->Remaining &= ~((PACCESS_ALLOWED_ACE)Ace)->Mask; 02168 } else { 02169 SepAddAccessTypeList( 02170 LocalTypeList, // List to modify 02171 LocalTypeListLength, // Length of list 02172 0, // Element to update 02173 ((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask, // Access Granted 02174 UpdateRemaining ); 02175 } 02176 } 02177 02178 // 02179 // If no object type list was passed, 02180 // don't grant access to anyone. 02181 // 02182 02183 } else if ( ObjectTypeListLength == 0 ) { 02184 02185 // Drop through 02186 02187 02188 // 02189 // If an object type is in the ACE, 02190 // Find it in the LocalTypeList before using the ACE. 02191 // 02192 } else { 02193 02194 if ( SepSidInToken( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), FALSE ) ) { 02195 02196 if ( SepObjectInTypeList( ObjectTypeInAce, 02197 LocalTypeList, 02198 LocalTypeListLength, 02199 &Index ) ) { 02200 SepAddAccessTypeList( 02201 LocalTypeList, // List to modify 02202 LocalTypeListLength, // Length of list 02203 Index, // Element already updated 02204 ((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask, // Access Granted 02205 UpdateRemaining ); 02206 } 02207 } 02208 } 02209 02210 02211 // 02212 // Handle a compound Access Allowed ACE 02213 // 02214 } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE) ) { 02215 02216 // 02217 // See comment in MAXIMUM_ALLOWED case as to why we can use EToken here 02218 // for the client. 02219 // 02220 02221 if ( SepSidInToken(EToken, PrincipalSelfSid, RtlCompoundAceClientSid( Ace ), FALSE) && 02222 SepSidInToken(PrimaryToken, NULL, RtlCompoundAceServerSid( Ace ), FALSE) ) { 02223 02224 // Optimize 'normal' case 02225 if ( LocalTypeListLength == 1 ) { 02226 LocalTypeList->Remaining &= ~((PCOMPOUND_ACCESS_ALLOWED_ACE)Ace)->Mask; 02227 } else { 02228 SepAddAccessTypeList( 02229 LocalTypeList, // List to modify 02230 LocalTypeListLength, // Length of list 02231 0, // Element to update 02232 ((PCOMPOUND_ACCESS_ALLOWED_ACE)Ace)->Mask, // Access Granted 02233 UpdateRemaining ); 02234 } 02235 } 02236 02237 02238 02239 // 02240 // Handle an Access Denied ACE 02241 // 02242 02243 } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_ACE_TYPE) ) { 02244 02245 if ( SepSidInToken( EToken, PrincipalSelfSid, &((PACCESS_DENIED_ACE)Ace)->SidStart, TRUE ) ) { 02246 02247 // 02248 // The zeroeth element represents the object itself. 02249 // Just check that element. 02250 // 02251 if (LocalTypeList->Remaining & ((PACCESS_DENIED_ACE)Ace)->Mask) { 02252 02253 break; 02254 } 02255 } 02256 02257 02258 // 02259 // Handle an object specific Access Denied ACE 02260 // 02261 } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_OBJECT_ACE_TYPE) ) { 02262 02263 if ( SepSidInToken( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), TRUE ) ) { 02264 GUID *ObjectTypeInAce; 02265 02266 // 02267 // If there is no object type in the ACE, 02268 // or if the caller didn't specify an object type list, 02269 // apply this deny ACE to the entire object. 02270 // 02271 02272 ObjectTypeInAce = RtlObjectAceObjectType(Ace); 02273 if ( ObjectTypeInAce == NULL || 02274 ObjectTypeListLength == 0 ) { 02275 02276 // 02277 // The zeroeth element represents the object itself. 02278 // Just check that element. 02279 // 02280 if (LocalTypeList->Remaining & ((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask) { 02281 break; 02282 } 02283 02284 // 02285 // Otherwise apply the deny ACE to the object specified 02286 // in the ACE. 02287 // 02288 02289 } else if ( SepObjectInTypeList( ObjectTypeInAce, 02290 LocalTypeList, 02291 LocalTypeListLength, 02292 &Index ) ) { 02293 02294 if (LocalTypeList[Index].Remaining & ((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask) { 02295 break; 02296 } 02297 02298 } 02299 } 02300 } 02301 02302 } 02303 } 02304 02305 #endif 02306 02307 // 02308 // Do the normal access check first 02309 // 02310 02311 SepNormalAccessCheck( 02312 Remaining, 02313 EToken, 02314 PrimaryToken, 02315 Dacl, 02316 PrincipalSelfSid, 02317 LocalTypeListLength, 02318 LocalTypeList, 02319 ObjectTypeListLength, 02320 FALSE 02321 ); 02322 02323 if (LocalTypeList->Remaining != 0) { 02324 Status = STATUS_ACCESS_DENIED; 02325 PreviouslyGrantedAccess = 0; 02326 goto ReturnOneStatus; 02327 } 02328 02329 // 02330 // If this is a restricted token, do the additional access check 02331 // 02332 02333 if (SeTokenIsRestricted( EToken ) ) { 02334 SepNormalAccessCheck( 02335 Remaining, 02336 EToken, 02337 PrimaryToken, 02338 Dacl, 02339 PrincipalSelfSid, 02340 LocalTypeListLength, 02341 LocalTypeList, 02342 ObjectTypeListLength, 02343 TRUE 02344 ); 02345 } 02346 02347 02348 if (LocalTypeList->Remaining != 0) { 02349 Status = STATUS_ACCESS_DENIED; 02350 PreviouslyGrantedAccess = 0; 02351 goto ReturnOneStatus; 02352 } 02353 02354 Status = STATUS_SUCCESS; 02355 PreviouslyGrantedAccess |= DesiredAccess; 02356 02357 // 02358 // Return a single status code to the caller. 02359 // 02360 02361 ReturnOneStatus: 02362 if ( Status == STATUS_SUCCESS && PreviouslyGrantedAccess == 0 ) { 02363 Status = STATUS_ACCESS_DENIED; 02364 } 02365 02366 // 02367 // If the caller asked for a list of status', 02368 // duplicate the status all over. 02369 // 02370 if ( ReturnResultList ) { 02371 for ( ResultListIndex=0; ResultListIndex<ObjectTypeListLength; ResultListIndex++ ) { 02372 AccessStatus[ResultListIndex] = Status; 02373 GrantedAccess[ResultListIndex] = PreviouslyGrantedAccess; 02374 } 02375 } else { 02376 *AccessStatus = Status; 02377 *GrantedAccess = PreviouslyGrantedAccess; 02378 } 02379 02380 if ( NT_SUCCESS(Status) ) { 02381 if ( PrivilegeCount > 0 ) { 02382 02383 SepAssemblePrivileges( 02384 PrivilegeCount, 02385 SystemSecurity, 02386 WriteOwner, 02387 Privileges 02388 ); 02389 } 02390 02391 if ( ARGUMENT_PRESENT(ReturnSomeAccessGranted)) { 02392 *ReturnSomeAccessGranted = TRUE; 02393 } 02394 if ( ARGUMENT_PRESENT(ReturnSomeAccessDenied)) { 02395 *ReturnSomeAccessDenied = FALSE; 02396 } 02397 } else { 02398 if ( ARGUMENT_PRESENT(ReturnSomeAccessGranted)) { 02399 *ReturnSomeAccessGranted = FALSE; 02400 } 02401 if ( ARGUMENT_PRESENT(ReturnSomeAccessDenied)) { 02402 *ReturnSomeAccessDenied = TRUE;; 02403 } 02404 } 02405 return; 02406 02407 }

VOID SepAddAccessTypeList IN PIOBJECT_TYPE_LIST  ObjectTypeList,
IN ULONG  ObjectTypeListLength,
IN ULONG  StartIndex,
IN ACCESS_MASK  AccessMask,
IN ACCESS_MASK_FIELD_TO_UPDATE  FieldToUpdate
 

Definition at line 574 of file accessck.c.

References FALSE, Index, PAGED_CODE, SepUpdateParentTypeList(), TRUE, UpdateCurrentDenied, UpdateCurrentGranted, and UpdateRemaining.

Referenced by SepAccessCheck(), SepMaximumAccessCheck(), and SepNormalAccessCheck().

00583 : 00584 00585 This routine grants the specified AccessMask to all of the objects that 00586 are descendents of the object specified by StartIndex. 00587 00588 The Access fields of the parent objects are also recomputed as needed. 00589 00590 For example, if an ACE granting access to a Property Set is found, 00591 that access is granted to all the Properties in the Property Set. 00592 00593 Arguments: 00594 00595 ObjectTypeList - The object type list to update. 00596 00597 ObjectTypeListLength - Number of elements in ObjectTypeList 00598 00599 StartIndex - Index to the target element to update. 00600 00601 AccessMask - Mask of access to grant to the target element and 00602 all of its decendents 00603 00604 FieldToUpdate - Indicate which fields to update in object type list 00605 00606 Return Value: 00607 00608 None. 00609 00610 --*/ 00611 00612 { 00613 ULONG Index; 00614 ACCESS_MASK OldRemaining; 00615 ACCESS_MASK OldCurrentGranted; 00616 ACCESS_MASK OldCurrentDenied; 00617 BOOLEAN AvoidParent = FALSE; 00618 00619 PAGED_CODE(); 00620 00621 // 00622 // Update the requested field. 00623 // 00624 // Always handle the target entry. 00625 // 00626 // If we've not actually changed the bits, 00627 // early out. 00628 // 00629 00630 switch (FieldToUpdate ) { 00631 case UpdateRemaining: 00632 00633 OldRemaining = ObjectTypeList[StartIndex].Remaining; 00634 ObjectTypeList[StartIndex].Remaining = OldRemaining & ~AccessMask; 00635 00636 if ( OldRemaining == ObjectTypeList[StartIndex].Remaining ) { 00637 return; 00638 } 00639 break; 00640 00641 case UpdateCurrentGranted: 00642 00643 OldCurrentGranted = ObjectTypeList[StartIndex].CurrentGranted; 00644 ObjectTypeList[StartIndex].CurrentGranted |= 00645 AccessMask & ~ObjectTypeList[StartIndex].CurrentDenied; 00646 00647 if ( OldCurrentGranted == ObjectTypeList[StartIndex].CurrentGranted ) { 00648 // 00649 // We can't simply return here. 00650 // We have to visit our children. Consider the case where there 00651 // was a previous deny ACE on a child. That deny would have 00652 // propagated up the tree to this entry. However, this allow ACE 00653 // needs to be added all of the children that haven't been 00654 // explictly denied. 00655 // 00656 AvoidParent = TRUE; 00657 } 00658 break; 00659 00660 case UpdateCurrentDenied: 00661 00662 OldCurrentDenied = ObjectTypeList[StartIndex].CurrentDenied; 00663 ObjectTypeList[StartIndex].CurrentDenied |= 00664 AccessMask & ~ObjectTypeList[StartIndex].CurrentGranted; 00665 00666 if ( OldCurrentDenied == ObjectTypeList[StartIndex].CurrentDenied ) { 00667 return; 00668 } 00669 break; 00670 00671 default: 00672 return; 00673 } 00674 00675 00676 // 00677 // Go update parent of the target. 00678 // 00679 00680 if ( !AvoidParent ) { 00681 SepUpdateParentTypeList( ObjectTypeList, 00682 ObjectTypeListLength, 00683 StartIndex ); 00684 } 00685 00686 // 00687 // Loop handling all children of the target. 00688 // 00689 00690 for ( Index=StartIndex+1; Index<ObjectTypeListLength; Index++ ) { 00691 00692 // 00693 // By definition, the children of an object are all those entries 00694 // immediately following the target. The list of children (or 00695 // grandchildren) stops as soon as we reach an entry the has the 00696 // same level as the target (a sibling) or lower than the target 00697 // (an uncle). 00698 // 00699 00700 if ( ObjectTypeList[Index].Level <= ObjectTypeList[StartIndex].Level ) { 00701 break; 00702 } 00703 00704 // 00705 // Grant access to the children 00706 // 00707 00708 switch (FieldToUpdate) { 00709 case UpdateRemaining: 00710 00711 ObjectTypeList[Index].Remaining &= ~AccessMask; 00712 break; 00713 00714 case UpdateCurrentGranted: 00715 00716 ObjectTypeList[Index].CurrentGranted |= 00717 AccessMask & ~ObjectTypeList[Index].CurrentDenied; 00718 break; 00719 00720 case UpdateCurrentDenied: 00721 00722 ObjectTypeList[Index].CurrentDenied |= 00723 AccessMask & ~ObjectTypeList[Index].CurrentGranted; 00724 break; 00725 00726 default: 00727 return; 00728 } 00729 } 00730 }

VOID SepMaximumAccessCheck IN PTOKEN  EToken,
IN PTOKEN  PrimaryToken,
IN PACL  Dacl,
IN PSID  PrincipalSelfSid,
IN ULONG  LocalTypeListLength,
IN PIOBJECT_TYPE_LIST  LocalTypeList,
IN ULONG  ObjectTypeListLength,
IN BOOLEAN  Restricted
 

Definition at line 992 of file accessck.c.

References Dacl, FALSE, FirstAce, Index, NextAce, NULL, PrimaryToken, Restricted, SepAddAccessTypeList(), SepObjectInTypeList(), SepSidInTokenEx(), TRUE, UpdateCurrentDenied, and UpdateCurrentGranted.

Referenced by SepAccessCheck().

01004 : 01005 01006 Does an access check for maximum allowed or with a result list. If the 01007 Restricted flag is set, it is done for a restricted token. The sids 01008 checked are the restricted sids, not the users and groups. The current 01009 granted access is stored in the Remaining access and then another access 01010 check is run. 01011 01012 Arguments: 01013 01014 EToken - Effective token of caller. 01015 01016 PrimaryToken - Process token of calling process 01017 01018 Dacl - ACL to check 01019 01020 PrincipalSelfSid - Sid to use in replacing the well-known self sid 01021 01022 LocalTypeListLength - Length of list of types. 01023 01024 LocalTypeList - List of types. 01025 01026 ObjectTypeList - Length of caller-supplied list of object types. 01027 01028 Return Value: 01029 01030 none 01031 01032 --*/ 01033 01034 { 01035 ULONG i,j; 01036 PVOID Ace; 01037 ULONG AceCount; 01038 ULONG Index; 01039 ULONG ResultListIndex; 01040 01041 // 01042 // The remaining bits are the granted bits for each object type on a 01043 // restricted check 01044 // 01045 01046 if ( Restricted ) { 01047 for ( j=0; j<LocalTypeListLength; j++ ) { 01048 LocalTypeList[j].Remaining = LocalTypeList[j].CurrentGranted; 01049 LocalTypeList[j].CurrentGranted = 0; 01050 } 01051 } 01052 01053 01054 AceCount = Dacl->AceCount; 01055 01056 // 01057 // granted == NUL 01058 // denied == NUL 01059 // 01060 // for each ACE 01061 // 01062 // if grant 01063 // for each SID 01064 // if SID match, then add all that is not denied to grant mask 01065 // 01066 // if deny 01067 // for each SID 01068 // if SID match, then add all that is not granted to deny mask 01069 // 01070 01071 for ( i = 0, Ace = FirstAce( Dacl ) ; 01072 i < AceCount ; 01073 i++, Ace = NextAce( Ace ) 01074 ) { 01075 01076 if ( !(((PACE_HEADER)Ace)->AceFlags & INHERIT_ONLY_ACE)) { 01077 01078 if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_ACE_TYPE) ) { 01079 01080 if (SepSidInTokenEx( EToken, PrincipalSelfSid, &((PACCESS_ALLOWED_ACE)Ace)->SidStart, FALSE, Restricted )) { 01081 01082 // 01083 // Only grant access types from this mask that have 01084 // not already been denied 01085 // 01086 01087 // Optimize 'normal' case 01088 if ( LocalTypeListLength == 1 ) { 01089 LocalTypeList->CurrentGranted |= 01090 (((PACCESS_ALLOWED_ACE)Ace)->Mask & ~LocalTypeList->CurrentDenied); 01091 } else { 01092 // 01093 // The zeroeth object type represents the object itself. 01094 // 01095 SepAddAccessTypeList( 01096 LocalTypeList, // List to modify 01097 LocalTypeListLength, // Length of list 01098 0, // Element to update 01099 ((PACCESS_ALLOWED_ACE)Ace)->Mask, // Access Granted 01100 UpdateCurrentGranted ); 01101 } 01102 } 01103 01104 01105 // 01106 // Handle an object specific Access Allowed ACE 01107 // 01108 } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE) ) { 01109 GUID *ObjectTypeInAce; 01110 01111 // 01112 // If no object type is in the ACE, 01113 // treat this as an ACCESS_ALLOWED_ACE. 01114 // 01115 01116 ObjectTypeInAce = RtlObjectAceObjectType(Ace); 01117 01118 if ( ObjectTypeInAce == NULL ) { 01119 01120 if ( SepSidInTokenEx( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), FALSE, Restricted ) ) { 01121 01122 // Optimize 'normal' case 01123 if ( LocalTypeListLength == 1 ) { 01124 LocalTypeList->CurrentGranted |= 01125 (((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask & ~LocalTypeList->CurrentDenied); 01126 } else { 01127 SepAddAccessTypeList( 01128 LocalTypeList, // List to modify 01129 LocalTypeListLength, // Length of list 01130 0, // Element to update 01131 ((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask, // Access Granted 01132 UpdateCurrentGranted ); 01133 } 01134 } 01135 01136 // 01137 // If no object type list was passed, 01138 // don't grant access to anyone. 01139 // 01140 01141 } else if ( ObjectTypeListLength == 0 ) { 01142 01143 // Drop through 01144 01145 01146 // 01147 // If an object type is in the ACE, 01148 // Find it in the LocalTypeList before using the ACE. 01149 // 01150 } else { 01151 01152 if ( SepSidInTokenEx( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), FALSE, Restricted ) ) { 01153 01154 if ( SepObjectInTypeList( ObjectTypeInAce, 01155 LocalTypeList, 01156 LocalTypeListLength, 01157 &Index ) ) { 01158 SepAddAccessTypeList( 01159 LocalTypeList, // List to modify 01160 LocalTypeListLength, // Length of list 01161 Index, // Element already updated 01162 ((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask, // Access Granted 01163 UpdateCurrentGranted ); 01164 } 01165 } 01166 } 01167 01168 } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE) ) { 01169 01170 // 01171 // If we're impersonating, EToken is set to the Client, and if we're not, 01172 // EToken is set to the Primary. According to the DSA architecture, if 01173 // we're asked to evaluate a compound ACE and we're not impersonating, 01174 // pretend we are impersonating ourselves. So we can just use the EToken 01175 // for the client token, since it's already set to the right thing. 01176 // 01177 01178 01179 if ( SepSidInTokenEx(EToken, PrincipalSelfSid, RtlCompoundAceClientSid( Ace ), FALSE, Restricted) && 01180 SepSidInTokenEx(PrimaryToken, NULL, RtlCompoundAceServerSid( Ace ), FALSE, FALSE) 01181 ) { 01182 01183 // 01184 // Only grant access types from this mask that have 01185 // not already been denied 01186 // 01187 01188 // Optimize 'normal' case 01189 if ( LocalTypeListLength == 1 ) { 01190 LocalTypeList->CurrentGranted |= 01191 (((PCOMPOUND_ACCESS_ALLOWED_ACE)Ace)->Mask & ~LocalTypeList->CurrentDenied); 01192 } else { 01193 // 01194 // The zeroeth object type represents the object itself. 01195 // 01196 SepAddAccessTypeList( 01197 LocalTypeList, // List to modify 01198 LocalTypeListLength, // Length of list 01199 0, // Element to update 01200 ((PCOMPOUND_ACCESS_ALLOWED_ACE)Ace)->Mask, // Access Granted 01201 UpdateCurrentGranted ); 01202 } 01203 01204 } 01205 01206 01207 } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_ACE_TYPE) ) { 01208 01209 if ( SepSidInTokenEx( EToken, PrincipalSelfSid, &((PACCESS_DENIED_ACE)Ace)->SidStart, TRUE, Restricted )) { 01210 01211 // 01212 // Only deny access types from this mask that have 01213 // not already been granted 01214 // 01215 01216 // Optimize 'normal' case 01217 if ( LocalTypeListLength == 1 ) { 01218 LocalTypeList->CurrentDenied |= 01219 (((PACCESS_DENIED_ACE)Ace)->Mask & ~LocalTypeList->CurrentGranted); 01220 } else { 01221 // 01222 // The zeroeth object type represents the object itself. 01223 // 01224 SepAddAccessTypeList( 01225 LocalTypeList, // List to modify 01226 LocalTypeListLength, // Length of list 01227 0, // Element to update 01228 ((PACCESS_DENIED_ACE)Ace)->Mask, // Access denied 01229 UpdateCurrentDenied ); 01230 } 01231 } 01232 01233 01234 // 01235 // Handle an object specific Access Denied ACE 01236 // 01237 } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_OBJECT_ACE_TYPE) ) { 01238 01239 if ( SepSidInTokenEx( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), TRUE, Restricted ) ) { 01240 GUID *ObjectTypeInAce; 01241 01242 // 01243 // If there is no object type in the ACE, 01244 // or if the caller didn't specify an object type list, 01245 // apply this deny ACE to the entire object. 01246 // 01247 01248 ObjectTypeInAce = RtlObjectAceObjectType(Ace); 01249 01250 if ( ObjectTypeInAce == NULL ) { 01251 01252 if ( LocalTypeListLength == 1 ) { 01253 LocalTypeList->CurrentDenied |= 01254 (((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask & ~LocalTypeList->CurrentGranted); 01255 } else { 01256 01257 // 01258 // The zeroeth object type represents the object itself. 01259 // 01260 01261 SepAddAccessTypeList( 01262 LocalTypeList, // List to modify 01263 LocalTypeListLength, // Length of list 01264 0, 01265 ((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask, // Access denied 01266 UpdateCurrentDenied ); 01267 } 01268 // 01269 // If no object type list was passed, 01270 // don't grant access to anyone. 01271 // 01272 01273 } else if ( ObjectTypeListLength == 0 ) { 01274 01275 LocalTypeList->CurrentDenied |= 01276 (((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask & ~LocalTypeList->CurrentGranted); 01277 01278 01279 // 01280 // If an object type is in the ACE, 01281 // Find it in the LocalTypeList before using the ACE. 01282 // 01283 01284 } else if ( SepObjectInTypeList( ObjectTypeInAce, 01285 LocalTypeList, 01286 LocalTypeListLength, 01287 &Index ) ) { 01288 01289 SepAddAccessTypeList( 01290 LocalTypeList, // List to modify 01291 LocalTypeListLength, // Length of list 01292 Index, // Element to update 01293 ((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask, // Access denied 01294 UpdateCurrentDenied ); 01295 01296 } 01297 } 01298 } 01299 } 01300 } 01301 }

VOID SepNormalAccessCheck IN ACCESS_MASK  Remaining,
IN PTOKEN  EToken,
IN PTOKEN  PrimaryToken,
IN PACL  Dacl,
IN PSID  PrincipalSelfSid,
IN ULONG  LocalTypeListLength,
IN PIOBJECT_TYPE_LIST  LocalTypeList,
IN ULONG  ObjectTypeListLength,
IN BOOLEAN  Restricted
 

Definition at line 1304 of file accessck.c.

References Dacl, FALSE, FirstAce, Index, NextAce, NULL, PrimaryToken, Restricted, SepAddAccessTypeList(), SepObjectInTypeList(), SepSidInTokenEx(), TRUE, and UpdateRemaining.

Referenced by SepAccessCheck().

01317 : 01318 01319 Does an access check when the caller isn't asking for MAXIMUM_ALLOWED or 01320 a type result list. If the Restricted flag is set, the sids checked are 01321 the restricted sids, not the users and groups. The Remaining field is 01322 reset to the original remaining value and then another access check is run. 01323 01324 Arguments: 01325 01326 Remaining - Remaining access desired after special checks 01327 01328 EToken - Effective token of caller. 01329 01330 PrimaryToken - Process token of calling process 01331 01332 Dacl - ACL to check 01333 01334 PrincipalSelfSid - Sid to use in replacing the well-known self sid 01335 01336 LocalTypeListLength - Length of list of types. 01337 01338 LocalTypeList - List of types. 01339 01340 ObjectTypeList - Length of caller-supplied list of object types. 01341 01342 Restricted - Use the restricted sids for the access check. 01343 01344 Return Value: 01345 01346 none 01347 01348 --*/ 01349 { 01350 ULONG i,j; 01351 PVOID Ace; 01352 ULONG AceCount; 01353 ULONG Index; 01354 01355 AceCount = Dacl->AceCount; 01356 01357 // 01358 // The remaining bits are "remaining" at all levels 01359 // 01360 01361 for ( j=0; j<LocalTypeListLength; j++ ) { 01362 LocalTypeList[j].Remaining = Remaining; 01363 } 01364 01365 // 01366 // Process the DACL handling individual access bits. 01367 // 01368 01369 for ( i = 0, Ace = FirstAce( Dacl ) ; 01370 ( i < AceCount ) && ( LocalTypeList->Remaining != 0 ) ; 01371 i++, Ace = NextAce( Ace ) ) { 01372 01373 if ( !(((PACE_HEADER)Ace)->AceFlags & INHERIT_ONLY_ACE)) { 01374 01375 // 01376 // Handle an Access Allowed ACE 01377 // 01378 01379 if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_ACE_TYPE) ) { 01380 01381 if ( SepSidInTokenEx( EToken, PrincipalSelfSid, &((PACCESS_ALLOWED_ACE )Ace)->SidStart, FALSE, Restricted ) ) { 01382 01383 // Optimize 'normal' case 01384 if ( LocalTypeListLength == 1 ) { 01385 LocalTypeList->Remaining &= ~((PACCESS_ALLOWED_ACE)Ace)->Mask; 01386 } else { 01387 // 01388 // The zeroeth object type represents the object itself. 01389 // 01390 SepAddAccessTypeList( 01391 LocalTypeList, // List to modify 01392 LocalTypeListLength, // Length of list 01393 0, // Element to update 01394 ((PACCESS_ALLOWED_ACE)Ace)->Mask, // Access Granted 01395 UpdateRemaining ); 01396 } 01397 01398 } 01399 01400 01401 // 01402 // Handle an object specific Access Allowed ACE 01403 // 01404 } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE) ) { 01405 GUID *ObjectTypeInAce; 01406 01407 // 01408 // If no object type is in the ACE, 01409 // treat this as an ACCESS_ALLOWED_ACE. 01410 // 01411 01412 ObjectTypeInAce = RtlObjectAceObjectType(Ace); 01413 01414 if ( ObjectTypeInAce == NULL ) { 01415 01416 if ( SepSidInTokenEx( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), FALSE, Restricted ) ) { 01417 01418 // Optimize 'normal' case 01419 if ( LocalTypeListLength == 1 ) { 01420 LocalTypeList->Remaining &= ~((PACCESS_ALLOWED_ACE)Ace)->Mask; 01421 } else { 01422 SepAddAccessTypeList( 01423 LocalTypeList, // List to modify 01424 LocalTypeListLength, // Length of list 01425 0, // Element to update 01426 ((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask, // Access Granted 01427 UpdateRemaining ); 01428 } 01429 } 01430 01431 // 01432 // If no object type list was passed, 01433 // don't grant access to anyone. 01434 // 01435 01436 } else if ( ObjectTypeListLength == 0 ) { 01437 01438 // Drop through 01439 01440 01441 // 01442 // If an object type is in the ACE, 01443 // Find it in the LocalTypeList before using the ACE. 01444 // 01445 } else { 01446 01447 if ( SepSidInTokenEx( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), FALSE, Restricted ) ) { 01448 01449 if ( SepObjectInTypeList( ObjectTypeInAce, 01450 LocalTypeList, 01451 LocalTypeListLength, 01452 &Index ) ) { 01453 SepAddAccessTypeList( 01454 LocalTypeList, // List to modify 01455 LocalTypeListLength, // Length of list 01456 Index, // Element already updated 01457 ((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask, // Access Granted 01458 UpdateRemaining ); 01459 } 01460 } 01461 } 01462 01463 01464 // 01465 // Handle a compound Access Allowed ACE 01466 // 01467 01468 } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE) ) { 01469 01470 // 01471 // See comment in MAXIMUM_ALLOWED case as to why we can use EToken here 01472 // for the client. 01473 // 01474 01475 if ( SepSidInTokenEx(EToken, PrincipalSelfSid, RtlCompoundAceClientSid( Ace ), FALSE, Restricted) && 01476 SepSidInTokenEx(PrimaryToken, NULL, RtlCompoundAceServerSid( Ace ), FALSE, Restricted) ) { 01477 01478 // Optimize 'normal' case 01479 if ( LocalTypeListLength == 1 ) { 01480 LocalTypeList->Remaining &= ~((PCOMPOUND_ACCESS_ALLOWED_ACE)Ace)->Mask; 01481 } else { 01482 SepAddAccessTypeList( 01483 LocalTypeList, // List to modify 01484 LocalTypeListLength, // Length of list 01485 0, // Element to update 01486 ((PCOMPOUND_ACCESS_ALLOWED_ACE)Ace)->Mask, // Access Granted 01487 UpdateRemaining ); 01488 } 01489 } 01490 01491 01492 01493 // 01494 // Handle an Access Denied ACE 01495 // 01496 01497 } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_ACE_TYPE) ) { 01498 01499 if ( SepSidInTokenEx( EToken, PrincipalSelfSid, &((PACCESS_DENIED_ACE)Ace)->SidStart, TRUE, Restricted ) ) { 01500 01501 // 01502 // The zeroeth element represents the object itself. 01503 // Just check that element. 01504 // 01505 if (LocalTypeList->Remaining & ((PACCESS_DENIED_ACE)Ace)->Mask) { 01506 01507 break; 01508 } 01509 } 01510 01511 01512 // 01513 // Handle an object specific Access Denied ACE 01514 // 01515 } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_OBJECT_ACE_TYPE) ) { 01516 01517 if ( SepSidInTokenEx( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), TRUE, Restricted ) ) { 01518 GUID *ObjectTypeInAce; 01519 01520 // 01521 // If there is no object type in the ACE, 01522 // or if the caller didn't specify an object type list, 01523 // apply this deny ACE to the entire object. 01524 // 01525 01526 ObjectTypeInAce = RtlObjectAceObjectType(Ace); 01527 if ( ObjectTypeInAce == NULL || 01528 ObjectTypeListLength == 0 ) { 01529 01530 // 01531 // The zeroeth element represents the object itself. 01532 // Just check that element. 01533 // 01534 if (LocalTypeList->Remaining & ((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask) { 01535 break; 01536 } 01537 01538 // 01539 // Otherwise apply the deny ACE to the object specified 01540 // in the ACE. 01541 // 01542 01543 } else if ( SepObjectInTypeList( ObjectTypeInAce, 01544 LocalTypeList, 01545 LocalTypeListLength, 01546 &Index ) ) { 01547 01548 if (LocalTypeList[Index].Remaining & ((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask) { 01549 break; 01550 } 01551 01552 } 01553 } 01554 } 01555 01556 } 01557 } 01558 01559 01560 }

BOOLEAN SepObjectInTypeList IN GUID *  ObjectType,
IN PIOBJECT_TYPE_LIST  ObjectTypeList,
IN ULONG  ObjectTypeListLength,
OUT PULONG  ReturnedIndex
 

Definition at line 388 of file accessck.c.

References ASSERT, FALSE, Index, PAGED_CODE, and TRUE.

Referenced by SepAccessCheck(), SepExamineSaclEx(), SepMaximumAccessCheck(), and SepNormalAccessCheck().

00396 : 00397 00398 This routine searches an ObjectTypeList to determine if the specified 00399 object type is in the list. 00400 00401 Arguments: 00402 00403 ObjectType - Object Type to search for. 00404 00405 ObjectTypeList - The object type list to search. 00406 00407 ObjectTypeListLength - Number of elements in ObjectTypeList 00408 00409 ReturnedIndex - Index to the element ObjectType was found in 00410 00411 00412 Return Value: 00413 00414 TRUE: ObjectType was found in list. 00415 FALSE: ObjectType was not found in list. 00416 00417 --*/ 00418 00419 { 00420 ULONG Index; 00421 GUID *LocalObjectType; 00422 00423 PAGED_CODE(); 00424 00425 ASSERT( sizeof(GUID) == sizeof(ULONG) * 4 ); 00426 for ( Index=0; Index<ObjectTypeListLength; Index++ ) { 00427 00428 LocalObjectType = &ObjectTypeList[Index].ObjectType; 00429 00430 if ( RtlpIsEqualGuid( ObjectType, LocalObjectType ) ) { 00431 *ReturnedIndex = Index; 00432 return TRUE; 00433 } 00434 } 00435 00436 return FALSE; 00437 }

NTSTATUS SePrivilegePolicyCheck IN OUT PACCESS_MASK  RemainingDesiredAccess,
IN OUT PACCESS_MASK  PreviouslyGrantedAccess,
IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext  OPTIONAL,
IN PACCESS_TOKEN ExplicitToken  OPTIONAL,
OUT PPRIVILEGE_SET *  PrivilegeSet,
IN KPROCESSOR_MODE  PreviousMode
 

Definition at line 3652 of file accessck.c.

References ANYSIZE_ARRAY, EffectiveToken, ExAllocatePoolWithTag, FALSE, NULL, PAGED_CODE, PagedPool, PTOKEN, SepSinglePrivilegeCheck(), SeSecurityPrivilege, SeTakeOwnershipPrivilege, Token, and TRUE.

Referenced by SeAccessCheckByType(), and SepAccessCheckAndAuditAlarm().

03663 : 03664 03665 This routine implements privilege policy by examining the bits in 03666 a DesiredAccess mask and adjusting them based on privilege checks. 03667 03668 Currently, a request for ACCESS_SYSTEM_SECURITY may only be satisfied 03669 by the caller having SeSecurityPrivilege. WRITE_OWNER may optionally 03670 be satisfied via SeTakeOwnershipPrivilege. 03671 03672 Arguments: 03673 03674 RemainingDesiredAccess - The desired access for the current operation. 03675 Bits may be cleared in this if the subject has particular privileges. 03676 03677 PreviouslyGrantedAccess - Supplies an access mask describing any 03678 accesses that have already been granted. Bits may be set in 03679 here as a result of privilge checks. 03680 03681 SubjectSecurityContext - Optionally provides the subject's security 03682 context. 03683 03684 ExplicitToken - Optionally provides the token to be examined. 03685 03686 PrivilegeSet - Supplies a pointer to a location in which will be 03687 returned a pointer to a privilege set. 03688 03689 PreviousMode - The previous processor mode. 03690 03691 Return Value: 03692 03693 STATUS_SUCCESS - Any access requests that could be satisfied via 03694 privileges were done. 03695 03696 STATUS_PRIVILEGE_NOT_HELD - An access type was being requested that 03697 requires a privilege, and the current subject did not have the 03698 privilege. 03699 03700 03701 03702 --*/ 03703 03704 { 03705 BOOLEAN Success; 03706 PTOKEN Token; 03707 BOOLEAN WriteOwner = FALSE; 03708 BOOLEAN SystemSecurity = FALSE; 03709 ULONG PrivilegeNumber = 0; 03710 ULONG PrivilegeCount = 0; 03711 ULONG SizeRequired; 03712 03713 PAGED_CODE(); 03714 03715 if (ARGUMENT_PRESENT( SubjectSecurityContext )) { 03716 03717 Token = (PTOKEN)EffectiveToken( SubjectSecurityContext ); 03718 03719 } else { 03720 03721 Token = (PTOKEN)ExplicitToken; 03722 } 03723 03724 03725 if (*RemainingDesiredAccess & ACCESS_SYSTEM_SECURITY) { 03726 03727 Success = SepSinglePrivilegeCheck ( 03728 SeSecurityPrivilege, 03729 Token, 03730 PreviousMode 03731 ); 03732 03733 if (!Success) { 03734 03735 return( STATUS_PRIVILEGE_NOT_HELD ); 03736 } 03737 03738 PrivilegeCount++; 03739 SystemSecurity = TRUE; 03740 03741 *RemainingDesiredAccess &= ~ACCESS_SYSTEM_SECURITY; 03742 *PreviouslyGrantedAccess |= ACCESS_SYSTEM_SECURITY; 03743 } 03744 03745 if (*RemainingDesiredAccess & WRITE_OWNER) { 03746 03747 Success = SepSinglePrivilegeCheck ( 03748 SeTakeOwnershipPrivilege, 03749 Token, 03750 PreviousMode 03751 ); 03752 03753 if (Success) { 03754 03755 PrivilegeCount++; 03756 WriteOwner = TRUE; 03757 03758 *RemainingDesiredAccess &= ~WRITE_OWNER; 03759 *PreviouslyGrantedAccess |= WRITE_OWNER; 03760 03761 } 03762 } 03763 03764 if (PrivilegeCount > 0) { 03765 SizeRequired = sizeof(PRIVILEGE_SET) + 03766 (PrivilegeCount - ANYSIZE_ARRAY) * 03767 (ULONG)sizeof(LUID_AND_ATTRIBUTES); 03768 03769 *PrivilegeSet = ExAllocatePoolWithTag( PagedPool, SizeRequired, 'rPeS' ); 03770 03771 if ( *PrivilegeSet == NULL ) { 03772 return( STATUS_INSUFFICIENT_RESOURCES ); 03773 } 03774 03775 (*PrivilegeSet)->PrivilegeCount = PrivilegeCount; 03776 (*PrivilegeSet)->Control = 0; 03777 03778 if (WriteOwner) { 03779 (*PrivilegeSet)->Privilege[PrivilegeNumber].Luid = SeTakeOwnershipPrivilege; 03780 (*PrivilegeSet)->Privilege[PrivilegeNumber].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS; 03781 PrivilegeNumber++; 03782 } 03783 03784 if (SystemSecurity) { 03785 (*PrivilegeSet)->Privilege[PrivilegeNumber].Luid = SeSecurityPrivilege; 03786 (*PrivilegeSet)->Privilege[PrivilegeNumber].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS; 03787 } 03788 } 03789 03790 return( STATUS_SUCCESS ); 03791 }

BOOLEAN SeProxyAccessCheck IN PUNICODE_STRING  Volume,
IN PUNICODE_STRING  RelativePath,
IN BOOLEAN  ContainerObject,
IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN PSECURITY_SUBJECT_CONTEXT  SubjectSecurityContext,
IN BOOLEAN  SubjectContextLocked,
IN ACCESS_MASK  DesiredAccess,
IN ACCESS_MASK  PreviouslyGrantedAccess,
OUT PPRIVILEGE_SET *Privileges  OPTIONAL,
IN PGENERIC_MAPPING  GenericMapping,
IN KPROCESSOR_MODE  AccessMode,
OUT PACCESS_MASK  GrantedAccess,
OUT PNTSTATUS  AccessStatus
 

Definition at line 3564 of file accessck.c.

References SeAccessCheck().

03582 : 03583 03584 03585 Arguments: 03586 03587 Volume - Supplies the volume information of the file being opened. 03588 03589 RelativePath - The volume-relative path of the file being opened. The full path of the 03590 file is the RelativePath appended to the Volume string. 03591 03592 ContainerObject - Indicates if the access is to a container object (TRUE), or a leaf object (FALSE). 03593 03594 SecurityDescriptor - Supplies the security descriptor protecting the 03595 object being accessed 03596 03597 SubjectSecurityContext - A pointer to the subject's captured security 03598 context 03599 03600 SubjectContextLocked - Supplies a flag indiciating whether or not 03601 the user's subject context is locked, so that it does not have 03602 to be locked again. 03603 03604 DesiredAccess - Supplies the access mask that the user is attempting to 03605 acquire 03606 03607 PreviouslyGrantedAccess - Supplies any accesses that the user has 03608 already been granted, for example, as a result of holding a 03609 privilege. 03610 03611 Privileges - Supplies a pointer in which will be returned a privilege 03612 set indicating any privileges that were used as part of the 03613 access validation. 03614 03615 GenericMapping - Supplies the generic mapping associated with this 03616 object type. 03617 03618 AccessMode - Supplies the access mode to be used in the check 03619 03620 GrantedAccess - Pointer to a returned access mask indicatating the 03621 granted access 03622 03623 AccessStatus - Status value that may be returned indicating the 03624 reason why access was denied. Routines should avoid hardcoding a 03625 return value of STATUS_ACCESS_DENIED so that a different value can 03626 be returned when mandatory access control is implemented. 03627 03628 03629 Return Value: 03630 03631 BOOLEAN - TRUE if access is allowed and FALSE otherwise 03632 03633 --*/ 03634 03635 { 03636 return SeAccessCheck ( 03637 SecurityDescriptor, 03638 SubjectSecurityContext, 03639 SubjectContextLocked, 03640 DesiredAccess, 03641 PreviouslyGrantedAccess, 03642 Privileges, 03643 GenericMapping, 03644 AccessMode, 03645 GrantedAccess, 03646 AccessStatus 03647 ); 03648 }

BOOLEAN SepSidInToken IN PACCESS_TOKEN  AToken,
IN PSID  PrincipalSelfSid,
IN PSID  Sid,
IN BOOLEAN  DenyAce
 

Definition at line 733 of file accessck.c.

References FALSE, NULL, PAGED_CODE, PTOKEN, RtlEqualSid(), SepDumpTokenInfo(), SePrincipalSelfSid, Token, and TRUE.

Referenced by SepAccessCheck(), SepExamineSacl(), SepExamineSaclEx(), and SepTokenIsOwner().

00742 : 00743 00744 Checks to see if a given SID is in the given token. 00745 00746 N.B. The code to compute the length of a SID and test for equality 00747 is duplicated from the security runtime since this is such a 00748 frequently used routine. 00749 00750 Arguments: 00751 00752 Token - Pointer to the token to be examined 00753 00754 PrincipalSelfSid - If the object being access checked is an object which 00755 represents a principal (e.g., a user object), this parameter should 00756 be the SID of the object. Any ACE containing the constant 00757 PRINCIPAL_SELF_SID is replaced by this SID. 00758 00759 The parameter should be NULL if the object does not represent a principal. 00760 00761 00762 Sid - Pointer to the SID of interest 00763 00764 Return Value: 00765 00766 A value of TRUE indicates that the SID is in the token, FALSE 00767 otherwise. 00768 00769 --*/ 00770 00771 { 00772 00773 ULONG i; 00774 PISID MatchSid; 00775 ULONG SidLength; 00776 PTOKEN Token; 00777 PSID_AND_ATTRIBUTES TokenSid; 00778 ULONG UserAndGroupCount; 00779 00780 PAGED_CODE(); 00781 00782 #if DBG 00783 00784 SepDumpTokenInfo(AToken); 00785 00786 #endif 00787 00788 // 00789 // If Sid is the constant PrincipalSelfSid, 00790 // replace it with the passed in PrincipalSelfSid. 00791 // 00792 00793 if ( PrincipalSelfSid != NULL && 00794 RtlEqualSid( SePrincipalSelfSid, Sid ) ) { 00795 Sid = PrincipalSelfSid; 00796 } 00797 00798 // 00799 // Get the length of the source SID since this only needs to be computed 00800 // once. 00801 // 00802 00803 SidLength = 8 + (4 * ((PISID)Sid)->SubAuthorityCount); 00804 00805 // 00806 // Get address of user/group array and number of user/groups. 00807 // 00808 00809 Token = (PTOKEN)AToken; 00810 TokenSid = Token->UserAndGroups; 00811 UserAndGroupCount = Token->UserAndGroupCount; 00812 00813 // 00814 // Scan through the user/groups and attempt to find a match with the 00815 // specified SID. 00816 // 00817 00818 for (i = 0 ; i < UserAndGroupCount ; i += 1) { 00819 MatchSid = (PISID)TokenSid->Sid; 00820 00821 // 00822 // If the SID revision and length matches, then compare the SIDs 00823 // for equality. 00824 // 00825 00826 if ((((PISID)Sid)->Revision == MatchSid->Revision) && 00827 (SidLength == (8 + (4 * (ULONG)MatchSid->SubAuthorityCount)))) { 00828 if (RtlEqualMemory(Sid, MatchSid, SidLength)) { 00829 00830 // 00831 // If this is the first one in the list, then it is the User, 00832 // and return success immediately. 00833 // 00834 // If this is not the first one, then it represents a group, 00835 // and we must make sure the group is currently enabled before 00836 // we can say that the group is "in" the token. 00837 // 00838 00839 if ((i == 0) || (TokenSid->Attributes & SE_GROUP_ENABLED) || 00840 (DenyAce && (TokenSid->Attributes & SE_GROUP_USE_FOR_DENY_ONLY))) { 00841 return TRUE; 00842 00843 } else { 00844 return FALSE; 00845 } 00846 } 00847 } 00848 00849 TokenSid += 1; 00850 } 00851 00852 return FALSE; 00853 }

BOOLEAN SepSidInTokenEx IN PACCESS_TOKEN  AToken,
IN PSID  PrincipalSelfSid,
IN PSID  Sid,
IN BOOLEAN  DenyAce,
IN BOOLEAN  Restricted
 

Definition at line 856 of file accessck.c.

References FALSE, NULL, PAGED_CODE, PTOKEN, Restricted, RtlEqualSid(), SepDumpTokenInfo(), SePrincipalSelfSid, Token, and TRUE.

Referenced by SepMaximumAccessCheck(), SepNormalAccessCheck(), and SepTokenIsOwner().

00866 : 00867 00868 Checks to see if a given restricted SID is in the given token. 00869 00870 N.B. The code to compute the length of a SID and test for equality 00871 is duplicated from the security runtime since this is such a 00872 frequently used routine. 00873 00874 Arguments: 00875 00876 Token - Pointer to the token to be examined 00877 00878 PrincipalSelfSid - If the object being access checked is an object which 00879 represents a principal (e.g., a user object), this parameter should 00880 be the SID of the object. Any ACE containing the constant 00881 PRINCIPAL_SELF_SID is replaced by this SID. 00882 00883 The parameter should be NULL if the object does not represent a principal. 00884 00885 00886 Sid - Pointer to the SID of interest 00887 00888 DenyAce - The ACE being evaluated is a DENY or ACCESS DENIED ace 00889 00890 Restricted - The access check being performed uses the restricted sids. 00891 00892 Return Value: 00893 00894 A value of TRUE indicates that the SID is in the token, FALSE 00895 otherwise. 00896 00897 --*/ 00898 00899 { 00900 00901 ULONG i; 00902 PISID MatchSid; 00903 ULONG SidLength; 00904 PTOKEN Token; 00905 PSID_AND_ATTRIBUTES TokenSid; 00906 ULONG UserAndGroupCount; 00907 00908 PAGED_CODE(); 00909 00910 #if DBG 00911 00912 SepDumpTokenInfo(AToken); 00913 00914 #endif 00915 00916 // 00917 // If Sid is the constant PrincipalSelfSid, 00918 // replace it with the passed in PrincipalSelfSid. 00919 // 00920 00921 if ( PrincipalSelfSid != NULL && 00922 RtlEqualSid( SePrincipalSelfSid, Sid ) ) { 00923 Sid = PrincipalSelfSid; 00924 } 00925 00926 // 00927 // Get the length of the source SID since this only needs to be computed 00928 // once. 00929 // 00930 00931 SidLength = 8 + (4 * ((PISID)Sid)->SubAuthorityCount); 00932 00933 // 00934 // Get address of user/group array and number of user/groups. 00935 // 00936 00937 Token = (PTOKEN)AToken; 00938 if (Restricted) { 00939 TokenSid = Token->RestrictedSids; 00940 UserAndGroupCount = Token->RestrictedSidCount; 00941 } else { 00942 TokenSid = Token->UserAndGroups; 00943 UserAndGroupCount = Token->UserAndGroupCount; 00944 } 00945 00946 // 00947 // Scan through the user/groups and attempt to find a match with the 00948 // specified SID. 00949 // 00950 00951 for (i = 0; i < UserAndGroupCount ; i += 1) { 00952 MatchSid = (PISID)TokenSid->Sid; 00953 00954 // 00955 // If the SID revision and length matches, then compare the SIDs 00956 // for equality. 00957 // 00958 00959 if ((((PISID)Sid)->Revision == MatchSid->Revision) && 00960 (SidLength == (8 + (4 * (ULONG)MatchSid->SubAuthorityCount)))) { 00961 if (RtlEqualMemory(Sid, MatchSid, SidLength)) { 00962 00963 // 00964 // If this is the first one in the list and not deny-only it 00965 // is not a restricted token then it is the User, and return 00966 // success immediately. 00967 // 00968 // If this is not the first one, then it represents a group, 00969 // and we must make sure the group is currently enabled before 00970 // we can say that the group is "in" the token. 00971 // 00972 00973 if ((!Restricted && (i == 0) && ((TokenSid->Attributes & SE_GROUP_USE_FOR_DENY_ONLY) == 0)) || 00974 (TokenSid->Attributes & SE_GROUP_ENABLED) || 00975 (DenyAce && (TokenSid->Attributes & SE_GROUP_USE_FOR_DENY_ONLY))) { 00976 return TRUE; 00977 00978 } else { 00979 return FALSE; 00980 } 00981 00982 } 00983 } 00984 00985 TokenSid += 1; 00986 } 00987 00988 return FALSE; 00989 }

BOOLEAN SepTokenIsOwner IN PACCESS_TOKEN  EffectiveToken,
IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN BOOLEAN  TokenLocked
 

Definition at line 3796 of file accessck.c.

References ASSERT, EffectiveToken, FALSE, NULL, Owner, PAGED_CODE, PTOKEN, SepAcquireTokenReadLock, SepReleaseTokenReadLock, SepSidInToken(), SepSidInTokenEx(), Token, TOKEN_IS_RESTRICTED, and TRUE.

Referenced by SeAccessCheck(), SeAccessCheckByType(), and SepAccessCheckAndAuditAlarm().

03804 : 03805 03806 This routine will determine of the Owner of the passed security descriptor 03807 is in the passed token. If the token is restricted it cannot be the 03808 owner. 03809 03810 03811 Arguments: 03812 03813 Token - The token representing the current user. 03814 03815 SecurityDescriptor - The security descriptor for the object being 03816 accessed. 03817 03818 TokenLocked - A boolean describing whether the caller has taken 03819 a read lock for the token. 03820 03821 03822 Return Value: 03823 03824 TRUE - The user of the token is the owner of the object. 03825 03826 FALSE - The user of the token is not the owner of the object. 03827 03828 --*/ 03829 03830 { 03831 PSID Owner; 03832 BOOLEAN rc; 03833 03834 PISECURITY_DESCRIPTOR ISecurityDescriptor; 03835 PTOKEN Token; 03836 03837 PAGED_CODE(); 03838 03839 ISecurityDescriptor = (PISECURITY_DESCRIPTOR)SecurityDescriptor; 03840 Token = (PTOKEN)EffectiveToken; 03841 03842 if (!TokenLocked) { 03843 SepAcquireTokenReadLock( Token ); 03844 } 03845 03846 Owner = RtlpOwnerAddrSecurityDescriptor( ISecurityDescriptor ); 03847 ASSERT( Owner != NULL ); 03848 03849 rc = SepSidInToken( Token, NULL, Owner, FALSE ); 03850 03851 // 03852 // For restricted tokens, check the restricted sids too. 03853 // 03854 03855 if (rc && (Token->TokenFlags & TOKEN_IS_RESTRICTED) != 0) { 03856 rc = SepSidInTokenEx( Token, NULL, Owner, FALSE, TRUE ); 03857 03858 } 03859 03860 if (!TokenLocked) { 03861 SepReleaseTokenReadLock( Token ); 03862 } 03863 03864 return( rc ); 03865 }

VOID SepUpdateParentTypeList IN PIOBJECT_TYPE_LIST  ObjectTypeList,
IN ULONG  ObjectTypeListLength,
IN ULONG  StartIndex
 

Definition at line 441 of file accessck.c.

References Index, and PAGED_CODE.

Referenced by SepAddAccessTypeList().

00448 : 00449 00450 Update the Access fields of the parent object of the specified object. 00451 00452 00453 The "remaining" field of a parent object is the logical OR of 00454 the remaining field of all of its children. 00455 00456 The CurrentGranted field of the parent is the collection of bits 00457 granted to every one of its children.. 00458 00459 The CurrentDenied fields of the parent is the logical OR of 00460 the bits denied to any of its children. 00461 00462 This routine takes an index to one of the children and updates the 00463 remaining field of the parent (and grandparents recursively). 00464 00465 Arguments: 00466 00467 ObjectTypeList - The object type list to update. 00468 00469 ObjectTypeListLength - Number of elements in ObjectTypeList 00470 00471 StartIndex - Index to the "child" element whose parents are to be updated. 00472 00473 Return Value: 00474 00475 None. 00476 00477 00478 --*/ 00479 00480 { 00481 ULONG Index; 00482 ULONG ParentIndex; 00483 ULONG Level; 00484 ACCESS_MASK NewRemaining = 0; 00485 ACCESS_MASK NewCurrentGranted = 0xFFFFFFFF; 00486 ACCESS_MASK NewCurrentDenied = 0; 00487 00488 PAGED_CODE(); 00489 00490 // 00491 // If the target node is at the root, 00492 // we're all done. 00493 // 00494 00495 if ( ObjectTypeList[StartIndex].ParentIndex == -1 ) { 00496 return; 00497 } 00498 00499 // 00500 // Get the index to the parent that needs updating and the level of 00501 // the siblings. 00502 // 00503 00504 ParentIndex = ObjectTypeList[StartIndex].ParentIndex; 00505 Level = ObjectTypeList[StartIndex].Level; 00506 00507 // 00508 // Loop through all the children. 00509 // 00510 00511 for ( Index=ParentIndex+1; Index<ObjectTypeListLength; Index++ ) { 00512 00513 // 00514 // By definition, the children of an object are all those entries 00515 // immediately following the target. The list of children (or 00516 // grandchildren) stops as soon as we reach an entry the has the 00517 // same level as the target (a sibling) or lower than the target 00518 // (an uncle). 00519 // 00520 00521 if ( ObjectTypeList[Index].Level <= ObjectTypeList[ParentIndex].Level ) { 00522 break; 00523 } 00524 00525 // 00526 // Only handle direct children of the parent. 00527 // 00528 00529 if ( ObjectTypeList[Index].Level != Level ) { 00530 continue; 00531 } 00532 00533 // 00534 // Compute the new bits for the parent. 00535 // 00536 00537 NewRemaining |= ObjectTypeList[Index].Remaining; 00538 NewCurrentGranted &= ObjectTypeList[Index].CurrentGranted; 00539 NewCurrentDenied |= ObjectTypeList[Index].CurrentDenied; 00540 00541 } 00542 00543 // 00544 // If we've not changed the access to the parent, 00545 // we're done. 00546 // 00547 00548 if ( NewRemaining == ObjectTypeList[ParentIndex].Remaining && 00549 NewCurrentGranted == ObjectTypeList[ParentIndex].CurrentGranted && 00550 NewCurrentDenied == ObjectTypeList[ParentIndex].CurrentDenied ) { 00551 return; 00552 } 00553 00554 00555 // 00556 // Change the parent. 00557 // 00558 00559 ObjectTypeList[ParentIndex].Remaining = NewRemaining; 00560 ObjectTypeList[ParentIndex].CurrentGranted = NewCurrentGranted; 00561 ObjectTypeList[ParentIndex].CurrentDenied = NewCurrentDenied; 00562 00563 // 00564 // Go update the grand parents. 00565 // 00566 00567 SepUpdateParentTypeList( ObjectTypeList, 00568 ObjectTypeListLength, 00569 ParentIndex ); 00570 }


Generated on Sat May 15 19:42:49 2004 for test by doxygen 1.3.7